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