108 lines
4.3 KiB
C++
108 lines
4.3 KiB
C++
/*
|
|
* 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 <functional>
|
|
#include <string>
|
|
|
|
#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
|