• 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 "applypatch/transfer_manager.h"
16 #include <fcntl.h>
17 #include <sstream>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include "applypatch/command_function.h"
21 #include "log/log.h"
22 #include "utils.h"
23 
24 namespace Updater {
25 using namespace Updater::Utils;
26 static TransferManagerPtr g_transferManagerInstance = nullptr;
GetTransferManagerInstance()27 TransferManagerPtr TransferManager::GetTransferManagerInstance()
28 {
29     if (g_transferManagerInstance == nullptr) {
30         g_transferManagerInstance = new TransferManager();
31         g_transferManagerInstance->Init();
32     }
33     return g_transferManagerInstance;
34 }
35 
ReleaseTransferManagerInstance(TransferManagerPtr transferManager)36 void TransferManager::ReleaseTransferManagerInstance(TransferManagerPtr transferManager)
37 {
38     delete transferManager;
39     g_transferManagerInstance = nullptr;
40     transferManager = nullptr;
41 }
42 
~TransferManager()43 TransferManager::~TransferManager()
44 {
45     if (globalParams != nullptr) {
46         if (globalParams->writerThreadInfo != nullptr) {
47             globalParams->writerThreadInfo.reset();
48         }
49         globalParams.reset();
50     }
51 }
52 
CommandsParser(int fd,const std::vector<std::string> & context)53 bool TransferManager::CommandsParser(int fd, const std::vector<std::string> &context)
54 {
55     UPDATER_ERROR_CHECK(context.size() >= 1, "too small context in transfer file", return false);
56     UPDATER_ERROR_CHECK(globalParams != nullptr, "globalParams is nullptr", return false);
57     std::vector<std::string>::const_iterator ct = context.begin();
58     globalParams->version = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
59     globalParams->blockCount = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
60     globalParams->maxEntries = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
61     globalParams->maxBlocks = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
62     size_t totalSize = globalParams->blockCount;
63     std::string retryCmd = "";
64     if (globalParams->env != nullptr && globalParams->env->IsRetry()) {
65         retryCmd = ReloadForRetry();
66     }
67     std::unique_ptr<Command> cmd;
68     size_t initBlock = 0;
69     for (; ct != context.end(); ct++) {
70         cmd = std::make_unique<Command>();
71         UPDATER_ERROR_CHECK(cmd != nullptr, "Failed to parse command line.", return false);
72         if (!cmd->Init(*ct) || cmd->GetCommandType() == CommandType::LAST || globalParams->env == nullptr) {
73             continue;
74         }
75         if (!retryCmd.empty() && globalParams->env->IsRetry()) {
76             if (*ct == retryCmd) {
77                 retryCmd.clear();
78             }
79             if (cmd->GetCommandType() != CommandType::NEW) {
80                 LOG(INFO) << "Retry: Command " << *ct << " passed";
81                 continue;
82             }
83         }
84         cmd->SetFileDescriptor(fd);
85         std::unique_ptr<CommandFunction> cf = CommandFunctionFactory::GetCommandFunction(cmd->GetCommandType());
86         UPDATER_ERROR_CHECK(cf != nullptr, "Failed to get cmd exec", return false);
87         CommandResult ret = cf->Execute(const_cast<Command &>(*cmd.get()));
88         CommandFunctionFactory::ReleaseCommandFunction(cf);
89         if (CheckResult(ret, cmd->GetCommandLine(), cmd->GetCommandType()) == false) {
90             return false;
91         }
92         if (initBlock == 0) {
93             initBlock = globalParams->written;
94         }
95         if (totalSize != 0 && globalParams->env != nullptr && NeedSetProgress(cmd->GetCommandType())) {
96             globalParams->env->PostMessage("set_progress",
97                 std::to_string((static_cast<double>(globalParams->written) - initBlock) / totalSize));
98         }
99         LOG(INFO) << "Running command : " << cmd->GetArgumentByPos(0) << " success";
100     }
101     return true;
102 }
103 
Init()104 void TransferManager::Init()
105 {
106     globalParams = std::make_unique<GlobalParams>();
107     globalParams->writerThreadInfo = std::make_unique<WriterThreadInfo>();
108     blocksetMap.clear();
109 }
110 
RegisterForRetry(const std::string & cmd)111 bool TransferManager::RegisterForRetry(const std::string &cmd)
112 {
113     std::string path = globalParams->retryFile;
114     int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
115     if (fd == -1) {
116         LOG(ERROR) << "Failed to create";
117         return false;
118     }
119     if (fchown(fd, O_USER_GROUP_ID, O_USER_GROUP_ID) != 0) {
120         LOG(ERROR) << "Failed to chown";
121         close(fd);
122         return -1;
123     }
124     bool ret = Utils::WriteStringToFile(fd, cmd);
125     if (ret == false) {
126         LOG(ERROR) << "Write retry flag error";
127     }
128     fsync(fd);
129     close(fd);
130     return ret;
131 }
132 
ReloadForRetry() const133 std::string TransferManager::ReloadForRetry() const
134 {
135     std::string path = globalParams->retryFile;
136     int fd = open(path.c_str(), O_RDONLY);
137     if (fd < 0) {
138         LOG(ERROR) << "Failed to open";
139         return "";
140     }
141     (void)lseek(fd, 0, SEEK_SET);
142     std::string cmd = "";
143     if (!Utils::ReadFileToString(fd, cmd)) {
144         LOG(ERROR) << "Error to read retry flag";
145     }
146     close(fd);
147     return cmd;
148 }
149 
NeedSetProgress(const CommandType & type)150 bool TransferManager::NeedSetProgress(const CommandType &type)
151 {
152     return type == CommandType::NEW ||
153         type == CommandType::IMGDIFF ||
154         type == CommandType::BSDIFF ||
155         type == CommandType::ZERO;
156 }
157 
CheckResult(const CommandResult result,const std::string & cmd,const CommandType & type)158 bool TransferManager::CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type)
159 {
160     switch (result) {
161         case SUCCESS:
162             if (type != CommandType::NEW) {
163                 RegisterForRetry(cmd);
164             }
165             break;
166         case NEED_RETRY:
167             LOG(INFO) << "Running command need retry!";
168             if (globalParams->env != nullptr) {
169                 globalParams->env->PostMessage("retry_update", cmd);
170             }
171             return false;
172         case FAILED:
173         default:
174             LOG(ERROR) << "Running command failed";
175             return false;
176     }
177     return true;
178 }
179 } // namespace Updater
180