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