1 // Copyright (c) 2012 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_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 <sys/syscall.h> 13 #include <unistd.h> 14 15 #include "base/logging.h" 16 #include "base/macros.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 ~DirReaderLinux()40 ~DirReaderLinux() { 41 if (fd_ >= 0) { 42 if (IGNORE_EINTR(close(fd_))) 43 RAW_LOG(ERROR, "Failed to close directory handle"); 44 } 45 } 46 IsValid()47 bool IsValid() const { 48 return fd_ >= 0; 49 } 50 51 // Move to the next entry returning false if the iteration is complete. Next()52 bool Next() { 53 if (size_) { 54 linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]); 55 offset_ += dirent->d_reclen; 56 } 57 58 if (offset_ != size_) 59 return true; 60 61 const int r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_)); 62 if (r == 0) 63 return false; 64 if (r == -1) { 65 DPLOG(FATAL) << "getdents64 returned an error: " << errno; 66 return false; 67 } 68 size_ = r; 69 offset_ = 0; 70 return true; 71 } 72 name()73 const char* name() const { 74 if (!size_) 75 return nullptr; 76 77 const linux_dirent* dirent = 78 reinterpret_cast<const linux_dirent*>(&buf_[offset_]); 79 return dirent->d_name; 80 } 81 fd()82 int fd() const { 83 return fd_; 84 } 85 IsFallback()86 static bool IsFallback() { 87 return false; 88 } 89 90 private: 91 const int fd_; 92 alignas(linux_dirent) unsigned char buf_[512]; 93 size_t offset_; 94 size_t size_; 95 96 DISALLOW_COPY_AND_ASSIGN(DirReaderLinux); 97 }; 98 99 } // namespace base 100 101 #endif // BASE_FILES_DIR_READER_LINUX_H_ 102