• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <getopt.h>
20 
21 #include "securec.h"
22 
23 #include "hnp_pack.h"
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
AddHnpCfgFileToZip(zipFile zf,const char * hnpSrcPath,HnpCfgInfo * hnpCfg)29 static int AddHnpCfgFileToZip(zipFile zf, const char *hnpSrcPath, HnpCfgInfo *hnpCfg)
30 {
31     int ret;
32     char *strPtr;
33     int offset;
34     char hnpCfgFile[MAX_FILE_PATH_LEN];
35     char *buff;
36 
37     // zip压缩文件内只保存相对路径,不保存绝对路径信息,偏移到压缩文件夹位置
38     strPtr = strrchr(hnpSrcPath, DIR_SPLIT_SYMBOL);
39     if (strPtr == NULL) {
40         offset = 0;
41     } else {
42         offset = strPtr - hnpSrcPath + 1;
43     }
44 
45     // zip函数根据后缀是否'/'区分目录还是文件
46     ret = sprintf_s(hnpCfgFile, MAX_FILE_PATH_LEN, "%s%c"HNP_CFG_FILE_NAME, hnpSrcPath + offset, DIR_SPLIT_SYMBOL);
47     if (ret < 0) {
48         HNP_LOGE("sprintf unsuccess.");
49         return HNP_ERRNO_BASE_SPRINTF_FAILED;
50     }
51     // 根据配置信息生成hnp.json内容
52     ret = GetHnpJsonBuff(hnpCfg, &buff);
53     if (ret != 0) {
54         HNP_LOGE("get hnp json content by cfg info unsuccess.");
55         return ret;
56     }
57     // 将hnp.json文件写入到.hnp压缩文件中
58     ret = HnpAddFileToZip(zf, hnpCfgFile, buff, strlen(buff) + 1);
59     free(buff);
60     if (ret != 0) {
61         HNP_LOGE("add file to zip failed, file=%{public}s", hnpCfgFile);
62         return ret;
63     }
64 
65     return 0;
66 }
67 
PackHnp(const char * hnpSrcPath,const char * hnpDstPath,HnpPackInfo * hnpPack)68 static int PackHnp(const char *hnpSrcPath, const char *hnpDstPath, HnpPackInfo *hnpPack)
69 {
70     int ret;
71     char hnp_file_path[MAX_FILE_PATH_LEN];
72     HnpCfgInfo *hnpCfg = &hnpPack->cfgInfo;
73 
74     HNP_LOGI("PackHnp start. srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s ",
75         hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath);
76 
77     /* 拼接hnp文件名 */
78     ret = sprintf_s(hnp_file_path, MAX_FILE_PATH_LEN, "%s%c%s.hnp", hnpDstPath, DIR_SPLIT_SYMBOL, hnpCfg->name);
79     if (ret < 0) {
80         HNP_LOGE("sprintf unsuccess.");
81         return HNP_ERRNO_PACK_GET_HNP_PATH_FAILED;
82     }
83 
84     HNP_LOGI("HnpZip dir=%{public}s, output=%{public}s ", hnpSrcPath, hnp_file_path);
85 
86     zipFile zf = zipOpen(hnp_file_path, APPEND_STATUS_CREATE);
87     if (zf == NULL) {
88         HNP_LOGE("open zip=%{public}s unsuccess ", hnp_file_path);
89         return HNP_ERRNO_BASE_CREATE_ZIP_FAILED;
90     }
91 
92     /* 将软件包压缩成独立的.hnp文件 */
93     ret = HnpZip(hnpSrcPath, zf);
94     if (ret != 0) {
95         HNP_LOGE("zip dir unsuccess! srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s"
96             "ret=%{public}d", hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath, ret);
97         zipClose(zf, NULL);
98         return HNP_ERRNO_PACK_ZIP_DIR_FAILED;
99     }
100 
101     /* 如果软件包中不存在hnp.json文件,则需要在hnp压缩文件中添加 */
102     if (hnpPack->hnpCfgExist == 0) {
103         ret = AddHnpCfgFileToZip(zf, hnpSrcPath, &hnpPack->cfgInfo);
104         if (ret != 0) {
105             HNP_LOGE("add file to zip failed ret=%d. zip=%s, src=%s",
106                 ret, hnp_file_path, hnpSrcPath);
107             zipClose(zf, NULL);
108             return ret;
109         }
110     }
111 
112     zipClose(zf, NULL);
113 
114     HNP_LOGI("PackHnp end. srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s,"
115         "linkNum=%{public}d, ret=%{public}d", hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath, hnpCfg->linkNum,
116         ret);
117 
118     return ret;
119 }
120 
GetHnpCfgInfo(const char * hnpCfgPath,const char * sourcePath,HnpCfgInfo * hnpCfg)121 static int GetHnpCfgInfo(const char *hnpCfgPath, const char *sourcePath, HnpCfgInfo *hnpCfg)
122 {
123     NativeBinLink *linkArr = NULL;
124     char linksource[MAX_FILE_PATH_LEN] = {0};
125 
126     int ret = ParseHnpCfgFile(hnpCfgPath, hnpCfg);
127     if (ret != 0) {
128         HNP_LOGE("parse hnp cfg[%{public}s] unsuccess! ret=%{public}d", hnpCfgPath, ret);
129         return ret;
130     }
131     /* 校验软连接的source文件是否存在 */
132     linkArr = hnpCfg->links;
133     for (unsigned int i = 0; i < hnpCfg->linkNum; i++, linkArr++) {
134         ret = sprintf_s(linksource, MAX_FILE_PATH_LEN, "%s/%s", sourcePath, linkArr->source);
135         if (ret < 0) {
136             free(hnpCfg->links);
137             hnpCfg->links = NULL;
138             HNP_LOGE("sprintf unsuccess.");
139             return HNP_ERRNO_BASE_SPRINTF_FAILED;
140         }
141         if (access(linksource, F_OK) != 0) {
142             free(hnpCfg->links);
143             hnpCfg->links = NULL;
144             HNP_LOGE("links source[%{public}s] not exist.", linksource);
145             return HNP_ERRNO_PACK_GET_REALPATH_FAILED;
146         }
147     }
148     return 0;
149 }
150 
ParsePackArgs(HnpPackArgv * packArgv,HnpPackInfo * packInfo)151 static int ParsePackArgs(HnpPackArgv *packArgv, HnpPackInfo *packInfo)
152 {
153     char cfgPath[MAX_FILE_PATH_LEN];
154 
155     if (packArgv->source == NULL) {
156         HNP_LOGE("source dir is null.");
157         return HNP_ERRNO_OPERATOR_ARGV_MISS;
158     }
159     if (GetRealPath(packArgv->source, packInfo->source) != 0) {
160         HNP_LOGE("source dir path=%{public}s is invalid.", packArgv->source);
161         return HNP_ERRNO_PACK_GET_REALPATH_FAILED;
162     }
163     if (packArgv->output == NULL) {
164         packArgv->output = ".";
165     }
166 
167     if (GetRealPath(packArgv->output, packInfo->output) != 0) {
168         HNP_LOGE("output dir path=%{public}s is invalid.", packArgv->output);
169         return HNP_ERRNO_PACK_GET_REALPATH_FAILED;
170     }
171     /* 确认hnp.json文件是否存在,存在则对hnp.json文件进行解析并校验内容是否正确 */
172     int ret = sprintf_s(cfgPath, MAX_FILE_PATH_LEN, "%s%c"HNP_CFG_FILE_NAME, packInfo->source, DIR_SPLIT_SYMBOL);
173     if (ret < 0) {
174         HNP_LOGE("sprintf unsuccess.");
175         return HNP_ERRNO_BASE_SPRINTF_FAILED;
176     }
177     if (access(cfgPath, F_OK) != 0) {
178         /* hnp.json文件不存在则要求用户传入name和version信息 */
179         if ((packArgv->name == NULL) || (packArgv->version == NULL)) {
180             HNP_LOGE("name or version argv is miss.");
181             return HNP_ERRNO_OPERATOR_ARGV_MISS;
182         }
183         if (strcpy_s(packInfo->cfgInfo.name, MAX_FILE_PATH_LEN, packArgv->name) != EOK) {
184             HNP_LOGE("strcpy name argv unsuccess.");
185             return HNP_ERRNO_BASE_COPY_FAILED;
186         }
187         if (strcpy_s(packInfo->cfgInfo.version, HNP_VERSION_LEN, packArgv->version) != EOK) {
188             HNP_LOGE("strcpy version argv unsuccess.");
189             return HNP_ERRNO_BASE_COPY_FAILED;
190         }
191         packInfo->hnpCfgExist = 0;
192     } else {
193         ret = GetHnpCfgInfo(cfgPath, packInfo->source, &packInfo->cfgInfo);
194         if (ret != 0) {
195             return ret;
196         }
197         packInfo->hnpCfgExist = 1;
198     }
199     return 0;
200 }
201 
HnpCmdPack(int argc,char * argv[])202 int HnpCmdPack(int argc, char *argv[])
203 {
204     HnpPackArgv packArgv = {0};
205     HnpPackInfo packInfo = {0};
206     int opt;
207 
208     optind = 1; // 从头开始遍历参数
209     while ((opt = getopt_long(argc, argv, "hi:o:n:v:", NULL, NULL)) != -1) {
210         switch (opt) {
211             case 'h' :
212                 return HNP_ERRNO_OPERATOR_ARGV_MISS;
213             case 'i' :
214                 packArgv.source = optarg;
215                 break;
216             case 'o' :
217                 packArgv.output = optarg;
218                 break;
219             case 'n' :
220                 packArgv.name = optarg;
221                 break;
222             case 'v' :
223                 packArgv.version = optarg;
224                 break;
225             default:
226                 break;
227         }
228     }
229 
230     // 解析参数并生成打包信息
231     int ret = ParsePackArgs(&packArgv, &packInfo);
232     if (ret != 0) {
233         return ret;
234     }
235 
236     // 根据打包信息进行打包操作
237     ret = PackHnp(packInfo.source, packInfo.output, &packInfo);
238 
239     // 释放软链接占用的内存
240     if (packInfo.cfgInfo.links != NULL) {
241         free(packInfo.cfgInfo.links);
242         packInfo.cfgInfo.links = NULL;
243     }
244 
245     return ret;
246 }
247 
248 #ifdef __cplusplus
249 }
250 #endif