• 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 "update_partitions.h"
16 #include <cerrno>
17 #include <cstdio>
18 #include <sstream>
19 #include <string>
20 #include "cJSON.h"
21 #include "log/log.h"
22 #include "updater/updater_const.h"
23 #include "utils.h"
24 
25 using namespace std;
26 using namespace Uscript;
27 using namespace Hpackage;
28 using namespace Updater;
29 constexpr int MIN_PARTITIONS_NUM = 2;
30 constexpr int MAX_PARTITIONS_NUM = 20;
31 namespace Updater {
ParsePartitionInfo(const std::string & partitionInfo,PartitonList & newPartList) const32 int UpdatePartitions::ParsePartitionInfo(const std::string &partitionInfo, PartitonList &newPartList) const
33 {
34     cJSON* root = cJSON_Parse(partitionInfo.c_str());
35     UPDATER_ERROR_CHECK(root != nullptr, "Error get root", return -1);
36     cJSON* partitions = cJSON_GetObjectItem(root, "Partition");
37     UPDATER_ERROR_CHECK(partitions != nullptr, "Error get Partitions", cJSON_Delete(root); return -1);
38     int number = cJSON_GetArraySize(partitions);
39     UPDATER_ERROR_CHECK(number > MIN_PARTITIONS_NUM, "Error partitions number < 3", cJSON_Delete(root); return -1);
40     UPDATER_ERROR_CHECK(number < MAX_PARTITIONS_NUM, "Error partitions number > 20", cJSON_Delete(root); return -1);
41     LOG(INFO) << "Partitions numbers " << number;
42     int i = 0;
43     for (i = 0; i < number; i++) {
44         struct Partition* myPartition = static_cast<struct Partition*>(calloc(1, sizeof(struct Partition)));
45         if (!myPartition) {
46             LOG(ERROR) << "Allocate memory for partition failed: " << errno;
47             cJSON_Delete(root);
48             return 0;
49         }
50         cJSON* thisPartition = cJSON_GetArrayItem(partitions, i);
51         UPDATER_ERROR_CHECK(thisPartition != nullptr, "Error get thisPartion", free(myPartition);
52             myPartition = nullptr; break);
53 
54         cJSON* item = cJSON_GetObjectItem(thisPartition, "start");
55         UPDATER_ERROR_CHECK(item != nullptr, "Error get start", free(myPartition); myPartition = nullptr; break);
56         myPartition->start = static_cast<size_t>(item->valueint);
57 
58         item = cJSON_GetObjectItem(thisPartition, "length");
59         UPDATER_ERROR_CHECK(item != nullptr, "Error get length", free(myPartition); myPartition = nullptr; break);
60         myPartition->length = static_cast<size_t>(item->valueint);
61         myPartition->partNum = 0;
62         myPartition->devName = "mmcblk0px";
63 
64         item = cJSON_GetObjectItem(thisPartition, "partName");
65         UPDATER_ERROR_CHECK(item != nullptr, "Error get partName", free(myPartition); myPartition = nullptr; break);
66         myPartition->partName = (item->valuestring);
67 
68         item = cJSON_GetObjectItem(thisPartition, "fsType");
69         UPDATER_ERROR_CHECK(item != nullptr, "Error get fsType", free(myPartition); myPartition = nullptr; break);
70         myPartition->fsType = (item->valuestring);
71 
72         LOG(INFO) << "<start> <length> <devname> <partname> <fstype>";
73         LOG(INFO) << myPartition->start << " " << myPartition->length << " " << myPartition->devName << " " <<
74             myPartition->partName << " " << myPartition->fsType;
75         newPartList.push_back(myPartition);
76     }
77     cJSON_Delete(root);
78     return 1;
79 }
80 
DoNewPartitions(PartitonList & newPartList)81 int UpdatePartitions::DoNewPartitions(PartitonList &newPartList)
82 {
83     int ret = DoPartitions(newPartList);
84     newPartList.clear();
85     if (ret <= 0) {
86         LOG(INFO) << "do_partitions FAIL ";
87     } else if (ret == 1) {
88         LOG(INFO) << "partitions not changed,Skip.";
89     } else if (ret > 1) {
90         LOG(INFO) << "do_partitions success reboot";
91 #ifndef UPDATER_UT
92         Utils::DoReboot("updater");
93 #endif
94     }
95     return ret;
96 }
97 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)98 int32_t UpdatePartitions::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
99 {
100     LOG(INFO) << "enter UpdatePartitions::Execute ";
101     if (context.GetParamCount() != 1) {
102         LOG(ERROR) << "Invalid UpdatePartitions::Execute param";
103         return USCRIPT_INVALID_PARAM;
104     }
105     std::string filePath;
106     int32_t ret = context.GetParam(0, filePath);
107     if (ret != USCRIPT_SUCCESS) {
108         LOG(ERROR) << "Fail to get filePath";
109         return USCRIPT_INVALID_PARAM;
110     } else {
111         LOG(INFO) << "UpdatePartitions::Execute filePath " << filePath;
112     }
113     Hpackage::PkgManager::StreamPtr outStream = nullptr;
114     const FileInfo *info = env.GetPkgManager()->GetFileInfo(filePath);
115     UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", return USCRIPT_ERROR_EXECUTE);
116     std::string tmpPath = "/data/updater";
117     std::string tmpPath1 = tmpPath + filePath;
118     char realPath[PATH_MAX + 1] = {};
119     UPDATER_ERROR_CHECK(realpath(tmpPath1.c_str(), realPath) != nullptr,
120         "Error to create tmpPath1", return USCRIPT_ERROR_EXECUTE);
121     ret = env.GetPkgManager()->CreatePkgStream(outStream,
122         tmpPath1, info->unpackedSize, PkgStream::PkgStreamType_Write);
123     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream",
124         return USCRIPT_ERROR_EXECUTE);
125     ret = env.GetPkgManager()->ExtractFile(filePath, outStream);
126     UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file",
127         env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
128     FILE *fp = fopen(realPath, "rb");
129     if (!fp) {
130         LOG(ERROR) << "Open " << tmpPath1 << " failed: " << errno;
131         env.GetPkgManager()->ClosePkgStream(outStream);
132         return USCRIPT_ERROR_EXECUTE;
133     }
134     char partitionInfo[MAX_LOG_BUF_SIZE];
135     size_t partitionCount = fread(partitionInfo, 1, MAX_LOG_BUF_SIZE, fp);
136     fclose(fp);
137     if (partitionCount <= LEAST_PARTITION_COUNT) {
138         env.GetPkgManager()->ClosePkgStream(outStream);
139         LOG(ERROR) << "Invalid partition size, too small";
140         return USCRIPT_ERROR_EXECUTE;
141     }
142     PartitonList newPartList {};
143     if (ParsePartitionInfo(std::string(partitionInfo), newPartList) == 0) {
144         env.GetPkgManager()->ClosePkgStream(outStream);
145         return USCRIPT_ABOART;
146     }
147     if (newPartList.empty()) {
148         LOG(ERROR) << "Partition is empty ";
149         env.GetPkgManager()->ClosePkgStream(outStream);
150         return USCRIPT_SUCCESS; // Partitions table is empty not require partition.
151     }
152     DoNewPartitions(newPartList);
153     env.GetPkgManager()->ClosePkgStream(outStream);
154     return USCRIPT_SUCCESS;
155 }
156 } // namespace Updater
157