aboutsummaryrefslogtreecommitdiff
path: root/brillo/files/file_util.cc
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-06-19 12:01:48 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-06-19 12:01:48 +0000
commit9063677c3726d766de3c5fc3a2cd3feabd840d08 (patch)
tree8f6ec66173bb45a55a65c8449f382c2c16b3b13a /brillo/files/file_util.cc
parent9e260fa59a43bc04701216c51053922d445fefd8 (diff)
parent6901182adc9a85d7f514df4d68605a179c195f75 (diff)
downloadlibbrillo-c8fb7718ed046a13722df2c09e11b77a85e8535f.tar.gz
Change-Id: I1756a28b97a568bbb2c02438730597bb2aa59efe
Diffstat (limited to 'brillo/files/file_util.cc')
-rw-r--r--brillo/files/file_util.cc112
1 files changed, 112 insertions, 0 deletions
diff --git a/brillo/files/file_util.cc b/brillo/files/file_util.cc
new file mode 100644
index 0000000..c642d14
--- /dev/null
+++ b/brillo/files/file_util.cc
@@ -0,0 +1,112 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "brillo/files/file_util.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include <base/files/file_util.h>
+#include <base/logging.h>
+#include <base/strings/stringprintf.h>
+#include <brillo/syslog_logging.h>
+
+namespace brillo {
+
+namespace {
+
+enum class FSObjectType {
+ RegularFile = 0,
+ Directory,
+};
+
+SafeFD::SafeFDResult OpenOrRemake(SafeFD* parent,
+ const std::string& name,
+ FSObjectType type,
+ int permissions,
+ uid_t uid,
+ gid_t gid,
+ int flags) {
+ SafeFD::Error err = IsValidFilename(name);
+ if (SafeFD::IsError(err)) {
+ return std::make_pair(SafeFD(), err);
+ }
+
+ SafeFD::SafeFDResult (SafeFD::*maker)(const base::FilePath&, mode_t, uid_t,
+ gid_t, int);
+ if (type == FSObjectType::Directory) {
+ maker = &SafeFD::MakeDir;
+ } else {
+ maker = &SafeFD::MakeFile;
+ }
+
+ SafeFD child;
+ std::tie(child, err) =
+ (parent->*maker)(base::FilePath(name), permissions, uid, gid, flags);
+ if (child.is_valid()) {
+ return std::make_pair(std::move(child), err);
+ }
+
+ // Rmdir should be used on directories. However, kWrongType indicates when
+ // a directory was expected and a non-directory was found or when a
+ // directory was found but not expected, so XOR was used.
+ if ((type == FSObjectType::Directory) ^ (err == SafeFD::Error::kWrongType)) {
+ err = parent->Rmdir(name, true /*recursive*/);
+ } else {
+ err = parent->Unlink(name);
+ }
+ if (SafeFD::IsError(err)) {
+ PLOG(ERROR) << "Failed to clean up \"" << name << "\"";
+ return std::make_pair(SafeFD(), err);
+ }
+
+ std::tie(child, err) =
+ (parent->*maker)(base::FilePath(name), permissions, uid, gid, flags);
+ return std::make_pair(std::move(child), err);
+}
+
+} // namespace
+
+SafeFD::Error IsValidFilename(const std::string& filename) {
+ if (filename == "." || filename == ".." ||
+ filename.find("/") != std::string::npos) {
+ return SafeFD::Error::kBadArgument;
+ }
+ return SafeFD::Error::kNoError;
+}
+
+base::FilePath GetFDPath(int fd) {
+ const base::FilePath proc_fd(base::StringPrintf("/proc/self/fd/%d", fd));
+ base::FilePath resolved;
+ if (!base::ReadSymbolicLink(proc_fd, &resolved)) {
+ LOG(ERROR) << "Failed to read " << proc_fd.value();
+ return base::FilePath();
+ }
+ return resolved;
+}
+
+SafeFD::SafeFDResult OpenOrRemakeDir(SafeFD* parent,
+ const std::string& name,
+ int permissions,
+ uid_t uid,
+ gid_t gid,
+ int flags) {
+ return OpenOrRemake(parent, name, FSObjectType::Directory, permissions, uid,
+ gid, flags);
+}
+
+SafeFD::SafeFDResult OpenOrRemakeFile(SafeFD* parent,
+ const std::string& name,
+ int permissions,
+ uid_t uid,
+ gid_t gid,
+ int flags) {
+ return OpenOrRemake(parent, name, FSObjectType::RegularFile, permissions, uid,
+ gid, flags);
+}
+
+} // namespace brillo