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 <chrono>
16 #include <dirent.h>
17 #include <fcntl.h>
18 #include <sys/mount.h>
19 #include <sys/stat.h>
20 #include <sys/statvfs.h>
21
22 #include "applypatch/partition_record.h"
23 #include "flashd/flashd.h"
24 #include "log/log.h"
25 #include "misc_info/misc_info.h"
26 #include "package/pkg_manager.h"
27 #include "securec.h"
28 #include "updater/updater.h"
29 #include "updater/updater_const.h"
30 #include "updater_ui.h"
31 #include "utils.h"
32
33 namespace Updater {
34 using namespace Hpackage;
35 using namespace Updater::Utils;
36
DeleteUpdaterPath(const std::string & path)37 bool DeleteUpdaterPath(const std::string &path)
38 {
39 auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
40 if (pDir == nullptr) {
41 LOG(INFO) << "Can not open dir";
42 return true;
43 }
44 struct dirent *dp = nullptr;
45 while ((dp = readdir(pDir.get())) != nullptr) {
46 std::string currentName(dp->d_name);
47 if (currentName[0] != '.' && (currentName.compare("log") != 0) &&
48 (currentName.compare(UPDATER_RESULT_FILE) != 0) &&
49 (currentName.compare(UPDATER_LOCALE_FILE) != 0)) {
50 std::string tmpName(path);
51 tmpName.append("/" + currentName);
52 if (IsDirExist(tmpName)) {
53 DeleteUpdaterPath(tmpName);
54 }
55 #ifndef UPDATER_UT
56 remove(tmpName.c_str());
57 #endif
58 }
59 }
60 return true;
61 }
62
ClearMisc()63 bool ClearMisc()
64 {
65 struct UpdateMessage cleanBoot {};
66 if (!WriteUpdaterMiscMsg(cleanBoot)) {
67 LOG(ERROR) << "ClearMisc clear boot message to misc failed";
68 return false;
69 }
70 auto miscBlockDev = GetBlockDeviceByMountPoint(MISC_PATH);
71 if (miscBlockDev.empty()) {
72 LOG(INFO) << "cannot get block device of partition";
73 miscBlockDev = MISC_FILE;
74 }
75 LOG(INFO) << "ClearMisc::misc path : " << miscBlockDev;
76 auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(miscBlockDev.c_str(), "rb+"), fclose);
77 if (fp == nullptr) {
78 LOG(ERROR) << "WriteVersionCode fopen failed" << " : " << strerror(errno);
79 return false;
80 }
81 if (fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET) != 0) {
82 LOG(ERROR) << "ClearMisc fseek failed";
83 return false;
84 }
85 off_t clearOffset = 0;
86 if (fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) != 1) {
87 LOG(ERROR) << "ClearMisc write misc initOffset 0 failed" << " : " << strerror(errno);
88 return false;
89 }
90
91 struct PartitionRecordInfo cleanPartition {};
92 for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
93 sizeof(PartitionRecordInfo)) {
94 if (fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET) != 0) {
95 LOG(ERROR) << "ClearMisc fseek failed";
96 return false;
97 }
98 if (fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) != 1) {
99 LOG(ERROR) << "ClearMisc write misc cleanPartition failed" << " : " << strerror(errno);
100 return false;
101 }
102 }
103 return true;
104 }
105
IsSDCardExist(const std::string & sdcardPath)106 bool IsSDCardExist(const std::string &sdcardPath)
107 {
108 // Record system error codes.
109 int save_errno = errno;
110 struct stat st {};
111 if (stat(sdcardPath.c_str(), &st) < 0) {
112 return false;
113 } else {
114 errno = save_errno;
115 return true;
116 }
117 }
118
PostUpdater(bool clearMisc)119 void PostUpdater(bool clearMisc)
120 {
121 STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
122 std::string updaterLogPath = UPDATER_LOG;
123 std::string stageLogPath = UPDATER_STAGE_LOG;
124 std::string errorCodePath = ERROR_CODE_PATH;
125
126 (void)SetupPartitions();
127 // clear update misc partition.
128 if (clearMisc) {
129 UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed");
130 }
131 if (!access(COMMAND_FILE, 0)) {
132 UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE) == 0, "Delete command failed");
133 }
134
135 // delete updater tmp files
136 if (access(UPDATER_PATH, 0) == 0 && access(SDCARD_CARD_PATH, 0) != 0) {
137 UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed");
138 }
139 if (!access(SDCARD_CARD_PATH, 0)) {
140 UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed");
141 }
142 if (access(Flashd::FLASHD_FILE_PATH, 0) == 0) {
143 UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(Flashd::FLASHD_FILE_PATH), "DeleteUpdaterPath failed");
144 }
145
146 // save logs
147 bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath);
148 UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy updater log failed!");
149 ret = CopyUpdaterLogs(TMP_ERROR_CODE_PATH, errorCodePath);
150 UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error code log failed!");
151 ret = CopyUpdaterLogs(Flashd::FLASHD_HDC_LOG_PATH, UPDATER_HDC_LOG);
152 UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error hdc log failed!");
153
154 mode_t mode = 0640;
155 chmod(updaterLogPath.c_str(), mode);
156 chmod(UPDATER_HDC_LOG, mode);
157 chmod(errorCodePath.c_str(), mode);
158 STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater";
159 ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath);
160 chmod(stageLogPath.c_str(), mode);
161 UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy stage log failed!");
162 }
163
ParseParams(int argc,char ** argv)164 std::vector<std::string> ParseParams(int argc, char **argv)
165 {
166 struct UpdateMessage boot {};
167 // read from misc
168 if (!ReadUpdaterMiscMsg(boot)) {
169 LOG(ERROR) << "ReadUpdaterMessage MISC_FILE failed!";
170 }
171 // if boot.update is empty, read from command.The Misc partition may have dirty data,
172 // so strlen(boot.update) is not used, which can cause system exceptions.
173 if (boot.update[0] == '\0' && !access(COMMAND_FILE, 0)) {
174 if (!ReadUpdaterMessage(COMMAND_FILE, boot)) {
175 LOG(ERROR) << "ReadUpdaterMessage COMMAND_FILE failed!";
176 }
177 }
178 STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update;
179 std::vector<std::string> parseParams(argv, argv + argc);
180 boot.update[sizeof(boot.update) - 1] = '\0';
181 std::vector<std::string> parseParams1 = Utils::SplitString(boot.update, "\n");
182 parseParams.insert(parseParams.end(), parseParams1.begin(), parseParams1.end());
183 return parseParams;
184 }
185
GetBootMode(int & mode)186 int GetBootMode(int &mode)
187 {
188 #ifndef UPDATER_UT
189 mode = BOOT_UPDATER;
190 #else
191 mode = BOOT_FLASHD;
192 #endif
193 struct UpdateMessage boot {};
194 // read from misc
195 bool ret = ReadUpdaterMiscMsg(boot);
196 if (!ret) {
197 return -1;
198 }
199
200 LOG(INFO) << "GetBootMode, boot.update" << boot.update;
201 if (strncmp(boot.update, "boot_flash", strlen("boot_flash")) == 0) {
202 mode = BOOT_FLASHD;
203 }
204 return 0;
205 }
206 } // namespace Updater
207