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> 24 #include <string_view> 25 #include <utility> 26 #include <vector> 27 28 #include "aidl/com/android/server/art/FsPermission.h" 29 #include "android-base/result.h" 30 #include "base/os.h" 31 32 namespace art { 33 namespace artd { 34 35 // A class that creates a new file that will eventually be committed to the given path. The new file 36 // is created at a temporary location. It will not overwrite the file at the given path until 37 // `CommitOrAbandon` has been called and will be automatically cleaned up on object destruction 38 // unless `CommitOrAbandon` has been called. 39 // The new file is opened without O_CLOEXEC so that it can be passed to subprocesses. 40 class NewFile { 41 public: 42 // Creates a new file at the given path with the given permission. 43 static android::base::Result<std::unique_ptr<NewFile>> Create( 44 const std::string& path, const aidl::com::android::server::art::FsPermission& fs_permission); 45 46 NewFile(const NewFile&) = delete; 47 NewFile& operator=(const NewFile&) = delete; NewFile(NewFile && other)48 NewFile(NewFile&& other) noexcept 49 : fd_(std::exchange(other.fd_, -1)), 50 final_path_(std::move(other.final_path_)), 51 temp_path_(std::move(other.temp_path_)), 52 temp_id_(std::move(other.temp_id_)), 53 fs_permission_(other.fs_permission_) {} 54 55 // Deletes the file if it is not committed. 56 virtual ~NewFile(); 57 Fd()58 int Fd() const { return fd_; } 59 60 // The path that the file will eventually be committed to. FinalPath()61 const std::string& FinalPath() const { return final_path_; } 62 63 // The path to the new file. TempPath()64 const std::string& TempPath() const { return temp_path_; } 65 66 // The unique ID of the new file. Can be used by `BuildTempPath` for reconstructing the path to 67 // the file. TempId()68 const std::string& TempId() const { return temp_id_; } 69 70 // Closes the new file, keeps it, moves the file to the final path, and overwrites any existing 71 // file at that path, or abandons the file on failure. The fd will be invalid after this function 72 // is called. 73 android::base::Result<void> CommitOrAbandon(); 74 75 // Closes the new file and keeps it at the temporary location. The file will not be automatically 76 // cleaned up on object destruction. The file can be found at `TempPath()` (i.e., 77 // `BuildTempPath(FinalPath(), TempId())`). The fd will be invalid after this function is called. 78 virtual android::base::Result<void> Keep(); 79 80 // Unlinks and closes the new file if it is not committed. The fd will be invalid after this 81 // function is called. 82 void Cleanup(); 83 84 // Commits all new files, replacing old files, and removes given files in addition. Or abandons 85 // new files and restores old files at best effort if any error occurs. The fds will be invalid 86 // after this function is called. 87 // 88 // Note: This function is NOT thread-safe. It is intended to be used in single-threaded code or in 89 // cases where some race condition is acceptable. 90 // 91 // Usage: 92 // 93 // Commit `file_1` and `file_2`, and remove the file at "path_3": 94 // CommitAllOrAbandon({file_1, file_2}, {"path_3"}); 95 static android::base::Result<void> CommitAllOrAbandon( 96 const std::vector<NewFile*>& files_to_commit, 97 const std::vector<std::string_view>& files_to_remove = {}); 98 99 // Returns the path to a temporary file. See `Keep`. 100 static std::string BuildTempPath(std::string_view final_path, const std::string& id); 101 102 private: NewFile(const std::string & path,const aidl::com::android::server::art::FsPermission & fs_permission)103 NewFile(const std::string& path, 104 const aidl::com::android::server::art::FsPermission& fs_permission) 105 : final_path_(path), fs_permission_(fs_permission) {} 106 107 android::base::Result<void> Init(); 108 109 // Unlinks the new file. The fd will still be valid after this function is called. 110 void Unlink(); 111 112 int fd_ = -1; 113 std::string final_path_; 114 std::string temp_path_; 115 std::string temp_id_; 116 aidl::com::android::server::art::FsPermission fs_permission_; 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 // Moves every file in `files_to_move` from a given location to another, replacing the existing file 133 // at the destination if it exists, and removes files in `files_to_remove` in addition. Or abandons 134 // all files in `files_to_move` and restores old files at best effort if any error occurs. 135 // 136 // This function does not accept duplicate paths. Passing duplicate paths to this function leads to 137 // undefined behavior. 138 // 139 // Note: This function is NOT thread-safe. It is intended to be used in single-threaded code or in 140 // cases where some race condition is acceptable. 141 // 142 // Usage: 143 // 144 // Move file at `path_1` to `path_2`, move file at `path_3` to `file_4`, and remove the file at 145 // "path_5": 146 // MoveAllOrAbandon({{"path_1", "path_2"}, {"path_3", "path_4}}, {"path_5"}); 147 android::base::Result<void> MoveAllOrAbandon( 148 const std::vector<std::pair<std::string_view, std::string_view>>& files_to_move, 149 const std::vector<std::string_view>& files_to_remove = {}); 150 151 // Same as above, but takes `std::string`s. 152 android::base::Result<void> MoveAllOrAbandon( 153 const std::vector<std::pair<std::string, std::string>>& files_to_move, 154 const std::vector<std::string>& files_to_remove = {}); 155 156 } // namespace artd 157 } // namespace art 158 159 #endif // ART_ARTD_FILE_UTILS_H_ 160