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 #include "updaterkits/updaterkits.h"
16
17 #include <string>
18 #include <unistd.h>
19 #include "init_reboot.h"
20 #include "log.h"
21 #include "misc_info/misc_info.h"
22 #include "securec.h"
23 #include "utils.h"
24
25 using namespace Updater;
26 using Updater::Utils::SplitString;
27
WriteToMiscAndRebootToUpdater(const struct UpdateMessage & updateMsg)28 static bool WriteToMiscAndRebootToUpdater(const struct UpdateMessage &updateMsg)
29 {
30 // Write package name to misc, then trigger reboot.
31 const char *bootCmd = "boot_updater";
32 int ret = strncpy_s(const_cast<char*>(updateMsg.command), sizeof(updateMsg.command), bootCmd,
33 sizeof(updateMsg.command) - 1);
34 if (ret != 0) {
35 return false;
36 }
37 #ifndef UPDATER_UT
38 WriteUpdaterMiscMsg(updateMsg);
39 DoReboot("updater");
40 while (true) {
41 pause();
42 }
43 #else
44 return true;
45 #endif
46 }
47
AddPkgPath(struct UpdateMessage & msg,size_t updateOffset,const std::vector<std::string> & packageName)48 static bool AddPkgPath(struct UpdateMessage &msg, size_t updateOffset, const std::vector<std::string> &packageName)
49 {
50 for (auto path : packageName) {
51 if (updateOffset > sizeof(msg.update)) {
52 LOG(ERROR) << "updaterkits: updateOffset > msg.update, return false";
53 return false;
54 }
55 int ret;
56 if (path.find("--force_update_action=") != std::string::npos) {
57 ret = snprintf_s(msg.update + updateOffset, sizeof(msg.update) - updateOffset,
58 sizeof(msg.update) - 1 - updateOffset, "%s\n", path.c_str());
59 } else {
60 ret = snprintf_s(msg.update + updateOffset, sizeof(msg.update) - updateOffset,
61 sizeof(msg.update) - 1 - updateOffset, "--update_package=%s\n", path.c_str());
62 }
63 if (ret < 0) {
64 LOG(ERROR) << "updaterkits: copy updater message failed";
65 return false;
66 }
67 updateOffset += static_cast<size_t>(ret);
68 }
69 return true;
70 }
71
RebootAndInstallSdcardPackage(const std::string & miscFile,const std::vector<std::string> & packageName)72 bool RebootAndInstallSdcardPackage(const std::string &miscFile, const std::vector<std::string> &packageName)
73 {
74 struct UpdateMessage msg {};
75 int ret = snprintf_s(msg.update, sizeof(msg.update), sizeof(msg.update) - 1, "--sdcard_update\n");
76 if (ret < 0) {
77 LOG(ERROR) << "updaterkits: copy updater message failed";
78 return false;
79 }
80
81 if (packageName.size() != 0 && !AddPkgPath(msg, static_cast<size_t>(ret), packageName)) {
82 LOG(ERROR) << "get sdcard pkg path fail";
83 return false;
84 }
85 WriteToMiscAndRebootToUpdater(msg);
86
87 // Never get here.
88 return true;
89 }
90
RebootAndInstallUpgradePackage(const std::string & miscFile,const std::vector<std::string> & packageName)91 bool RebootAndInstallUpgradePackage(const std::string &miscFile, const std::vector<std::string> &packageName)
92 {
93 if (packageName.size() == 0) {
94 LOG(ERROR) << "updaterkits: invalid argument. one of arugments is empty";
95 return false;
96 }
97
98 for (auto path : packageName) {
99 if (path.find("--force_update_action=") != std::string::npos) {
100 continue;
101 }
102 if (access(path.c_str(), R_OK) < 0) {
103 LOG(ERROR) << "updaterkits: " << path << " is not readable";
104 return false;
105 }
106 }
107 struct UpdateMessage updateMsg {};
108 if (!AddPkgPath(updateMsg, 0, packageName)) {
109 return false;
110 }
111
112 WriteToMiscAndRebootToUpdater(updateMsg);
113
114 // Never get here.
115 return true;
116 }
117
RebootAndCleanUserData(const std::string & miscFile,const std::string & cmd)118 bool RebootAndCleanUserData(const std::string &miscFile, const std::string &cmd)
119 {
120 if (miscFile.empty() || cmd.empty()) {
121 LOG(ERROR) << "updaterkits: invalid argument. one of arugments is empty";
122 return false;
123 }
124
125 // Write package name to misc, then trigger reboot.
126 struct UpdateMessage updateMsg {};
127 if (strncpy_s(updateMsg.update, sizeof(updateMsg.update), cmd.c_str(), cmd.size()) != EOK) {
128 LOG(ERROR) << "updaterkits: copy updater message failed";
129 return false;
130 }
131
132 WriteToMiscAndRebootToUpdater(updateMsg);
133
134 // Never get here.
135 return true;
136 }
137