blob: ddd13dec8df4d2d15b52404a31f762423f40c317 [file] [log] [blame]
Ethan Yonker8373cfe2017-09-08 06:50:54 -05001/*
bigbiffd58ba182020-03-23 10:02:29 -04002 * Copyright (C) TeamWin
Ethan Yonker8373cfe2017-09-08 06:50:54 -05003 * This file is part of TWRP/TeamWin Recovery Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#include "zipwrap.hpp"
19#include <string>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <errno.h>
25#ifdef USE_MINZIP
26#include "minzip/Zip.h"
27#include "minzip/SysUtil.h"
28#else
29#include <ziparchive/zip_archive.h>
bigbiffd58ba182020-03-23 10:02:29 -040030#include "ZipUtil.h"
31#include "otautil/sysutil.h"
Ethan Yonker8373cfe2017-09-08 06:50:54 -050032#endif
33
34ZipWrap::ZipWrap() {
35 zip_open = false;
36}
37
38ZipWrap::~ZipWrap() {
39 if (zip_open)
40 Close();
41}
42
43bool ZipWrap::Open(const char* file, MemMapping* map) {
44 if (zip_open) {
45 printf("ZipWrap '%s' is already open\n", zip_file.c_str());
46 return true;
47 }
48 zip_file = file;
49#ifdef USE_MINZIP
50 if (mzOpenZipArchive(map->addr, map->length, &Zip) != 0)
51 return false;
52#else
53 if (OpenArchiveFromMemory(map->addr, map->length, file, &Zip) != 0)
54 return false;
55#endif
56 zip_open = true;
57 return true;
58}
59
60void ZipWrap::Close() {
61 if (zip_open)
62#ifdef USE_MINZIP
63 mzCloseZipArchive(&Zip);
64#else
65 CloseArchive(Zip);
66#endif
67 zip_open = false;
68}
69
70bool ZipWrap::EntryExists(const string& filename) {
71#ifdef USE_MINZIP
72 const ZipEntry* file_location = mzFindZipEntry(&Zip, filename.c_str());
73 if (file_location != NULL)
74 return true;
75 return false;
76#else
77 ZipString zip_string(filename.c_str());
78 ZipEntry file_entry;
79
80 if (FindEntry(Zip, zip_string, &file_entry) != 0)
81 return false;
82 return true;
83#endif
84}
85
86bool ZipWrap::ExtractEntry(const string& source_file, const string& target_file, mode_t mode) {
87 if (access(target_file.c_str(), F_OK) == 0 && unlink(target_file.c_str()) != 0)
88 printf("Unable to unlink '%s': %s\n", target_file.c_str(), strerror(errno));
89
90 int fd = creat(target_file.c_str(), mode);
91 if (fd < 0) {
92 printf("Failed to create '%s'\n", target_file.c_str());
93 return false;
94 }
95
96#ifdef USE_MINZIP
97 const ZipEntry* file_entry = mzFindZipEntry(&Zip, source_file.c_str());
98 if (file_entry == NULL) {
99 printf("'%s' does not exist in zip '%s'\n", source_file.c_str(), zip_file.c_str());
100 return false;
101 }
102 int ret_val = mzExtractZipEntryToFile(&Zip, file_entry, fd);
103 close(fd);
104
105 if (!ret_val) {
106 printf("Could not extract '%s'\n", target_file.c_str());
107 return false;
108 }
109#else
110 ZipString zip_string(source_file.c_str());
111 ZipEntry file_entry;
112
113 if (FindEntry(Zip, zip_string, &file_entry) != 0)
114 return false;
115 int32_t ret_val = ExtractEntryToFile(Zip, &file_entry, fd);
116 close(fd);
117
118 if (ret_val != 0) {
119 printf("Could not extract '%s'\n", target_file.c_str());
120 return false;
121 }
122#endif
123 return true;
124}
125
126bool ZipWrap::ExtractRecursive(const string& source_dir, const string& target_dir) {
127 struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
128#ifdef USE_MINZIP
129 return mzExtractRecursive(&Zip, source_dir.c_str(), target_dir.c_str(), &timestamp, NULL, NULL, NULL);
130#else
131 return ExtractPackageRecursive(Zip, source_dir, target_dir, &timestamp, NULL);
132#endif
133}
134
135long ZipWrap::GetUncompressedSize(const string& filename) {
136#ifdef USE_MINZIP
137 const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
138 if (file_entry == NULL) {
139 printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
140 return 0;
141 }
142 return file_entry->uncompLen;
143#else
144 ZipString zip_string(filename.c_str());
145 ZipEntry file_entry;
146
147 if (FindEntry(Zip, zip_string, &file_entry) != 0)
148 return 0;
149 return file_entry.uncompressed_length;
150#endif
151}
152
153bool ZipWrap::ExtractToBuffer(const string& filename, uint8_t* buffer) {
154#ifdef USE_MINZIP
155 const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
156 if (file_entry == NULL) {
157 printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
158 return false;
159 }
160 if (!mzExtractZipEntryToBuffer(&Zip, file_entry, buffer)) {
161 printf("Failed to read '%s'\n", filename.c_str());
162 return false;
163 }
164#else
165 ZipString zip_string(filename.c_str());
166 ZipEntry file_entry;
167
168 if (FindEntry(Zip, zip_string, &file_entry) != 0)
169 return false;
170 if (ExtractToMemory(Zip, &file_entry, buffer, file_entry.uncompressed_length) != 0) {
171 printf("Failed to read '%s'\n", filename.c_str());
172 return false;
173 }
174#endif
175 return true;
176}
177
178#ifdef USE_MINZIP
179loff_t ZipWrap::GetEntryOffset(const string& filename) {
180 const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
181 if (file_entry == NULL) {
182 printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
183 return 0;
184 }
185 return mzGetZipEntryOffset(file_entry);
186}
187#else
188off64_t ZipWrap::GetEntryOffset(const string& filename) {
189 ZipString zip_string(filename.c_str());
190 ZipEntry file_entry;
191
192 if (FindEntry(Zip, zip_string, &file_entry) != 0) {
193 printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
194 return 0;
195 }
196 return file_entry.offset;
197}
198
199ZipArchiveHandle ZipWrap::GetZipArchiveHandle() {
200 return Zip;
201}
202#endif