xref: /aosp_15_r20/art/artd/file_utils.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_ARTD_FILE_UTILS_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_ARTD_FILE_UTILS_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <string>
24*795d594fSAndroid Build Coastguard Worker #include <string_view>
25*795d594fSAndroid Build Coastguard Worker #include <utility>
26*795d594fSAndroid Build Coastguard Worker #include <vector>
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/FsPermission.h"
29*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker namespace art {
33*795d594fSAndroid Build Coastguard Worker namespace artd {
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker // A class that creates a new file that will eventually be committed to the given path. The new file
36*795d594fSAndroid Build Coastguard Worker // is created at a temporary location. It will not overwrite the file at the given path until
37*795d594fSAndroid Build Coastguard Worker // `CommitOrAbandon` has been called and will be automatically cleaned up on object destruction
38*795d594fSAndroid Build Coastguard Worker // unless `CommitOrAbandon` has been called.
39*795d594fSAndroid Build Coastguard Worker // The new file is opened without O_CLOEXEC so that it can be passed to subprocesses.
40*795d594fSAndroid Build Coastguard Worker class NewFile {
41*795d594fSAndroid Build Coastguard Worker  public:
42*795d594fSAndroid Build Coastguard Worker   // Creates a new file at the given path with the given permission.
43*795d594fSAndroid Build Coastguard Worker   static android::base::Result<std::unique_ptr<NewFile>> Create(
44*795d594fSAndroid Build Coastguard Worker       const std::string& path, const aidl::com::android::server::art::FsPermission& fs_permission);
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker   NewFile(const NewFile&) = delete;
47*795d594fSAndroid Build Coastguard Worker   NewFile& operator=(const NewFile&) = delete;
NewFile(NewFile && other)48*795d594fSAndroid Build Coastguard Worker   NewFile(NewFile&& other) noexcept
49*795d594fSAndroid Build Coastguard Worker       : fd_(std::exchange(other.fd_, -1)),
50*795d594fSAndroid Build Coastguard Worker         final_path_(std::move(other.final_path_)),
51*795d594fSAndroid Build Coastguard Worker         temp_path_(std::move(other.temp_path_)),
52*795d594fSAndroid Build Coastguard Worker         temp_id_(std::move(other.temp_id_)),
53*795d594fSAndroid Build Coastguard Worker         fs_permission_(other.fs_permission_) {}
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker   // Deletes the file if it is not committed.
56*795d594fSAndroid Build Coastguard Worker   virtual ~NewFile();
57*795d594fSAndroid Build Coastguard Worker 
Fd()58*795d594fSAndroid Build Coastguard Worker   int Fd() const { return fd_; }
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker   // The path that the file will eventually be committed to.
FinalPath()61*795d594fSAndroid Build Coastguard Worker   const std::string& FinalPath() const { return final_path_; }
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker   // The path to the new file.
TempPath()64*795d594fSAndroid Build Coastguard Worker   const std::string& TempPath() const { return temp_path_; }
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker   // The unique ID of the new file. Can be used by `BuildTempPath` for reconstructing the path to
67*795d594fSAndroid Build Coastguard Worker   // the file.
TempId()68*795d594fSAndroid Build Coastguard Worker   const std::string& TempId() const { return temp_id_; }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker   // Closes the new file, keeps it, moves the file to the final path, and overwrites any existing
71*795d594fSAndroid Build Coastguard Worker   // file at that path, or abandons the file on failure. The fd will be invalid after this function
72*795d594fSAndroid Build Coastguard Worker   // is called.
73*795d594fSAndroid Build Coastguard Worker   android::base::Result<void> CommitOrAbandon();
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   // Closes the new file and keeps it at the temporary location. The file will not be automatically
76*795d594fSAndroid Build Coastguard Worker   // cleaned up on object destruction. The file can be found at `TempPath()` (i.e.,
77*795d594fSAndroid Build Coastguard Worker   // `BuildTempPath(FinalPath(), TempId())`). The fd will be invalid after this function is called.
78*795d594fSAndroid Build Coastguard Worker   virtual android::base::Result<void> Keep();
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   // Unlinks and closes the new file if it is not committed. The fd will be invalid after this
81*795d594fSAndroid Build Coastguard Worker   // function is called.
82*795d594fSAndroid Build Coastguard Worker   void Cleanup();
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker   // Commits all new files, replacing old files, and removes given files in addition. Or abandons
85*795d594fSAndroid Build Coastguard Worker   // new files and restores old files at best effort if any error occurs. The fds will be invalid
86*795d594fSAndroid Build Coastguard Worker   // after this function is called.
87*795d594fSAndroid Build Coastguard Worker   //
88*795d594fSAndroid Build Coastguard Worker   // Note: This function is NOT thread-safe. It is intended to be used in single-threaded code or in
89*795d594fSAndroid Build Coastguard Worker   // cases where some race condition is acceptable.
90*795d594fSAndroid Build Coastguard Worker   //
91*795d594fSAndroid Build Coastguard Worker   // Usage:
92*795d594fSAndroid Build Coastguard Worker   //
93*795d594fSAndroid Build Coastguard Worker   // Commit `file_1` and `file_2`, and remove the file at "path_3":
94*795d594fSAndroid Build Coastguard Worker   //   CommitAllOrAbandon({file_1, file_2}, {"path_3"});
95*795d594fSAndroid Build Coastguard Worker   static android::base::Result<void> CommitAllOrAbandon(
96*795d594fSAndroid Build Coastguard Worker       const std::vector<NewFile*>& files_to_commit,
97*795d594fSAndroid Build Coastguard Worker       const std::vector<std::string_view>& files_to_remove = {});
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker   // Returns the path to a temporary file. See `Keep`.
100*795d594fSAndroid Build Coastguard Worker   static std::string BuildTempPath(std::string_view final_path, const std::string& id);
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker  private:
NewFile(const std::string & path,const aidl::com::android::server::art::FsPermission & fs_permission)103*795d594fSAndroid Build Coastguard Worker   NewFile(const std::string& path,
104*795d594fSAndroid Build Coastguard Worker           const aidl::com::android::server::art::FsPermission& fs_permission)
105*795d594fSAndroid Build Coastguard Worker       : final_path_(path), fs_permission_(fs_permission) {}
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker   android::base::Result<void> Init();
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   // Unlinks the new file. The fd will still be valid after this function is called.
110*795d594fSAndroid Build Coastguard Worker   void Unlink();
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker   int fd_ = -1;
113*795d594fSAndroid Build Coastguard Worker   std::string final_path_;
114*795d594fSAndroid Build Coastguard Worker   std::string temp_path_;
115*795d594fSAndroid Build Coastguard Worker   std::string temp_id_;
116*795d594fSAndroid Build Coastguard Worker   aidl::com::android::server::art::FsPermission fs_permission_;
117*795d594fSAndroid Build Coastguard Worker };
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker // Opens a file for reading.
120*795d594fSAndroid Build Coastguard Worker android::base::Result<std::unique_ptr<File>> OpenFileForReading(const std::string& path);
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker // Converts FsPermission to Linux access mode for a file.
123*795d594fSAndroid Build Coastguard Worker mode_t FileFsPermissionToMode(const aidl::com::android::server::art::FsPermission& fs_permission);
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker // Converts FsPermission to Linux access mode for a directory.
126*795d594fSAndroid Build Coastguard Worker mode_t DirFsPermissionToMode(const aidl::com::android::server::art::FsPermission& fs_permission);
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker // Changes the owner based on FsPermission.
129*795d594fSAndroid Build Coastguard Worker android::base::Result<void> Chown(
130*795d594fSAndroid Build Coastguard Worker     const std::string& path, const aidl::com::android::server::art::FsPermission& fs_permission);
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker // Moves every file in `files_to_move` from a given location to another, replacing the existing file
133*795d594fSAndroid Build Coastguard Worker // at the destination if it exists, and removes files in `files_to_remove` in addition. Or abandons
134*795d594fSAndroid Build Coastguard Worker // all files in `files_to_move` and restores old files at best effort if any error occurs.
135*795d594fSAndroid Build Coastguard Worker //
136*795d594fSAndroid Build Coastguard Worker // This function does not accept duplicate paths. Passing duplicate paths to this function leads to
137*795d594fSAndroid Build Coastguard Worker // undefined behavior.
138*795d594fSAndroid Build Coastguard Worker //
139*795d594fSAndroid Build Coastguard Worker // Note: This function is NOT thread-safe. It is intended to be used in single-threaded code or in
140*795d594fSAndroid Build Coastguard Worker // cases where some race condition is acceptable.
141*795d594fSAndroid Build Coastguard Worker //
142*795d594fSAndroid Build Coastguard Worker // Usage:
143*795d594fSAndroid Build Coastguard Worker //
144*795d594fSAndroid Build Coastguard Worker // Move file at `path_1` to `path_2`, move file at `path_3` to `file_4`, and remove the file at
145*795d594fSAndroid Build Coastguard Worker // "path_5":
146*795d594fSAndroid Build Coastguard Worker //   MoveAllOrAbandon({{"path_1", "path_2"}, {"path_3", "path_4}}, {"path_5"});
147*795d594fSAndroid Build Coastguard Worker android::base::Result<void> MoveAllOrAbandon(
148*795d594fSAndroid Build Coastguard Worker     const std::vector<std::pair<std::string_view, std::string_view>>& files_to_move,
149*795d594fSAndroid Build Coastguard Worker     const std::vector<std::string_view>& files_to_remove = {});
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker // Same as above, but takes `std::string`s.
152*795d594fSAndroid Build Coastguard Worker android::base::Result<void> MoveAllOrAbandon(
153*795d594fSAndroid Build Coastguard Worker     const std::vector<std::pair<std::string, std::string>>& files_to_move,
154*795d594fSAndroid Build Coastguard Worker     const std::vector<std::string>& files_to_remove = {});
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker }  // namespace artd
157*795d594fSAndroid Build Coastguard Worker }  // namespace art
158*795d594fSAndroid Build Coastguard Worker 
159*795d594fSAndroid Build Coastguard Worker #endif  // ART_ARTD_FILE_UTILS_H_
160