1 /*
2 * Copyright (c) 2022 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 "update_commander.h"
17
18 #include <unordered_map>
19
20 #include "datetime_ex.h"
21 #include "flashd_define.h"
22 #include "flashd_utils.h"
23 #include "fs_manager/mount.h"
24 #include "package/pkg_manager.h"
25 #include "updater/updater.h"
26 #include "updater/updater_const.h"
27 #include "updaterkits/updaterkits.h"
28 #include "utils.h"
29
30 namespace Flashd {
31 namespace {
32 constexpr size_t CMD_PARAM_COUNT_MIN = 1;
33 }
34
~UpdateCommander()35 UpdateCommander::~UpdateCommander()
36 {
37 SafeCloseFile(fd_);
38 }
39
DoCommand(const std::string & cmdParam,size_t fileSize)40 void UpdateCommander::DoCommand(const std::string &cmdParam, size_t fileSize)
41 {
42 FLASHD_LOGI("start to update");
43 startTime_ = OHOS::GetMicroTickCount();
44 auto params = Split(cmdParam, { "-f" });
45 if (params.size() < CMD_PARAM_COUNT_MIN) {
46 FLASHD_LOGE("update param count is %u, not invaild", params.size());
47 NotifyFail(CmdType::UPDATE);
48 return;
49 }
50
51 if (auto ret = Updater::MountForPath(GetPathRoot(FLASHD_FILE_PATH)); ret != 0) {
52 FLASHD_LOGE("MountForPath fail, ret = %d", ret);
53 NotifyFail(CmdType::UPDATE);
54 return;
55 }
56
57 if (access(FLASHD_FILE_PATH, F_OK) == -1) {
58 mkdir(FLASHD_FILE_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
59 }
60
61 fileSize_ = fileSize;
62 filePath_ = FLASHD_FILE_PATH + GetFileName(cmdParam);
63 fd_ = open(filePath_.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
64 if (fd_ < 0) {
65 NotifyFail(CmdType::UPDATE);
66 FLASHD_LOGE("open file fail, errno = %d ", errno);
67 return;
68 }
69 }
70
DoCommand(const uint8_t * payload,int payloadSize)71 void UpdateCommander::DoCommand(const uint8_t *payload, int payloadSize)
72 {
73 if (payload == nullptr || payloadSize <= 0) {
74 NotifyFail(CmdType::UPDATE);
75 FLASHD_LOGE("payload is null or payloadSize is invaild");
76 return;
77 }
78
79 if (!DoUpdate(payload, payloadSize)) {
80 NotifyFail(CmdType::UPDATE);
81 return;
82 }
83 }
84
DoUpdate(const uint8_t * payload,int payloadSize)85 bool UpdateCommander::DoUpdate(const uint8_t *payload, int payloadSize)
86 {
87 if (fd_ < 0) {
88 FLASHD_LOGE("file fd is invaild");
89 return false;
90 }
91
92 auto writeSize = std::min(static_cast<size_t>(payloadSize), fileSize_ - currentSize_);
93 if (writeSize <= 0) {
94 FLASHD_LOGW("all the data has been written");
95 return true;
96 }
97
98 if (!Updater::Utils::WriteFully(fd_, payload, writeSize)) {
99 FLASHD_LOGE("WriteFully fail, errno = %d", errno);
100 return false;
101 }
102
103 currentSize_ += writeSize;
104 if (currentSize_ >= fileSize_) {
105 fsync(fd_);
106 SafeCloseFile(fd_);
107 auto useSec = static_cast<double>(OHOS::GetMicroTickCount() - startTime_) / OHOS::SEC_TO_MICROSEC;
108 FLASHD_LOGI("update write file success, size = %u bytes, %.3lf s", fileSize_, useSec);
109 NotifySuccess(CmdType::UPDATE);
110 return true;
111 }
112 UpdateProgress(CmdType::UPDATE);
113 return true;
114 }
115
ExecUpdate() const116 bool UpdateCommander::ExecUpdate() const
117 {
118 const std::string miscFile = "/dev/block/by-name/misc";
119 std::vector<std::string> filePath;
120 filePath.push_back(filePath_);
121 if (RebootAndInstallUpgradePackage(miscFile, filePath) == 0) {
122 return true;
123 }
124 return false;
125 }
126
PostCommand()127 void UpdateCommander::PostCommand()
128 {
129 SaveLog();
130 if (!ExecUpdate()) {
131 FLASHD_LOGE("ExecUpdate failed");
132 }
133 }
134
SaveLog() const135 void UpdateCommander::SaveLog() const
136 {
137 const std::unordered_map<std::string, std::string> logMap = {
138 { Updater::TMP_LOG, Updater::UPDATER_LOG },
139 { Updater::TMP_ERROR_CODE_PATH, Updater::ERROR_CODE_PATH },
140 { FLASHD_HDC_LOG_PATH, Updater::UPDATER_HDC_LOG },
141 { Updater::TMP_STAGE_LOG, Updater::UPDATER_STAGE_LOG },
142 };
143 constexpr mode_t mode = 0640;
144
145 for (const auto &iter : logMap) {
146 if (!Updater::Utils::CopyUpdaterLogs(iter.first, iter.second)) {
147 FLASHD_LOGW("Copy %s failed!", GetFileName(iter.second).c_str());
148 }
149 chmod((iter.second).c_str(), mode);
150 }
151 }
152 } // namespace Flashd