dir_reader_linux.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/eintr_wrapper.h" 16 17// See the comments in dir_reader_posix.h about this. 18 19namespace base { 20 21struct 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 29class 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 (HANDLE_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