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