xref: /aosp_15_r20/system/server_configurable_flags/aconfigd/aconfigd_util.cpp (revision 207333786ba243bc7d4d69ef6b05487aa7071806)
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