diff --git a/base/cvd/cuttlefish/files/BUILD.bazel b/base/cvd/cuttlefish/files/BUILD.bazel index ede092a5b07..8602d955288 100644 --- a/base/cvd/cuttlefish/files/BUILD.bazel +++ b/base/cvd/cuttlefish/files/BUILD.bazel @@ -48,6 +48,7 @@ cf_cc_library( srcs = ["directory_contents.cc"], hdrs = ["directory_contents.h"], deps = [ + "//cuttlefish/posix:open_dir", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", ], @@ -90,7 +91,7 @@ cf_cc_library( srcs = ["is_directory_empty.cc"], hdrs = ["is_directory_empty.h"], deps = [ - "//cuttlefish/posix:strerror", + "//cuttlefish/posix:open_dir", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", ], diff --git a/base/cvd/cuttlefish/files/directory_contents.cc b/base/cvd/cuttlefish/files/directory_contents.cc index 4d706c0d165..388f5e7e728 100644 --- a/base/cvd/cuttlefish/files/directory_contents.cc +++ b/base/cvd/cuttlefish/files/directory_contents.cc @@ -23,6 +23,7 @@ #include #include +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" @@ -30,8 +31,7 @@ namespace cuttlefish { Result> DirectoryContents(const std::string& path) { std::vector ret; - std::unique_ptr dir(opendir(path.c_str()), closedir); - CF_EXPECTF(dir != nullptr, "Could not read from dir \"{}\"", path); + std::unique_ptr dir = CF_EXPECT(OpenDir(path)); struct dirent* ent{}; while ((ent = readdir(dir.get()))) { if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { diff --git a/base/cvd/cuttlefish/files/is_directory_empty.cc b/base/cvd/cuttlefish/files/is_directory_empty.cc index 75f86157a51..30aad9d5648 100644 --- a/base/cvd/cuttlefish/files/is_directory_empty.cc +++ b/base/cvd/cuttlefish/files/is_directory_empty.cc @@ -17,20 +17,18 @@ #include "cuttlefish/files/is_directory_empty.h" #include -#include #include #include -#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" namespace cuttlefish { Result IsDirectoryEmpty(const std::string& path) { - std::unique_ptr direc(opendir(path.c_str()), closedir); - CF_EXPECTF(direc.get(), "opendir('{}') failed: {}", path, StrError(errno)); + std::unique_ptr direc = CF_EXPECT(OpenDir(path)); int cnt = 0; while (::readdir(direc.get())) { diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel b/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel index 8b2e3d83572..f829355091d 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel @@ -189,6 +189,7 @@ cf_cc_library( "//cuttlefish/common/libs/utils:in_sandbox", "//cuttlefish/files:directory_contents", "//cuttlefish/host/libs/config:config_utils", + "//cuttlefish/posix:open_dir", "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/process:proc_file_utils", diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc b/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc index 8ee9e67cd3d..5dd627b8478 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc @@ -36,6 +36,7 @@ #include "cuttlefish/common/libs/utils/in_sandbox.h" #include "cuttlefish/files/directory_contents.h" #include "cuttlefish/host/libs/config/config_utils.h" +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/process/proc_file_utils.h" @@ -66,10 +67,7 @@ Result CleanPriorFiles(const std::string& path, } return {}; } - std::unique_ptr dir(opendir(path.c_str()), closedir); - if (!dir) { - return CF_ERRNO("Could not clean \"" << path << "\""); - } + std::unique_ptr dir = CF_EXPECT(OpenDir(path)); for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) { std::string entity_name(entity->d_name); diff --git a/base/cvd/cuttlefish/host/commands/stop/BUILD.bazel b/base/cvd/cuttlefish/host/commands/stop/BUILD.bazel index 388981f2b53..a814e85eb13 100644 --- a/base/cvd/cuttlefish/host/commands/stop/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/stop/BUILD.bazel @@ -18,6 +18,7 @@ cf_cc_binary( "//cuttlefish/flag_parser", "//cuttlefish/host/libs/command_util", "//cuttlefish/host/libs/config:cuttlefish_config", + "//cuttlefish/posix:open_dir", "//cuttlefish/posix:strerror", "//cuttlefish/result", "@abseil-cpp//absl/log", diff --git a/base/cvd/cuttlefish/host/commands/stop/main.cc b/base/cvd/cuttlefish/host/commands/stop/main.cc index a0d550676c3..8f108ff06c9 100644 --- a/base/cvd/cuttlefish/host/commands/stop/main.cc +++ b/base/cvd/cuttlefish/host/commands/stop/main.cc @@ -47,6 +47,7 @@ #include "cuttlefish/host/libs/command_util/runner/defs.h" #include "cuttlefish/host/libs/command_util/util.h" #include "cuttlefish/host/libs/config/cuttlefish_config.h" +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/result.h" @@ -63,14 +64,13 @@ std::set FallbackDirs() { std::string parent_path = StringFromEnv("HOME", "."); paths.insert(parent_path + "/cuttlefish_assembly"); - std::unique_ptr dir(opendir(parent_path.c_str()), - closedir); - if (!dir) { + Result> dir = OpenDir(parent_path); + if (!dir.has_value()) { return paths; } - for (auto entity = readdir(dir.get()); entity != nullptr; - entity = readdir(dir.get())) { + for (auto entity = readdir(dir->get()); entity != nullptr; + entity = readdir(dir->get())) { std::string subdir(entity->d_name); if (!absl::StartsWith(subdir, "cuttlefish_runtime.")) { continue; diff --git a/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel b/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel index c87e5b35b56..8f92973fbbe 100644 --- a/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel +++ b/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel @@ -18,6 +18,7 @@ cf_cc_library( "//cuttlefish/common/libs/utils:environment", "//cuttlefish/common/libs/utils:files", "//cuttlefish/common/libs/utils:users", + "//cuttlefish/posix:open_dir", "//cuttlefish/posix:rename", "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", diff --git a/base/cvd/cuttlefish/host/libs/directories/xdg.cpp b/base/cvd/cuttlefish/host/libs/directories/xdg.cpp index 863a7adabf3..34f5a9bde34 100644 --- a/base/cvd/cuttlefish/host/libs/directories/xdg.cpp +++ b/base/cvd/cuttlefish/host/libs/directories/xdg.cpp @@ -29,6 +29,7 @@ #include "cuttlefish/common/libs/utils/environment.h" #include "cuttlefish/common/libs/utils/files.h" #include "cuttlefish/common/libs/utils/users.h" +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/posix/rename.h" #include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" @@ -144,9 +145,7 @@ Result> FindCvdDataFiles(std::string_view path) { results.emplace_back(std::move(test_path)); continue; } - std::unique_ptr dir_iter(opendir(test_path.c_str()), - closedir); - CF_EXPECTF(dir_iter.get(), "Failed to open '{}'", path); + std::unique_ptr dir_iter = CF_EXPECT(OpenDir(test_path)); dirent* entry; while ((entry = readdir(dir_iter.get())) != nullptr) { std::string entry_name(entry->d_name); diff --git a/base/cvd/cuttlefish/host/libs/web/BUILD.bazel b/base/cvd/cuttlefish/host/libs/web/BUILD.bazel index 71d1899fe48..bc5ede12c7d 100644 --- a/base/cvd/cuttlefish/host/libs/web/BUILD.bazel +++ b/base/cvd/cuttlefish/host/libs/web/BUILD.bazel @@ -42,6 +42,7 @@ cf_cc_library( "//cuttlefish/host/libs/zip:remote_zip", "//cuttlefish/host/libs/zip/libzip_cc:seekable_source", "//cuttlefish/host/libs/zip/libzip_cc:writable_source", + "//cuttlefish/posix:open_dir", "//cuttlefish/posix:symlink", "//cuttlefish/result", "//libbase", diff --git a/base/cvd/cuttlefish/host/libs/web/android_build_api.cpp b/base/cvd/cuttlefish/host/libs/web/android_build_api.cpp index ffe7165b5e7..f7d08bfbd58 100644 --- a/base/cvd/cuttlefish/host/libs/web/android_build_api.cpp +++ b/base/cvd/cuttlefish/host/libs/web/android_build_api.cpp @@ -57,6 +57,7 @@ #include "cuttlefish/host/libs/zip/libzip_cc/seekable_source.h" #include "cuttlefish/host/libs/zip/libzip_cc/writable_source.h" #include "cuttlefish/host/libs/zip/remote_zip.h" +#include "cuttlefish/posix/open_dir.h" #include "cuttlefish/posix/symlink.h" #include "cuttlefish/result/result.h" @@ -70,10 +71,6 @@ bool StatusIsTerminal(const std::string& status) { return terminal_statuses.count(status) > 0; } -struct CloseDir { - void operator()(DIR* dir) { closedir(dir); } -}; - Result GetResponseJson(const HttpResponse& response, const bool allow_redirect = false) { // debug information in error responses floods stderr with too much text @@ -363,8 +360,7 @@ Result> AndroidBuildApi::Artifacts( const DirectoryBuild& build, const std::vector&) { std::unordered_set artifacts; for (const auto& path : build.paths) { - auto dir = std::unique_ptr(opendir(path.c_str())); - CF_EXPECT(dir != nullptr, "Could not read files from \"" << path << "\""); + std::unique_ptr dir = CF_EXPECT(OpenDir(path)); for (auto entity = readdir(dir.get()); entity != nullptr; entity = readdir(dir.get())) { artifacts.emplace(std::string(entity->d_name)); diff --git a/base/cvd/cuttlefish/posix/BUILD.bazel b/base/cvd/cuttlefish/posix/BUILD.bazel index c674b3bbac5..ddfa67246aa 100644 --- a/base/cvd/cuttlefish/posix/BUILD.bazel +++ b/base/cvd/cuttlefish/posix/BUILD.bazel @@ -4,6 +4,17 @@ package( default_visibility = ["//:android_cuttlefish"], ) +cf_cc_library( + name = "open_dir", + srcs = ["open_dir.cc"], + hdrs = ["open_dir.h"], + deps = [ + "//cuttlefish/posix:strerror", + "//cuttlefish/result:expect", + "//cuttlefish/result:result_type", + ], +) + cf_cc_library( name = "rename", srcs = ["rename.cc"], diff --git a/base/cvd/cuttlefish/posix/open_dir.cc b/base/cvd/cuttlefish/posix/open_dir.cc new file mode 100644 index 00000000000..54977611bee --- /dev/null +++ b/base/cvd/cuttlefish/posix/open_dir.cc @@ -0,0 +1,51 @@ +// +// Copyright (C) 2026 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cuttlefish/posix/open_dir.h" + +#include +#include + +#include +#include +#include + +#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/result/expect.h" +#include "cuttlefish/result/result_type.h" + +namespace cuttlefish { + +void CloseDir::operator()(DIR* dir) { + if (dir) { + closedir(dir); + } +} + +Result> OpenDir(const char* path) { + std::unique_ptr ret(opendir(path)); + CF_EXPECTF(ret.get(), "opendir('{}') failed: {}'", path, StrError(errno)); + return ret; +} + +Result> OpenDir(const std::string& path) { + return CF_EXPECT(OpenDir(path.c_str())); +} + +Result> OpenDir(std::string_view path) { + return CF_EXPECT(OpenDir(std::string(path))); +} + +} // namespace cuttlefish diff --git a/base/cvd/cuttlefish/posix/open_dir.h b/base/cvd/cuttlefish/posix/open_dir.h new file mode 100644 index 00000000000..7c53973c91b --- /dev/null +++ b/base/cvd/cuttlefish/posix/open_dir.h @@ -0,0 +1,36 @@ +// +// Copyright (C) 2026 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +#include +#include +#include + +#include "cuttlefish/result/result_type.h" + +namespace cuttlefish { + +struct CloseDir { + void operator()(DIR* dir); +}; + +Result> OpenDir(const char*); +Result> OpenDir(const std::string&); +Result> OpenDir(std::string_view); + +} // namespace cuttlefish