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