1 // Copyright 2012 The Chromium Authors 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_FILES_DIR_READER_LINUX_H_ 6 #define BASE_FILES_DIR_READER_LINUX_H_ 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <stddef.h> 11 #include <stdint.h> 12 #include <string.h> 13 #include <sys/syscall.h> 14 #include <unistd.h> 15 16 #include "base/logging.h" 17 #include "base/posix/eintr_wrapper.h" 18 19 // See the comments in dir_reader_posix.h about this. 20 21 namespace base { 22 23 struct linux_dirent { 24 uint64_t d_ino; 25 int64_t d_off; 26 unsigned short d_reclen; 27 unsigned char d_type; 28 char d_name[0]; 29 }; 30 31 class DirReaderLinux { 32 public: DirReaderLinux(const char * directory_path)33 explicit DirReaderLinux(const char* directory_path) 34 : fd_(open(directory_path, O_RDONLY | O_DIRECTORY)), 35 offset_(0), 36 size_(0) { 37 memset(buf_, 0, sizeof(buf_)); 38 } 39 40 DirReaderLinux(const DirReaderLinux&) = delete; 41 DirReaderLinux& operator=(const DirReaderLinux&) = delete; 42 ~DirReaderLinux()43 ~DirReaderLinux() { 44 if (fd_ >= 0) { 45 if (IGNORE_EINTR(close(fd_))) 46 RAW_LOG(ERROR, "Failed to close directory handle"); 47 } 48 } 49 IsValid()50 bool IsValid() const { 51 return fd_ >= 0; 52 } 53 54 // Move to the next entry returning false if the iteration is complete. Next()55 bool Next() { 56 if (size_) { 57 linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]); 58 offset_ += dirent->d_reclen; 59 } 60 61 if (offset_ != size_) 62 return true; 63 64 const long r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_)); 65 if (r == 0) 66 return false; 67 if (r < 0) { 68 if (errno != ENOENT) { 69 DPLOG(FATAL) << "getdents64 failed"; 70 } 71 return false; 72 } 73 size_ = static_cast<size_t>(r); 74 offset_ = 0; 75 return true; 76 } 77 name()78 const char* name() const { 79 if (!size_) 80 return nullptr; 81 82 const linux_dirent* dirent = 83 reinterpret_cast<const linux_dirent*>(&buf_[offset_]); 84 return dirent->d_name; 85 } 86 fd()87 int fd() const { 88 return fd_; 89 } 90 IsFallback()91 static bool IsFallback() { 92 return false; 93 } 94 95 private: 96 const int fd_; 97 alignas(linux_dirent) unsigned char buf_[512]; 98 size_t offset_; 99 size_t size_; 100 }; 101 102 } // namespace base 103 104 #endif // BASE_FILES_DIR_READER_LINUX_H_ 105