simple_file_enumerator.cc 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2022 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. #include "net/disk_cache/simple/simple_file_enumerator.h"
  5. #include "base/files/file.h"
  6. #include "base/files/file_util.h"
  7. #include "base/logging.h"
  8. // We have an optimized implementation for POSIX, and a fallback
  9. // implementation for other platforms.
  10. namespace disk_cache {
  11. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  12. SimpleFileEnumerator::SimpleFileEnumerator(const base::FilePath& path)
  13. : path_(path), dir_(opendir(path.value().c_str())), has_error_(!dir_) {
  14. if (has_error_) {
  15. PLOG(ERROR) << "opendir " << path;
  16. }
  17. }
  18. SimpleFileEnumerator::~SimpleFileEnumerator() = default;
  19. bool SimpleFileEnumerator::HasError() const {
  20. return has_error_;
  21. }
  22. absl::optional<SimpleFileEnumerator::Entry> SimpleFileEnumerator::Next() {
  23. if (!dir_) {
  24. return absl::nullopt;
  25. }
  26. while (true) {
  27. // errno must be set to 0 before every readdir() call to detect errors.
  28. errno = 0;
  29. dirent* entry = readdir(dir_.get());
  30. if (!entry) {
  31. // Some implementations of readdir() (particularly older versions of
  32. // Android Bionic) may leave errno set to EINTR even after they handle
  33. // this case internally. It's safe to ignore EINTR in that case.
  34. if (errno && errno != EINTR) {
  35. PLOG(ERROR) << "readdir " << path_;
  36. has_error_ = true;
  37. dir_ = nullptr;
  38. return absl::nullopt;
  39. }
  40. break;
  41. }
  42. const std::string filename(entry->d_name);
  43. if (filename == "." || filename == "..") {
  44. continue;
  45. }
  46. base::FilePath path = path_.Append(base::FilePath(filename));
  47. base::File::Info file_info;
  48. if (!base::GetFileInfo(path, &file_info)) {
  49. LOG(ERROR) << "Could not get file info for " << path;
  50. continue;
  51. }
  52. if (file_info.is_directory) {
  53. continue;
  54. }
  55. return absl::make_optional<Entry>(std::move(path), file_info.size,
  56. file_info.last_accessed,
  57. file_info.last_modified);
  58. }
  59. dir_ = nullptr;
  60. return absl::nullopt;
  61. }
  62. #else
  63. SimpleFileEnumerator::SimpleFileEnumerator(const base::FilePath& path)
  64. : enumerator_(path,
  65. /*recursive=*/false,
  66. base::FileEnumerator::FILES) {}
  67. SimpleFileEnumerator::~SimpleFileEnumerator() = default;
  68. bool SimpleFileEnumerator::HasError() const {
  69. return enumerator_.GetError() != base::File::FILE_OK;
  70. }
  71. absl::optional<SimpleFileEnumerator::Entry> SimpleFileEnumerator::Next() {
  72. base::FilePath path = enumerator_.Next();
  73. if (path.empty()) {
  74. return absl::nullopt;
  75. }
  76. base::FileEnumerator::FileInfo info = enumerator_.GetInfo();
  77. return absl::make_optional<Entry>(std::move(path), info.GetSize(),
  78. /*last_accessed=*/base::Time(),
  79. info.GetLastModifiedTime());
  80. }
  81. #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  82. } // namespace disk_cache