/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <getopt.h> #include "securec.h" #include "hnp_pack.h" #ifdef __cplusplus extern "C" { #endif static int AddHnpCfgFileToZip(char *zipPath, const char *hnpSrcPath, HnpCfgInfo *hnpCfg) { int ret; char *strPtr; int offset; char hnpCfgFile[MAX_FILE_PATH_LEN]; char *buff; // zip压缩文件内åªä¿å˜ç›¸å¯¹è·¯å¾„,ä¸ä¿å˜ç»å¯¹è·¯å¾„ä¿¡æ¯ï¼Œå移到压缩文件夹ä½ç½® strPtr = strrchr(hnpSrcPath, DIR_SPLIT_SYMBOL); if (strPtr == NULL) { offset = 0; } else { offset = strPtr - hnpSrcPath + 1; } // zipå‡½æ•°æ ¹æ®åŽç¼€æ˜¯å¦'/'区分目录还是文件 ret = sprintf_s(hnpCfgFile, MAX_FILE_PATH_LEN, "%s%c"HNP_CFG_FILE_NAME, hnpSrcPath + offset, DIR_SPLIT_SYMBOL); if (ret < 0) { HNP_LOGE("sprintf unsuccess."); return HNP_ERRNO_BASE_SPRINTF_FAILED; } // æ ¹æ®é…置信æ¯ç”Ÿæˆhnp.json内容 ret = GetHnpJsonBuff(hnpCfg, &buff); if (ret != 0) { HNP_LOGE("get hnp json content by cfg info unsuccess."); return ret; } // å°†hnp.json文件写入到.hnpåŽ‹ç¼©æ–‡ä»¶ä¸ ret = HnpAddFileToZip(zipPath, hnpCfgFile, buff, strlen(buff) + 1); free(buff); if (ret != 0) { HNP_LOGE("add file to zip failed.zip=%{public}s, file=%{public}s", zipPath, hnpCfgFile); return ret; } return 0; } static int PackHnp(const char *hnpSrcPath, const char *hnpDstPath, HnpPackInfo *hnpPack) { int ret; char hnp_file_path[MAX_FILE_PATH_LEN]; HnpCfgInfo *hnpCfg = &hnpPack->cfgInfo; HNP_LOGI("PackHnp start. srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s ", hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath); /* 拼接hnp文件å */ ret = sprintf_s(hnp_file_path, MAX_FILE_PATH_LEN, "%s%c%s.hnp", hnpDstPath, DIR_SPLIT_SYMBOL, hnpCfg->name); if (ret < 0) { HNP_LOGE("sprintf unsuccess."); return HNP_ERRNO_PACK_GET_HNP_PATH_FAILED; } /* 将软件包压缩æˆç‹¬ç«‹çš„.hnp文件 */ ret = HnpZip(hnpSrcPath, hnp_file_path); if (ret != 0) { HNP_LOGE("zip dir unsuccess! srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s" "ret=%{public}d", hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath, ret); return HNP_ERRNO_PACK_ZIP_DIR_FAILED; } /* 如果软件包ä¸ä¸å˜åœ¨hnp.json文件,则需è¦åœ¨hnpåŽ‹ç¼©æ–‡ä»¶ä¸æ·»åŠ */ if (hnpPack->hnpCfgExist == 0) { ret = AddHnpCfgFileToZip(hnp_file_path, hnpSrcPath, &hnpPack->cfgInfo); if (ret != 0) { HNP_LOGE("add file to zip failed ret=%d. zip=%s, src=%s", ret, hnp_file_path, hnpSrcPath); return ret; } } HNP_LOGI("PackHnp end. srcPath=%{public}s, hnpName=%{public}s, hnpVer=%{public}s, hnpDstPath=%{public}s," "linkNum=%{public}d, ret=%{public}d", hnpSrcPath, hnpCfg->name, hnpCfg->version, hnpDstPath, hnpCfg->linkNum, ret); return ret; } static int GetHnpCfgInfo(const char *hnpCfgPath, const char *sourcePath, HnpCfgInfo *hnpCfg) { NativeBinLink *linkArr = NULL; char linksource[MAX_FILE_PATH_LEN] = {0}; int ret = ParseHnpCfgFile(hnpCfgPath, hnpCfg); if (ret != 0) { HNP_LOGE("parse hnp cfg[%{public}s] unsuccess! ret=%{public}d", hnpCfgPath, ret); return ret; } /* æ ¡éªŒè½¯è¿žæŽ¥çš„source文件是å¦å˜åœ¨ */ linkArr = hnpCfg->links; for (unsigned int i = 0; i < hnpCfg->linkNum; i++, linkArr++) { ret = sprintf_s(linksource, MAX_FILE_PATH_LEN, "%s/%s", sourcePath, linkArr->source); if (ret < 0) { free(hnpCfg->links); hnpCfg->links = NULL; HNP_LOGE("sprintf unsuccess."); return HNP_ERRNO_BASE_SPRINTF_FAILED; } if (access(linksource, F_OK) != 0) { free(hnpCfg->links); hnpCfg->links = NULL; HNP_LOGE("links source[%{public}s] not exist.", linksource); return HNP_ERRNO_PACK_GET_REALPATH_FAILED; } } return 0; } static int ParsePackArgs(HnpPackArgv *packArgv, HnpPackInfo *packInfo) { char cfgPath[MAX_FILE_PATH_LEN]; if (packArgv->source == NULL) { HNP_LOGE("source dir is null."); return HNP_ERRNO_OPERATOR_ARGV_MISS; } if (GetRealPath(packArgv->source, packInfo->source) != 0) { HNP_LOGE("source dir path=%{public}s is invalid.", packArgv->source); return HNP_ERRNO_PACK_GET_REALPATH_FAILED; } if (packArgv->output == NULL) { packArgv->output = "."; } if (GetRealPath(packArgv->output, packInfo->output) != 0) { HNP_LOGE("output dir path=%{public}s is invalid.", packArgv->output); return HNP_ERRNO_PACK_GET_REALPATH_FAILED; } /* 确认hnp.json文件是å¦å˜åœ¨ï¼Œå˜åœ¨åˆ™å¯¹hnp.json文件进行解æžå¹¶æ ¡éªŒå†…å®¹æ˜¯å¦æ£ç¡® */ int ret = sprintf_s(cfgPath, MAX_FILE_PATH_LEN, "%s%c"HNP_CFG_FILE_NAME, packInfo->source, DIR_SPLIT_SYMBOL); if (ret < 0) { HNP_LOGE("sprintf unsuccess."); return HNP_ERRNO_BASE_SPRINTF_FAILED; } if (access(cfgPath, F_OK) != 0) { /* hnp.json文件ä¸å˜åœ¨åˆ™è¦æ±‚ç”¨æˆ·ä¼ å…¥nameå’Œversionä¿¡æ¯ */ if ((packArgv->name == NULL) || (packArgv->version == NULL)) { HNP_LOGE("name or version argv is miss."); return HNP_ERRNO_OPERATOR_ARGV_MISS; } if (strcpy_s(packInfo->cfgInfo.name, MAX_FILE_PATH_LEN, packArgv->name) != EOK) { HNP_LOGE("strcpy name argv unsuccess."); return HNP_ERRNO_BASE_COPY_FAILED; } if (strcpy_s(packInfo->cfgInfo.version, HNP_VERSION_LEN, packArgv->version) != EOK) { HNP_LOGE("strcpy version argv unsuccess."); return HNP_ERRNO_BASE_COPY_FAILED; } packInfo->hnpCfgExist = 0; } else { ret = GetHnpCfgInfo(cfgPath, packInfo->source, &packInfo->cfgInfo); if (ret != 0) { return ret; } packInfo->hnpCfgExist = 1; } return 0; } int HnpCmdPack(int argc, char *argv[]) { HnpPackArgv packArgv = {0}; HnpPackInfo packInfo = {0}; int opt; optind = 1; // 从头开始éåŽ†å‚æ•° while ((opt = getopt_long(argc, argv, "hi:o:n:v:", NULL, NULL)) != -1) { switch (opt) { case 'h' : return HNP_ERRNO_OPERATOR_ARGV_MISS; case 'i' : packArgv.source = optarg; break; case 'o' : packArgv.output = optarg; break; case 'n' : packArgv.name = optarg; break; case 'v' : packArgv.version = optarg; break; default: break; } } // è§£æžå‚æ•°å¹¶ç”Ÿæˆæ‰“åŒ…ä¿¡æ¯ int ret = ParsePackArgs(&packArgv, &packInfo); if (ret != 0) { return ret; } // æ ¹æ®æ‰“包信æ¯è¿›è¡Œæ‰“包æ“作 ret = PackHnp(packInfo.source, packInfo.output, &packInfo); // 释放软链接å ç”¨çš„å†…å˜ if (packInfo.cfgInfo.links != NULL) { free(packInfo.cfgInfo.links); packInfo.cfgInfo.links = NULL; } return ret; } #ifdef __cplusplus } #endif