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