• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "module_utils.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <dirent.h>
20 #include <sys/mount.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <thread>
24 #include <fcntl.h>
25 #include "init_reboot.h"
26 #include "if_system_ability_manager.h"
27 #include "iremote_object.h"
28 #include "iservice_registry.h"
29 #include "directory_ex.h"
30 #include "log/log.h"
31 #include "package/package.h"
32 #include "parameter.h"
33 #include "parameters.h"
34 #include "singleton.h"
35 #include "utils.h"
36 #include "module_constants.h"
37 #include "module_file.h"
38 
39 namespace OHOS {
40 namespace SysInstaller {
41 using namespace Updater;
42 
43 namespace {
44 constexpr const char *BOOT_COMPLETE_PARAM = "bootevent.boot.completed";
45 constexpr const char *BOOT_SUCCESS_VALUE = "true";
46 constexpr int32_t PARAM_VALUE_SIZE = 10;
47 constexpr std::chrono::milliseconds WAIT_FOR_FILE_TIME(5);
48 constexpr uint32_t BYTE_SIZE = 8;
49 constexpr mode_t ALL_PERMISSIONS = 0777;
50 constexpr const char *PREFIXES[] = {UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR, UPDATE_BACKUP_DIR, MODULE_PREINSTALL_DIR};
51 }
52 
CreateDirIfNeeded(const std::string & path,mode_t mode)53 bool CreateDirIfNeeded(const std::string &path, mode_t mode)
54 {
55     struct stat statData;
56 
57     if (stat(path.c_str(), &statData) != 0) {
58         if (errno == ENOENT) {
59             if (mkdir(path.c_str(), mode) != 0) {
60                 LOG(ERROR) << "Could not mkdir " << path;
61                 return false;
62             }
63         } else {
64             LOG(ERROR) << "Could not stat " << path;
65             return false;
66         }
67     } else {
68         if (!S_ISDIR(statData.st_mode)) {
69             LOG(ERROR) << path << " exists and is not a directory";
70             return false;
71         }
72     }
73 
74     // Need to manually call chmod because mkdir will create a folder with
75     // permissions mode & ~umask.
76     if (chmod(path.c_str(), mode) != 0) {
77         LOG(WARNING) << "Could not chmod " << path;
78     }
79     return true;
80 }
81 
CheckPathExists(const std::string & path)82 bool CheckPathExists(const std::string &path)
83 {
84     struct stat buffer;
85     return stat(path.c_str(), &buffer) == 0;
86 }
87 
CheckFileSuffix(const std::string & file,const std::string & suffix)88 bool CheckFileSuffix(const std::string &file, const std::string &suffix)
89 {
90     std::size_t pos = file.find_last_of('.');
91     if (pos == std::string::npos) {
92         LOG(ERROR) << "Invalid file name " << file;
93         return false;
94     }
95     std::string fileSuffix = file.substr(pos);
96     return fileSuffix == suffix;
97 }
98 
GetFileName(const std::string & file)99 std::string GetFileName(const std::string &file)
100 {
101     std::size_t startPos = file.find_last_of('/') + 1;
102     std::size_t endPos = file.find_last_of('.');
103     return file.substr(startPos, endPos - startPos);
104 }
105 
106 // Get hmpName from path such as "/data/module_update_package/hmpName/sa1.zip"
GetHmpName(const std::string & filePath)107 std::string GetHmpName(const std::string &filePath)
108 {
109     std::size_t endPos = filePath.find_last_of('/');
110     if (endPos == std::string::npos) {
111         LOG(ERROR) << "Invalid package path " << filePath;
112         return "";
113     }
114 
115     std::size_t startPos = 0;
116     for (auto &iter : PREFIXES) {
117         if (StartsWith(filePath, iter)) {
118             startPos = strlen(iter) + 1;
119             break;
120         }
121     }
122     if (startPos == 0 || startPos >= endPos) {
123         LOG(ERROR) << "Invalid package path " << filePath;
124         return "";
125     }
126     return filePath.substr(startPos, endPos - startPos);
127 }
128 
WaitForFile(const std::string & path,const std::chrono::nanoseconds & timeout)129 bool WaitForFile(const std::string &path, const std::chrono::nanoseconds &timeout)
130 {
131     Timer timer;
132     bool hasSlept = false;
133     while (timer.duration() < timeout) {
134         struct stat buffer;
135         if (stat(path.c_str(), &buffer) != -1) {
136             if (hasSlept) {
137                 LOG(INFO) << "wait for '" << path << "' took " << timer;
138             }
139             return true;
140         }
141         std::this_thread::sleep_for(WAIT_FOR_FILE_TIME);
142         hasSlept = true;
143     }
144     LOG(ERROR) << "wait for '" << path << "' timed out and took " << timer;
145     return false;
146 }
147 
StartsWith(const std::string & str,const std::string & prefix)148 bool StartsWith(const std::string &str, const std::string &prefix)
149 {
150     return str.substr(0, prefix.size()) == prefix;
151 }
152 
ReadFullyAtOffset(int fd,uint8_t * data,size_t count,off_t offset)153 bool ReadFullyAtOffset(int fd, uint8_t *data, size_t count, off_t offset)
154 {
155     while (count > 0) {
156         ssize_t readSize = pread(fd, data, count, offset);
157         if (readSize <= 0) {
158             return false;
159         }
160         data += readSize;
161         count -= static_cast<size_t>(readSize);
162         offset += readSize;
163     }
164     return true;
165 }
166 
WriteFullyAtOffset(int fd,const uint8_t * data,size_t count,off_t offset)167 bool WriteFullyAtOffset(int fd, const uint8_t *data, size_t count, off_t offset)
168 {
169     while (count > 0) {
170         ssize_t writeSize = pwrite(fd, data, count, offset);
171         if (writeSize <= 0) {
172             return false;
173         }
174         data += writeSize;
175         count -= static_cast<size_t>(writeSize);
176         offset += writeSize;
177     }
178     return true;
179 }
180 
ReadLE16(const uint8_t * buff)181 uint16_t ReadLE16(const uint8_t *buff)
182 {
183     if (buff == nullptr) {
184         LOG(ERROR) << "buff is null";
185         return 0;
186     }
187     uint16_t value16 = buff[0];
188     value16 += static_cast<uint16_t>(buff[1] << BYTE_SIZE);
189     return value16;
190 }
191 
ReadLE32(const uint8_t * buff)192 uint32_t ReadLE32(const uint8_t *buff)
193 {
194     if (buff == nullptr) {
195         LOG(ERROR) << "buff is null";
196         return 0;
197     }
198     uint16_t low = ReadLE16(buff);
199     uint16_t high = ReadLE16(buff + sizeof(uint16_t));
200     uint32_t value = ((static_cast<uint32_t>(high)) << (BYTE_SIZE * sizeof(uint16_t))) | low;
201     return value;
202 }
203 
operator <<(std::ostream & os,const Timer & timer)204 std::ostream &operator<<(std::ostream &os, const Timer &timer)
205 {
206     os << timer.duration().count() << "ms";
207     return os;
208 }
209 
GetRealPath(const std::string & filePath)210 std::string GetRealPath(const std::string &filePath)
211 {
212     char path[PATH_MAX] = {'\0'};
213     if (realpath(filePath.c_str(), path) == nullptr) {
214         LOG(ERROR) << "get real path fail " << filePath;
215         return "";
216     }
217     if (!CheckPathExists(path)) {
218         LOG(ERROR) << "path " << path << " doesn't exist";
219         return "";
220     }
221     std::string realPath(path);
222     return realPath;
223 }
224 
MountModuleUpdateDir(void)225 __attribute__((weak)) void MountModuleUpdateDir(void)
226 {
227     LOG(INFO) << "mount /module_update.";
228     if (mount("tmpfs", "/module_update", "tmpfs", MS_NOEXEC | MS_NODEV | MS_NOSUID, "mode=0755") != 0) {
229         LOG(ERROR) << "mount module_Update tmpfs fail, " << strerror(errno);
230     }
231     if (mount(nullptr, "/module_update", nullptr, MS_SHARED, nullptr) != 0) {
232         LOG(ERROR) << "mount module_Update shared fail, " << strerror(errno);
233     }
234 }
235 
RevertImageCert(const std::string & hmpName,bool revertMore)236 __attribute__((weak)) bool RevertImageCert(const std::string &hmpName, bool revertMore)
237 {
238     LOG(INFO) << "Revert image cert, default is true";
239     return true;
240 }
241 
VerityInfoWrite(const ModuleFile & file)242 __attribute__((weak)) bool VerityInfoWrite(const ModuleFile &file)
243 {
244     LOG(INFO) << "VerityInfoWrite, default is true.";
245     return true;
246 }
247 
PrepareFileToDestDir(const std::string & pkgPath,const std::string & outPath)248 __attribute__((weak)) bool PrepareFileToDestDir(const std::string &pkgPath, const std::string &outPath)
249 {
250     if (ExtraPackageDir(pkgPath.c_str(), nullptr, nullptr, outPath.c_str()) != 0) {
251         LOG(ERROR) << "Failed to unpack hmp package " << pkgPath;
252         return false;
253     }
254     return true;
255 }
256 
SetModuleVersion(const ModuleFile & file)257 __attribute__((weak)) void SetModuleVersion(const ModuleFile &file)
258 {
259     LOG(INFO) << "Set module version.";
260 }
261 
Revert(const std::string & hmpName,bool reboot)262 void Revert(const std::string &hmpName, bool reboot)
263 {
264     LOG(INFO) << "RevertAndReboot, reboot: " << reboot << "; hmpName: " << hmpName;
265     std::string installPath = std::string(UPDATE_INSTALL_DIR) + "/" + hmpName;
266     if (CheckPathExists(installPath)) {
267         if (!ForceRemoveDirectory(installPath)) {
268             LOG(ERROR) << "Failed to remove installPath: " << installPath << " err=" << errno;
269             return;
270         }
271     }
272     struct stat statData;
273     std::string activePath = std::string(UPDATE_ACTIVE_DIR) + "/" + hmpName;
274     int ret = stat(activePath.c_str(), &statData);
275     if (ret != 0) {
276         LOG(ERROR) << "Failed to access " << activePath << " err=" << errno;
277         return;
278     }
279     if (!ForceRemoveDirectory(activePath)) {
280         LOG(ERROR) << "Failed to remove " << activePath << " err=" << errno;
281         return;
282     }
283 
284     std::string backupPath = std::string(UPDATE_BACKUP_DIR) + "/" + hmpName;
285     if (CheckPathExists(backupPath)) {
286         ret = rename(backupPath.c_str(), activePath.c_str());
287         if (ret != 0) {
288             LOG(ERROR) << "Failed to rename " << backupPath << " to " << activePath << " err=" << errno;
289         }
290         if (ret == 0 && chmod(activePath.c_str(), statData.st_mode & ALL_PERMISSIONS) != 0) {
291             LOG(ERROR) << "Failed to restore original permissions for " << activePath << " err=" << errno;
292         }
293     }
294     RevertImageCert(hmpName, true);
295     sync();
296     if (reboot) {
297         LOG(INFO) << "Rebooting";
298         DoReboot("module_update revert.");
299     }
300 }
301 
IsHotSa(int32_t saId)302 bool IsHotSa(int32_t saId)
303 {
304     std::vector<int32_t> onDemandSaIds;
305     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
306     if (samgr == nullptr) {
307         LOG(ERROR) << "get system ability manager error";
308         return false;
309     }
310     samgr->GetOnDemandSystemAbilityIds(onDemandSaIds);
311     if (onDemandSaIds.empty()) {
312         LOG(ERROR) << "get ondemand saIds fail";
313         return false;
314     }
315     if (find(onDemandSaIds.begin(), onDemandSaIds.end(), saId) == onDemandSaIds.end()) {
316         LOG(INFO) << "this is not an ondemand sa, saId=" << saId;
317         return false;
318     }
319     return true;
320 }
321 
IsRunning(int32_t saId)322 bool IsRunning(int32_t saId)
323 {
324     sptr<ISystemAbilityManager> samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
325     if (samgr == nullptr) {
326         LOG(ERROR) << "get system ability manager error";
327         return false;
328     }
329     auto object = samgr->CheckSystemAbility(saId);
330     if (object == nullptr) {
331         LOG(INFO) << "sa not exists, saId=" << saId;
332         return false;
333     }
334     return true;
335 }
336 
CheckBootComplete(void)337 bool CheckBootComplete(void)
338 {
339     char value[PARAM_VALUE_SIZE] = "";
340     int ret = GetParameter(BOOT_COMPLETE_PARAM, "", value, PARAM_VALUE_SIZE);
341     if (ret < 0) {
342         LOG(ERROR) << "Failed to get parameter " << BOOT_COMPLETE_PARAM;
343         return false;
344     }
345     return strcmp(value, BOOT_SUCCESS_VALUE) == 0;
346 }
347 
GetDeviceSaSdkVersion(void)348 std::string GetDeviceSaSdkVersion(void)
349 {
350     std::string sdkVersion = system::GetParameter("const.build.sa_sdk_version", "");
351     if (sdkVersion.empty()) {
352         LOG(ERROR) << "get device sa sdk version failed.";
353         return sdkVersion;
354     }
355     return sdkVersion;
356 }
357 
GetDeviceApiVersion(void)358 int GetDeviceApiVersion(void)
359 {
360     std::string apiVersion = system::GetParameter("const.ohos.apiversion", "");
361     if (apiVersion.empty()) {
362         LOG(ERROR) << "get device api version failed.";
363         return 0;
364     }
365     return Utils::String2Int<int>(apiVersion, Utils::N_DEC);
366 }
367 
GetContentFromZip(const std::string & zipPath,const std::string & fileName)368 std::string GetContentFromZip(const std::string &zipPath, const std::string &fileName)
369 {
370     ModuleZipHelper helper(zipPath);
371     if (!helper.IsValid()) {
372         LOG(ERROR) << "Failed to open file: " << zipPath;
373         return "";
374     }
375     std::string content;
376     if (!ExtractZipFile(helper, fileName, content)) {
377         LOG(ERROR) << "Failed to extract: " << fileName << " from package: " << zipPath;
378         return "";
379     }
380     return content;
381 }
382 
RemoveSpecifiedDir(const std::string & path,bool keepDir)383 bool RemoveSpecifiedDir(const std::string &path, bool keepDir)
384 {
385     if (!CheckPathExists(path)) {
386         return false;
387     }
388     LOG(INFO) << "Clear specified dir: " << path << "; keepdir: " << keepDir;
389     if (!keepDir) {
390         if (!ForceRemoveDirectory(path)) {
391             LOG(WARNING) << "Failed to remove: " << path << ", err: " << errno;
392             return false;
393         }
394         return true;
395     }
396     if (!std::filesystem::is_directory(path)) {
397         LOG(WARNING) << "The file is not a directory: " << path.c_str();
398         return false;
399     }
400     bool ret = true;
401     for (const auto &entry : std::filesystem::directory_iterator(path)) {
402         std::error_code errorCode;
403         LOG(INFO) << "deleted " << entry.path().c_str() << ";";
404         if (!std::filesystem::remove_all(entry.path(), errorCode)) {
405             LOG(ERROR) << "Failed to deleted " << entry.path().c_str() << "; errorCode: " << errorCode.value();
406             ret = false;
407         }
408     }
409     return ret;
410 }
411 
CheckAndUpdateRevertResult(const std::string & hmpPath,const std::string & resultInfo,const std::string & keyWord)412 bool CheckAndUpdateRevertResult(const std::string &hmpPath, const std::string &resultInfo, const std::string &keyWord)
413 {
414     if (resultInfo.find(keyWord) == std::string::npos) {
415         return false;
416     }
417     std::ifstream ifs { MODULE_RESULT_PATH };
418     if (!ifs.is_open()) {
419         LOG(ERROR) << "ifs open result_file fail" << strerror(errno);
420         return false;
421     }
422     std::string line;
423     std::vector<std::string> lines;
424     bool ret = false;
425     while (getline(ifs, line)) {
426         if (line.find(hmpPath) == std::string::npos) {
427             lines.push_back(line);
428             continue;
429         }
430         std::vector<std::string> results = Utils::SplitString(line, ";");
431         if (results.size() < 3) {  // 3: hmp|result|msg
432             LOG(ERROR) << "Split result fail: " << line;
433             continue;
434         }
435         if (results[1] != "0") {  // 1: index of result
436             lines.push_back(line);
437             continue;
438         }
439         ret = true;
440         lines.push_back(resultInfo);
441     }
442     ifs.close();
443     std::ofstream outfile(MODULE_RESULT_PATH, std::ios::binary | std::ios::trunc);
444     if (!outfile) {
445         LOG(ERROR) << "ofs open result_file fail" << strerror(errno);
446         return false;
447     }
448     for (const auto &info : lines) {
449         outfile << info;
450     }
451     LOG(INFO) << "Update revert result succ";
452     sync();
453     return ret;
454 }
455 
GetCurrentHmpName(void)456 std::string GetCurrentHmpName(void)
457 {
458     std::vector<std::string> files;
459     GetDirFiles(MODULE_PREINSTALL_DIR, files);
460     for (const auto &file : files) {
461         if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
462             continue;
463         }
464         std::string hmpName = GetHmpName(file);
465         if (hmpName.empty()) {
466             continue;
467         }
468         return hmpName;
469     }
470     return "";
471 }
472 
NotifyBmsRevert(const std::string & hmpName,bool record)473 int32_t NotifyBmsRevert(const std::string &hmpName, bool record)
474 {
475     LOG(INFO) << "Start to collect module name which contains hap or hsp";
476     SetParameter(BMS_START_INSTALL, NOTIFY_BMS_REVERT);
477     std::string preInstalledPath = std::string(MODULE_PREINSTALL_DIR) + "/" + hmpName + "/" + HMP_INFO_NAME;
478     std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(preInstalledPath);
479     if (moduleFile == nullptr) {
480         LOG(ERROR) << "Invalid preinstalled file " << preInstalledPath;
481         return -1;
482     }
483     int32_t result = 0;
484     std::ostringstream oss;
485     oss << BMS_START_INSTALL << "=" << NOTIFY_BMS_REVERT << "\n";
486     for (const auto &[key, value] : moduleFile->GetVersionInfo().moduleMap) {
487         if (value.bundleInfoList.empty()) {
488             continue;
489         }
490         std::string attr = std::string(BMS_RESULT_PREFIX) + "." + key;
491         if (!record && SetParameter(attr.c_str(), BMS_INSTALL_FAIL) != 0) {
492             LOG(WARNING) << "Failed to set module params: " << attr;
493             result++;
494         }
495         oss << attr << "=" << BMS_INSTALL_FAIL << "\n";
496     }
497     if (record) {
498         WriteStringToFile(MODULE_UPDATE_PARAMS_FILE, oss.str());
499     }
500     return result;
501 }
502 
WriteStringToFile(const std::string & filePath,const std::string & content)503 int32_t WriteStringToFile(const std::string &filePath, const std::string &content)
504 {
505     // if file not exist, create file or appead
506     std::ofstream file (filePath, std::ios::app);
507     if (!file.is_open()) {
508         LOG(ERROR) << "open file fail: " << filePath << "; err is " << strerror(errno);
509         return -1;
510     }
511     file << content;
512     if (file.bad()) {
513         LOG(ERROR) << "write to file fail, " << filePath;
514     }
515     file.close();
516     sync();
517     return 0;
518 }
519 } // namespace SysInstaller
520 } // namespace OHOS