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