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(¤tTime);
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