xref: /aosp_15_r20/system/apex/apexd/apexd_rollback_utils.h (revision 33f3758387333dbd2962d7edbd98681940d895da)
1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker  *
4*33f37583SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker  *
8*33f37583SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker  *
10*33f37583SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker  * limitations under the License.
15*33f37583SAndroid Build Coastguard Worker  */
16*33f37583SAndroid Build Coastguard Worker 
17*33f37583SAndroid Build Coastguard Worker #ifndef ANDROID_APEXD_APEXD_ROLLBACK_UTILS_H_
18*33f37583SAndroid Build Coastguard Worker #define ANDROID_APEXD_APEXD_ROLLBACK_UTILS_H_
19*33f37583SAndroid Build Coastguard Worker 
20*33f37583SAndroid Build Coastguard Worker #include <filesystem>
21*33f37583SAndroid Build Coastguard Worker #include <string>
22*33f37583SAndroid Build Coastguard Worker 
23*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
24*33f37583SAndroid Build Coastguard Worker #include <android-base/macros.h>
25*33f37583SAndroid Build Coastguard Worker #include <android-base/result.h>
26*33f37583SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
27*33f37583SAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
28*33f37583SAndroid Build Coastguard Worker 
29*33f37583SAndroid Build Coastguard Worker namespace android {
30*33f37583SAndroid Build Coastguard Worker namespace apex {
31*33f37583SAndroid Build Coastguard Worker 
32*33f37583SAndroid Build Coastguard Worker static constexpr const char* kCpPath = "/system/bin/cp";
33*33f37583SAndroid Build Coastguard Worker 
34*33f37583SAndroid Build Coastguard Worker /**
35*33f37583SAndroid Build Coastguard Worker  * Copies everything including directories from the "from" path to the "to"
36*33f37583SAndroid Build Coastguard Worker  * path. Note that this will fail if run before APEXes are mounted, due to a
37*33f37583SAndroid Build Coastguard Worker  * dependency on runtime.
38*33f37583SAndroid Build Coastguard Worker  */
CopyDirectoryRecursive(const char * from,const char * to)39*33f37583SAndroid Build Coastguard Worker inline int32_t CopyDirectoryRecursive(const char* from, const char* to) {
40*33f37583SAndroid Build Coastguard Worker   const char* const argv[] = {
41*33f37583SAndroid Build Coastguard Worker       kCpPath,
42*33f37583SAndroid Build Coastguard Worker       "-F", /* delete any existing destination file first
43*33f37583SAndroid Build Coastguard Worker                       (--remove-destination) */
44*33f37583SAndroid Build Coastguard Worker       "--preserve=mode,ownership,timestamps,xattr", /* preserve properties */
45*33f37583SAndroid Build Coastguard Worker       "-R", /* recurse into subdirectories (DEST must be a directory) */
46*33f37583SAndroid Build Coastguard Worker       "-P", /* Do not follow symlinks [default] */
47*33f37583SAndroid Build Coastguard Worker       "-d", /* don't dereference symlinks */
48*33f37583SAndroid Build Coastguard Worker       from,
49*33f37583SAndroid Build Coastguard Worker       to};
50*33f37583SAndroid Build Coastguard Worker 
51*33f37583SAndroid Build Coastguard Worker   LOG(DEBUG) << "Copying " << from << " to " << to;
52*33f37583SAndroid Build Coastguard Worker   return logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG,
53*33f37583SAndroid Build Coastguard Worker                              false, nullptr);
54*33f37583SAndroid Build Coastguard Worker }
55*33f37583SAndroid Build Coastguard Worker 
56*33f37583SAndroid Build Coastguard Worker /**
57*33f37583SAndroid Build Coastguard Worker  * Deletes any files at to_path, and then copies all files and directories
58*33f37583SAndroid Build Coastguard Worker  * from from_path into to_path. Note that this must be run after APEXes are
59*33f37583SAndroid Build Coastguard Worker  * mounted.
60*33f37583SAndroid Build Coastguard Worker  */
ReplaceFiles(const std::string & from_path,const std::string & to_path)61*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> ReplaceFiles(const std::string& from_path,
62*33f37583SAndroid Build Coastguard Worker                                                 const std::string& to_path) {
63*33f37583SAndroid Build Coastguard Worker   namespace fs = std::filesystem;
64*33f37583SAndroid Build Coastguard Worker 
65*33f37583SAndroid Build Coastguard Worker   std::error_code error_code;
66*33f37583SAndroid Build Coastguard Worker   fs::remove_all(to_path, error_code);
67*33f37583SAndroid Build Coastguard Worker   if (error_code) {
68*33f37583SAndroid Build Coastguard Worker     return android::base::Error() << "Failed to delete existing files at "
69*33f37583SAndroid Build Coastguard Worker                                   << to_path << " : " << error_code.message();
70*33f37583SAndroid Build Coastguard Worker   }
71*33f37583SAndroid Build Coastguard Worker 
72*33f37583SAndroid Build Coastguard Worker   auto deleter = [&] {
73*33f37583SAndroid Build Coastguard Worker     std::error_code error_code;
74*33f37583SAndroid Build Coastguard Worker     fs::remove_all(to_path, error_code);
75*33f37583SAndroid Build Coastguard Worker     if (error_code) {
76*33f37583SAndroid Build Coastguard Worker       LOG(ERROR) << "Failed to clean up files at " << to_path << " : "
77*33f37583SAndroid Build Coastguard Worker                  << error_code.message();
78*33f37583SAndroid Build Coastguard Worker     }
79*33f37583SAndroid Build Coastguard Worker   };
80*33f37583SAndroid Build Coastguard Worker   auto scope_guard = android::base::make_scope_guard(deleter);
81*33f37583SAndroid Build Coastguard Worker 
82*33f37583SAndroid Build Coastguard Worker   int rc = CopyDirectoryRecursive(from_path.c_str(), to_path.c_str());
83*33f37583SAndroid Build Coastguard Worker   if (rc != 0) {
84*33f37583SAndroid Build Coastguard Worker     return android::base::Error() << "Failed to copy from [" << from_path
85*33f37583SAndroid Build Coastguard Worker                                   << "] to [" << to_path << "]";
86*33f37583SAndroid Build Coastguard Worker   }
87*33f37583SAndroid Build Coastguard Worker   scope_guard.Disable();
88*33f37583SAndroid Build Coastguard Worker   return {};
89*33f37583SAndroid Build Coastguard Worker }
90*33f37583SAndroid Build Coastguard Worker 
91*33f37583SAndroid Build Coastguard Worker }  // namespace apex
92*33f37583SAndroid Build Coastguard Worker }  // namespace android
93*33f37583SAndroid Build Coastguard Worker 
94*33f37583SAndroid Build Coastguard Worker #endif  // ANDROID_APEXD_APEXD_ROLLBACK_UTILS_H_
95