blob: b5fd1706762946f25813284c67d7f07d68b935ee [file] [log] [blame]
Jiakai Zhanga2ba6962022-07-04 16:56:12 +01001/*
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
31namespace art {
32namespace 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.
39class 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;
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
57 int Fd() const { return fd_; }
58
59 // The path that the file will eventually be committed to.
60 const std::string& FinalPath() const { return final_path_; }
61
62 // The path to the new file.
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.
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:
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.
120android::base::Result<std::unique_ptr<File>> OpenFileForReading(const std::string& path);
121
Jiakai Zhang3aaecf02022-08-10 15:35:28 +0100122// Converts FsPermission to Linux access mode for a file.
123mode_t FileFsPermissionToMode(const aidl::com::android::server::art::FsPermission& fs_permission);
124
125// Converts FsPermission to Linux access mode for a directory.
126mode_t DirFsPermissionToMode(const aidl::com::android::server::art::FsPermission& fs_permission);
127
128// Changes the owner based on FsPermission.
129android::base::Result<void> Chown(
130 const std::string& path, const aidl::com::android::server::art::FsPermission& fs_permission);
Jiakai Zhanga2ba6962022-07-04 16:56:12 +0100131
132} // namespace artd
133} // namespace art
134
135#endif // ART_ARTD_FILE_UTILS_H_