• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "module_zip_helper.h"
17 
18 #include <fcntl.h>
19 
20 #include "log/log.h"
21 #include "module_utils.h"
22 #include "unique_fd.h"
23 
24 namespace OHOS {
25 namespace SysInstaller {
26 using namespace Updater;
27 
28 namespace {
29 struct __attribute__((packed)) LocalFileHeader {
30     uint32_t signature = 0;
31     uint16_t versionNeeded = 0;
32     uint16_t flags = 0;
33     uint16_t compressionMethod = 0;
34     uint16_t modifiedTime = 0;
35     uint16_t modifiedDate = 0;
36     uint32_t crc = 0;
37     uint32_t compressedSize = 0;
38     uint32_t uncompressedSize = 0;
39     uint16_t nameSize = 0;
40     uint16_t extraSize = 0;
41 };
42 
43 struct __attribute__((packed)) CentralDirEntry {
44     uint32_t signature = 0;
45     uint16_t versionMade = 0;
46     uint16_t versionNeeded = 0;
47     uint16_t flags = 0; // general purpose bit flag
48     uint16_t compressionMethod = 0;
49     uint16_t modifiedTime = 0;
50     uint16_t modifiedDate = 0;
51     uint32_t crc = 0;
52     uint32_t compressedSize = 0;
53     uint32_t uncompressedSize = 0;
54     uint16_t nameSize = 0;
55     uint16_t extraSize = 0;
56     uint16_t commentSize = 0;
57     uint16_t diskNumStart = 0;
58     uint16_t internalAttr = 0;
59     uint32_t externalAttr = 0;
60     uint32_t localHeaderOffset = 0;
61 };
62 
63 constexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50;
64 constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50;
65 }
66 
ModuleZipHelper(const std::string & path)67 ModuleZipHelper::ModuleZipHelper(const std::string &path)
68 {
69     handle_ = unzOpen(path.c_str());
70     hasLocated_ = false;
71     zipPath_ = path;
72 }
73 
~ModuleZipHelper()74 ModuleZipHelper::~ModuleZipHelper()
75 {
76     if (IsValid()) {
77         int err = unzClose(handle_);
78         if (err != UNZ_OK) {
79             LOG(WARNING) << "Close handle error " << err << ". path=" << zipPath_;
80         }
81     }
82 }
83 
GetNumberOfEntry(uint32_t & number)84 bool ModuleZipHelper::GetNumberOfEntry(uint32_t &number)
85 {
86     if (!IsValid()) {
87         LOG(ERROR) << "Cannot get entry number with invalid handle. path=" << zipPath_;
88         return false;
89     }
90     unz_global_info info;
91     int err = unzGetGlobalInfo(handle_, &info);
92     if (err != UNZ_OK) {
93         LOG(ERROR) << "Get global info error " << err << ". path=" << zipPath_;
94         return false;
95     }
96     number = static_cast<uint32_t>(info.number_entry);
97     return true;
98 }
99 
LocateFile(const std::string & filename)100 bool ModuleZipHelper::LocateFile(const std::string &filename)
101 {
102     if (!IsValid()) {
103         LOG(ERROR) << "Cannot locate file with invalid handle. path=" << zipPath_;
104         return false;
105     }
106     int err = unzLocateFile2(handle_, filename.c_str(), 0);
107     if (err != UNZ_OK) {
108         LOG(ERROR) << filename << " is not found in " << zipPath_;
109         hasLocated_ = false;
110         return false;
111     }
112     hasLocated_ = true;
113     filename_ = filename;
114     return true;
115 }
116 
GetFileSize(uint32_t & size)117 bool ModuleZipHelper::GetFileSize(uint32_t &size)
118 {
119     if (!hasLocated_) {
120         LOG(ERROR) << "Cannot get file size without located file. path=" << zipPath_;
121         return false;
122     }
123     unz_file_info info;
124     int err = unzGetCurrentFileInfo(handle_, &info, nullptr, 0, nullptr, 0, nullptr, 0);
125     if (err != UNZ_OK) {
126         LOG(ERROR) << "Get file size error " << err << ". " << filename_ << " in " << zipPath_;
127         return false;
128     }
129     size = static_cast<uint32_t>(info.uncompressed_size);
130     return true;
131 }
132 
GetFileOffset(uint32_t & offset)133 bool ModuleZipHelper::GetFileOffset(uint32_t &offset)
134 {
135     if (!hasLocated_) {
136         LOG(ERROR) << "Cannot get file offset without located file. path=" << zipPath_;
137         return false;
138     }
139     unz_file_pos filePos;
140     int err = unzGetFilePos(handle_, &filePos);
141     if (err != UNZ_OK) {
142         LOG(ERROR) << "Get file pos error " << err << ". " << filename_ << " in " << zipPath_;
143         return false;
144     }
145     uint32_t centralDirOffset = static_cast<uint32_t>(filePos.pos_in_zip_directory);
146     if (!GetFileEntryOffset(offset, centralDirOffset)) {
147         LOG(ERROR) << "Cannot get file entry offset";
148         return false;
149     }
150     return true;
151 }
152 
GetFileEntryOffset(uint32_t & offset,uint32_t centralDirOffset) const153 bool ModuleZipHelper::GetFileEntryOffset(uint32_t &offset, uint32_t centralDirOffset) const
154 {
155     std::string realPath = GetRealPath(zipPath_);
156     if (realPath.empty()) {
157         LOG(ERROR) << "Invalid path " << zipPath_;
158         return false;
159     }
160     UniqueFd fd(open(realPath.c_str(), O_RDONLY | O_CLOEXEC));
161     if (fd.Get() == -1) {
162         LOG(ERROR) << "Cannot open package " << zipPath_;
163         return false;
164     }
165     uint8_t centralDirBuf[sizeof(CentralDirEntry)];
166     if (!ReadFullyAtOffset(fd.Get(), centralDirBuf, sizeof(CentralDirEntry), centralDirOffset)) {
167         LOG(ERROR) << "Unable to read central directory";
168         return false;
169     }
170     uint32_t centralSignature = ReadLE32(centralDirBuf + offsetof(CentralDirEntry, signature));
171     if (centralSignature != CENTRAL_SIGNATURE) {
172         LOG(ERROR) << "Check central signature error";
173         return false;
174     }
175     uint32_t localHeaderOffset = ReadLE32(centralDirBuf + offsetof(CentralDirEntry, localHeaderOffset));
176     uint8_t localHeaderBuf[sizeof(LocalFileHeader)];
177     if (!ReadFullyAtOffset(fd.Get(), localHeaderBuf, sizeof(LocalFileHeader), localHeaderOffset)) {
178         LOG(ERROR) << "Unable to read local file header";
179         return false;
180     }
181     uint32_t localHeaderSignature = ReadLE32(localHeaderBuf + offsetof(LocalFileHeader, signature));
182     if (localHeaderSignature != LOCAL_HEADER_SIGNATURE) {
183         LOG(ERROR) << "Check local header signature error";
184         return false;
185     }
186     uint16_t nameSize = ReadLE16(localHeaderBuf + offsetof(LocalFileHeader, nameSize));
187     uint16_t extraSize = ReadLE16(localHeaderBuf + offsetof(LocalFileHeader, extraSize));
188     offset = localHeaderOffset + sizeof(LocalFileHeader) + nameSize + extraSize;
189     return true;
190 }
191 
GetFileContent(std::string & buf)192 bool ModuleZipHelper::GetFileContent(std::string &buf)
193 {
194     if (!hasLocated_) {
195         LOG(ERROR) << "Cannot get file content without located file. path=" << zipPath_;
196         return false;
197     }
198     uint32_t length;
199     if (!GetFileSize(length)) {
200         LOG(ERROR) << "Cannot get buf length.";
201         return false;
202     }
203     buf.resize(length, '\0');
204 
205     int err = unzOpenCurrentFile(handle_);
206     if (err != UNZ_OK) {
207         LOG(ERROR) << "Open current file error " << err << ". " << filename_ << " in " << zipPath_;
208         return false;
209     }
210     int size = unzReadCurrentFile(handle_, reinterpret_cast<void *>(&(buf)[0]), length);
211     err = unzCloseCurrentFile(handle_);
212     if (size < 0) {
213         LOG(ERROR) << "Read current file error. " << filename_ << " in " << zipPath_;
214         return false;
215     }
216     if (err != UNZ_OK) {
217         LOG(ERROR) << "Close current file error " << err << ". " << filename_ << " in " << zipPath_;
218         return false;
219     }
220     return true;
221 }
222 } // namespace SysInstaller
223 } // namespace OHOS