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 "parameter.h"
41 #include "securec.h"
42 #include "updater/updater_const.h"
43 #include "scope_guard.h"
44
45 namespace Updater {
46 using namespace Hpackage;
47
48 namespace Utils {
49 constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4;
50 constexpr int MAX_TIME_SIZE = 20;
51 constexpr size_t PARAM_SIZE = 32;
52 constexpr const char *PREFIX_PARTITION_NODE = "/dev/block/by-name/";
53 constexpr mode_t DEFAULT_DIR_MODE = 0775;
54 constexpr long MAX_FILE_LENGTH = 4096;
55
56 namespace {
UpdateInfoInMisc(const std::string headInfo,const std::optional<int> message,bool isRemove)57 void UpdateInfoInMisc(const std::string headInfo, const std::optional<int> message, bool isRemove)
58 {
59 if (headInfo.empty()) {
60 return;
61 }
62 std::vector<std::string> args = Utils::ParseParams(0, nullptr);
63 struct UpdateMessage msg {};
64 if (!ReadUpdaterMiscMsg(msg)) {
65 LOG(ERROR) << "SetMessageToMisc read misc failed";
66 return;
67 }
68
69 (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
70 for (const auto& arg : args) {
71 if (arg.find(headInfo) == std::string::npos) {
72 if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
73 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
74 return;
75 }
76 if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
77 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
78 return;
79 }
80 }
81 }
82 char buffer[128] {}; // 128 : set headInfo size
83 if (isRemove) {
84 LOG(INFO) << "remove --" << headInfo << " from misc";
85 } else if (!message.has_value()) {
86 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) {
87 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
88 return;
89 }
90 } else {
91 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d",
92 headInfo.c_str(), message.value()) == -1) {
93 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
94 return;
95 }
96 }
97 if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
98 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
99 return;
100 }
101 if (WriteUpdaterMiscMsg(msg) != true) {
102 LOG(ERROR) << "Write command to misc failed.";
103 }
104 }
105 } // namespace
106
SaveLogs()107 void SaveLogs()
108 {
109 std::string updaterLogPath = std::string(UPDATER_LOG);
110 std::string stageLogPath = std::string(UPDATER_STAGE_LOG);
111
112 // save logs
113 STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdaterLog";
114 bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath);
115 if (!ret) {
116 LOG(ERROR) << "Copy updater log failed!";
117 }
118
119 mode_t mode = 0660;
120 #ifndef __WIN32
121 SetFileAttributes(updaterLogPath, USER_UPDATE_AUTHORITY, GROUP_UPDATE_AUTHORITY, mode);
122 #endif
123
124 STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater";
125 ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath);
126 chmod(stageLogPath.c_str(), mode);
127 if (!ret) {
128 LOG(ERROR) << "Copy stage log failed!";
129 }
130 }
131
DeleteFile(const std::string & filename)132 int32_t DeleteFile(const std::string& filename)
133 {
134 if (filename.empty()) {
135 LOG(ERROR) << "Invalid filename";
136 return -1;
137 }
138 if (unlink(filename.c_str()) == -1 && errno != ENOENT) {
139 LOG(ERROR) << "unlink " << filename << " failed";
140 return -1;
141 }
142 return 0;
143 }
144
SplitString(const std::string & str,const std::string del)145 std::vector<std::string> SplitString(const std::string &str, const std::string del)
146 {
147 std::vector<std::string> result;
148 size_t found = std::string::npos;
149 size_t start = 0;
150 while (true) {
151 found = str.find_first_of(del, start);
152 result.push_back(str.substr(start, found - start));
153 if (found == std::string::npos) {
154 break;
155 }
156 start = found + 1;
157 }
158 return result;
159 }
160
Trim(const std::string & str)161 std::string Trim(const std::string &str)
162 {
163 if (str.empty()) {
164 LOG(ERROR) << "str is empty";
165 return str;
166 }
167 size_t start = 0;
168 size_t end = str.size() - 1;
169 while (start < str.size()) {
170 if (!isspace(str[start])) {
171 break;
172 }
173 start++;
174 }
175 while (start < end) {
176 if (!isspace(str[end])) {
177 break;
178 }
179 end--;
180 }
181 if (end < start) {
182 return "";
183 }
184 return str.substr(start, end - start + 1);
185 }
186
ConvertSha256Hex(const uint8_t * shaDigest,size_t length)187 std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length)
188 {
189 const std::string hexChars = "0123456789abcdef";
190 std::string haxSha256 = "";
191 unsigned int c;
192 for (size_t i = 0; i < length; ++i) {
193 auto d = shaDigest[i];
194 c = (d >> SHIFT_RIGHT_FOUR_BITS) & 0xf; // last 4 bits
195 haxSha256.push_back(hexChars[c]);
196 haxSha256.push_back(hexChars[d & 0xf]);
197 }
198 return haxSha256;
199 }
200
SetRebootMisc(const std::string & rebootTarget,const std::string & extData,struct UpdateMessage & msg)201 bool SetRebootMisc(const std::string& rebootTarget, const std::string &extData, struct UpdateMessage &msg)
202 {
203 static const int32_t maxCommandSize = 16;
204 int result = 0;
205 if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) {
206 result = strcpy_s(msg.command, maxCommandSize, "boot_updater");
207 } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) {
208 result = strcpy_s(msg.command, maxCommandSize, "boot_flash");
209 } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) {
210 result = strcpy_s(msg.command, maxCommandSize, "boot_loader");
211 }
212 if (result != EOK) {
213 LOG(ERROR) << "reboot set misc strcpy failed";
214 return false;
215 }
216 msg.command[maxCommandSize] = 0;
217 if (extData.empty()) {
218 (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
219 return true;
220 }
221 if (strcpy_s(msg.update, sizeof(msg.update) - 1, extData.c_str()) != EOK) {
222 LOG(ERROR) << "failed to copy update";
223 return false;
224 }
225 msg.update[sizeof(msg.update) - 1] = 0;
226 return true;
227 }
228
UpdaterDoReboot(const std::string & rebootTarget,const std::string & rebootReason,const std::string & extData)229 void UpdaterDoReboot(const std::string& rebootTarget, const std::string &rebootReason, const std::string &extData)
230 {
231 LOG(INFO) << ", rebootTarget: " << rebootTarget;
232 LOG(INFO) << ", rebootReason: " << rebootReason;
233 LoadFstab();
234 struct UpdateMessage msg = {};
235 if (rebootTarget.empty()) {
236 if (WriteUpdaterMiscMsg(msg) != true) {
237 LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMessage empty error";
238 }
239 } else {
240 if (!ReadUpdaterMiscMsg(msg)) {
241 LOG(ERROR) << "UpdaterDoReboot read misc failed";
242 }
243 if (!SetRebootMisc(rebootTarget, extData, msg)) {
244 LOG(ERROR) << "UpdaterDoReboot set misc failed";
245 }
246 if (!WriteUpdaterMiscMsg(msg)) {
247 LOG(INFO) << "UpdaterDoReboot: WriteUpdaterMiscMsg error";
248 }
249 }
250 sync();
251 #ifndef UPDATER_UT
252 DoRebootExt(rebootTarget.c_str(), rebootReason.c_str());
253 while (true) {
254 pause();
255 }
256 #else
257 return;
258 #endif
259 }
260
DoShutdown(const std::string & shutdownReason)261 void DoShutdown(const std::string &shutdownReason)
262 {
263 UpdateMessage msg = {};
264 if (!WriteUpdaterMiscMsg(msg)) {
265 LOG(ERROR) << "DoShutdown: WriteUpdaterMessage empty error";
266 return;
267 }
268 sync();
269 DoRebootExt("shutdown", shutdownReason.c_str());
270 }
271
GetCertName()272 std::string GetCertName()
273 {
274 #ifndef UPDATER_UT
275 static std::string signingCertName = "/etc/certificate/signing_cert.crt";
276 #ifdef SIGN_ON_SERVER
277 signingCertName = Updater::Utils::ON_SERVER;
278 #endif
279 #else
280 static std::string signingCertName = "/data/updater/src/signing_cert.crt";
281 #endif
282 return signingCertName;
283 }
284
WriteFully(int fd,const uint8_t * data,size_t size)285 bool WriteFully(int fd, const uint8_t *data, size_t size)
286 {
287 ssize_t written = 0;
288 size_t rest = size;
289
290 while (rest > 0) {
291 do {
292 written = write(fd, data, rest);
293 } while (written < 0 && errno == EINTR);
294 if (written < 0) {
295 return false;
296 }
297 data += written;
298 rest -= static_cast<size_t>(written);
299 if (rest != 0) {
300 LOG(INFO) << "totalSize = " << size << ", rest = " << rest;
301 }
302 }
303 return true;
304 }
305
ReadFully(int fd,void * data,size_t size)306 bool ReadFully(int fd, void *data, size_t size)
307 {
308 auto p = reinterpret_cast<uint8_t *>(data);
309 size_t remaining = size;
310 while (remaining > 0) {
311 ssize_t sread = read(fd, p, remaining);
312 if (sread == -1) {
313 LOG(ERROR) << "read failed: " << strerror(errno);
314 return false;
315 }
316 if (sread == 0) {
317 LOG(ERROR) << "read reached unexpected EOF";
318 return false;
319 }
320 p += sread;
321 remaining -= static_cast<size_t>(sread);
322 }
323 return true;
324 }
325
ReadFileToString(int fd,std::string & content)326 bool ReadFileToString(int fd, std::string &content)
327 {
328 struct stat sb {};
329 if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
330 content.resize(static_cast<size_t>(sb.st_size));
331 }
332 ssize_t n;
333 auto remaining = static_cast<size_t>(sb.st_size);
334 auto p = reinterpret_cast<char *>(content.data());
335 while (remaining > 0) {
336 n = read(fd, p, remaining);
337 if (n <= 0) {
338 return false;
339 }
340 p += n;
341 remaining -= static_cast<size_t>(n);
342 }
343 return true;
344 }
345
ReadStringFromProcFile(const std::string & filePath,std::string & content)346 bool ReadStringFromProcFile(const std::string &filePath, std::string &content)
347 {
348 std::ifstream file(filePath.c_str());
349 if (!file.is_open()) {
350 LOG(ERROR) << "failed to open " << filePath << ", err: " << strerror(errno);
351 return false;
352 }
353
354 file.seekg(0, std::ios::end);
355 const long fileLength = file.tellg();
356 if (fileLength > MAX_FILE_LENGTH) {
357 LOG(ERROR) << "file oversize " << fileLength << ", max is " << MAX_FILE_LENGTH;
358 return false;
359 }
360
361 content.clear();
362 file.seekg(0, std::ios::beg);
363 std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(content));
364 return true;
365 }
366
WriteStringToFile(int fd,const std::string & content)367 bool WriteStringToFile(int fd, const std::string& content)
368 {
369 const char *p = content.data();
370 size_t remaining = content.size();
371 while (remaining > 0) {
372 ssize_t n = write(fd, p, remaining);
373 if (n == -1) {
374 return false;
375 }
376 p += n;
377 remaining -= static_cast<size_t>(n);
378 }
379 return true;
380 }
381
SyncFile(const std::string & dst)382 void SyncFile(const std::string &dst)
383 {
384 int fd = open(dst.c_str(), O_RDWR);
385 if (fd < 0) {
386 LOG(ERROR) << "open " << dst << " failed! err " << strerror(errno);
387 return;
388 }
389 fsync(fd);
390 close(fd);
391 }
392
CopyFile(const std::string & src,const std::string & dest,bool isAppend)393 bool CopyFile(const std::string &src, const std::string &dest, bool isAppend)
394 {
395 char realPath[PATH_MAX + 1] = {0};
396 if (realpath(src.c_str(), realPath) == nullptr) {
397 LOG(ERROR) << src << " get realpath fail";
398 return false;
399 }
400
401 std::ios_base::openmode mode = isAppend ? std::ios::app | std::ios::out : std::ios_base::out;
402 std::ifstream fin(realPath);
403 std::ofstream fout(dest, mode);
404 if (!fin.is_open() || !fout.is_open()) {
405 return false;
406 }
407
408 fout << fin.rdbuf();
409 if (fout.fail()) {
410 fout.clear();
411 return false;
412 }
413 fout.flush();
414 fout.close();
415 SyncFile(dest); // no way to get fd from ofstream, so reopen to sync this file
416 return true;
417 }
418
CopyDir(const std::string & srcPath,const std::string & dstPath)419 bool CopyDir(const std::string &srcPath, const std::string &dstPath)
420 {
421 DIR *dir = opendir(srcPath.c_str());
422 if (dir == nullptr) {
423 LOG(ERROR) << "opendir failed, path: " << srcPath.c_str() << ", err: " << strerror(errno);
424 return false;
425 }
426 ON_SCOPE_EXIT(closedir) {
427 closedir(dir);
428 };
429 bool existFlag = (access(dstPath.c_str(), 0) == 0);
430 if ((!existFlag) && (mkdir(dstPath.c_str(), DEFAULT_DIR_MODE) != 0)) {
431 LOG(ERROR) << "mkdir failed, path: " << dstPath.c_str() << ", err: " << strerror(errno);
432 return false;
433 }
434 ON_SCOPE_EXIT(rmdir) {
435 if (!existFlag) {
436 remove(dstPath.c_str());
437 }
438 };
439 dirent *dirent = nullptr;
440 while ((dirent = readdir(dir)) != nullptr) {
441 if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
442 continue;
443 }
444 if (dirent->d_type == DT_DIR) {
445 std::string fullSourcePath = srcPath + dirent->d_name + "/";
446 std::string fullDestPath = dstPath + dirent->d_name + "/";
447 if (!CopyDir(fullSourcePath, fullDestPath)) {
448 LOG(ERROR) << "copydir failed, fullSourcePath: " << fullSourcePath.c_str()
449 << ", fullDestPath: " << fullDestPath.c_str();
450 return false;
451 }
452 } else {
453 std::string fullSourcePath = srcPath + dirent->d_name;
454 std::string fullDestPath = dstPath + dirent->d_name;
455 if (!CopyFile(fullSourcePath, fullDestPath)) {
456 LOG(ERROR) << "copyfile failed, fullSourcePath: " << fullSourcePath.c_str()
457 << ", fullDestPath: " << fullDestPath.c_str();
458 return false;
459 }
460 }
461 }
462 CANCEL_SCOPE_EXIT_GUARD(rmdir);
463 return true;
464 }
465
GetLocalBoardId()466 std::string GetLocalBoardId()
467 {
468 return "HI3516";
469 }
470
CreateCompressLogFile(const std::string & pkgName,std::vector<std::pair<std::string,ZipFileInfo>> & files)471 int32_t CreateCompressLogFile(const std::string &pkgName, std::vector<std::pair<std::string, ZipFileInfo>> &files)
472 {
473 PkgInfo pkgInfo;
474 pkgInfo.signMethod = PKG_SIGN_METHOD_NONE;
475 pkgInfo.digestMethod = PKG_SIGN_METHOD_NONE;
476 pkgInfo.pkgType = PKG_PACK_TYPE_ZIP;
477 PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
478 if (pkgManager == nullptr) {
479 LOG(ERROR) << "pkgManager is nullptr";
480 return -1;
481 }
482 int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files);
483 PkgManager::ReleasePackageInstance(pkgManager);
484 return ret;
485 }
486
CompressFiles(std::vector<std::string> & files,const std::string & zipFile)487 void CompressFiles(std::vector<std::string> &files, const std::string &zipFile)
488 {
489 (void)DeleteFile(zipFile);
490 std::vector<std::pair<std::string, ZipFileInfo>> zipFiles {};
491 for (auto path : files) {
492 ZipFileInfo file {};
493 file.fileInfo.identity = path.substr(path.find_last_of("/") + 1);
494 file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
495 file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
496 zipFiles.push_back(std::pair<std::string, ZipFileInfo>(path, file));
497 }
498
499 int32_t ret = CreateCompressLogFile(zipFile, zipFiles);
500 if (ret != 0) {
501 LOG(WARNING) << "CompressFiles failed: " << zipFile;
502 return;
503 }
504 mode_t mode = 0660;
505 #ifndef __WIN32
506 SetFileAttributes(zipFile, USER_UPDATE_AUTHORITY, GROUP_SYS_AUTHORITY, mode);
507 #endif
508 }
509
CompressLogs(const std::string & logName)510 void CompressLogs(const std::string &logName)
511 {
512 std::vector<std::pair<std::string, ZipFileInfo>> files;
513 // Build the zip file to be packaged
514 std::vector<std::string> testFileNames;
515 std::string realName = logName.substr(logName.find_last_of("/") + 1);
516 std::string logPath = logName.substr(0, logName.find_last_of("/"));
517 testFileNames.push_back(realName);
518 for (auto name : testFileNames) {
519 ZipFileInfo file;
520 file.fileInfo.identity = name;
521 file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
522 file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
523 std::string fileName = logName;
524 files.push_back(std::pair<std::string, ZipFileInfo>(fileName, file));
525 }
526
527 char realTime[MAX_TIME_SIZE] = {0};
528 auto sysTime = std::chrono::system_clock::now();
529 auto currentTime = std::chrono::system_clock::to_time_t(sysTime);
530 struct tm *localTime = std::localtime(¤tTime);
531 if (localTime != nullptr) {
532 std::strftime(realTime, sizeof(realTime), "%Y%m%d%H%M%S", localTime);
533 }
534 char pkgName[MAX_LOG_NAME_SIZE];
535 if (snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1,
536 "%s/%s_%s.zip", logPath.c_str(), realName.c_str(), realTime) == -1) {
537 return;
538 }
539 int32_t ret = CreateCompressLogFile(pkgName, files);
540 if (ret != 0) {
541 LOG(WARNING) << "CompressLogs failed";
542 return;
543 }
544 mode_t mode = 0660;
545 #ifndef __WIN32
546 SetFileAttributes(pkgName, USER_UPDATE_AUTHORITY, GROUP_SYS_AUTHORITY, mode);
547 #endif
548 sync();
549 if (access(pkgName, 0) != 0) {
550 LOG(ERROR) << "Failed to create zipfile: " << pkgName;
551 } else {
552 (void)DeleteFile(logName);
553 }
554 }
555
GetFileSize(const std::string & filePath)556 size_t GetFileSize(const std::string &filePath)
557 {
558 size_t ret = 0;
559 std::ifstream ifs(filePath, std::ios::binary | std::ios::in);
560 if (ifs.is_open()) {
561 ifs.seekg(0, std::ios::end);
562 ret = static_cast<size_t>(ifs.tellg());
563 }
564 return ret;
565 }
566
RestoreconPath(const std::string & path)567 bool RestoreconPath(const std::string &path)
568 {
569 if (MountForPath(path) != 0) {
570 LOG(ERROR) << "MountForPath " << path << " failed!";
571 return false;
572 }
573 #ifdef WITH_SELINUX
574 if (RestoreconRecurse(path.c_str()) == -1) {
575 LOG(WARNING) << "restore " << path << " failed";
576 }
577 #endif // WITH_SELINUX
578 if (UmountForPath(path) != 0) {
579 LOG(WARNING) << "UmountForPath " << path << " failed!";
580 }
581 return true;
582 }
583
CopyUpdaterLogs(const std::string & sLog,const std::string & dLog)584 bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog)
585 {
586 std::size_t found = dLog.find_last_of("/");
587 if (found == std::string::npos) {
588 LOG(ERROR) << "Dest filePath error";
589 return false;
590 }
591 std::string destPath = dLog.substr(0, found);
592 if (MountForPath(destPath) != 0) {
593 LOG(WARNING) << "MountForPath /data/log failed!";
594 }
595
596 if (access(destPath.c_str(), 0) != 0) {
597 if (MkdirRecursive(destPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
598 LOG(ERROR) << "MkdirRecursive error!";
599 return false;
600 }
601 #ifdef WITH_SELINUX
602 RestoreconRecurse(UPDATER_PATH);
603 #endif // WITH_SELINUX
604 }
605
606 if (Utils::GetFileSize(sLog) > MAX_LOG_SIZE) {
607 LOG(ERROR) << "Size bigger for" << sLog;
608 STAGE(UPDATE_STAGE_FAIL) << "Log file error, unable to copy";
609 return false;
610 }
611
612 while (Utils::GetFileSize(sLog) + GetDirSizeForFile(dLog) > MAX_LOG_DIR_SIZE) {
613 LOG(ERROR) << "Size bigger for" << sLog;
614 STAGE(UPDATE_STAGE_FAIL) << "sLog and dLog file error, unable to copy";
615 if (DeleteOldFile(destPath) != true) {
616 break;
617 }
618 }
619
620 if (!CopyFile(sLog, dLog, true)) {
621 LOG(ERROR) << "copy log file failed.";
622 return false;
623 }
624 if (GetFileSize(dLog) >= MAX_LOG_SIZE) {
625 LOG(INFO) << "log size greater than 5M!";
626 CompressLogs(dLog);
627 }
628 sync();
629 return true;
630 }
631
CheckResultFail()632 bool CheckResultFail()
633 {
634 std::ifstream ifs;
635 const std::string resultPath = std::string(UPDATER_PATH) + "/" + std::string(UPDATER_RESULT_FILE);
636 ifs.open(resultPath, std::ios::in);
637 std::string buff;
638 while (ifs.is_open() && getline(ifs, buff)) {
639 if (buff.find("fail|") != std::string::npos) {
640 ifs.close();
641 return true;
642 }
643 }
644 LOG(ERROR) << "open result file failed";
645 return false;
646 }
647
WriteDumpResult(const std::string & result,const std::string & fileName)648 void WriteDumpResult(const std::string &result, const std::string &fileName)
649 {
650 if (access(UPDATER_PATH, 0) != 0) {
651 if (MkdirRecursive(UPDATER_PATH, 0755) != 0) { // 0755: -rwxr-xr-x
652 LOG(ERROR) << "MkdirRecursive error!";
653 return;
654 }
655 }
656 const std::string resultPath = std::string(UPDATER_PATH) + "/" + fileName;
657 FILE *fp = fopen(resultPath.c_str(), "w+");
658 if (fp == nullptr) {
659 LOG(ERROR) << "open result file failed";
660 return;
661 }
662 char buf[MAX_RESULT_BUFF_SIZE] = "Pass\n";
663 if (sprintf_s(buf, MAX_RESULT_BUFF_SIZE - 1, "%s\n", result.c_str()) < 0) {
664 LOG(WARNING) << "sprintf status fialed";
665 }
666 if (fwrite(buf, 1, strlen(buf) + 1, fp) <= 0) {
667 LOG(WARNING) << "write result file failed, err:" << errno;
668 }
669 if (fclose(fp) != 0) {
670 LOG(WARNING) << "close result file failed";
671 }
672
673 (void)chown(resultPath.c_str(), USER_ROOT_AUTHORITY, GROUP_UPDATE_AUTHORITY);
674 (void)chmod(resultPath.c_str(), 0660); // 0660: -rw-rw----
675 }
676
GetDirSize(const std::string & folderPath)677 long long int GetDirSize(const std::string &folderPath)
678 {
679 DIR* dir = opendir(folderPath.c_str());
680 if (dir == nullptr) {
681 LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl;
682 return 0;
683 }
684
685 struct dirent* entry;
686 long long int totalSize = 0;
687 while ((entry = readdir(dir)) != nullptr) {
688 std::string fileName = entry->d_name;
689 std::string filePath = folderPath + "/" + fileName;
690 struct stat fileStat;
691 if (stat(filePath.c_str(), &fileStat) != 0) {
692 LOG(ERROR) << "Failed to get file status: " << filePath << std::endl;
693 continue;
694 }
695 if (S_ISDIR(fileStat.st_mode)) {
696 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
697 continue;
698 }
699 std::string subFolderPath = filePath;
700 totalSize += GetDirSize(subFolderPath);
701 } else {
702 totalSize += fileStat.st_size;
703 }
704 }
705 closedir(dir);
706 return totalSize;
707 }
708
GetDirSizeForFile(const std::string & filePath)709 long long int GetDirSizeForFile(const std::string &filePath)
710 {
711 std::size_t found = filePath.find_last_of("/");
712 if (found == std::string::npos) {
713 LOG(ERROR) << "filePath error";
714 return -1;
715 }
716 return GetDirSize(filePath.substr(0, found));
717 }
718
DeleteOldFile(const std::string folderPath)719 bool DeleteOldFile(const std::string folderPath)
720 {
721 DIR* dir = opendir(folderPath.c_str());
722 if (dir == nullptr) {
723 LOG(ERROR) << "Failed to open folder: " << folderPath << std::endl;
724 return false;
725 }
726
727 struct dirent* entry;
728 std::string oldestFilePath = "";
729 time_t oldestFileTime = std::numeric_limits<time_t>::max();
730 while ((entry = readdir(dir)) != nullptr) {
731 std::string fileName = entry->d_name;
732 std::string filePath = folderPath + "/" + fileName;
733 struct stat fileStat;
734 if (stat(filePath.c_str(), &fileStat) != 0) {
735 LOG(ERROR) << "Failed to get file status: " << filePath;
736 continue;
737 }
738 if (fileName == "." || fileName == "..") {
739 continue;
740 }
741 if (fileStat.st_mtime < oldestFileTime) {
742 oldestFileTime = fileStat.st_mtime;
743 oldestFilePath = filePath;
744 }
745 }
746 closedir(dir);
747 if (oldestFilePath.empty()) {
748 LOG(ERROR) << "Unable to delete file";
749 return false;
750 }
751 size_t size = GetFileSize(oldestFilePath);
752 if (remove(oldestFilePath.c_str()) != 0) {
753 LOG(ERROR) << "Failed to delete file: " << oldestFilePath;
754 return false;
755 }
756 LOG(INFO) << "Delete old file: " << oldestFilePath << " size: " << size;
757 return true;
758 }
759
ParseParams(int argc,char ** argv)760 std::vector<std::string> ParseParams(int argc, char **argv)
761 {
762 struct UpdateMessage boot {};
763 // read from misc
764 if (!ReadUpdaterMiscMsg(boot)) {
765 LOG(ERROR) << "ReadUpdaterMessage MISC_FILE failed!";
766 }
767 // if boot.update is empty, read from command.The Misc partition may have dirty data,
768 // so strlen(boot.update) is not used, which can cause system exceptions.
769 if (boot.update[0] == '\0' && !access(COMMAND_FILE, 0)) {
770 if (!ReadUpdaterMessage(COMMAND_FILE, boot)) {
771 LOG(ERROR) << "ReadUpdaterMessage COMMAND_FILE failed!";
772 }
773 }
774
775 boot.update[sizeof(boot.update) - 1] = '\0';
776 std::vector<std::string> parseParams = Utils::SplitString(boot.update, "\n");
777 if (argc != 0 && argv != nullptr) {
778 parseParams.insert(parseParams.begin(), argv, argv + argc);
779 }
780 return parseParams;
781 }
782
TrimUpdateMode(const std::string & mode)783 std::string TrimUpdateMode(const std::string &mode)
784 {
785 std::string optEqual = "=";
786 std::string modePrefix = "--"; // misc = --update_package=xxxx / --sdcard_update
787 size_t optPos = mode.size();
788 size_t prefixPos = 0;
789 if (mode.empty() || mode == "") {
790 return "";
791 }
792 if (mode.find(optEqual) != std::string::npos) {
793 optPos = mode.find(optEqual);
794 }
795 if (mode.find(modePrefix) != std::string::npos) {
796 prefixPos = mode.find(modePrefix) + modePrefix.size();
797 }
798 if (optPos < prefixPos) {
799 return mode;
800 }
801 return mode.substr(prefixPos, optPos - prefixPos);
802 }
803
CheckUpdateMode(const std::string & mode)804 bool CheckUpdateMode(const std::string &mode)
805 {
806 std::vector<std::string> args = ParseParams(0, nullptr);
807 for (const auto &arg : args) {
808 if (TrimUpdateMode(arg) == mode) {
809 return true;
810 }
811 }
812 return false;
813 }
814
DurationToString(std::vector<std::chrono::duration<double>> & durations,std::size_t pkgPosition,int precision)815 std::string DurationToString(std::vector<std::chrono::duration<double>> &durations, std::size_t pkgPosition,
816 int precision)
817 {
818 if (pkgPosition >= durations.size()) {
819 LOG(ERROR) << "pkg position is " << pkgPosition << ", duration's size is " << durations.size();
820 return "0";
821 }
822 std::ostringstream oss;
823 oss << std::fixed << std::setprecision(precision) << durations[pkgPosition].count();
824 return oss.str();
825 }
826
GetRealPath(const std::string & path)827 std::string GetRealPath(const std::string &path)
828 {
829 char realPath[PATH_MAX + 1] = {0};
830 auto ret = realpath(path.c_str(), realPath);
831 return (ret == nullptr) ? "" : ret;
832 }
833
GetPartitionRealPath(const std::string & name)834 std::string GetPartitionRealPath(const std::string &name)
835 {
836 return GetRealPath(PREFIX_PARTITION_NODE + name);
837 }
838
SetMessageToMisc(const std::string & miscCmd,const int message,const std::string headInfo)839 void SetMessageToMisc(const std::string &miscCmd, const int message, const std::string headInfo)
840 {
841 if (headInfo.empty()) {
842 return;
843 }
844 std::vector<std::string> args = ParseParams(0, nullptr);
845 struct UpdateMessage msg {};
846 if (!ReadUpdaterMiscMsg(msg)) {
847 LOG(ERROR) << "SetMessageToMisc read misc failed";
848 return;
849 }
850 (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command));
851 if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) {
852 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
853 return;
854 }
855 (void)memset_s(msg.update, sizeof(msg.update), 0, sizeof(msg.update));
856 for (const auto& arg : args) {
857 if (arg.find(headInfo) == std::string::npos) {
858 if (strncat_s(msg.update, sizeof(msg.update), arg.c_str(), strlen(arg.c_str()) + 1) != EOK) {
859 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
860 return;
861 }
862 if (strncat_s(msg.update, sizeof(msg.update), "\n", strlen("\n") + 1) != EOK) {
863 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
864 return;
865 }
866 }
867 }
868 char buffer[128] {}; // 128 : set headInfo size
869 if (headInfo == "sdcard_update") {
870 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s", headInfo.c_str()) == -1) {
871 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
872 return;
873 }
874 } else {
875 if (snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "--%s=%d", headInfo.c_str(), message) == -1) {
876 LOG(ERROR) << "SetMessageToMisc snprintf_s failed";
877 return;
878 }
879 }
880 if (strncat_s(msg.update, sizeof(msg.update), buffer, strlen(buffer) + 1) != EOK) {
881 LOG(ERROR) << "SetMessageToMisc strncat_s failed";
882 return;
883 }
884 if (WriteUpdaterMiscMsg(msg) != true) {
885 LOG(ERROR) << "Write command to misc failed.";
886 }
887 }
888
SetCmdToMisc(const std::string & miscCmd)889 void SetCmdToMisc(const std::string &miscCmd)
890 {
891 struct UpdateMessage msg {};
892 if (!ReadUpdaterMiscMsg(msg)) {
893 LOG(ERROR) << "SetMessageToMisc read misc failed";
894 return;
895 }
896
897 (void)memset_s(msg.command, sizeof(msg.command), 0, sizeof(msg.command));
898 if (strncpy_s(msg.command, sizeof(msg.command), miscCmd.c_str(), miscCmd.size() + 1) != EOK) {
899 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
900 return;
901 }
902
903 if (WriteUpdaterMiscMsg(msg) != true) {
904 LOG(ERROR) << "Write command to misc failed.";
905 }
906 }
907
AddUpdateInfoToMisc(const std::string headInfo,const std::optional<int> message)908 void AddUpdateInfoToMisc(const std::string headInfo, const std::optional<int> message)
909 {
910 UpdateInfoInMisc(headInfo, message, false);
911 }
912
RemoveUpdateInfoFromMisc(const std::string & headInfo)913 void RemoveUpdateInfoFromMisc(const std::string &headInfo)
914 {
915 UpdateInfoInMisc(headInfo, std::nullopt, true);
916 }
917
SetFaultInfoToMisc(const std::string & faultInfo)918 void SetFaultInfoToMisc(const std::string &faultInfo)
919 {
920 struct UpdateMessage msg {};
921 if (!ReadUpdaterMiscMsg(msg)) {
922 LOG(ERROR) << "SetMessageToMisc read misc failed";
923 return;
924 }
925
926 (void)memset_s(msg.faultinfo, sizeof(msg.faultinfo), 0, sizeof(msg.faultinfo));
927 if (strncpy_s(msg.faultinfo, sizeof(msg.faultinfo), faultInfo.c_str(), faultInfo.size() + 1) != EOK) {
928 LOG(ERROR) << "SetMessageToMisc strncpy_s failed";
929 return;
930 }
931
932 if (WriteUpdaterMiscMsg(msg) != true) {
933 LOG(ERROR) << "Write fault info to misc failed.";
934 }
935 }
936
CheckFaultInfo(const std::string & faultInfo)937 bool CheckFaultInfo(const std::string &faultInfo)
938 {
939 struct UpdateMessage msg = {};
940 if (!ReadUpdaterMiscMsg(msg)) {
941 LOG(ERROR) << "read misc data failed";
942 return false;
943 }
944
945 if (strcmp(msg.faultinfo, faultInfo.c_str()) == 0) {
946 return true;
947 }
948 return false;
949 }
950
GetTagValInStr(const std::string & str,const std::string & tag,std::string & val)951 void GetTagValInStr(const std::string &str, const std::string &tag, std::string &val)
952 {
953 if (str.find(tag + "=") != std::string::npos) {
954 val = str.substr(str.find("=") + 1, str.size() - str.find("="));
955 }
956 }
957
IsValidHexStr(const std::string & str)958 bool IsValidHexStr(const std::string &str)
959 {
960 for (const auto &ch : str) {
961 if (isxdigit(ch) == 0) {
962 return false;
963 }
964 }
965 return true;
966 }
967
TrimString(std::string & str)968 void TrimString(std::string &str)
969 {
970 auto pos = str.find_last_not_of("\r\n");
971 if (pos != std::string::npos) {
972 str.erase(pos + 1, str.size() - pos);
973 }
974 }
975
IsEsDevice()976 bool IsEsDevice()
977 {
978 char deviceType[PARAM_SIZE + 1] = {0};
979 if (GetParameter("ohos.boot.chiptype", "", deviceType, sizeof(deviceType) - 1) <= 0) {
980 LOG(ERROR) << "get device type failed";
981 return false;
982 }
983 LOG(INFO) << "device type is " << deviceType;
984 if (strstr(deviceType, "_es") == nullptr) {
985 return false;
986 }
987 return true;
988 }
989
ConvertToUnsignedLongLong(const std::string & str,uint64_t & value)990 bool ConvertToUnsignedLongLong(const std::string &str, uint64_t &value)
991 {
992 char *endPtr = nullptr;
993 errno = 0;
994
995 value = std::strtoull(str.c_str(), &endPtr, 0);
996 #ifndef UPDATER_UT
997 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
998 LOG(ERROR) << "Convert string to uint64_t failed, str " << str << " converted to value " << value;
999 return false;
1000 }
1001 #endif
1002 return true;
1003 }
1004
ConvertToLongLong(const std::string & str,int64_t & value)1005 bool ConvertToLongLong(const std::string &str, int64_t &value)
1006 {
1007 char *endPtr = nullptr;
1008 errno = 0;
1009
1010 value = std::strtoll(str.c_str(), &endPtr, 10); // 10 : decimal scale
1011 #ifndef UPDATER_UT
1012 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
1013 LOG(ERROR) << "Convert string to int64_t failed, str " << str << " converted to value " << value;
1014 return false;
1015 }
1016 #endif
1017 return true;
1018 }
1019
ConvertToLong(const std::string & str,int32_t & value)1020 bool ConvertToLong(const std::string &str, int32_t &value)
1021 {
1022 char *endPtr = nullptr;
1023 errno = 0;
1024
1025 value = std::strtol(str.c_str(), &endPtr, 10); // 10 : decimal scale
1026 #ifndef UPDATER_UT
1027 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
1028 LOG(ERROR) << "Convert string to int32_t failed, str " << str << " converted to value " << value;
1029 return false;
1030 }
1031 #endif
1032 return true;
1033 }
1034
ConvertToUnsignedLong(const std::string & str,uint32_t & value,int base)1035 bool ConvertToUnsignedLong(const std::string &str, uint32_t &value, int base)
1036 {
1037 char *endPtr = nullptr;
1038 errno = 0;
1039
1040 value = std::strtoul(str.c_str(), &endPtr, base);
1041 #ifndef UPDATER_UT
1042 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
1043 LOG(ERROR) << "Convert string to uint32_t failed, str " << str << " converted to value " << value;
1044 return false;
1045 }
1046 #endif
1047 return true;
1048 }
1049
ConvertToDouble(const std::string & str,double & value)1050 bool ConvertToDouble(const std::string &str, double &value)
1051 {
1052 char *endPtr = nullptr;
1053 errno = 0;
1054
1055 value = std::strtod(str.c_str(), &endPtr);
1056 #ifndef UPDATER_UT
1057 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
1058 LOG(ERROR) << "Convert string to double failed, str " << str << " converted to value " << value;
1059 return false;
1060 }
1061 #endif
1062 return true;
1063 }
1064
ConvertToFloat(const std::string & str,float & value)1065 bool ConvertToFloat(const std::string &str, float &value)
1066 {
1067 char *endPtr = nullptr;
1068 errno = 0;
1069
1070 value = std::strtof(str.c_str(), &endPtr);
1071 #ifndef UPDATER_UT
1072 if (endPtr == str.c_str() || *endPtr != '\0' || errno == ERANGE) {
1073 LOG(ERROR) << "Convert string to float failed, str " << str << " converted to value " << value;
1074 return false;
1075 }
1076 #endif
1077 return true;
1078 }
1079
IsVabDevice()1080 bool IsVabDevice()
1081 {
1082 char partType[PARAM_SIZE + 1] = {0};
1083 if (GetParameter("ohos.boot.update.partition_type", "", partType, sizeof(partType) - 1) <= 0) {
1084 LOG(ERROR) << "get part partition failed";
1085 return false;
1086 }
1087 LOG(INFO) << "device type is " << partType;
1088 return std::string(partType) == "vab";
1089 }
1090
SetUpdateSlot(int setSlot)1091 bool SetUpdateSlot(int setSlot)
1092 {
1093 if (setSlot == -1) {
1094 LOG(ERROR) << "setSlot is invalid value";
1095 return false;
1096 }
1097 int tryNum = 3;
1098 std::string setSlotStr = std::to_string(setSlot);
1099 while (tryNum-- > 0) {
1100 if (SetParameter("update.part.slot", setSlotStr.c_str()) != 0) {
1101 LOG(ERROR) << "set update.part.slot fail";
1102 continue;
1103 }
1104 if (GetUpdateSlot() == setSlot) {
1105 LOG(INFO) << "set update.part.slot is " << setSlot;
1106 return true;
1107 }
1108 if (tryNum != 0) {
1109 sleep(1);
1110 }
1111 }
1112 return false;
1113 }
1114
SetUpdateSuffix(std::string stringsuffix)1115 bool SetUpdateSuffix(std::string stringsuffix)
1116 {
1117 int tryNum = 3;
1118 while (tryNum-- > 0) {
1119 if (SetParameter("update.part.suffix", stringsuffix.c_str()) != 0) {
1120 LOG(ERROR) << "set update.part.suffix fail";
1121 continue;
1122 }
1123 if (strcmp(GetUpdateSuffix().c_str(), stringsuffix.c_str()) == 0) {
1124 LOG(INFO) << "set update.part.suffix is " << stringsuffix;
1125 return true;
1126 }
1127 if (tryNum != 0) {
1128 sleep(1);
1129 }
1130 }
1131 return false;
1132 }
1133
GetUpdateSlot()1134 int GetUpdateSlot()
1135 {
1136 if (!IsVabDevice()) {
1137 return NOT_AB;
1138 }
1139 char paramValue[PARAM_SIZE + 1] = {0};
1140 if (GetParameter("update.part.slot", "", paramValue, sizeof(paramValue) - 1) <= 0) {
1141 LOG(ERROR) << "get update.part.slot failed";
1142 return -1;
1143 }
1144 int updateSlot = -1;
1145 if (!Utils::ConvertToLong(paramValue, updateSlot)) {
1146 LOG(ERROR) << "ConvertToLong failed";
1147 return -1;
1148 }
1149 return updateSlot;
1150 }
1151
GetUpdateSuffix()1152 std::string GetUpdateSuffix()
1153 {
1154 char paramValue[PARAM_SIZE + 1] = {0};
1155 if (GetParameter("update.part.suffix", "", paramValue, sizeof(paramValue) - 1) <= 0) {
1156 LOG(ERROR) << "get update.part.suffix failed";
1157 return std::string(paramValue);
1158 }
1159 LOG(INFO) << "GetUpdateSuffix = " << paramValue;
1160 return std::string(paramValue);
1161 }
1162
GetUpdateActiveSuffix()1163 std::string GetUpdateActiveSuffix()
1164 {
1165 char paramValue[PARAM_SIZE + 1] = {0};
1166 if (GetParameter("update.part.suffix", "", paramValue, sizeof(paramValue) - 1) <= 0) {
1167 LOG(ERROR) << "get update.part.suffix failed";
1168 return std::string(paramValue);
1169 }
1170 if (strcmp(paramValue, "_a") == 0) {
1171 strncpy_s(paramValue, sizeof(paramValue), "_b", sizeof("_b"));
1172 } else if (strcmp(paramValue, "_b") == 0) {
1173 strncpy_s(paramValue, sizeof(paramValue), "_a", sizeof("_a"));
1174 } else {
1175 LOG(ERROR) << "Unexpected suffix value: " << paramValue;
1176 return std::string(paramValue);
1177 }
1178 LOG(INFO) << "GetUpdateActiveSuffix = " << paramValue;
1179 return std::string(paramValue);
1180 }
1181
GetAllTids(pid_t pid)1182 std::vector<pid_t> GetAllTids(pid_t pid)
1183 {
1184 std::vector<pid_t> tids;
1185 tids.push_back(pid);
1186 std::string pathName = std::string("/proc/").append(std::to_string(pid)).append("/task");
1187 char tmpPath[PATH_MAX + 1] = {0};
1188 if (realpath(pathName.c_str(), tmpPath) == nullptr || tmpPath[0] == '\0') {
1189 LOG(ERROR) << "realpath fail pathName:" << pathName;
1190 return tids;
1191 }
1192 DIR *dir = opendir(tmpPath);
1193 if (dir == nullptr) {
1194 LOG(ERROR) << "opendir fail pathName:" << pathName;
1195 return tids;
1196 }
1197 struct dirent *de = nullptr;
1198 while ((de = readdir(dir)) != nullptr) {
1199 if (!(de->d_type & DT_DIR) || !isdigit(de->d_name[0])) {
1200 continue;
1201 }
1202 int32_t temp = -1;
1203 if (!Utils::ConvertToLong(de->d_name, temp)) {
1204 LOG(ERROR) << "ConvertToLong failed";
1205 continue;
1206 }
1207 pid_t tid = static_cast<pid_t>(temp);
1208 if (tid > 0) {
1209 tids.push_back(tid);
1210 }
1211 }
1212 closedir(dir);
1213 return tids;
1214 }
1215
VectorToString(const std::vector<pid_t> & pids)1216 std::string VectorToString(const std::vector<pid_t> &pids)
1217 {
1218 if (pids.empty()) {
1219 return "";
1220 }
1221 std::ostringstream oss;
1222 auto it = pids.begin();
1223 oss << *it++;
1224 while (it != pids.end()) {
1225 oss << "," << *it++;
1226 }
1227 return oss.str();
1228 }
1229
1230 #ifndef __WIN32
SetFileAttributes(const std::string & file,uid_t owner,gid_t group,mode_t mode)1231 void SetFileAttributes(const std::string& file, uid_t owner, gid_t group, mode_t mode)
1232 {
1233 #ifdef WITH_SELINUX
1234 RestoreconRecurse(file.c_str());
1235 #endif // WITH_SELINUX
1236 if (chown(file.c_str(), USER_ROOT_AUTHORITY, GROUP_ROOT_AUTHORITY) != 0) {
1237 LOG(ERROR) << "Chown failed: " << file << " " << USER_ROOT_AUTHORITY << "," << GROUP_ROOT_AUTHORITY;
1238 }
1239 if (chmod(file.c_str(), mode) != EOK) {
1240 LOG(ERROR) << "chmod failed: " << file << " " << mode;
1241 }
1242 if (chown(file.c_str(), owner, group) != 0) {
1243 LOG(ERROR) << "Chown failed: " << file << " " << owner << "," << group;
1244 }
1245 }
1246 #endif
1247 } // Utils
InitLogger(const std::string & tag)1248 void __attribute__((weak)) InitLogger(const std::string &tag)
1249 {
1250 if (Utils::IsUpdaterMode()) {
1251 InitUpdaterLogger(tag, TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH);
1252 } else {
1253 InitUpdaterLogger(tag, SYS_INSTALLER_LOG, UPDATER_STAGE_LOG, ERROR_CODE_PATH);
1254 }
1255 }
1256 } // namespace Updater
1257