dir_reader_linux.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. #ifndef BASE_FILES_DIR_READER_LINUX_H_
  5. #define BASE_FILES_DIR_READER_LINUX_H_
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <stddef.h>
  9. #include <stdint.h>
  10. #include <string.h>
  11. #include <sys/syscall.h>
  12. #include <unistd.h>
  13. #include "base/logging.h"
  14. #include "base/posix/eintr_wrapper.h"
  15. // See the comments in dir_reader_posix.h about this.
  16. namespace base {
  17. struct linux_dirent {
  18. uint64_t d_ino;
  19. int64_t d_off;
  20. unsigned short d_reclen;
  21. unsigned char d_type;
  22. char d_name[0];
  23. };
  24. class DirReaderLinux {
  25. public:
  26. explicit DirReaderLinux(const char* directory_path)
  27. : fd_(open(directory_path, O_RDONLY | O_DIRECTORY)),
  28. offset_(0),
  29. size_(0) {
  30. memset(buf_, 0, sizeof(buf_));
  31. }
  32. DirReaderLinux(const DirReaderLinux&) = delete;
  33. DirReaderLinux& operator=(const DirReaderLinux&) = delete;
  34. ~DirReaderLinux() {
  35. if (fd_ >= 0) {
  36. if (IGNORE_EINTR(close(fd_)))
  37. RAW_LOG(ERROR, "Failed to close directory handle");
  38. }
  39. }
  40. bool IsValid() const {
  41. return fd_ >= 0;
  42. }
  43. // Move to the next entry returning false if the iteration is complete.
  44. bool Next() {
  45. if (size_) {
  46. linux_dirent* dirent = reinterpret_cast<linux_dirent*>(&buf_[offset_]);
  47. offset_ += dirent->d_reclen;
  48. }
  49. if (offset_ != size_)
  50. return true;
  51. const long r = syscall(__NR_getdents64, fd_, buf_, sizeof(buf_));
  52. if (r == 0)
  53. return false;
  54. if (r < 0) {
  55. DPLOG(FATAL) << "getdents64 failed";
  56. return false;
  57. }
  58. size_ = static_cast<size_t>(r);
  59. offset_ = 0;
  60. return true;
  61. }
  62. const char* name() const {
  63. if (!size_)
  64. return nullptr;
  65. const linux_dirent* dirent =
  66. reinterpret_cast<const linux_dirent*>(&buf_[offset_]);
  67. return dirent->d_name;
  68. }
  69. int fd() const {
  70. return fd_;
  71. }
  72. static bool IsFallback() {
  73. return false;
  74. }
  75. private:
  76. const int fd_;
  77. alignas(linux_dirent) unsigned char buf_[512];
  78. size_t offset_;
  79. size_t size_;
  80. };
  81. } // namespace base
  82. #endif // BASE_FILES_DIR_READER_LINUX_H_