|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 #ifndef BASE_DIR_READER_LINUX_H_ |
|
6 #define BASE_DIR_READER_LINUX_H_ |
|
7 #pragma once |
|
8 |
|
9 #include <errno.h> |
|
10 #include <fcntl.h> |
|
11 #include <stdint.h> |
|
12 #include <sys/syscall.h> |
|
13 #include <unistd.h> |
|
14 |
|
15 #include "base/logging.h" |
|
16 #include "base/eintr_wrapper.h" |
|
17 |
|
18 // See the comments in dir_reader_posix.h about this. |
|
19 |
|
20 namespace base { |
|
21 |
|
22 struct linux_dirent { |
|
23 uint64_t d_ino; |
|
24 int64_t d_off; |
|
25 unsigned short d_reclen; |
|
26 unsigned char d_type; |
|
27 char d_name[0]; |
|
28 }; |
|
29 |
|
30 class DirReaderLinux { |
|
31 public: |
|
32 explicit DirReaderLinux(const char* directory_path) |
|
33 : fd_(open(directory_path, O_RDONLY | O_DIRECTORY)), |
|
34 offset_(0), |
|
35 size_(0) { |
|
36 memset(buf_, 0, sizeof(buf_)); |
|
37 } |
|
38 |
|
39 ~DirReaderLinux() { |
|
40 if (fd_ >= 0) { |
|
41 if (HANDLE_EINTR(close(fd_))) |
|
42 DLOG(ERROR) << "Failed to close directory handle"; |
|
43 } |
|
44 } |
|
45 |
|
46 bool IsValid() const { |
|
47 return fd_ >= 0; |
|
48 } |
|
49 |
|
50 // Move to the next entry returning false if the iteration is complete. |
|
51 bool Next() { |
|
52 if (size_) { |
|
53 linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]); |
|
54 offset_ += dirent->d_reclen; |
|
55 } |
|
56 |
|
57 if (offset_ != size_) |
|
58 return true; |
|
59 |
|
60 const int r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_)); |
|
61 if (r == 0) |
|
62 return false; |
|
63 if (r == -1) { |
|
64 DLOG(ERROR) << "getdents64 returned an error: " << errno; |
|
65 return false; |
|
66 } |
|
67 size_ = r; |
|
68 offset_ = 0; |
|
69 return true; |
|
70 } |
|
71 |
|
72 const char* name() const { |
|
73 if (!size_) |
|
74 return NULL; |
|
75 |
|
76 const linux_dirent* dirent = |
|
77 reinterpret_cast<const linux_dirent*>(&buf_[offset_]); |
|
78 return dirent->d_name; |
|
79 } |
|
80 |
|
81 int fd() const { |
|
82 return fd_; |
|
83 } |
|
84 |
|
85 static bool IsFallback() { |
|
86 return false; |
|
87 } |
|
88 |
|
89 private: |
|
90 const int fd_; |
|
91 unsigned char buf_[512]; |
|
92 size_t offset_, size_; |
|
93 |
|
94 DISALLOW_COPY_AND_ASSIGN(DirReaderLinux); |
|
95 }; |
|
96 |
|
97 } // namespace base |
|
98 |
|
99 #endif // BASE_DIR_READER_LINUX_H_ |