• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "utils.h"
17 #include <algorithm>
18 #include <cerrno>
19 #include <cstdint>
20 #include <cstdlib>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <limits>
24 #include <linux/reboot.h>
25 #include <string>
26 #include <sys/reboot.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <unistd.h>
30 #include <vector>
31 #include "fs_manager/mount.h"
32 #include "init_reboot.h"
33 #include "log/log.h"
34 #include "misc_info/misc_info.h"
35 #ifdef WITH_SELINUX
36 #include <policycoreutils.h>
37 #include "selinux/selinux.h"
38 #endif
39 #include "package/pkg_manager.h"
40 #include "securec.h"
41 #include "updater/updater_const.h"
42 
43 namespace Updater {
44 using namespace Hpackage;
45 
46 namespace Utils {
47 constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4;
48 constexpr int MAX_TIME_SIZE = 20;
49 constexpr const char *PREFIX_PARTITION_NODE = "/dev/block/by-name/";
50 
51 namespace {
UpdateInfoInMisc(const std::string headInfo,const std::optional<int> message,bool isRemove)52 void UpdateInfoInMisc(const std::string headInfo, const std::optional<int> message, bool isRemove)
53 {
54     if (headInfo.empty()) {
55         return;
56     }
57     std::vector<std::string> args = Utils::ParseParams(0, nullptr);
58     struct UpdateMessage msg {};
59     if (!ReadUpdaterMiscMsg(msg)) {
60         LOG(ERROR) << "SetMessageToMisc read misc failed";
61         return;
62     }
63 
64     (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
65     for (const auto& arg : args) {
66         if (arg.find(headInfo) == std::string::npos) {
67             if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
68                 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
69                 return;
70             }
71             if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
72                 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
73                 return;
74             }
75         }
76     }
77     char buffer[128] {}; // 128 : set headInfo size
78     if (isRemove) {
79         LOG(INFO) << "remove --" << headInfo << " from misc";
80     } else if (!message.has_value()) {
81         if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) {
82             LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
83             return;
84         }
85     } else {
86         if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d",
87             headInfo.c_str(), message.value()) == -1) {
88             LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
89             return;
90         }
91     }
92     if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
93         LOG(ERROR) << "SetMessageToMisc strncat_s failed";
94         return;
95     }
96     if (WriteUpdaterMiscMsg(msg) != true) {
97         LOG(ERROR) << "Write command to misc failed.";
98     }
99 }
100 } // namespace
101 
SaveLogs()102 void SaveLogs()
103 {
104     std::string updaterLogPath = std::string(UPDATER_LOG);
105     std::string stageLogPath = std::string(UPDATER_STAGE_LOG);
106 
107     // save logs
108     bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath);
109     if (!ret) {
110         LOG(ERROR) << "Copy updater log failed!";
111     }
112 
113     mode_t mode = 0660;
114 #ifndef __WIN32
115     SetFileAttributes(updaterLogPath, USER_UPDATE_AUTHORITY, GROUP_UPDATE_AUTHORITY, mode);
116 #endif
117 
118     STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater";
119     ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath);
120     chmod(stageLogPath.c_str(), mode);
121     if (!ret) {
122         LOG(ERROR) << "Copy stage log failed!";
123     }
124 }
125 
DeleteFile(const std::string & filename)126 int32_t DeleteFile(const std::string& filename)
127 {
128     if (filename.empty()) {
129         LOG(ERROR) << "Invalid filename";
130         return -1;
131     }
132     if (unlink(filename.c_str()) == -1 && errno != ENOENT) {
133         LOG(ERROR) << "unlink " << filename << " failed";
134         return -1;
135     }
136     return 0;
137 }
138 
SplitString(const std::string & str,const std::string del)139 std::vector<std::string> SplitString(const std::string &str, const std::string del)
140 {
141     std::vector<std::string> result;
142     size_t found = std::string::npos;
143     size_t start = 0;
144     while (true) {
145         found = str.find_first_of(del, start);
146         result.push_back(str.substr(start, found - start));
147         if (found == std::string::npos) {
148             break;
149         }
150         start = found + 1;
151     }
152     return result;
153 }
154 
Trim(const std::string & str)155 std::string Trim(const std::string &str)
156 {
157     if (str.empty()) {
158         LOG(ERROR) << "str is empty";
159         return str;
160     }
161     size_t start = 0;
162     size_t end = str.size() - 1;
163     while (start < str.size()) {
164         if (!isspace(str[start])) {
165             break;
166         }
167         start++;
168     }
169     while (start < end) {
170         if (!isspace(str[end])) {
171             break;
172         }
173         end--;
174     }
175     if (end < start) {
176         return "";
177     }
178     return str.substr(start, end - start + 1);
179 }
180 
ConvertSha256Hex(const uint8_t * shaDigest,size_t length)181 std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length)
182 {
183     const std::string hexChars = "0123456789abcdef";
184     std::string haxSha256 = "";
185     unsigned int c;
186     for (size_t i = 0; i < length; ++i) {
187         auto d = shaDigest[i];
188         c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf;     // last 4 bits
189         haxSha256.push_back(hexChars[c]);
190         haxSha256.push_back(hexChars[d & 0xf]);
191     }
192     return haxSha256;
193 }
194 
SetRebootMisc(const std::string & rebootTarget,const std::string & extData,struct UpdateMessage & msg)195 bool SetRebootMisc(const std::string& rebootTarget, const std::string &extData, struct UpdateMessage &msg)
196 {
197     static const int32_t maxCommandSize = 16;
198     int result = 0;
199     if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) {
200         result = strcpy_s(msg.command, maxCommandSize, "boot_updater");
201     } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) {
202         result = strcpy_s(msg.command, maxCommandSize, "boot_flash");
203     } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) {
204         result = strcpy_s(msg.command, maxCommandSize, "boot_loader");
205     }
206     if (result != EOK) {
207         LOG(ERROR) << "reboot set misc strcpy failed";
208         return false;
209     }
210     msg.command[maxCommandSize] = 0;
211     if (extData.empty()) {
212         (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
213         return true;
214     }
215     if (strcpy_s(msg.update, sizeof(msg.update) - 1, extData.c_str()) != EOK) {
216         LOG(ERROR) << "failed to copy update";
217         return false;
218     }
219     msg.update[sizeof(msg.update) - 1] = 0;
220     return true;
221 }
222 
UpdaterDoReboot(const std::string & rebootTarget,const std::string & extData)223 void UpdaterDoReboot(const std::string& rebootTarget, const std::string &extData)
224 {
225     LOG(INFO) << ", rebootTarget: " << rebootTarget;
226     LoadFstab();
227     struct UpdateMessage msg = {};
228     if (rebootTarget.empty()) {
229         if (WriteUpdaterMiscMsg(msg) != true) {
230             LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMessage empty error";
231             return;
232         }
233     } else {
234         if (!ReadUpdaterMiscMsg(msg)) {
235             LOG(ERROR) << "UpdaterDoReboot read misc failed";
236             return;
237         }
238         if (!SetRebootMisc(rebootTarget, extData, msg)) {
239             LOG(ERROR) << "UpdaterDoReboot set misc failed";
240             return;
241         }
242         if (!WriteUpdaterMiscMsg(msg)) {
243             LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMiscMsg error";
244             return;
245         }
246     }
247     sync();
248 #ifndef UPDATER_UT
249     DoReboot(rebootTarget.c_str());
250     while (true) {
251         pause();
252     }
253 #else
254     return;
255 #endif
256 }
257 
DoShutdown()258 void DoShutdown()
259 {
260     UpdateMessage msg = {};
261     if (!WriteUpdaterMiscMsg(msg)) {
262         LOG(ERROR) << "DoShutdown: WriteUpdaterMessage empty error";
263         return;
264     }
265     sync();
266     DoReboot("shutdown");
267 }
268 
GetCertName()269 std::string GetCertName()
270 {
271 #ifndef UPDATER_UT
272     static std::string signingCertName = "/etc/certificate/signing_cert.crt";
273 #else
274     static std::string signingCertName = "/data/updater/src/signing_cert.crt";
275 #endif
276     return signingCertName;
277 }
278 
WriteFully(int fd,const uint8_t * data,size_t size)279 bool WriteFully(int fd, const uint8_t *data, size_t size)
280 {
281     ssize_t written = 0;
282     size_t rest = size;
283 
284     while (rest > 0) {
285         do {
286             written = write(fd, data, rest);
287         } while (written < 0 && errno == EINTR);
288 
289         if (written < 0) {
290             return false;
291         }
292         data += written;
293         rest -= static_cast<size_t>(written);
294     }
295     return true;
296 }
297 
ReadFully(int fd,void * data,size_t size)298 bool ReadFully(int fd, void *data, size_t size)
299 {
300     auto p = reinterpret_cast<uint8_t *>(data);
301     size_t remaining = size;
302     while (remaining > 0) {
303         ssize_t sread = read(fd, p, remaining);
304         if (sread <= 0) {
305             LOG(ERROR) << "Utils::ReadFully run error";
306             return false;
307         }
308         p += sread;
309         remaining -= static_cast<size_t>(sread);
310     }
311     return true;
312 }
313 
ReadFileToString(int fd,std::string & content)314 bool ReadFileToString(int fd, std::string &content)
315 {
316     struct stat sb {};
317     if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
318         content.resize(static_cast<size_t>(sb.st_size));
319     }
320     ssize_t n;
321     auto remaining = static_cast<size_t>(sb.st_size);
322     auto p = reinterpret_cast<char *>(content.data());
323     while (remaining > 0) {
324         n = read(fd, p, remaining);
325         if (n <= 0) {
326             return false;
327         }
328         p += n;
329         remaining -= static_cast<size_t>(n);
330     }
331     return true;
332 }
333 
WriteStringToFile(int fd,const std::string & content)334 bool WriteStringToFile(int fd, const std::string& content)
335 {
336     const char *p = content.data();
337     size_t remaining = content.size();
338     while (remaining > 0) {
339         ssize_t n = write(fd, p, remaining);
340         if (n == -1) {
341             return false;
342         }
343         p += n;
344         remaining -= static_cast<size_t>(n);
345     }
346     return true;
347 }
348 
SyncFile(const std::string & dst)349 void SyncFile(const std::string &dst)
350 {
351     int fd = open(dst.c_str(), O_RDWR);
352     if (fd < 0) {
353         LOG(ERROR) << "open " << dst << " failed! err " << strerror(errno);
354         return;
355     }
356     fsync(fd);
357     close(fd);
358 }
359 
CopyFile(const std::string & src,const std::string & dest,bool isAppend)360 bool CopyFile(const std::string &src, const std::string &dest, bool isAppend)
361 {
362     char realPath[PATH_MAX + 1] = {0};
363     if (realpath(src.c_str(), realPath) == nullptr) {
364         LOG(ERROR) << src << " get realpath fail";
365         return false;
366     }
367 
368     std::ios_base::openmode mode = isAppend ? std::ios::app | std::ios::out : std::ios_base::out;
369     std::ifstream fin(realPath);
370     std::ofstream fout(dest, mode);
371     if (!fin.is_open() || !fout.is_open()) {
372         return false;
373     }
374 
375     fout << fin.rdbuf();
376     if (fout.fail()) {
377         fout.clear();
378         return false;
379     }
380     fout.flush();
381     fout.close();
382     SyncFile(dest); // no way to get fd from ofstream, so reopen to sync this file
383     return true;
384 }
385 
GetLocalBoardId()386 std::string GetLocalBoardId()
387 {
388     return "HI3516";
389 }
390 
CompressLogs(const std::string & logName)391 void CompressLogs(const std::string &logName)
392 {
393     PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
394     if (pkgManager == nullptr) {
395         LOG(ERROR) << "pkgManager is nullptr";
396         return;
397     }
398     std::vector<std::pair<std::string, ZipFileInfo>> files;
399     // Build the zip file to be packaged
400     std::vector<std::string> testFileNames;
401     std::string realName = logName.substr(logName.find_last_of("/") + 1);
402     std::string logPath = logName.substr(0, logName.find_last_of("/"));
403     testFileNames.push_back(realName);
404     for (auto name : testFileNames) {
405         ZipFileInfo file;
406         file.fileInfo.identity = name;
407         file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
408         file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
409         std::string fileName = logName;
410         files.push_back(std::pair<std::string, ZipFileInfo>(fileName, file));
411     }
412 
413     PkgInfo pkgInfo;
414     pkgInfo.signMethod = PKG_SIGN_METHOD_NONE;
415     pkgInfo.digestMethod = PKG_SIGN_METHOD_NONE;
416     pkgInfo.pkgType = PKG_PACK_TYPE_ZIP;
417 
418     char realTime[MAX_TIME_SIZE] = {0};
419     auto sysTime = std::chrono::system_clock::now();
420     auto currentTime = std::chrono::system_clock::to_time_t(sysTime);
421     struct tm *localTime = std::localtime(&currentTime);
422     if (localTime != nullptr) {
423         std::strftime(realTime, sizeof(realTime), "%Y%m%d%H%M%S", localTime);
424     }
425     char pkgName[MAX_LOG_NAME_SIZE];
426     if (snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1,
427         "%s/%s_%s.zip", logPath.c_str(), realName.c_str(), realTime) == -1) {
428         PkgManager::ReleasePackageInstance(pkgManager);
429         return;
430     }
431     int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files);
432     if (ret != 0) {
433         LOG(WARNING) << "CompressLogs failed";
434         PkgManager::ReleasePackageInstance(pkgManager);
435         return;
436     }
437     mode_t mode = 0660;
438 #ifndef __WIN32
439     SetFileAttributes(pkgName, USER_UPDATE_AUTHORITY, GROUP_UPDATE_AUTHORITY, mode);
440 #endif
441     (void)DeleteFile(logName);
442     PkgManager::ReleasePackageInstance(pkgManager);
443 }
444 
GetFileSize(const std::string & filePath)445 size_t GetFileSize(const std::string &filePath)
446 {
447     int ret = 0;
448     std::ifstream ifs(filePath, std::ios::binary | std::ios::in);
449     if (ifs.is_open()) {
450         ifs.seekg(0, std::ios::end);
451         ret = ifs.tellg();
452     }
453     return ret;
454 }
455 
RestoreconPath(const std::string & path)456 bool RestoreconPath(const std::string &path)
457 {
458     if (MountForPath(path) != 0) {
459         LOG(ERROR) << "MountForPath " << path << " failed!";
460         return false;
461     }
462 #ifdef WITH_SELINUX
463     if (RestoreconRecurse(path.c_str()) == -1) {
464         LOG(WARNING) << "restore " << path << " failed";
465     }
466 #endif // WITH_SELINUX
467     if (UmountForPath(path) != 0) {
468         LOG(WARNING) << "UmountForPath " << path << " failed!";
469     }
470     return true;
471 }
472 
CopyUpdaterLogs(const std::string & sLog,const std::string & dLog)473 bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog)
474 {
475     std::size_t found = dLog.find_last_of("/");
476     if (found == std::string::npos) {
477         LOG(ERROR) << "Dest filePath error";
478         return false;
479     }
480     std::string destPath = dLog.substr(0, found);
481     if (MountForPath(destPath) != 0) {
482         LOG(WARNING) << "MountForPath /data/log failed!";
483     }
484 
485     if (access(destPath.c_str(), 0) != 0) {
486         if (MkdirRecursive(destPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
487             LOG(ERROR) << "MkdirRecursive error!";
488             return false;
489         }
490         #ifdef WITH_SELINUX
491             RestoreconRecurse(UPDATER_PATH);
492         #endif // WITH_SELINUX
493     }
494 
495     if (Utils::GetFileSize(sLog) > MAX_LOG_SIZE) {
496         LOG(ERROR) << "Size bigger for" << sLog;
497         STAGE(UPDATE_STAGE_FAIL) << "Log file error, unable to copy";
498         return false;
499     }
500 
501     while (Utils::GetFileSize(sLog) + GetDirSizeForFile(dLog) > MAX_LOG_DIR_SIZE) {
502         if (DeleteOldFile(destPath) != true) {
503             break;
504         }
505     }
506 
507     if (!CopyFile(sLog, dLog, true)) {
508         LOG(ERROR) << "copy log file failed.";
509         return false;
510     }
511     if (GetFileSize(dLog) >= MAX_LOG_SIZE) {
512         LOG(INFO) << "log size greater than 5M!";
513         CompressLogs(dLog);
514     }
515     sync();
516     return true;
517 }
518 
CheckResultFail()519 bool CheckResultFail()
520 {
521     std::ifstream ifs;
522     const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
523     ifs.open(resultPath, std::ios::in);
524     std::string buff;
525     while (ifs.is_open() && getline(ifs, buff)) {
526         if (buff.find("fail|") != std::string::npos) {
527             ifs.close();
528             return true;
529         }
530     }
531     LOG(ERROR) << "open result file failed";
532     return false;
533 }
534 
WriteDumpResult(const std::string & result,const std::string & fileName)535 void WriteDumpResult(const std::string &result, const std::string &fileName)
536 {
537     if (access(UPDATER_PATH, 0) != 0) {
538         if (MkdirRecursive(UPDATER_PATH, 0755) != 0) { // 0755: -rwxr-xr-x
539             LOG(ERROR) << "MkdirRecursive error!";
540             return;
541         }
542     }
543     LOG(INFO) << "WriteDumpResult: " << result;
544     const std::string resultPath = std::string(UPDATER_PATH) + "/" + fileName;
545     FILE *fp = fopen(resultPath.c_str(), "w+");
546     if (fp == nullptr) {
547         LOG(ERROR) << "open result file failed";
548         return;
549     }
550     char buf[MAX_RESULT_BUFF_SIZE] = "Pass\n";
551     if (sprintf_s(buf, MAX_RESULT_BUFF_SIZE - 1, "%s\n", result.c_str()) < 0) {
552         LOG(WARNING) << "sprintf status fialed";
553     }
554     if (fwrite(buf, 1, strlen(buf) + 1, fp) <= 0) {
555         LOG(WARNING) << "write result file failed, err:" << errno;
556     }
557     if (fclose(fp) != 0) {
558         LOG(WARNING) << "close result file failed";
559     }
560 
561     (void)chown(resultPath.c_str(), USER_ROOT_AUTHORITY, GROUP_UPDATE_AUTHORITY);
562     (void)chmod(resultPath.c_str(), 0660); // 0660: -rw-rw----
563 }
564 
GetDirSize(const std::string & folderPath)565 long long int GetDirSize(const std::string &folderPath)
566 {
567     DIR* dir = opendir(folderPath.c_str());
568     if (dir == nullptr) {
569         LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl;
570         return 0;
571     }
572 
573     struct dirent* entry;
574     long long int totalSize = 0;
575     while ((entry = readdir(dir)) != nullptr) {
576         std::string fileName = entry->d_name;
577         std::string filePath = folderPath + "/" + fileName;
578         struct stat fileStat;
579         if (stat(filePath.c_str(), &fileStat) != 0) {
580             LOG(ERROR) << "Failed to get file status: " << filePath << std::endl;
581             continue;
582         }
583         if (S_ISDIR(fileStat.st_mode)) {
584             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
585                 continue;
586             }
587             std::string subFolderPath = filePath;
588             totalSize += GetDirSize(subFolderPath);
589         } else {
590             totalSize += fileStat.st_size;
591         }
592     }
593     closedir(dir);
594     return totalSize;
595 }
596 
GetDirSizeForFile(const std::string & filePath)597 long long int GetDirSizeForFile(const std::string &filePath)
598 {
599     std::size_t found = filePath.find_last_of("/");
600     if (found == std::string::npos) {
601         LOG(ERROR) << "filePath error";
602         return -1;
603     }
604     return GetDirSize(filePath.substr(0, found));
605 }
606 
DeleteOldFile(const std::string folderPath)607 bool DeleteOldFile(const std::string folderPath)
608 {
609     DIR* dir = opendir(folderPath.c_str());
610     if (dir == nullptr) {
611         LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl;
612         return false;
613     }
614 
615     struct dirent* entry;
616     std::string oldestFilePath = "";
617     time_t oldestFileTime = std::numeric_limits<time_t>::max();
618     while ((entry = readdir(dir)) != nullptr) {
619         std::string fileName = entry->d_name;
620         std::string filePath = folderPath + "/" + fileName;
621         struct stat fileStat;
622         if (stat(filePath.c_str(), &fileStat) != 0) {
623             LOG(ERROR) << "Failed to get file status: " << filePath;
624             continue;
625         }
626         if (fileName == "." || fileName == "..") {
627             continue;
628         }
629         if (fileStat.st_mtime < oldestFileTime) {
630             oldestFileTime = fileStat.st_mtime;
631             oldestFilePath = filePath;
632         }
633     }
634     closedir(dir);
635     if (oldestFilePath.empty()) {
636         LOG(ERROR) << "Unable to delete file";
637         return false;
638     }
639     if (remove(oldestFilePath.c_str()) != 0) {
640         LOG(ERROR) << "Failed to delete file: " << oldestFilePath;
641         return false;
642     }
643     return true;
644 }
645 
ParseParams(int argc,char ** argv)646 std::vector<std::string> ParseParams(int argc, char **argv)
647 {
648     struct UpdateMessage boot {};
649     // read from misc
650     if (!ReadUpdaterMiscMsg(boot)) {
651         LOG(ERROR) << "ReadUpdaterMessage MISC_FILE failed!";
652     }
653     // if boot.update is empty, read from command.The Misc partition may have dirty data,
654     // so strlen(boot.update) is not used, which can cause system exceptions.
655     if (boot.update[0] == '\0' && !access(COMMAND_FILE, 0)) {
656         if (!ReadUpdaterMessage(COMMAND_FILE, boot)) {
657             LOG(ERROR) << "ReadUpdaterMessage COMMAND_FILE failed!";
658         }
659     }
660     STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update;
661     boot.update[sizeof(boot.update) - 1] = '\0';
662     std::vector<std::string> parseParams = Utils::SplitString(boot.update, "\n");
663     if (argc != 0 && argv != nullptr) {
664         parseParams.insert(parseParams.begin(), argv, argv + argc);
665     }
666     return parseParams;
667 }
668 
CheckUpdateMode(const std::string & mode)669 bool CheckUpdateMode(const std::string &mode)
670 {
671     std::vector<std::string> args = ParseParams(0, nullptr);
672     for (const auto &arg : args) {
673         if (arg.find(mode) != std::string::npos) {
674             return true;
675         }
676     }
677     return false;
678 }
679 
DurationToString(std::vector<std::chrono::duration<double>> & durations,std::size_t pkgPosition,int precision)680 std::string DurationToString(std::vector<std::chrono::duration<double>> &durations, std::size_t pkgPosition,
681     int precision)
682 {
683     if (pkgPosition >= durations.size()) {
684         LOG(ERROR) << "pkg position is " << pkgPosition << ", duration's size is " << durations.size();
685         return "0";
686     }
687     std::ostringstream oss;
688     oss << std::fixed << std::setprecision(precision) << durations[pkgPosition].count();
689     return oss.str();
690 }
691 
GetRealPath(const std::string & path)692 std::string GetRealPath(const std::string &path)
693 {
694     char realPath[PATH_MAX + 1] = {0};
695     auto ret = realpath(path.c_str(), realPath);
696     return (ret == nullptr) ? "" : ret;
697 }
698 
GetPartitionRealPath(const std::string & name)699 std::string GetPartitionRealPath(const std::string &name)
700 {
701     return GetRealPath(PREFIX_PARTITION_NODE + name);
702 }
703 
SetMessageToMisc(const std::string & miscCmd,const int message,const std::string headInfo)704 void SetMessageToMisc(const std::string &miscCmd, const int message, const std::string headInfo)
705 {
706     if (headInfo.empty()) {
707         return;
708     }
709     std::vector<std::string> args = ParseParams(0, nullptr);
710     struct UpdateMessage msg {};
711     if (!ReadUpdaterMiscMsg(msg)) {
712         LOG(ERROR) << "SetMessageToMisc read misc failed";
713         return;
714     }
715     (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command));
716     if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) {
717         LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
718         return;
719     }
720     (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
721     for (const auto& arg : args) {
722         if (arg.find(headInfo) == std::string::npos) {
723             if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
724                 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
725                 return;
726             }
727             if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
728                 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
729                 return;
730             }
731         }
732     }
733     char buffer[128] {}; // 128 : set headInfo size
734     if (headInfo == "sdcard_update") {
735         if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) {
736             LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
737             return;
738         }
739     } else {
740         if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", headInfo.c_str(), message) == -1) {
741             LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
742             return;
743         }
744     }
745     if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
746         LOG(ERROR) << "SetMessageToMisc strncat_s failed";
747         return;
748     }
749     if (WriteUpdaterMiscMsg(msg) != true) {
750         LOG(ERROR) << "Write command to misc failed.";
751     }
752 }
753 
SetCmdToMisc(const std::string & miscCmd)754 void SetCmdToMisc(const std::string &miscCmd)
755 {
756     struct UpdateMessage msg {};
757     if (!ReadUpdaterMiscMsg(msg)) {
758         LOG(ERROR) << "SetMessageToMisc read misc failed";
759         return;
760     }
761 
762     (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command));
763     if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) {
764         LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
765         return;
766     }
767 
768     if (WriteUpdaterMiscMsg(msg) != true) {
769         LOG(ERROR) << "Write command to misc failed.";
770     }
771 }
772 
AddUpdateInfoToMisc(const std::string headInfo,const std::optional<int> message)773 void AddUpdateInfoToMisc(const std::string headInfo, const std::optional<int> message)
774 {
775     UpdateInfoInMisc(headInfo, message, false);
776 }
777 
RemoveUpdateInfoFromMisc(const std::string & headInfo)778 void RemoveUpdateInfoFromMisc(const std::string &headInfo)
779 {
780     UpdateInfoInMisc(headInfo, std::nullopt, true);
781 }
782 
SetFaultInfoToMisc(const std::string & faultInfo)783 void SetFaultInfoToMisc(const std::string &faultInfo)
784 {
785     struct UpdateMessage msg {};
786     if (!ReadUpdaterMiscMsg(msg)) {
787         LOG(ERROR) << "SetMessageToMisc read misc failed";
788         return;
789     }
790 
791     (void)memset_s(msg.faultinfo, sizeof(msg.faultinfo), 0, sizeof(msg.faultinfo));
792     if (strncpy_s(msg.faultinfo, sizeof(msg.faultinfo), faultInfo.c_str(), faultInfo.size() + 1) != EOK) {
793         LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
794         return;
795     }
796 
797     if (WriteUpdaterMiscMsg(msg) != true) {
798         LOG(ERROR) << "Write fault info to misc failed.";
799     }
800 }
801 
CheckFaultInfo(const std::string & faultInfo)802 bool CheckFaultInfo(const std::string &faultInfo)
803 {
804     struct UpdateMessage msg = {};
805     if (!ReadUpdaterMiscMsg(msg)) {
806         LOG(ERROR) << "read misc data failed";
807         return false;
808     }
809 
810     if (strcmp(msg.faultinfo, faultInfo.c_str()) == 0) {
811         return true;
812     }
813     return false;
814 }
815 
GetTagValInStr(const std::string & str,const std::string & tag,std::string & val)816 void GetTagValInStr(const std::string &str, const std::string &tag, std::string &val)
817 {
818     if (str.find(tag + "=") != std::string::npos) {
819         val = str.substr(str.find("=") + 1, str.size() - str.find("="));
820     }
821 }
822 
IsValidHexStr(const std::string & str)823 bool IsValidHexStr(const std::string &str)
824 {
825     for (const auto &ch : str) {
826         if (isxdigit(ch) == 0) {
827             return false;
828         }
829     }
830     return true;
831 }
832 
TrimString(std::string & str)833 void TrimString(std::string &str)
834 {
835     auto pos = str.find_last_not_of("\r\n");
836     if (pos != std::string::npos) {
837         str.erase(pos + 1, str.size() - pos);
838     }
839 }
840 
841 #ifndef __WIN32
SetFileAttributes(const std::string & file,uid_t owner,gid_t group,mode_t mode)842 void SetFileAttributes(const std::string& file, uid_t owner, gid_t group, mode_t mode)
843 {
844 #ifdef WITH_SELINUX
845     RestoreconRecurse(file.c_str());
846 #endif // WITH_SELINUX
847     if (chown(file.c_str(), USER_ROOT_AUTHORITY, GROUP_ROOT_AUTHORITY) != 0) {
848         LOG(ERROR) << "Chown failed: " << file << " " << USER_ROOT_AUTHORITY << "," << GROUP_ROOT_AUTHORITY;
849     }
850     if (chmod(file.c_str(), mode) != EOK) {
851         LOG(ERROR) << "chmod failed: " << file << " " << mode;
852     }
853     if (chown(file.c_str(), owner, group) != 0) {
854         LOG(ERROR) << "Chown failed: " << file << " " << owner << "," << group;
855     }
856 }
857 #endif
858 } // Utils
InitLogger(const std::string & tag)859 void __attribute__((weak)) InitLogger(const std::string &tag)
860 {
861     if (Utils::IsUpdaterMode()) {
862         InitUpdaterLogger(tag, TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH);
863     } else {
864         InitUpdaterLogger(tag, SYS_INSTALLER_LOG, UPDATER_STAGE_LOG, ERROR_CODE_PATH);
865     }
866 }
867 } // namespace Updater
868