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