xref: /aosp_15_r20/external/libbrillo/brillo/files/file_util.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright 2019 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include "brillo/files/file_util.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #include <fcntl.h>
8*1a96fba6SXin Li #include <sys/stat.h>
9*1a96fba6SXin Li #include <unistd.h>
10*1a96fba6SXin Li 
11*1a96fba6SXin Li #include <utility>
12*1a96fba6SXin Li 
13*1a96fba6SXin Li #include <base/files/file_util.h>
14*1a96fba6SXin Li #include <base/logging.h>
15*1a96fba6SXin Li #include <base/strings/stringprintf.h>
16*1a96fba6SXin Li #include <brillo/syslog_logging.h>
17*1a96fba6SXin Li 
18*1a96fba6SXin Li namespace brillo {
19*1a96fba6SXin Li 
20*1a96fba6SXin Li namespace {
21*1a96fba6SXin Li 
22*1a96fba6SXin Li enum class FSObjectType {
23*1a96fba6SXin Li   RegularFile = 0,
24*1a96fba6SXin Li   Directory,
25*1a96fba6SXin Li };
26*1a96fba6SXin Li 
OpenOrRemake(SafeFD * parent,const std::string & name,FSObjectType type,int permissions,uid_t uid,gid_t gid,int flags)27*1a96fba6SXin Li SafeFD::SafeFDResult OpenOrRemake(SafeFD* parent,
28*1a96fba6SXin Li                                   const std::string& name,
29*1a96fba6SXin Li                                   FSObjectType type,
30*1a96fba6SXin Li                                   int permissions,
31*1a96fba6SXin Li                                   uid_t uid,
32*1a96fba6SXin Li                                   gid_t gid,
33*1a96fba6SXin Li                                   int flags) {
34*1a96fba6SXin Li   SafeFD::Error err = IsValidFilename(name);
35*1a96fba6SXin Li   if (SafeFD::IsError(err)) {
36*1a96fba6SXin Li     return std::make_pair(SafeFD(), err);
37*1a96fba6SXin Li   }
38*1a96fba6SXin Li 
39*1a96fba6SXin Li   SafeFD::SafeFDResult (SafeFD::*maker)(const base::FilePath&, mode_t, uid_t,
40*1a96fba6SXin Li                                         gid_t, int);
41*1a96fba6SXin Li   if (type == FSObjectType::Directory) {
42*1a96fba6SXin Li     maker = &SafeFD::MakeDir;
43*1a96fba6SXin Li   } else {
44*1a96fba6SXin Li     maker = &SafeFD::MakeFile;
45*1a96fba6SXin Li   }
46*1a96fba6SXin Li 
47*1a96fba6SXin Li   SafeFD child;
48*1a96fba6SXin Li   std::tie(child, err) =
49*1a96fba6SXin Li       (parent->*maker)(base::FilePath(name), permissions, uid, gid, flags);
50*1a96fba6SXin Li   if (child.is_valid()) {
51*1a96fba6SXin Li     return std::make_pair(std::move(child), err);
52*1a96fba6SXin Li   }
53*1a96fba6SXin Li 
54*1a96fba6SXin Li   // Rmdir should be used on directories. However, kWrongType indicates when
55*1a96fba6SXin Li   // a directory was expected and a non-directory was found or when a
56*1a96fba6SXin Li   // directory was found but not expected, so XOR was used.
57*1a96fba6SXin Li   if ((type == FSObjectType::Directory) ^ (err == SafeFD::Error::kWrongType)) {
58*1a96fba6SXin Li     err = parent->Rmdir(name, true /*recursive*/);
59*1a96fba6SXin Li   } else {
60*1a96fba6SXin Li     err = parent->Unlink(name);
61*1a96fba6SXin Li   }
62*1a96fba6SXin Li   if (SafeFD::IsError(err)) {
63*1a96fba6SXin Li     PLOG(ERROR) << "Failed to clean up \"" << name << "\"";
64*1a96fba6SXin Li     return std::make_pair(SafeFD(), err);
65*1a96fba6SXin Li   }
66*1a96fba6SXin Li 
67*1a96fba6SXin Li   std::tie(child, err) =
68*1a96fba6SXin Li       (parent->*maker)(base::FilePath(name), permissions, uid, gid, flags);
69*1a96fba6SXin Li   return std::make_pair(std::move(child), err);
70*1a96fba6SXin Li }
71*1a96fba6SXin Li 
72*1a96fba6SXin Li }  // namespace
73*1a96fba6SXin Li 
IsValidFilename(const std::string & filename)74*1a96fba6SXin Li SafeFD::Error IsValidFilename(const std::string& filename) {
75*1a96fba6SXin Li   if (filename == "." || filename == ".." ||
76*1a96fba6SXin Li       filename.find("/") != std::string::npos) {
77*1a96fba6SXin Li     return SafeFD::Error::kBadArgument;
78*1a96fba6SXin Li   }
79*1a96fba6SXin Li   return SafeFD::Error::kNoError;
80*1a96fba6SXin Li }
81*1a96fba6SXin Li 
GetFDPath(int fd)82*1a96fba6SXin Li base::FilePath GetFDPath(int fd) {
83*1a96fba6SXin Li   const base::FilePath proc_fd(base::StringPrintf("/proc/self/fd/%d", fd));
84*1a96fba6SXin Li   base::FilePath resolved;
85*1a96fba6SXin Li   if (!base::ReadSymbolicLink(proc_fd, &resolved)) {
86*1a96fba6SXin Li     LOG(ERROR) << "Failed to read " << proc_fd.value();
87*1a96fba6SXin Li     return base::FilePath();
88*1a96fba6SXin Li   }
89*1a96fba6SXin Li   return resolved;
90*1a96fba6SXin Li }
91*1a96fba6SXin Li 
OpenOrRemakeDir(SafeFD * parent,const std::string & name,int permissions,uid_t uid,gid_t gid,int flags)92*1a96fba6SXin Li SafeFD::SafeFDResult OpenOrRemakeDir(SafeFD* parent,
93*1a96fba6SXin Li                                      const std::string& name,
94*1a96fba6SXin Li                                      int permissions,
95*1a96fba6SXin Li                                      uid_t uid,
96*1a96fba6SXin Li                                      gid_t gid,
97*1a96fba6SXin Li                                      int flags) {
98*1a96fba6SXin Li   return OpenOrRemake(parent, name, FSObjectType::Directory, permissions, uid,
99*1a96fba6SXin Li                       gid, flags);
100*1a96fba6SXin Li }
101*1a96fba6SXin Li 
OpenOrRemakeFile(SafeFD * parent,const std::string & name,int permissions,uid_t uid,gid_t gid,int flags)102*1a96fba6SXin Li SafeFD::SafeFDResult OpenOrRemakeFile(SafeFD* parent,
103*1a96fba6SXin Li                                       const std::string& name,
104*1a96fba6SXin Li                                       int permissions,
105*1a96fba6SXin Li                                       uid_t uid,
106*1a96fba6SXin Li                                       gid_t gid,
107*1a96fba6SXin Li                                       int flags) {
108*1a96fba6SXin Li   return OpenOrRemake(parent, name, FSObjectType::RegularFile, permissions, uid,
109*1a96fba6SXin Li                       gid, flags);
110*1a96fba6SXin Li }
111*1a96fba6SXin Li 
112*1a96fba6SXin Li }  // namespace brillo
113