• 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 #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 {
34 static constexpr int USER_ROOT_AUTHORITY = 0;
35 static constexpr int GROUP_SYS_AUTHORITY = 1000;
36 }
37 namespace updater {
38 using namespace hpackage;
39 using namespace updater::utils;
CompressLogs(const std::string & name)40 void CompressLogs(const std::string &name)
41 {
42     PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance();
43     UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return);
44     std::vector<std::pair<std::string, ZipFileInfo>> files;
45     // Build the zip file to be packaged
46     std::vector<std::string> testFileNames;
47     std::string realName = name.substr(name.find_last_of("/") + 1);
48     testFileNames.push_back(realName);
49     for (auto name : testFileNames) {
50         ZipFileInfo file;
51         file.fileInfo.identity = name;
52         file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
53         file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
54         std::string fileName = "/data/updater/log/" + name;
55         files.push_back(std::pair<std::string, ZipFileInfo>(fileName, file));
56     }
57 
58     PkgInfo pkgInfo;
59     pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
60     pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256;
61     pkgInfo.pkgType = PKG_PACK_TYPE_ZIP;
62 
63     char realTime[MAX_TIME_SIZE] = { 0 };
64     auto sysTime = std::chrono::system_clock::now();
65     auto currentTime = std::chrono::system_clock::to_time_t(sysTime);
66     struct tm *localTime = std::localtime(&currentTime);
67     if (localTime != nullptr) {
68         std::strftime(realTime, sizeof(realTime), "%H_%M_%S", localTime);
69     }
70     char pkgName[MAX_LOG_NAME_SIZE];
71     UPDATER_CHECK_ONLY_RETURN(snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1,
72         "/data/updater/log/%s_%s.zip", realName.c_str(), realTime) != -1, return);
73     int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files);
74     UPDATER_CHECK_ONLY_RETURN(ret != 0, return);
75     UPDATER_CHECK_ONLY_RETURN(DeleteFile(name) == 0, return);
76 }
77 
CopyUpdaterLogs(const std::string & sLog,const std::string & dLog)78 bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog)
79 {
80     UPDATER_WARING_CHECK(MountForPath(UPDATER_LOG_DIR) == 0, "MountForPath /data/log failed!", return false);
81     if (access(UPDATER_LOG_DIR.c_str(), 0) != 0) {
82         UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_LOG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH),
83             "MkdirRecursive error!", return false);
84         UPDATER_ERROR_CHECK(chown(UPDATER_PATH.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY) == 0,
85             "Chown failed!", return false);
86         UPDATER_ERROR_CHECK(chmod(UPDATER_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0,
87             "Chmod failed!", return false);
88     }
89 
90     FILE *dFp = fopen(dLog.c_str(), "ab+");
91     UPDATER_ERROR_CHECK(dFp != nullptr, "open log failed", return false);
92 
93     FILE *sFp = fopen(sLog.c_str(), "r");
94     UPDATER_ERROR_CHECK(sFp != nullptr, "open log failed", fclose(dFp);
95         return false);
96 
97     char buf[MAX_LOG_BUF_SIZE];
98     size_t bytes;
99     while ((bytes = fread(buf, 1, sizeof(buf), sFp)) != 0) {
100         int ret = fwrite(buf, 1, bytes, dFp);
101         if (ret < 0) {
102             break;
103         }
104     }
105     (void)fseek(dFp, 0, SEEK_END);
106     UPDATER_INFO_CHECK(ftell(dFp) < MAX_LOG_SIZE, "log size greater than 5M!", CompressLogs(dLog));
107     sync();
108     (void)fclose(sFp);
109     (void)fclose(dFp);
110     return true;
111 }
112 
IsDir(const std::string & path)113 static bool IsDir(const std::string &path)
114 {
115     struct stat st {};
116     if (stat(path.c_str(), &st) < 0) {
117         return false;
118     }
119     return S_ISDIR(st.st_mode);
120 }
121 
DeleteUpdaterPath(const std::string & path)122 static bool DeleteUpdaterPath(const std::string &path)
123 {
124     auto pDir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(path.c_str()), closedir);
125     UPDATER_INFO_CHECK_NOT_RETURN(pDir != nullptr, "Can not open dir");
126     if (pDir == nullptr) {
127         return true;
128     }
129     struct dirent *dp = nullptr;
130     while ((dp = readdir(pDir.get())) != nullptr) {
131         std::string currentName(dp->d_name);
132         if (currentName[0] != '.' && (currentName.compare("log") != 0)) {
133             std::string tmpName(path);
134             tmpName.append("/" + currentName);
135             if (IsDir(tmpName)) {
136                 DeleteUpdaterPath(tmpName);
137             }
138 #ifndef UPDATER_UT
139             remove(tmpName.c_str());
140 #endif
141         }
142     }
143     return true;
144 }
145 
ClearMisc()146 static bool ClearMisc()
147 {
148     struct UpdateMessage cleanBoot {};
149     UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true,
150         "ClearMisc clear boot message to misc failed", return false);
151     auto fp = std::unique_ptr<FILE, decltype(&fclose)>(fopen(MISC_FILE.c_str(), "rb+"), fclose);
152     UPDATER_FILE_CHECK(fp != nullptr, "WriteVersionCode fopen failed", return false);
153     (void)fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET);
154     off_t clearOffset = 0;
155     UPDATER_FILE_CHECK(fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) == 1,
156         "ClearMisc write misc initOffset 0 failed", return false);
157 
158     struct PartitionRecordInfo cleanPartition {};
159     for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset +=
160         sizeof(PartitionRecordInfo)) {
161         (void)fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET);
162         UPDATER_FILE_CHECK(fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) == 1,
163             "ClearMisc write misc cleanPartition failed", return false);
164     }
165     return true;
166 }
167 
IsSDCardExist(const std::string & sdcardPath)168 bool IsSDCardExist(const std::string &sdcardPath)
169 {
170     // Record system error codes.
171     int save_errno = errno;
172     struct stat st {};
173     if (stat(sdcardPath.c_str(), &st) < 0) {
174         return false;
175     } else {
176         errno = save_errno;
177         return true;
178     }
179 }
180 
PostUpdaterForSdcard(std::string & updaterLogPath,std::string & stageLogPath,std::string & errorCodePath)181 void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath, std::string &errorCodePath)
182 {
183     if (SetupPartitions() != 0) {
184         ShowText(GetUpdateInfoLabel(), "Mount data failed.");
185         LOG(ERROR) << "Mount for /data failed.";
186         std::string sdcardPath = GetBlockDeviceByMountPoint(SDCARD_PATH);
187         if (IsSDCardExist(sdcardPath)) {
188             if (MountForPath(SDCARD_PATH) != 0) {
189                 int ret = mount(sdcardPath.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL);
190                 UPDATER_WARING_CHECK(ret == 0, "Mount for /sdcard failed!", return);
191             }
192             updaterLogPath = "/sdcard/updater/log/updater_log";
193             stageLogPath = "/sdcard/updater/log/updater_stage_log";
194             errorCodePath = "/sdcard/updater/log/error_code.log";
195         }
196     }
197     return;
198 }
199 
PostUpdater(bool clearMisc)200 void PostUpdater(bool clearMisc)
201 {
202     STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater";
203     std::string updaterLogPath = "/data/updater/log/updater_log";
204     std::string stageLogPath = "/data/updater/log/updater_stage_log";
205     std::string errorCodePath = "/data/updater/log/error_code.log";
206     PostUpdaterForSdcard(updaterLogPath, stageLogPath, errorCodePath);
207     // clear update misc partition.
208     if (clearMisc) {
209         UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed");
210     }
211     if (!access(COMMAND_FILE.c_str(), 0)) {
212         UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE.c_str()) == 0, "Delete command failed");
213     }
214 
215     // delete updater tmp files
216     if (access(UPDATER_PATH.c_str(), 0) == 0 && access(SDCARD_CARD_PATH.c_str(), 0) != 0) {
217         UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed");
218     }
219     if (!access(SDCARD_CARD_PATH.c_str(), 0)) {
220         UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed");
221     }
222     if (access(flashd::FLASHD_FILE_PATH.c_str(), 0) == 0) {
223         UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(flashd::FLASHD_FILE_PATH), "DeleteUpdaterPath failed");
224     }
225 
226     // save logs
227     bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath);
228     UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy updater log failed!");
229     ret = CopyUpdaterLogs(TMP_ERROR_CODE_PATH, errorCodePath);
230     UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error code log failed!");
231     ret = CopyUpdaterLogs(flashd::FLASHD_HDC_LOG_PATH, UPDATER_HDC_LOG);
232     UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error hdc log failed!");
233 
234     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
235     chmod(updaterLogPath.c_str(), mode);
236     chmod(stageLogPath.c_str(), mode);
237     chmod(errorCodePath.c_str(), mode);
238     STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater";
239     ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath);
240     UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy stage log failed!");
241 }
242 
IsSpaceCapacitySufficient(const std::string & packagePath)243 int IsSpaceCapacitySufficient(const std::string &packagePath)
244 {
245     hpackage::PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
246     UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT);
247     std::vector<std::string> fileIds;
248     int ret = pkgManager->LoadPackageWithoutUnPack(packagePath, fileIds);
249     UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "LoadPackageWithoutUnPack failed",
250         PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT);
251     const FileInfo *info = pkgManager->GetFileInfo("update.bin");
252     UPDATER_ERROR_CHECK(info != nullptr, "update.bin is not exist",
253         PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT);
254     uint64_t needSpace = static_cast<uint64_t>(info->unpackedSize);
255     PkgManager::ReleasePackageInstance(pkgManager);
256 
257     struct statvfs64 updaterVfs {};
258     if (strncmp(packagePath.c_str(), SDCARD_CARD_PATH.c_str(), SDCARD_CARD_PATH.size()) == 0) { // for sdcard
259         ret = statvfs64(SDCARD_PATH.c_str(), &updaterVfs);
260         UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /sdcard error!", return UPDATE_ERROR);
261     } else {
262         needSpace += MAX_LOG_SPACE;
263         ret = statvfs64(UPDATER_PATH.c_str(), &updaterVfs);
264         UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /data error!", return UPDATE_ERROR);
265     }
266     auto freeSpaceSize = static_cast<uint64_t>(updaterVfs.f_bfree);
267     auto blockSize = static_cast<uint64_t>(updaterVfs.f_bsize);
268     uint64_t totalFreeSize = freeSpaceSize * blockSize;
269     UPDATER_ERROR_CHECK(totalFreeSize > needSpace,
270         "Can not update, free space is not enough", return UPDATE_SPACE_NOTENOUGH);
271     return UPDATE_SUCCESS;
272 }
273 
ParseParams(int argc,char ** argv)274 std::vector<std::string> ParseParams(int argc, char **argv)
275 {
276     struct UpdateMessage boot {};
277     // read from misc
278     UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(MISC_FILE, boot) == true,
279         "ReadUpdaterMessage MISC_FILE failed!");
280     // if boot.update is empty, read from command.The Misc partition may have dirty data,
281     // so strlen(boot.update) is not used, which can cause system exceptions.
282     if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) {
283         UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(COMMAND_FILE, boot) == true,
284                                        "ReadUpdaterMessage COMMAND_FILE failed!");
285     }
286     STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update;
287     std::vector<std::string> parseParams(argv, argv + argc);
288     boot.update[sizeof(boot.update) - 1] = '\0';
289     std::vector<std::string> parseParams1 = utils::SplitString(boot.update, "\n");
290     parseParams.insert(parseParams.end(), parseParams1.begin(), parseParams1.end());
291     return parseParams;
292 }
293 
GetBootMode(int & mode)294 int GetBootMode(int &mode)
295 {
296 #ifndef UPDATER_UT
297     mode = BOOT_UPDATER;
298 #else
299     mode = BOOT_FLASHD;
300 #endif
301     struct UpdateMessage boot {};
302     // read from misc
303     bool ret = ReadUpdaterMessage(MISC_FILE, boot);
304     if (!ret) {
305         return -1;
306     }
307     // if boot.update is empty, read from command.The Misc partition may have dirty data,
308     // so strlen(boot.update) is not used, which can cause system exceptions.
309     if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) {
310         ret = ReadUpdaterMessage(COMMAND_FILE, boot);
311         if (!ret) {
312             return -1;
313         }
314     }
315     if (memcmp(boot.command, "boot_flash", strlen("boot_flash")) == 0) {
316         mode = BOOT_FLASHD;
317     }
318     return 0;
319 }
320 } // namespace updater
321