• 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 
CommandsExecute(int fd,Command & cmd)53 bool TransferManager::CommandsExecute(int fd, Command &cmd)
54 {
55     cmd.SetFileDescriptor(fd);
56     std::unique_ptr<CommandFunction> cf = CommandFunctionFactory::GetCommandFunction(cmd.GetCommandType());
57     if (cf == nullptr) {
58         LOG(ERROR) << "Failed to get cmd exec";
59         return false;
60     }
61     CommandResult ret = cf->Execute(cmd);
62     CommandFunctionFactory::ReleaseCommandFunction(cf);
63     if (!CheckResult(ret, cmd.GetCommandLine(), cmd.GetCommandType())) {
64         return false;
65     }
66     return true;
67 }
68 
CommandsParser(int fd,const std::vector<std::string> & context)69 bool TransferManager::CommandsParser(int fd, const std::vector<std::string> &context)
70 {
71     if (context.size() < 1) {
72         LOG(ERROR) << "too small context in transfer file";
73         return false;
74     }
75     if (globalParams == nullptr) {
76         LOG(ERROR) << "globalParams is nullptr";
77         return false;
78     }
79 
80     std::vector<std::string>::const_iterator ct = context.begin();
81     globalParams->version = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
82     globalParams->blockCount = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
83     globalParams->maxEntries = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
84     globalParams->maxBlocks = Utils::String2Int<size_t>(*ct++, Utils::N_DEC);
85     size_t totalSize = globalParams->blockCount;
86     std::string retryCmd = "";
87     if (globalParams->env != nullptr && globalParams->env->IsRetry()) {
88         retryCmd = ReloadForRetry();
89     }
90     size_t initBlock = 0;
91     for (; ct != context.end(); ct++) {
92         std::unique_ptr<Command> cmd = std::make_unique<Command>();
93         if (cmd == nullptr) {
94             LOG(ERROR) << "Failed to parse command line.";
95             return false;
96         }
97         if (!cmd->Init(*ct) || cmd->GetCommandType() == CommandType::LAST || globalParams->env == nullptr) {
98             continue;
99         }
100         if (!retryCmd.empty() && globalParams->env->IsRetry()) {
101             if (*ct == retryCmd) {
102                 retryCmd.clear();
103             }
104             if (cmd->GetCommandType() != CommandType::NEW) {
105                 LOG(INFO) << "Retry: Command " << *ct << " passed";
106                 continue;
107             }
108         }
109         if (!CommandsExecute(fd, *cmd)) {
110             LOG(ERROR) << "Running command : " << cmd->GetArgumentByPos(0) << " fail";
111             return false;
112         }
113         if (initBlock == 0) {
114             initBlock = globalParams->written;
115         }
116         if (totalSize != 0 && globalParams->env != nullptr && NeedSetProgress(cmd->GetCommandType())) {
117             globalParams->env->PostMessage("set_progress",
118                 std::to_string((static_cast<double>(globalParams->written) - initBlock) / totalSize));
119         }
120     }
121     return true;
122 }
123 
Init()124 void TransferManager::Init()
125 {
126     globalParams = std::make_unique<GlobalParams>();
127     globalParams->writerThreadInfo = std::make_unique<WriterThreadInfo>();
128     blocksetMap.clear();
129 }
130 
RegisterForRetry(const std::string & cmd)131 bool TransferManager::RegisterForRetry(const std::string &cmd)
132 {
133     std::string path = globalParams->retryFile;
134     int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
135     if (fd == -1) {
136         LOG(ERROR) << "Failed to create";
137         return false;
138     }
139     bool ret = Utils::WriteStringToFile(fd, cmd);
140     if (ret == false) {
141         LOG(ERROR) << "Write retry flag error";
142     }
143     fsync(fd);
144     close(fd);
145     return ret;
146 }
147 
ReloadForRetry() const148 std::string TransferManager::ReloadForRetry() const
149 {
150     std::string path = globalParams->retryFile;
151     int fd = open(path.c_str(), O_RDONLY);
152     if (fd < 0) {
153         LOG(ERROR) << "Failed to open";
154         return "";
155     }
156     (void)lseek(fd, 0, SEEK_SET);
157     std::string cmd = "";
158     if (!Utils::ReadFileToString(fd, cmd)) {
159         LOG(ERROR) << "Error to read retry flag";
160     }
161     close(fd);
162     return cmd;
163 }
164 
NeedSetProgress(const CommandType & type)165 bool TransferManager::NeedSetProgress(const CommandType &type)
166 {
167     return type == CommandType::NEW ||
168         type == CommandType::IMGDIFF ||
169         type == CommandType::BSDIFF ||
170         type == CommandType::ZERO;
171 }
172 
CheckResult(const CommandResult result,const std::string & cmd,const CommandType & type)173 bool TransferManager::CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type)
174 {
175     switch (result) {
176         case SUCCESS:
177             if (type != CommandType::NEW) {
178                 RegisterForRetry(cmd);
179             }
180             break;
181         case NEED_RETRY:
182             LOG(INFO) << "Running command need retry!";
183             if (globalParams->env != nullptr) {
184                 globalParams->env->PostMessage("retry_update", cmd);
185             }
186             return false;
187         case FAILED:
188         default:
189             LOG(ERROR) << "Running command failed";
190             return false;
191     }
192     return true;
193 }
194 } // namespace Updater
195