diff --git a/base/cvd/cuttlefish/common/libs/fs/BUILD.bazel b/base/cvd/cuttlefish/common/libs/fs/BUILD.bazel index 690ac0063e0..825323dac0a 100644 --- a/base/cvd/cuttlefish/common/libs/fs/BUILD.bazel +++ b/base/cvd/cuttlefish/common/libs/fs/BUILD.bazel @@ -108,6 +108,7 @@ cf_cc_library( deps = [ "//cuttlefish/common/libs/fs:file_instance", "//cuttlefish/common/libs/utils:environment", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result", "@abseil-cpp//absl/log", diff --git a/base/cvd/cuttlefish/common/libs/fs/unique_fd.cc b/base/cvd/cuttlefish/common/libs/fs/unique_fd.cc index 8e95ec6fddb..77bd3b9b4db 100644 --- a/base/cvd/cuttlefish/common/libs/fs/unique_fd.cc +++ b/base/cvd/cuttlefish/common/libs/fs/unique_fd.cc @@ -41,6 +41,7 @@ #include "fmt/format.h" #include "cuttlefish/common/libs/utils/known_paths.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/result.h" @@ -210,8 +211,7 @@ UniqueFd UniqueFd::Creat(const std::string& path, mode_t mode) { } Result UniqueFd::Fifo(const std::string& path, mode_t mode) { - struct stat st{}; - if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) == 0) { + if (Stat(path).has_value()) { CF_EXPECTF(TEMP_FAILURE_RETRY(remove(path.c_str())) == 0, "Failed to delete old file at '{}': '{}'", path, ::cuttlefish::StrError(errno)); diff --git a/base/cvd/cuttlefish/common/libs/utils/BUILD.bazel b/base/cvd/cuttlefish/common/libs/utils/BUILD.bazel index 47f90d4b2b5..c24a10a183a 100644 --- a/base/cvd/cuttlefish/common/libs/utils/BUILD.bazel +++ b/base/cvd/cuttlefish/common/libs/utils/BUILD.bazel @@ -123,6 +123,7 @@ cf_cc_library( "//cuttlefish/io:string", "//cuttlefish/posix:realpath", "//cuttlefish/posix:rename", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result", "//libbase", diff --git a/base/cvd/cuttlefish/common/libs/utils/files.cpp b/base/cvd/cuttlefish/common/libs/utils/files.cpp index 9c592aceb19..0e0e963581c 100644 --- a/base/cvd/cuttlefish/common/libs/utils/files.cpp +++ b/base/cvd/cuttlefish/common/libs/utils/files.cpp @@ -61,6 +61,7 @@ #include "cuttlefish/io/string.h" #include "cuttlefish/posix/realpath.h" #include "cuttlefish/posix/rename.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/result.h" @@ -224,19 +225,12 @@ std::string AbsolutePath(std::string_view path) { } off_t FileSize(const std::string& path) { - struct stat st{}; - if (stat(path.c_str(), &st) == -1) { - return 0; - } - return st.st_size; + static auto get_size = [](const struct stat& st) { return st.st_size; }; + return Stat(path).transform(get_size).value_or(0); } Result FileOwner(const std::string& path) { - struct stat st{}; - if (stat(path.c_str(), &st) == -1) { - return CF_ERRF("Failed to stat file '{}' : {}", path, StrError(errno)); - } - return st.st_uid; + return CF_EXPECT(Stat(path)).st_uid; } bool MakeFileExecutable(const std::string& path) { @@ -246,11 +240,7 @@ bool MakeFileExecutable(const std::string& path) { Result FileModificationTime( const std::string& path) { - struct stat st; - CF_EXPECTF(stat(path.c_str(), &st) == 0, - "stat() failed retrieving file modification time on \"{}\" with " - "error: {}", - path, strerror(errno)); + struct stat st = CF_EXPECT(Stat(path)); #ifdef __linux__ std::chrono::seconds seconds(st.st_mtim.tv_sec); #elif defined(__APPLE__) @@ -383,8 +373,8 @@ FileSizes SparseFileSizes(const std::string& path) { } bool FileIsSocket(const std::string& path) { - struct stat st{}; - return stat(path.c_str(), &st) == 0 && S_ISSOCK(st.st_mode); + static auto sock = [](const struct stat& st) { return S_ISSOCK(st.st_mode); }; + return Stat(path).transform(sock).value_or(false); } Result FindFile(const std::string& path, @@ -439,22 +429,19 @@ Result Search(const std::vector& path, Result CreateOrReuseAndDrainFifo(const std::string& path, mode_t mode) { - struct stat st{}; - bool existed = false; - if (TEMP_FAILURE_RETRY(stat(path.c_str(), &st)) != 0) { - CF_EXPECTF(TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode)) == 0, - "Failed to mkfifo('{}', {:o}): {}", path, mode, - ::cuttlefish::StrError(errno)); - } else { - CF_EXPECTF(S_ISFIFO(st.st_mode), "File at '{}' exists but is not a FIFO", + Result st = Stat(path); + if (st.has_value()) { + CF_EXPECTF(S_ISFIFO(st->st_mode), "File at '{}' exists but is not a FIFO", path); - existed = true; + } else { + CF_EXPECTF(TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode)) == 0, + "Failed to mkfifo('{}', {:o}): {}", path, mode, StrError(errno)); } - auto ret = SharedFD::Open(path, O_RDWR); + SharedFD ret = SharedFD::Open(path, O_RDWR); CF_EXPECTF(ret->IsOpen(), "Failed to open '{}': '{}'", path, ret->StrError()); - if (existed) { + if (st.has_value()) { int flags = ret->Fcntl(F_GETFL, 0); if (flags >= 0) { ret->Fcntl(F_SETFL, flags | O_NONBLOCK); diff --git a/base/cvd/cuttlefish/files/BUILD.bazel b/base/cvd/cuttlefish/files/BUILD.bazel index 168c7a9fa67..b1ad199f45d 100644 --- a/base/cvd/cuttlefish/files/BUILD.bazel +++ b/base/cvd/cuttlefish/files/BUILD.bazel @@ -12,7 +12,7 @@ cf_cc_library( hdrs = ["are_hard_linked.h"], deps = [ "//cuttlefish/files:file_device_id", - "//cuttlefish/posix:strerror", + "//cuttlefish/posix:stat", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", ], @@ -35,6 +35,7 @@ cf_cc_library( hdrs = ["copy_with_attributes.h"], deps = [ "//cuttlefish/files:copy", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", @@ -62,7 +63,7 @@ cf_cc_library( srcs = ["file_device_id.cc"], hdrs = ["file_device_id.h"], deps = [ - "//cuttlefish/posix:strerror", + "//cuttlefish/posix:stat", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", ], diff --git a/base/cvd/cuttlefish/files/are_hard_linked.cc b/base/cvd/cuttlefish/files/are_hard_linked.cc index 7be8be3628c..70165b360e3 100644 --- a/base/cvd/cuttlefish/files/are_hard_linked.cc +++ b/base/cvd/cuttlefish/files/are_hard_linked.cc @@ -16,14 +16,13 @@ #include "cuttlefish/files/are_hard_linked.h" -#include #include #include #include #include "cuttlefish/files/file_device_id.h" -#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" @@ -31,13 +30,7 @@ namespace cuttlefish { namespace { Result FileInodeNumber(const std::string& path) { - struct stat out; - CF_EXPECTF( - stat(path.c_str(), &out) == 0, - "stat() failed trying to retrieve inode num information for \"{}\" " - "with error: {}", - path, StrError(errno)); - return out.st_ino; + return CF_EXPECT(Stat(path)).st_ino; } } // namespace diff --git a/base/cvd/cuttlefish/files/copy_with_attributes.cc b/base/cvd/cuttlefish/files/copy_with_attributes.cc index 4c1e2d8147c..459555f573c 100644 --- a/base/cvd/cuttlefish/files/copy_with_attributes.cc +++ b/base/cvd/cuttlefish/files/copy_with_attributes.cc @@ -18,10 +18,12 @@ #include #include +#include #include #include "cuttlefish/files/copy.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" @@ -31,10 +33,8 @@ namespace cuttlefish { Result CopyWithAttributes(const std::string& from, const std::string& to) { CF_EXPECTF(Copy(from, to), "Failed to copy '{}' to '{}'", from, to); - struct stat st; - CF_EXPECTF(stat(from.c_str(), &st) >= 0, "Failed to stat '{}': {}", from, - StrError(errno)); - CF_EXPECTF(chmod(to.c_str(), st.st_mode) >= 0, "Failed to chmod '{}': {}", to, + mode_t mode = CF_EXPECT(Stat(from)).st_mode; + CF_EXPECTF(chmod(to.c_str(), mode) >= 0, "Failed to chmod '{}': {}", to, StrError(errno)); return {}; } diff --git a/base/cvd/cuttlefish/files/file_device_id.cc b/base/cvd/cuttlefish/files/file_device_id.cc index bb415795bf0..cfab8c50e37 100644 --- a/base/cvd/cuttlefish/files/file_device_id.cc +++ b/base/cvd/cuttlefish/files/file_device_id.cc @@ -16,26 +16,19 @@ #include "cuttlefish/files/file_device_id.h" -#include #include #include #include -#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" namespace cuttlefish { Result FileDeviceId(const std::string& path) { - struct stat out; - CF_EXPECTF( - stat(path.c_str(), &out) == 0, - "stat() failed trying to retrieve device ID information for \"{}\" " - "with error: {}", - path, StrError(errno)); - return out.st_dev; + return CF_EXPECT(Stat(path)).st_dev; } } // namespace cuttlefish diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel b/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel index f9e0c02547b..10b6ad61eae 100644 --- a/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/assemble_cvd/BUILD.bazel @@ -182,6 +182,7 @@ cf_cc_library( "//cuttlefish/common/libs/utils:in_sandbox", "//cuttlefish/files:directory_contents", "//cuttlefish/host/libs/config:config_utils", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/process:proc_file_utils", "//cuttlefish/result", diff --git a/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc b/base/cvd/cuttlefish/host/commands/assemble_cvd/clean.cc index 652f3acb26d..8ee9e67cd3d 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/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/process/proc_file_utils.h" #include "cuttlefish/result/result.h" @@ -149,14 +150,14 @@ Result CleanPriorFiles(const std::vector& paths, std::set prior_dirs; std::set prior_files; for (const auto& path : paths) { - struct stat statbuf; - if (stat(path.c_str(), &statbuf) < 0) { + Result statbuf = Stat(path); + if (!statbuf.has_value()) { if (errno == ENOENT) { continue; // it doesn't exist yet, so there is no work to do } return CF_ERRNO("Could not stat \"" << path << "\""); } - bool is_directory = (statbuf.st_mode & S_IFMT) == S_IFDIR; + bool is_directory = (statbuf->st_mode & S_IFMT) == S_IFDIR; (is_directory ? prior_dirs : prior_files).emplace(path); } VLOG(0) << fmt::format("Prior dirs: {}", fmt::join(prior_dirs, ", ")); diff --git a/base/cvd/cuttlefish/host/commands/cvdalloc/BUILD.bazel b/base/cvd/cuttlefish/host/commands/cvdalloc/BUILD.bazel index 0ef371fd8c2..7e4e4318ea6 100644 --- a/base/cvd/cuttlefish/host/commands/cvdalloc/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/cvdalloc/BUILD.bazel @@ -37,6 +37,7 @@ cf_cc_library( depend_on_what_you_use_enabled = False, include_cleaner_enabled = False, deps = [ + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result", "//libbase", diff --git a/base/cvd/cuttlefish/host/commands/cvdalloc/privilege.cpp b/base/cvd/cuttlefish/host/commands/cvdalloc/privilege.cpp index f0b41d43348..f6a92095993 100644 --- a/base/cvd/cuttlefish/host/commands/cvdalloc/privilege.cpp +++ b/base/cvd/cuttlefish/host/commands/cvdalloc/privilege.cpp @@ -17,7 +17,6 @@ #include #include -#include #if defined(__linux__) #include #include @@ -31,6 +30,7 @@ #include "absl/log/log.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" namespace cuttlefish { @@ -87,11 +87,9 @@ static int SetAmbientCapabilities() { #endif Result ValidateCvdallocBinary(std::string_view path) { - struct stat st; - int r = stat(path.data(), &st); - CF_EXPECTF(r == 0, "Could not stat the cvdalloc binary at '{}': '{}'", path, - StrError(errno)); + struct stat st = CF_EXPECT(Stat(path)); #if defined(__linux__) + (void)st; /* Try and determine if the cvdalloc binary has any capabilities. */ struct vfs_cap_data cap; ssize_t s = getxattr(path.data(), XATTR_NAME_CAPS, &cap, sizeof(cap)); diff --git a/base/cvd/cuttlefish/host/commands/run_cvd/launch/BUILD.bazel b/base/cvd/cuttlefish/host/commands/run_cvd/launch/BUILD.bazel index ddbcb87244e..35a550b2555 100644 --- a/base/cvd/cuttlefish/host/commands/run_cvd/launch/BUILD.bazel +++ b/base/cvd/cuttlefish/host/commands/run_cvd/launch/BUILD.bazel @@ -125,7 +125,7 @@ cf_cc_library( "//cuttlefish/host/libs/config:known_paths", "//cuttlefish/host/libs/feature", "//cuttlefish/host/libs/vm_manager", - "//cuttlefish/posix:strerror", + "//cuttlefish/posix:stat", "//cuttlefish/process:command", "//cuttlefish/process:subprocess", "//cuttlefish/result", diff --git a/base/cvd/cuttlefish/host/commands/run_cvd/launch/cvdalloc.cpp b/base/cvd/cuttlefish/host/commands/run_cvd/launch/cvdalloc.cpp index 9e00e2d5f68..f0cd52bdf07 100644 --- a/base/cvd/cuttlefish/host/commands/run_cvd/launch/cvdalloc.cpp +++ b/base/cvd/cuttlefish/host/commands/run_cvd/launch/cvdalloc.cpp @@ -15,9 +15,7 @@ #include "cuttlefish/host/commands/run_cvd/launch/cvdalloc.h" -#include #include -#include #include #include @@ -39,7 +37,7 @@ #include "cuttlefish/host/libs/feature/command_source.h" #include "cuttlefish/host/libs/feature/feature.h" #include "cuttlefish/host/libs/vm_manager/vm_manager.h" -#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/process/command.h" #include "cuttlefish/process/subprocess.h" #include "cuttlefish/result/result.h" @@ -103,10 +101,7 @@ Result Cvdalloc::ResultSetup() { } Result Cvdalloc::BinaryIsValid(std::string_view path) { - struct stat st; // NOLINT(misc-include-cleaner): sys/stat.h - int r = stat(path.data(), &st); - CF_EXPECT(r == 0, "Could not stat the cvdalloc binary at " - << path << ": " << StrError(errno)); + CF_EXPECT(Stat(path)); CF_EXPECT(ValidateCvdallocBinary(path)); return {}; } diff --git a/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel b/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel index 199d294c4b8..c87e5b35b56 100644 --- a/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel +++ b/base/cvd/cuttlefish/host/libs/directories/BUILD.bazel @@ -19,6 +19,7 @@ cf_cc_library( "//cuttlefish/common/libs/utils:files", "//cuttlefish/common/libs/utils:users", "//cuttlefish/posix:rename", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result", "//libbase", diff --git a/base/cvd/cuttlefish/host/libs/directories/xdg.cpp b/base/cvd/cuttlefish/host/libs/directories/xdg.cpp index 178a615c346..863a7adabf3 100644 --- a/base/cvd/cuttlefish/host/libs/directories/xdg.cpp +++ b/base/cvd/cuttlefish/host/libs/directories/xdg.cpp @@ -30,6 +30,7 @@ #include "cuttlefish/common/libs/utils/files.h" #include "cuttlefish/common/libs/utils/users.h" #include "cuttlefish/posix/rename.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/result.h" @@ -134,12 +135,12 @@ Result ReadCvdDataFile(std::string_view path) { Result> FindCvdDataFiles(std::string_view path) { std::vector results; for (const std::string& dir : CF_EXPECT(CvdDataDirs())) { - struct stat statbuf; std::string test_path = fmt::format("{}/{}", dir, path); - if (stat(test_path.c_str(), &statbuf) != 0) { + Result statbuf = Stat(test_path); + if (!statbuf.has_value()) { continue; } - if (!S_ISDIR(statbuf.st_mode)) { + if (!S_ISDIR(statbuf->st_mode)) { results.emplace_back(std::move(test_path)); continue; } diff --git a/base/cvd/cuttlefish/io/BUILD.bazel b/base/cvd/cuttlefish/io/BUILD.bazel index 702c950815c..d63ef367d8b 100644 --- a/base/cvd/cuttlefish/io/BUILD.bazel +++ b/base/cvd/cuttlefish/io/BUILD.bazel @@ -301,6 +301,7 @@ cf_cc_library( "//cuttlefish/io", "//cuttlefish/io:filesystem", "//cuttlefish/io:shared_fd", + "//cuttlefish/posix:stat", "//cuttlefish/posix:strerror", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", diff --git a/base/cvd/cuttlefish/io/native_filesystem.cc b/base/cvd/cuttlefish/io/native_filesystem.cc index 5bc8bdc8a70..36ff54f0c79 100644 --- a/base/cvd/cuttlefish/io/native_filesystem.cc +++ b/base/cvd/cuttlefish/io/native_filesystem.cc @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -28,6 +27,7 @@ #include "cuttlefish/common/libs/fs/shared_fd.h" #include "cuttlefish/io/io.h" #include "cuttlefish/io/shared_fd.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/strerror.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" @@ -45,9 +45,7 @@ Result> NativeFilesystem::CreateFile( } Result NativeFilesystem::FileAttributes(std::string_view path) const { - struct stat st; - CF_EXPECT_GE(stat(std::string(path).c_str(), &st), 0, StrError(errno)); - return st.st_mode; + return CF_EXPECT(Stat(path)).st_mode; } Result NativeFilesystem::DeleteFile(std::string_view path) { diff --git a/base/cvd/cuttlefish/package/BUILD.bazel b/base/cvd/cuttlefish/package/BUILD.bazel index 30c8716b55a..4214b5e8ccb 100644 --- a/base/cvd/cuttlefish/package/BUILD.bazel +++ b/base/cvd/cuttlefish/package/BUILD.bazel @@ -10,7 +10,7 @@ cf_cc_binary( "//cuttlefish/files:link_or_copy", "//cuttlefish/files:recursively_remove_directory", "//cuttlefish/flag_parser", - "//cuttlefish/posix:strerror", + "//cuttlefish/posix:stat", "//cuttlefish/posix:symlink", "//cuttlefish/result:expect", "//cuttlefish/result:result_type", diff --git a/base/cvd/cuttlefish/package/packager.cc b/base/cvd/cuttlefish/package/packager.cc index e60213ca15f..2b3d4668d9e 100644 --- a/base/cvd/cuttlefish/package/packager.cc +++ b/base/cvd/cuttlefish/package/packager.cc @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include #include #include @@ -37,7 +36,7 @@ #include "cuttlefish/files/recursively_remove_directory.h" #include "cuttlefish/flag_parser/flag.h" #include "cuttlefish/flag_parser/gflags_compat.h" -#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/posix/symlink.h" #include "cuttlefish/result/expect.h" #include "cuttlefish/result/result_type.h" @@ -121,9 +120,7 @@ Result PackagerMain(std::vector args_strs) { for (const auto& [pkg_path, src_path] : args.PackageToSrc()) { const std::string base_pkg = absl::StrCat(args.BaseDir(), "/", pkg_path); CF_EXPECT(EnsureDirectoryExists(android::base::Dirname(base_pkg))); - struct stat st; - CF_EXPECTF(stat(src_path.c_str(), &st) == 0, "Failed to stat('{}'): {}", - src_path, StrError(errno)); + struct stat st = CF_EXPECT(Stat(src_path)); // bin/cvd is sensitive to location, uses readlink("/proc/self/exe"). // Otherwise, the input may be either a file in the source tree or a bazel // artifact. If we hard link the file in the source tree, bazel will try to diff --git a/base/cvd/cuttlefish/posix/BUILD.bazel b/base/cvd/cuttlefish/posix/BUILD.bazel index 88425388e87..2b94d517014 100644 --- a/base/cvd/cuttlefish/posix/BUILD.bazel +++ b/base/cvd/cuttlefish/posix/BUILD.bazel @@ -53,3 +53,14 @@ cf_cc_library( "//cuttlefish/result:result_type", ], ) + +cf_cc_library( + name = "stat", + srcs = ["stat.cc"], + hdrs = ["stat.h"], + deps = [ + "//cuttlefish/posix:strerror", + "//cuttlefish/result:expect", + "//cuttlefish/result:result_type", + ], +) diff --git a/base/cvd/cuttlefish/posix/stat.cc b/base/cvd/cuttlefish/posix/stat.cc new file mode 100644 index 00000000000..8d7f4df0aef --- /dev/null +++ b/base/cvd/cuttlefish/posix/stat.cc @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2017 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/stat.h" + +#include +#include +#include + +#include +#include + +#include "cuttlefish/posix/strerror.h" +#include "cuttlefish/result/expect.h" +#include "cuttlefish/result/result_type.h" + +namespace cuttlefish { + +Result Stat(const char* path) { + struct stat ret; + int success = TEMP_FAILURE_RETRY(stat(path, &ret)); + CF_EXPECTF(success == 0, "Stat('{}') failed: ", path, StrError(errno)); + return ret; +} + +Result Stat(const std::string& path) { + return CF_EXPECT(Stat(path.c_str())); +} + +Result Stat(std::string_view path) { + return CF_EXPECT(Stat(std::string(path))); +} + +} // namespace cuttlefish diff --git a/base/cvd/cuttlefish/posix/stat.h b/base/cvd/cuttlefish/posix/stat.h new file mode 100644 index 00000000000..5ca61bacf45 --- /dev/null +++ b/base/cvd/cuttlefish/posix/stat.h @@ -0,0 +1,31 @@ +/* + * 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 "cuttlefish/result/result_type.h" + +namespace cuttlefish { + +Result Stat(const char*); +Result Stat(const std::string&); +Result Stat(std::string_view); + +} // namespace cuttlefish diff --git a/base/cvd/cuttlefish/process/BUILD.bazel b/base/cvd/cuttlefish/process/BUILD.bazel index 5fea33f9c6c..63213219639 100644 --- a/base/cvd/cuttlefish/process/BUILD.bazel +++ b/base/cvd/cuttlefish/process/BUILD.bazel @@ -72,6 +72,7 @@ cf_cc_library( "//cuttlefish/files:directory_contents", "//cuttlefish/files:directory_exists", "//cuttlefish/posix:readlink", + "//cuttlefish/posix:stat", "//cuttlefish/result", "//libbase", "@abseil-cpp//absl/log", diff --git a/base/cvd/cuttlefish/process/proc_file_utils.cc b/base/cvd/cuttlefish/process/proc_file_utils.cc index 5c32ed2612f..2afc015dbe6 100644 --- a/base/cvd/cuttlefish/process/proc_file_utils.cc +++ b/base/cvd/cuttlefish/process/proc_file_utils.cc @@ -43,6 +43,7 @@ #include "cuttlefish/files/directory_contents.h" #include "cuttlefish/files/directory_exists.h" #include "cuttlefish/posix/readlink.h" +#include "cuttlefish/posix/stat.h" #include "cuttlefish/result/result.h" namespace cuttlefish { @@ -50,10 +51,7 @@ namespace cuttlefish { // sometimes, files under /proc/ owned by a different user // e.g. /proc//exe static Result FileOwnerUid(const std::string& file_path) { - // NOLINTNEXTLINE(misc-include-cleaner): - struct stat buf; - CF_EXPECT_EQ(::stat(file_path.data(), &buf), 0); - return buf.st_uid; + return CF_EXPECT(Stat(file_path)).st_uid; } struct ProcStatusUids {