/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_INSTALLD_RESTORABLE_FILE_H #define ANDROID_INSTALLD_RESTORABLE_FILE_H #include #include #include "unique_file.h" namespace android { namespace installd { // This is a file abstraction which allows restoring to the original file while temporary work // file is updated. // // Typical flow for this API will be: // RestorableFile rf = RestorableFile::CreateWritableFile(...) // write to file using file descriptor acquired from: rf.fd() // Make work file into a regular file with: rf.CommitWorkFile() // Or throw away the work file by destroying the instance without calling CommitWorkFile(). // The temporary work file is closed / removed when an instance is destroyed without calling // CommitWorkFile(). The original file, if CommitWorkFile() is not called, will be kept. // // For safer restoration of original file when commit fails, following 3 steps can be taken: // 1. CreateBackupFile(): This renames an existing regular file into a separate backup file. // 2. CommitWorkFile(): Rename the work file into the regular file. // 3. RemoveBackupFile(): Removes the backup file // If CommitWorkFile fails, client can call RestoreBackupFile() which will restore regular file from // the backup. class RestorableFile { public: // Creates invalid instance with no fd (=-1) and empty path. RestorableFile(); RestorableFile(RestorableFile&& other) = default; ~RestorableFile(); // Passes all contents of other file into the current file. // Files kept for the current file will be either deleted or committed depending on // CommitWorkFile() and DisableCleanUp() calls made before this. RestorableFile& operator=(RestorableFile&& other) = default; // Gets file descriptor for backing work (=temporary) file. If work file does not exist, it will // return -1. int fd() const { return unique_file_.fd(); } // Gets the path name for the regular file (not temporary file). const std::string& path() const { return unique_file_.path(); } // Closes work file, deletes it and resets all internal states into default states. void reset(); // Closes work file and closes all files including work file, backup file and regular file. void ResetAndRemoveAllFiles(); // Creates a backup file by renaming existing regular file. This will return false if renaming // fails. If regular file for renaming does not exist, it will return true. bool CreateBackupFile(); // Closes existing work file and makes it a regular file. // Note that the work file is closed and fd() will return -1 after this. path() will still // return the original path. // This will return false when committing fails (=cannot rename). Both the regular file and tmp // file will be deleted when it fails. bool CommitWorkFile(); // Cancels the commit and restores the backup file into the regular one. If renaming fails, // it will return false. This returns true if the backup file does not exist. bool RestoreBackupFile(); // Removes the backup file. void RemoveBackupFile(); // Gets UniqueFile with the same path and fd() pointing to the work file. const UniqueFile& GetUniqueFile() const; // Creates writable RestorableFile. This involves creating tmp file for writing. static RestorableFile CreateWritableFile(const std::string& path, int permissions); // Removes the specified file together with tmp file generated as RestorableFile. static void RemoveAllFiles(const std::string& path); private: RestorableFile(int value, const std::string& path); // Used as a storage for work file fd and path string. UniqueFile unique_file_; }; } // namespace installd } // namespace android #endif // ANDROID_INSTALLD_RESTORABLE_FILE_H