diff options
author | 2022-07-04 16:56:12 +0100 | |
---|---|---|
committer | 2022-07-07 20:33:11 +0000 | |
commit | a2ba696d009f9e5755d6769e5ead6e892e303c69 (patch) | |
tree | 0cedad4bdd744e8f67b96d20cd85b6d42c7d2bf0 /artd/file_utils.h | |
parent | 99bd8dd2bf8eac1a60bf65e442462753ed7f2147 (diff) |
Add classes and functions for accessing files in artd.
This change includes:
- An AIDL representation of Linux filesystem permission and a function
to convert it to Linux access mode.
- A class that creates a new file for writing and cleans it up unless
the file is committed.
- A function that opens a file for reading.
Bug: 229268202
Test: m test-art-host-gtest-art_artd_tests
Ignore-AOSP-First: ART Services
Change-Id: I0e24e8fc31eee5e7004a35649df610b7da4d3178
Diffstat (limited to 'artd/file_utils.h')
-rw-r--r-- | artd/file_utils.h | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/artd/file_utils.h b/artd/file_utils.h new file mode 100644 index 0000000000..9dc41f4097 --- /dev/null +++ b/artd/file_utils.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2022 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 ART_ARTD_FILE_UTILS_H_ +#define ART_ARTD_FILE_UTILS_H_ + +#include <sys/types.h> + +#include <memory> +#include <string_view> +#include <utility> +#include <vector> + +#include "aidl/com/android/server/art/FsPermission.h" +#include "android-base/result.h" +#include "base/os.h" + +namespace art { +namespace artd { + +// A class that creates a new file that will eventually be committed to the given path. The new file +// is created at a temporary location. It will not overwrite the file at the given path until +// `CommitOrAbandon` has been called and will be automatically cleaned up on object destruction +// unless `CommitOrAbandon` has been called. +// The new file is opened without O_CLOEXEC so that it can be passed to subprocesses. +class NewFile { + public: + // Creates a new file at the given path with the given permission. + static android::base::Result<std::unique_ptr<NewFile>> Create( + const std::string& path, const aidl::com::android::server::art::FsPermission& fs_permission); + + NewFile(const NewFile&) = delete; + NewFile& operator=(const NewFile&) = delete; + NewFile(NewFile&& other) noexcept + : fd_(std::exchange(other.fd_, -1)), + final_path_(std::move(other.final_path_)), + temp_path_(std::move(other.temp_path_)), + temp_id_(std::move(other.temp_id_)), + fs_permission_(other.fs_permission_) {} + + // Deletes the file if it is not committed. + virtual ~NewFile(); + + int Fd() const { return fd_; } + + // The path that the file will eventually be committed to. + const std::string& FinalPath() const { return final_path_; } + + // The path to the new file. + const std::string& TempPath() const { return temp_path_; } + + // The unique ID of the new file. Can be used by `BuildTempPath` for reconstructing the path to + // the file. + const std::string& TempId() const { return temp_id_; } + + // Closes the new file, keeps it, moves the file to the final path, and overwrites any existing + // file at that path, or abandons the file on failure. The fd will be invalid after this function + // is called. + android::base::Result<void> CommitOrAbandon(); + + // Closes the new file and keeps it at the temporary location. The file will not be automatically + // cleaned up on object destruction. The file can be found at `TempPath()` (i.e., + // `BuildTempPath(FinalPath(), TempId())`). The fd will be invalid after this function is called. + virtual android::base::Result<void> Keep(); + + // Unlinks and closes the new file if it is not committed. The fd will be invalid after this + // function is called. + void Cleanup(); + + // Commits all new files, replacing old files, and removes given files in addition. Or abandons + // new files and restores old files at best effort if any error occurs. The fds will be invalid + // after this function is called. + // + // Note: This function is NOT thread-safe. It is intended to be used in single-threaded code or in + // cases where some race condition is acceptable. + // + // Usage: + // + // Commit `file_1` and `file_2`, and remove the file at "path_3": + // CommitAllOrAbandon({file_1, file_2}, {"path_3"}); + static android::base::Result<void> CommitAllOrAbandon( + const std::vector<NewFile*>& files_to_commit, + const std::vector<std::string_view>& files_to_remove = {}); + + // Returns the path to a temporary file. See `Keep`. + static std::string BuildTempPath(std::string_view final_path, const std::string& id); + + private: + NewFile(const std::string& path, + const aidl::com::android::server::art::FsPermission& fs_permission) + : final_path_(path), fs_permission_(fs_permission) {} + + android::base::Result<void> Init(); + + // Unlinks the new file. The fd will still be valid after this function is called. + void Unlink(); + + int fd_ = -1; + std::string final_path_; + std::string temp_path_; + std::string temp_id_; + aidl::com::android::server::art::FsPermission fs_permission_; + bool committed_ = false; +}; + +// Opens a file for reading. +android::base::Result<std::unique_ptr<File>> OpenFileForReading(const std::string& path); + +// Converts FsPermission to Linux access mode. +mode_t FsPermissionToMode(const aidl::com::android::server::art::FsPermission& fs_permission); + +} // namespace artd +} // namespace art + +#endif // ART_ARTD_FILE_UTILS_H_ |