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