1*20733378SAndroid Build Coastguard Worker /*
2*20733378SAndroid Build Coastguard Worker * Copyright (C) 2024 The Android Open Source Project
3*20733378SAndroid Build Coastguard Worker *
4*20733378SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*20733378SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*20733378SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*20733378SAndroid Build Coastguard Worker *
8*20733378SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*20733378SAndroid Build Coastguard Worker *
10*20733378SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*20733378SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*20733378SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*20733378SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*20733378SAndroid Build Coastguard Worker * limitations under the License.
15*20733378SAndroid Build Coastguard Worker */
16*20733378SAndroid Build Coastguard Worker
17*20733378SAndroid Build Coastguard Worker #include <memory>
18*20733378SAndroid Build Coastguard Worker #include <sys/sendfile.h>
19*20733378SAndroid Build Coastguard Worker #include <dirent.h>
20*20733378SAndroid Build Coastguard Worker #include <stdio.h>
21*20733378SAndroid Build Coastguard Worker #include <openssl/sha.h>
22*20733378SAndroid Build Coastguard Worker #include <fstream>
23*20733378SAndroid Build Coastguard Worker #include <sstream>
24*20733378SAndroid Build Coastguard Worker
25*20733378SAndroid Build Coastguard Worker #include <android-base/file.h>
26*20733378SAndroid Build Coastguard Worker #include <android-base/logging.h>
27*20733378SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
28*20733378SAndroid Build Coastguard Worker
29*20733378SAndroid Build Coastguard Worker #include <aconfigd.pb.h>
30*20733378SAndroid Build Coastguard Worker #include "aconfigd_util.h"
31*20733378SAndroid Build Coastguard Worker
32*20733378SAndroid Build Coastguard Worker using namespace android::base;
33*20733378SAndroid Build Coastguard Worker
34*20733378SAndroid Build Coastguard Worker namespace android {
35*20733378SAndroid Build Coastguard Worker namespace aconfigd {
36*20733378SAndroid Build Coastguard Worker
37*20733378SAndroid Build Coastguard Worker /// Remove all files in a dir
RemoveFilesInDir(const std::string & dir)38*20733378SAndroid Build Coastguard Worker Result<void> RemoveFilesInDir(const std::string& dir) {
39*20733378SAndroid Build Coastguard Worker auto dir_ptr = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(dir.c_str()), closedir);
40*20733378SAndroid Build Coastguard Worker if (!dir_ptr) {
41*20733378SAndroid Build Coastguard Worker return ErrnoError() << "failed to open dir " << dir;
42*20733378SAndroid Build Coastguard Worker }
43*20733378SAndroid Build Coastguard Worker
44*20733378SAndroid Build Coastguard Worker struct dirent* entry;
45*20733378SAndroid Build Coastguard Worker while ((entry = readdir(dir_ptr.get())) != nullptr) {
46*20733378SAndroid Build Coastguard Worker if (entry->d_type != DT_REG) {
47*20733378SAndroid Build Coastguard Worker continue;
48*20733378SAndroid Build Coastguard Worker }
49*20733378SAndroid Build Coastguard Worker auto file = dir + "/" + entry->d_name;
50*20733378SAndroid Build Coastguard Worker if (unlink(file.c_str()) == -1) {
51*20733378SAndroid Build Coastguard Worker return ErrnoError() << "unlink() failed for " << file;
52*20733378SAndroid Build Coastguard Worker }
53*20733378SAndroid Build Coastguard Worker }
54*20733378SAndroid Build Coastguard Worker
55*20733378SAndroid Build Coastguard Worker return {};
56*20733378SAndroid Build Coastguard Worker }
57*20733378SAndroid Build Coastguard Worker
58*20733378SAndroid Build Coastguard Worker /// Copy file
CopyFile(const std::string & src,const std::string & dst,mode_t mode)59*20733378SAndroid Build Coastguard Worker Result<void> CopyFile(const std::string& src, const std::string& dst, mode_t mode) {
60*20733378SAndroid Build Coastguard Worker android::base::unique_fd src_fd(
61*20733378SAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(open(src.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
62*20733378SAndroid Build Coastguard Worker if (src_fd == -1) {
63*20733378SAndroid Build Coastguard Worker return ErrnoError() << "open() failed for " << src;
64*20733378SAndroid Build Coastguard Worker }
65*20733378SAndroid Build Coastguard Worker
66*20733378SAndroid Build Coastguard Worker if (FileExists(dst.c_str())) {
67*20733378SAndroid Build Coastguard Worker if (chmod(dst.c_str(), 0644) == -1) {
68*20733378SAndroid Build Coastguard Worker return ErrnoError() << "chmod() failed for " << dst;
69*20733378SAndroid Build Coastguard Worker }
70*20733378SAndroid Build Coastguard Worker }
71*20733378SAndroid Build Coastguard Worker
72*20733378SAndroid Build Coastguard Worker android::base::unique_fd dst_fd(TEMP_FAILURE_RETRY(
73*20733378SAndroid Build Coastguard Worker open(dst.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0644)));
74*20733378SAndroid Build Coastguard Worker if (dst_fd == -1) {
75*20733378SAndroid Build Coastguard Worker return ErrnoError() << "open() failed for " << dst;
76*20733378SAndroid Build Coastguard Worker }
77*20733378SAndroid Build Coastguard Worker
78*20733378SAndroid Build Coastguard Worker struct stat st;
79*20733378SAndroid Build Coastguard Worker if (fstat(src_fd.get(), &st) == -1) {
80*20733378SAndroid Build Coastguard Worker return ErrnoError() << "fstat() failed";
81*20733378SAndroid Build Coastguard Worker }
82*20733378SAndroid Build Coastguard Worker auto len = st.st_size;
83*20733378SAndroid Build Coastguard Worker
84*20733378SAndroid Build Coastguard Worker if (sendfile(dst_fd, src_fd, nullptr, len) == -1) {
85*20733378SAndroid Build Coastguard Worker return ErrnoError() << "sendfile() failed";
86*20733378SAndroid Build Coastguard Worker }
87*20733378SAndroid Build Coastguard Worker
88*20733378SAndroid Build Coastguard Worker if (chmod(dst.c_str(), mode) == -1) {
89*20733378SAndroid Build Coastguard Worker return ErrnoError() << "chmod() failed";
90*20733378SAndroid Build Coastguard Worker }
91*20733378SAndroid Build Coastguard Worker
92*20733378SAndroid Build Coastguard Worker return {};
93*20733378SAndroid Build Coastguard Worker }
94*20733378SAndroid Build Coastguard Worker
95*20733378SAndroid Build Coastguard Worker /// Get a file's timestamp in nano second
GetFileTimeStamp(const std::string & file)96*20733378SAndroid Build Coastguard Worker Result<uint64_t> GetFileTimeStamp(const std::string& file) {
97*20733378SAndroid Build Coastguard Worker struct stat st;
98*20733378SAndroid Build Coastguard Worker int result = stat(file.c_str(), &st);
99*20733378SAndroid Build Coastguard Worker if (result == -1) {
100*20733378SAndroid Build Coastguard Worker return ErrnoError() << "stat() failed";
101*20733378SAndroid Build Coastguard Worker }
102*20733378SAndroid Build Coastguard Worker uint64_t timestamp = st.st_mtim.tv_sec*1000000000 + st.st_mtim.tv_nsec;
103*20733378SAndroid Build Coastguard Worker return timestamp;
104*20733378SAndroid Build Coastguard Worker }
105*20733378SAndroid Build Coastguard Worker
FileExists(const std::string & file)106*20733378SAndroid Build Coastguard Worker bool FileExists(const std::string& file) {
107*20733378SAndroid Build Coastguard Worker struct stat st;
108*20733378SAndroid Build Coastguard Worker return stat(file.c_str(), &st) == 0 ? true : false;
109*20733378SAndroid Build Coastguard Worker }
110*20733378SAndroid Build Coastguard Worker
FileNonZeroSize(const std::string & file)111*20733378SAndroid Build Coastguard Worker bool FileNonZeroSize(const std::string& file) {
112*20733378SAndroid Build Coastguard Worker struct stat st;
113*20733378SAndroid Build Coastguard Worker return stat(file.c_str(), &st) == 0 ? st.st_size > 0 : false;
114*20733378SAndroid Build Coastguard Worker }
115*20733378SAndroid Build Coastguard Worker
GetFilesDigest(const std::vector<std::string> & files)116*20733378SAndroid Build Coastguard Worker Result<std::string> GetFilesDigest(const std::vector<std::string>& files) {
117*20733378SAndroid Build Coastguard Worker SHA512_CTX ctx;
118*20733378SAndroid Build Coastguard Worker SHA512_Init(&ctx);
119*20733378SAndroid Build Coastguard Worker
120*20733378SAndroid Build Coastguard Worker for (const auto& file : files) {
121*20733378SAndroid Build Coastguard Worker std::ifstream stream(file, std::ios::binary);
122*20733378SAndroid Build Coastguard Worker if (stream.bad()) {
123*20733378SAndroid Build Coastguard Worker return Error() << "Failed to open " << file;
124*20733378SAndroid Build Coastguard Worker }
125*20733378SAndroid Build Coastguard Worker
126*20733378SAndroid Build Coastguard Worker char buf[1024];
127*20733378SAndroid Build Coastguard Worker while (!stream.eof()) {
128*20733378SAndroid Build Coastguard Worker stream.read(buf, 1024);
129*20733378SAndroid Build Coastguard Worker if (stream.bad()) {
130*20733378SAndroid Build Coastguard Worker return Error() << "Failed to read " << file;
131*20733378SAndroid Build Coastguard Worker }
132*20733378SAndroid Build Coastguard Worker int bytes_read = stream.gcount();
133*20733378SAndroid Build Coastguard Worker SHA512_Update(&ctx, buf, bytes_read);
134*20733378SAndroid Build Coastguard Worker }
135*20733378SAndroid Build Coastguard Worker }
136*20733378SAndroid Build Coastguard Worker
137*20733378SAndroid Build Coastguard Worker uint8_t hash[SHA512_DIGEST_LENGTH];
138*20733378SAndroid Build Coastguard Worker SHA512_Final(hash, &ctx);
139*20733378SAndroid Build Coastguard Worker std::stringstream ss;
140*20733378SAndroid Build Coastguard Worker ss << std::hex;
141*20733378SAndroid Build Coastguard Worker for (int i = 0; i < SHA512_DIGEST_LENGTH; i++) {
142*20733378SAndroid Build Coastguard Worker ss << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
143*20733378SAndroid Build Coastguard Worker }
144*20733378SAndroid Build Coastguard Worker return ss.str();
145*20733378SAndroid Build Coastguard Worker }
146*20733378SAndroid Build Coastguard Worker
147*20733378SAndroid Build Coastguard Worker /// convert override type enum to string
OverrideTypeToStr(const StorageRequestMessage::FlagOverrideType & override_type)148*20733378SAndroid Build Coastguard Worker std::string OverrideTypeToStr(
149*20733378SAndroid Build Coastguard Worker const StorageRequestMessage::FlagOverrideType& override_type) {
150*20733378SAndroid Build Coastguard Worker switch (override_type) {
151*20733378SAndroid Build Coastguard Worker case StorageRequestMessage::LOCAL_IMMEDIATE: {
152*20733378SAndroid Build Coastguard Worker return "local immediate";
153*20733378SAndroid Build Coastguard Worker }
154*20733378SAndroid Build Coastguard Worker case StorageRequestMessage::LOCAL_ON_REBOOT: {
155*20733378SAndroid Build Coastguard Worker return "local on reboot";
156*20733378SAndroid Build Coastguard Worker }
157*20733378SAndroid Build Coastguard Worker case StorageRequestMessage::SERVER_ON_REBOOT: {
158*20733378SAndroid Build Coastguard Worker return "server on reboot";
159*20733378SAndroid Build Coastguard Worker }
160*20733378SAndroid Build Coastguard Worker default: {
161*20733378SAndroid Build Coastguard Worker return "unknown";
162*20733378SAndroid Build Coastguard Worker }
163*20733378SAndroid Build Coastguard Worker }
164*20733378SAndroid Build Coastguard Worker }
165*20733378SAndroid Build Coastguard Worker
166*20733378SAndroid Build Coastguard Worker } // namespace aconfig
167*20733378SAndroid Build Coastguard Worker } // namespace android
168