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 "zip_util.h"
17
18 #include <cerrno>
19 #include <cstdlib>
20 #include <fstream>
21 #include <securec.h>
22
23 #include "media_log.h"
24
25 namespace OHOS::Media {
26 namespace {
27 constexpr int READ_MORE_LENGTH = 100 * 1024;
28 constexpr int ERROR_MEMSET_STRUCT = 1001;
29 constexpr int ERROR_GET_HANDLE = 1002;
30 };
31
CreateZipFile(const std::string & zipPath,int32_t zipMode)32 zipFile ZipUtil::CreateZipFile(const std::string& zipPath, int32_t zipMode)
33 {
34 return zipOpen(zipPath.c_str(), zipMode);
35 }
36
CloseZipFile(zipFile & zipfile)37 void ZipUtil::CloseZipFile(zipFile& zipfile)
38 {
39 zipClose(zipfile, nullptr);
40 }
41
AddFileInZip(zipFile & zipfile,const std::string & srcFile,int keepParentPathStatus,const std::string & destFileName)42 int ZipUtil::AddFileInZip(
43 zipFile& zipfile, const std::string& srcFile, int keepParentPathStatus, const std::string& destFileName)
44 {
45 zip_fileinfo zipInfo;
46 errno_t result = memset_s(&zipInfo, sizeof(zipInfo), 0, sizeof(zipInfo));
47 if (result != EOK) {
48 MEDIA_ERR_LOG("AddFileInZip memset_s error, file:%{public}s.", srcFile.c_str());
49 return ERROR_MEMSET_STRUCT;
50 }
51 FILE *srcFp = GetFileHandle(srcFile);
52 if (srcFp == nullptr) {
53 MEDIA_ERR_LOG("get file handle failed:%{public}s, errno: %{public}d.", srcFile.c_str(), errno);
54 return ERROR_GET_HANDLE;
55 }
56 std::string srcFileName = GetDestFilePath(srcFile, destFileName, keepParentPathStatus);
57 zipOpenNewFileInZip(
58 zipfile, srcFileName.c_str(), &zipInfo, nullptr, 0, nullptr, 0, nullptr, Z_DEFLATED, Z_DEFAULT_COMPRESSION);
59
60 int errcode = 0;
61 char buf[READ_MORE_LENGTH] = {0};
62 while (!feof(srcFp)) {
63 size_t numBytes = fread(buf, 1, sizeof(buf), srcFp);
64 if (numBytes == 0) {
65 break;
66 }
67 zipWriteInFileInZip(zipfile, buf, static_cast<unsigned int>(numBytes));
68 if (ferror(srcFp)) {
69 MEDIA_ERR_LOG("zip file failed:%{public}s, errno: %{public}d.", srcFile.c_str(), errno);
70 errcode = errno;
71 break;
72 }
73 }
74 (void)fclose(srcFp);
75 zipCloseFileInZip(zipfile);
76 return errcode;
77 }
78
GetFileHandle(const std::string & file)79 FILE* ZipUtil::GetFileHandle(const std::string& file)
80 {
81 char realPath[PATH_MAX] = {0};
82 if (realpath(file.c_str(), realPath) == nullptr) {
83 return nullptr;
84 }
85 return fopen(realPath, "rb");
86 }
87
GetDestFilePath(const std::string & srcFile,const std::string & destFilePath,int keepParentPathStatus)88 std::string ZipUtil::GetDestFilePath(
89 const std::string& srcFile, const std::string& destFilePath, int keepParentPathStatus)
90 {
91 if (!destFilePath.empty()) {
92 return destFilePath;
93 }
94 std::string file = srcFile;
95 std::string result = file;
96 std::string parentPathName;
97 auto pos = file.rfind("/");
98 if (pos != std::string::npos && pos != file.length() - 1) {
99 result = file.substr(pos + 1);
100 std::string parent = file.substr(0, pos);
101 pos = parent.rfind("/");
102 if (pos != std::string::npos && pos != parent.length() - 1) {
103 parentPathName = parent.substr(pos + 1);
104 } else {
105 parentPathName = parent;
106 }
107 }
108 parentPathName.append("/");
109 if (keepParentPathStatus == KEEP_ONE_PARENT_PATH) {
110 // srcFileName with relative directory path
111 result.insert(0, parentPathName);
112 }
113 return result;
114 }
115 }