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