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