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