1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker * Copyright (C) 2018 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_UTILS_H_
18*33f37583SAndroid Build Coastguard Worker #define ANDROID_APEXD_APEXD_UTILS_H_
19*33f37583SAndroid Build Coastguard Worker
20*33f37583SAndroid Build Coastguard Worker #include <android-base/chrono_utils.h>
21*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
22*33f37583SAndroid Build Coastguard Worker #include <android-base/properties.h>
23*33f37583SAndroid Build Coastguard Worker #include <android-base/result.h>
24*33f37583SAndroid Build Coastguard Worker #include <android-base/scopeguard.h>
25*33f37583SAndroid Build Coastguard Worker #include <android-base/strings.h>
26*33f37583SAndroid Build Coastguard Worker #include <cutils/android_reboot.h>
27*33f37583SAndroid Build Coastguard Worker #include <dirent.h>
28*33f37583SAndroid Build Coastguard Worker #include <selinux/android.h>
29*33f37583SAndroid Build Coastguard Worker #include <sys/stat.h>
30*33f37583SAndroid Build Coastguard Worker #include <sys/types.h>
31*33f37583SAndroid Build Coastguard Worker #include <sys/wait.h>
32*33f37583SAndroid Build Coastguard Worker
33*33f37583SAndroid Build Coastguard Worker #include <chrono>
34*33f37583SAndroid Build Coastguard Worker #include <cstdint>
35*33f37583SAndroid Build Coastguard Worker #include <filesystem>
36*33f37583SAndroid Build Coastguard Worker #include <span>
37*33f37583SAndroid Build Coastguard Worker #include <string>
38*33f37583SAndroid Build Coastguard Worker #include <thread>
39*33f37583SAndroid Build Coastguard Worker #include <type_traits>
40*33f37583SAndroid Build Coastguard Worker #include <vector>
41*33f37583SAndroid Build Coastguard Worker
42*33f37583SAndroid Build Coastguard Worker #include "apex_constants.h"
43*33f37583SAndroid Build Coastguard Worker
44*33f37583SAndroid Build Coastguard Worker namespace android {
45*33f37583SAndroid Build Coastguard Worker namespace apex {
46*33f37583SAndroid Build Coastguard Worker
47*33f37583SAndroid Build Coastguard Worker template <typename Fn>
WalkDir(const std::string & path,Fn fn)48*33f37583SAndroid Build Coastguard Worker android::base::Result<void> WalkDir(const std::string& path, Fn fn) {
49*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
50*33f37583SAndroid Build Coastguard Worker std::error_code ec;
51*33f37583SAndroid Build Coastguard Worker auto it = fs::directory_iterator(path, ec);
52*33f37583SAndroid Build Coastguard Worker auto end = fs::directory_iterator();
53*33f37583SAndroid Build Coastguard Worker while (!ec && it != end) {
54*33f37583SAndroid Build Coastguard Worker fn(*it);
55*33f37583SAndroid Build Coastguard Worker it.increment(ec);
56*33f37583SAndroid Build Coastguard Worker }
57*33f37583SAndroid Build Coastguard Worker if (ec) {
58*33f37583SAndroid Build Coastguard Worker return android::base::Error()
59*33f37583SAndroid Build Coastguard Worker << "Can't open " << path << " for reading : " << ec.message();
60*33f37583SAndroid Build Coastguard Worker }
61*33f37583SAndroid Build Coastguard Worker return {};
62*33f37583SAndroid Build Coastguard Worker }
63*33f37583SAndroid Build Coastguard Worker
64*33f37583SAndroid Build Coastguard Worker template <typename FilterFn>
ReadDir(const std::string & path,FilterFn fn)65*33f37583SAndroid Build Coastguard Worker android::base::Result<std::vector<std::string>> ReadDir(const std::string& path,
66*33f37583SAndroid Build Coastguard Worker FilterFn fn) {
67*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
68*33f37583SAndroid Build Coastguard Worker
69*33f37583SAndroid Build Coastguard Worker std::vector<std::string> ret;
70*33f37583SAndroid Build Coastguard Worker auto status = WalkDir(path, [&](const fs::directory_entry& entry) {
71*33f37583SAndroid Build Coastguard Worker if (fn(entry)) {
72*33f37583SAndroid Build Coastguard Worker ret.push_back(entry.path());
73*33f37583SAndroid Build Coastguard Worker }
74*33f37583SAndroid Build Coastguard Worker });
75*33f37583SAndroid Build Coastguard Worker if (!status.ok()) {
76*33f37583SAndroid Build Coastguard Worker return status.error();
77*33f37583SAndroid Build Coastguard Worker }
78*33f37583SAndroid Build Coastguard Worker return ret;
79*33f37583SAndroid Build Coastguard Worker }
80*33f37583SAndroid Build Coastguard Worker
IsEmptyDirectory(const std::string & path)81*33f37583SAndroid Build Coastguard Worker inline bool IsEmptyDirectory(const std::string& path) {
82*33f37583SAndroid Build Coastguard Worker auto res = ReadDir(path, [](auto _) { return true; });
83*33f37583SAndroid Build Coastguard Worker return res.ok() && res->empty();
84*33f37583SAndroid Build Coastguard Worker }
85*33f37583SAndroid Build Coastguard Worker
CreateDirIfNeeded(const std::string & path,mode_t mode)86*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> CreateDirIfNeeded(const std::string& path,
87*33f37583SAndroid Build Coastguard Worker mode_t mode) {
88*33f37583SAndroid Build Coastguard Worker struct stat stat_data;
89*33f37583SAndroid Build Coastguard Worker
90*33f37583SAndroid Build Coastguard Worker if (stat(path.c_str(), &stat_data) != 0) {
91*33f37583SAndroid Build Coastguard Worker if (errno == ENOENT) {
92*33f37583SAndroid Build Coastguard Worker if (mkdir(path.c_str(), mode) != 0) {
93*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Could not mkdir " << path;
94*33f37583SAndroid Build Coastguard Worker }
95*33f37583SAndroid Build Coastguard Worker } else {
96*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Could not stat " << path;
97*33f37583SAndroid Build Coastguard Worker }
98*33f37583SAndroid Build Coastguard Worker } else {
99*33f37583SAndroid Build Coastguard Worker if (!S_ISDIR(stat_data.st_mode)) {
100*33f37583SAndroid Build Coastguard Worker return android::base::Error()
101*33f37583SAndroid Build Coastguard Worker << path << " exists and is not a directory.";
102*33f37583SAndroid Build Coastguard Worker }
103*33f37583SAndroid Build Coastguard Worker }
104*33f37583SAndroid Build Coastguard Worker
105*33f37583SAndroid Build Coastguard Worker // Need to manually call chmod because mkdir will create a folder with
106*33f37583SAndroid Build Coastguard Worker // permissions mode & ~umask.
107*33f37583SAndroid Build Coastguard Worker if (chmod(path.c_str(), mode) != 0) {
108*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Could not chmod " << path;
109*33f37583SAndroid Build Coastguard Worker }
110*33f37583SAndroid Build Coastguard Worker
111*33f37583SAndroid Build Coastguard Worker return {};
112*33f37583SAndroid Build Coastguard Worker }
113*33f37583SAndroid Build Coastguard Worker
DeleteDirContent(const std::string & path)114*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> DeleteDirContent(const std::string& path) {
115*33f37583SAndroid Build Coastguard Worker auto files = ReadDir(path, [](auto _) { return true; });
116*33f37583SAndroid Build Coastguard Worker if (!files.ok()) {
117*33f37583SAndroid Build Coastguard Worker return android::base::Error()
118*33f37583SAndroid Build Coastguard Worker << "Failed to delete " << path << " : " << files.error();
119*33f37583SAndroid Build Coastguard Worker }
120*33f37583SAndroid Build Coastguard Worker for (const std::string& file : *files) {
121*33f37583SAndroid Build Coastguard Worker std::error_code ec;
122*33f37583SAndroid Build Coastguard Worker std::filesystem::remove_all(file, ec);
123*33f37583SAndroid Build Coastguard Worker if (ec) {
124*33f37583SAndroid Build Coastguard Worker return android::base::Error()
125*33f37583SAndroid Build Coastguard Worker << "Failed to delete path " << file << " : " << ec.message();
126*33f37583SAndroid Build Coastguard Worker }
127*33f37583SAndroid Build Coastguard Worker }
128*33f37583SAndroid Build Coastguard Worker return {};
129*33f37583SAndroid Build Coastguard Worker }
130*33f37583SAndroid Build Coastguard Worker
DeleteDir(const std::string & path)131*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> DeleteDir(const std::string& path) {
132*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
133*33f37583SAndroid Build Coastguard Worker std::error_code ec;
134*33f37583SAndroid Build Coastguard Worker fs::remove_all(path, ec);
135*33f37583SAndroid Build Coastguard Worker if (ec) {
136*33f37583SAndroid Build Coastguard Worker return android::base::Error()
137*33f37583SAndroid Build Coastguard Worker << "Failed to delete path " << path << " : " << ec.message();
138*33f37583SAndroid Build Coastguard Worker }
139*33f37583SAndroid Build Coastguard Worker return {};
140*33f37583SAndroid Build Coastguard Worker }
141*33f37583SAndroid Build Coastguard Worker
PathExists(const std::string & path)142*33f37583SAndroid Build Coastguard Worker inline android::base::Result<bool> PathExists(const std::string& path) {
143*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
144*33f37583SAndroid Build Coastguard Worker
145*33f37583SAndroid Build Coastguard Worker std::error_code ec;
146*33f37583SAndroid Build Coastguard Worker if (!fs::exists(fs::path(path), ec)) {
147*33f37583SAndroid Build Coastguard Worker if (ec) {
148*33f37583SAndroid Build Coastguard Worker return android::base::Error()
149*33f37583SAndroid Build Coastguard Worker << "Failed to access " << path << " : " << ec.message();
150*33f37583SAndroid Build Coastguard Worker } else {
151*33f37583SAndroid Build Coastguard Worker return false;
152*33f37583SAndroid Build Coastguard Worker }
153*33f37583SAndroid Build Coastguard Worker }
154*33f37583SAndroid Build Coastguard Worker return true;
155*33f37583SAndroid Build Coastguard Worker }
156*33f37583SAndroid Build Coastguard Worker
Reboot()157*33f37583SAndroid Build Coastguard Worker inline void Reboot() {
158*33f37583SAndroid Build Coastguard Worker LOG(INFO) << "Rebooting device";
159*33f37583SAndroid Build Coastguard Worker if (android_reboot(ANDROID_RB_RESTART2, 0, nullptr) != 0) {
160*33f37583SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to reboot device";
161*33f37583SAndroid Build Coastguard Worker }
162*33f37583SAndroid Build Coastguard Worker // Wait for reboot to complete as we expect this to be a terminal
163*33f37583SAndroid Build Coastguard Worker // command. Crash apexd if reboot does not complete even after
164*33f37583SAndroid Build Coastguard Worker // waiting an arbitrary significant amount of time.
165*33f37583SAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::seconds(120));
166*33f37583SAndroid Build Coastguard Worker LOG(FATAL) << "Device did not reboot within 120 seconds";
167*33f37583SAndroid Build Coastguard Worker }
168*33f37583SAndroid Build Coastguard Worker
WaitForFile(const std::string & path,std::chrono::nanoseconds timeout)169*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> WaitForFile(
170*33f37583SAndroid Build Coastguard Worker const std::string& path, std::chrono::nanoseconds timeout) {
171*33f37583SAndroid Build Coastguard Worker android::base::Timer t;
172*33f37583SAndroid Build Coastguard Worker bool has_slept = false;
173*33f37583SAndroid Build Coastguard Worker while (t.duration() < timeout) {
174*33f37583SAndroid Build Coastguard Worker struct stat sb;
175*33f37583SAndroid Build Coastguard Worker if (stat(path.c_str(), &sb) != -1) {
176*33f37583SAndroid Build Coastguard Worker if (has_slept) {
177*33f37583SAndroid Build Coastguard Worker LOG(INFO) << "wait for '" << path << "' took " << t;
178*33f37583SAndroid Build Coastguard Worker }
179*33f37583SAndroid Build Coastguard Worker return {};
180*33f37583SAndroid Build Coastguard Worker }
181*33f37583SAndroid Build Coastguard Worker std::this_thread::sleep_for(5ms);
182*33f37583SAndroid Build Coastguard Worker has_slept = true;
183*33f37583SAndroid Build Coastguard Worker }
184*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError()
185*33f37583SAndroid Build Coastguard Worker << "wait for '" << path << "' timed out and took " << t;
186*33f37583SAndroid Build Coastguard Worker }
187*33f37583SAndroid Build Coastguard Worker
GetSubdirs(const std::string & path)188*33f37583SAndroid Build Coastguard Worker inline android::base::Result<std::vector<std::string>> GetSubdirs(
189*33f37583SAndroid Build Coastguard Worker const std::string& path) {
190*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
191*33f37583SAndroid Build Coastguard Worker auto filter_fn = [](const std::filesystem::directory_entry& entry) {
192*33f37583SAndroid Build Coastguard Worker std::error_code ec;
193*33f37583SAndroid Build Coastguard Worker bool result = entry.is_directory(ec);
194*33f37583SAndroid Build Coastguard Worker if (ec) {
195*33f37583SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to check is_directory : " << ec.message();
196*33f37583SAndroid Build Coastguard Worker return false;
197*33f37583SAndroid Build Coastguard Worker }
198*33f37583SAndroid Build Coastguard Worker return result;
199*33f37583SAndroid Build Coastguard Worker };
200*33f37583SAndroid Build Coastguard Worker return ReadDir(path, filter_fn);
201*33f37583SAndroid Build Coastguard Worker }
202*33f37583SAndroid Build Coastguard Worker
GetDeUserDirs()203*33f37583SAndroid Build Coastguard Worker inline android::base::Result<std::vector<std::string>> GetDeUserDirs() {
204*33f37583SAndroid Build Coastguard Worker return GetSubdirs(kDeNDataDir);
205*33f37583SAndroid Build Coastguard Worker }
206*33f37583SAndroid Build Coastguard Worker
FindFilesBySuffix(const std::string & path,const std::vector<std::string> & suffix_list)207*33f37583SAndroid Build Coastguard Worker inline android::base::Result<std::vector<std::string>> FindFilesBySuffix(
208*33f37583SAndroid Build Coastguard Worker const std::string& path, const std::vector<std::string>& suffix_list) {
209*33f37583SAndroid Build Coastguard Worker auto filter_fn =
210*33f37583SAndroid Build Coastguard Worker [&suffix_list](const std::filesystem::directory_entry& entry) {
211*33f37583SAndroid Build Coastguard Worker for (const std::string& suffix : suffix_list) {
212*33f37583SAndroid Build Coastguard Worker std::error_code ec;
213*33f37583SAndroid Build Coastguard Worker auto name = entry.path().filename().string();
214*33f37583SAndroid Build Coastguard Worker if (entry.is_regular_file(ec) &&
215*33f37583SAndroid Build Coastguard Worker android::base::EndsWith(name, suffix)) {
216*33f37583SAndroid Build Coastguard Worker return true; // suffix matches, take.
217*33f37583SAndroid Build Coastguard Worker }
218*33f37583SAndroid Build Coastguard Worker }
219*33f37583SAndroid Build Coastguard Worker return false;
220*33f37583SAndroid Build Coastguard Worker };
221*33f37583SAndroid Build Coastguard Worker return ReadDir(path, filter_fn);
222*33f37583SAndroid Build Coastguard Worker }
223*33f37583SAndroid Build Coastguard Worker
224*33f37583SAndroid Build Coastguard Worker // Returns first path between |first_dir| and |second_dir| that correspond to a
225*33f37583SAndroid Build Coastguard Worker // existing directory. Returns error if neither |first_dir| nor |second_dir|
226*33f37583SAndroid Build Coastguard Worker // correspond to an existing directory.
FindFirstExistingDirectory(const std::string & first_dir,const std::string & second_dir)227*33f37583SAndroid Build Coastguard Worker inline android::base::Result<std::string> FindFirstExistingDirectory(
228*33f37583SAndroid Build Coastguard Worker const std::string& first_dir, const std::string& second_dir) {
229*33f37583SAndroid Build Coastguard Worker struct stat stat_buf;
230*33f37583SAndroid Build Coastguard Worker if (stat(first_dir.c_str(), &stat_buf) != 0) {
231*33f37583SAndroid Build Coastguard Worker PLOG(WARNING) << "Failed to stat " << first_dir;
232*33f37583SAndroid Build Coastguard Worker if (stat(second_dir.c_str(), &stat_buf) != 0) {
233*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Failed to stat " << second_dir;
234*33f37583SAndroid Build Coastguard Worker }
235*33f37583SAndroid Build Coastguard Worker if (!S_ISDIR(stat_buf.st_mode)) {
236*33f37583SAndroid Build Coastguard Worker return android::base::Error() << second_dir << " is not a directory";
237*33f37583SAndroid Build Coastguard Worker }
238*33f37583SAndroid Build Coastguard Worker return second_dir;
239*33f37583SAndroid Build Coastguard Worker }
240*33f37583SAndroid Build Coastguard Worker
241*33f37583SAndroid Build Coastguard Worker if (S_ISDIR(stat_buf.st_mode)) {
242*33f37583SAndroid Build Coastguard Worker return first_dir;
243*33f37583SAndroid Build Coastguard Worker }
244*33f37583SAndroid Build Coastguard Worker LOG(WARNING) << first_dir << " is not a directory";
245*33f37583SAndroid Build Coastguard Worker
246*33f37583SAndroid Build Coastguard Worker if (stat(second_dir.c_str(), &stat_buf) != 0) {
247*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Failed to stat " << second_dir;
248*33f37583SAndroid Build Coastguard Worker }
249*33f37583SAndroid Build Coastguard Worker if (!S_ISDIR(stat_buf.st_mode)) {
250*33f37583SAndroid Build Coastguard Worker return android::base::Error() << second_dir << " is not a directory";
251*33f37583SAndroid Build Coastguard Worker }
252*33f37583SAndroid Build Coastguard Worker return second_dir;
253*33f37583SAndroid Build Coastguard Worker }
254*33f37583SAndroid Build Coastguard Worker
255*33f37583SAndroid Build Coastguard Worker // Copies all entries under |from| directory to |to| directory, and then them.
256*33f37583SAndroid Build Coastguard Worker // Leaving |from| empty.
MoveDir(const std::string & from,const std::string & to)257*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> MoveDir(const std::string& from,
258*33f37583SAndroid Build Coastguard Worker const std::string& to) {
259*33f37583SAndroid Build Coastguard Worker struct stat stat_buf;
260*33f37583SAndroid Build Coastguard Worker if (stat(to.c_str(), &stat_buf) != 0) {
261*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Failed to stat " << to;
262*33f37583SAndroid Build Coastguard Worker }
263*33f37583SAndroid Build Coastguard Worker if (!S_ISDIR(stat_buf.st_mode)) {
264*33f37583SAndroid Build Coastguard Worker return android::base::Error() << to << " is not a directory";
265*33f37583SAndroid Build Coastguard Worker }
266*33f37583SAndroid Build Coastguard Worker
267*33f37583SAndroid Build Coastguard Worker namespace fs = std::filesystem;
268*33f37583SAndroid Build Coastguard Worker std::error_code ec;
269*33f37583SAndroid Build Coastguard Worker auto it = fs::directory_iterator(from, ec);
270*33f37583SAndroid Build Coastguard Worker if (ec) {
271*33f37583SAndroid Build Coastguard Worker return android::base::Error()
272*33f37583SAndroid Build Coastguard Worker << "Can't read " << from << " : " << ec.message();
273*33f37583SAndroid Build Coastguard Worker }
274*33f37583SAndroid Build Coastguard Worker
275*33f37583SAndroid Build Coastguard Worker for (const auto& end = fs::directory_iterator(); it != end;) {
276*33f37583SAndroid Build Coastguard Worker auto from_path = it->path();
277*33f37583SAndroid Build Coastguard Worker it.increment(ec);
278*33f37583SAndroid Build Coastguard Worker if (ec) {
279*33f37583SAndroid Build Coastguard Worker return android::base::Error()
280*33f37583SAndroid Build Coastguard Worker << "Can't read " << from << " : " << ec.message();
281*33f37583SAndroid Build Coastguard Worker }
282*33f37583SAndroid Build Coastguard Worker auto to_path = to / from_path.filename();
283*33f37583SAndroid Build Coastguard Worker fs::copy(from_path, to_path, fs::copy_options::recursive, ec);
284*33f37583SAndroid Build Coastguard Worker if (ec) {
285*33f37583SAndroid Build Coastguard Worker return android::base::Error() << "Failed to copy " << from_path << " to "
286*33f37583SAndroid Build Coastguard Worker << to_path << " : " << ec.message();
287*33f37583SAndroid Build Coastguard Worker }
288*33f37583SAndroid Build Coastguard Worker fs::remove_all(from_path, ec);
289*33f37583SAndroid Build Coastguard Worker if (ec) {
290*33f37583SAndroid Build Coastguard Worker return android::base::Error()
291*33f37583SAndroid Build Coastguard Worker << "Failed to delete " << from_path << " : " << ec.message();
292*33f37583SAndroid Build Coastguard Worker }
293*33f37583SAndroid Build Coastguard Worker }
294*33f37583SAndroid Build Coastguard Worker return {};
295*33f37583SAndroid Build Coastguard Worker }
296*33f37583SAndroid Build Coastguard Worker
GetFileSize(const std::string & file_path)297*33f37583SAndroid Build Coastguard Worker inline android::base::Result<uintmax_t> GetFileSize(
298*33f37583SAndroid Build Coastguard Worker const std::string& file_path) {
299*33f37583SAndroid Build Coastguard Worker std::error_code ec;
300*33f37583SAndroid Build Coastguard Worker auto value = std::filesystem::file_size(file_path, ec);
301*33f37583SAndroid Build Coastguard Worker if (ec) {
302*33f37583SAndroid Build Coastguard Worker return android::base::Error() << "Failed to get file size of " << file_path
303*33f37583SAndroid Build Coastguard Worker << " : " << ec.message();
304*33f37583SAndroid Build Coastguard Worker }
305*33f37583SAndroid Build Coastguard Worker
306*33f37583SAndroid Build Coastguard Worker return value;
307*33f37583SAndroid Build Coastguard Worker }
308*33f37583SAndroid Build Coastguard Worker
RestoreconPath(const std::string & path)309*33f37583SAndroid Build Coastguard Worker inline android::base::Result<void> RestoreconPath(const std::string& path) {
310*33f37583SAndroid Build Coastguard Worker unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
311*33f37583SAndroid Build Coastguard Worker if (selinux_android_restorecon(path.c_str(), seflags) < 0) {
312*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Failed to restorecon " << path;
313*33f37583SAndroid Build Coastguard Worker }
314*33f37583SAndroid Build Coastguard Worker return {};
315*33f37583SAndroid Build Coastguard Worker }
316*33f37583SAndroid Build Coastguard Worker
GetfileconPath(const std::string & path)317*33f37583SAndroid Build Coastguard Worker inline android::base::Result<std::string> GetfileconPath(
318*33f37583SAndroid Build Coastguard Worker const std::string& path) {
319*33f37583SAndroid Build Coastguard Worker char* ctx;
320*33f37583SAndroid Build Coastguard Worker if (getfilecon(path.c_str(), &ctx) < 0) {
321*33f37583SAndroid Build Coastguard Worker return android::base::ErrnoError() << "Failed to getfilecon " << path;
322*33f37583SAndroid Build Coastguard Worker }
323*33f37583SAndroid Build Coastguard Worker std::string ret(ctx);
324*33f37583SAndroid Build Coastguard Worker freecon(ctx);
325*33f37583SAndroid Build Coastguard Worker return ret;
326*33f37583SAndroid Build Coastguard Worker }
327*33f37583SAndroid Build Coastguard Worker
328*33f37583SAndroid Build Coastguard Worker // Adapter for a single-valued span
329*33f37583SAndroid Build Coastguard Worker template <typename T>
Single(const T & t)330*33f37583SAndroid Build Coastguard Worker std::span<const T> Single(const T& t) {
331*33f37583SAndroid Build Coastguard Worker return std::span{&t, 1};
332*33f37583SAndroid Build Coastguard Worker }
333*33f37583SAndroid Build Coastguard Worker
334*33f37583SAndroid Build Coastguard Worker } // namespace apex
335*33f37583SAndroid Build Coastguard Worker } // namespace android
336*33f37583SAndroid Build Coastguard Worker
337*33f37583SAndroid Build Coastguard Worker #endif // ANDROID_APEXD_APEXD_UTILS_H_
338