| /* |
| * Copyright (C) TeamWin |
| * This file is part of TWRP/TeamWin Recovery Project. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "zipwrap.hpp" |
| #include <string> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #ifdef USE_MINZIP |
| #include "minzip/Zip.h" |
| #include "minzip/SysUtil.h" |
| #else |
| #include <ziparchive/zip_archive.h> |
| #include "ZipUtil.h" |
| #include "otautil/sysutil.h" |
| #endif |
| |
| ZipWrap::ZipWrap() { |
| zip_open = false; |
| } |
| |
| ZipWrap::~ZipWrap() { |
| if (zip_open) |
| Close(); |
| } |
| |
| bool ZipWrap::Open(const char* file, MemMapping* map) { |
| if (zip_open) { |
| printf("ZipWrap '%s' is already open\n", zip_file.c_str()); |
| return true; |
| } |
| zip_file = file; |
| #ifdef USE_MINZIP |
| if (mzOpenZipArchive(map->addr, map->length, &Zip) != 0) |
| return false; |
| #else |
| if (OpenArchiveFromMemory(map->addr, map->length, file, &Zip) != 0) |
| return false; |
| #endif |
| zip_open = true; |
| return true; |
| } |
| |
| void ZipWrap::Close() { |
| if (zip_open) |
| #ifdef USE_MINZIP |
| mzCloseZipArchive(&Zip); |
| #else |
| CloseArchive(Zip); |
| #endif |
| zip_open = false; |
| } |
| |
| bool ZipWrap::EntryExists(const string& filename) { |
| #ifdef USE_MINZIP |
| const ZipEntry* file_location = mzFindZipEntry(&Zip, filename.c_str()); |
| if (file_location != NULL) |
| return true; |
| return false; |
| #else |
| ZipString zip_string(filename.c_str()); |
| ZipEntry file_entry; |
| |
| if (FindEntry(Zip, zip_string, &file_entry) != 0) |
| return false; |
| return true; |
| #endif |
| } |
| |
| bool ZipWrap::ExtractEntry(const string& source_file, const string& target_file, mode_t mode) { |
| if (access(target_file.c_str(), F_OK) == 0 && unlink(target_file.c_str()) != 0) |
| printf("Unable to unlink '%s': %s\n", target_file.c_str(), strerror(errno)); |
| |
| int fd = creat(target_file.c_str(), mode); |
| if (fd < 0) { |
| printf("Failed to create '%s'\n", target_file.c_str()); |
| return false; |
| } |
| |
| #ifdef USE_MINZIP |
| const ZipEntry* file_entry = mzFindZipEntry(&Zip, source_file.c_str()); |
| if (file_entry == NULL) { |
| printf("'%s' does not exist in zip '%s'\n", source_file.c_str(), zip_file.c_str()); |
| return false; |
| } |
| int ret_val = mzExtractZipEntryToFile(&Zip, file_entry, fd); |
| close(fd); |
| |
| if (!ret_val) { |
| printf("Could not extract '%s'\n", target_file.c_str()); |
| return false; |
| } |
| #else |
| ZipString zip_string(source_file.c_str()); |
| ZipEntry file_entry; |
| |
| if (FindEntry(Zip, zip_string, &file_entry) != 0) |
| return false; |
| int32_t ret_val = ExtractEntryToFile(Zip, &file_entry, fd); |
| close(fd); |
| |
| if (ret_val != 0) { |
| printf("Could not extract '%s'\n", target_file.c_str()); |
| return false; |
| } |
| #endif |
| return true; |
| } |
| |
| bool ZipWrap::ExtractRecursive(const string& source_dir, const string& target_dir) { |
| struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default |
| #ifdef USE_MINZIP |
| return mzExtractRecursive(&Zip, source_dir.c_str(), target_dir.c_str(), ×tamp, NULL, NULL, NULL); |
| #else |
| return ExtractPackageRecursive(Zip, source_dir, target_dir, ×tamp, NULL); |
| #endif |
| } |
| |
| long ZipWrap::GetUncompressedSize(const string& filename) { |
| #ifdef USE_MINZIP |
| const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str()); |
| if (file_entry == NULL) { |
| printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str()); |
| return 0; |
| } |
| return file_entry->uncompLen; |
| #else |
| ZipString zip_string(filename.c_str()); |
| ZipEntry file_entry; |
| |
| if (FindEntry(Zip, zip_string, &file_entry) != 0) |
| return 0; |
| return file_entry.uncompressed_length; |
| #endif |
| } |
| |
| bool ZipWrap::ExtractToBuffer(const string& filename, uint8_t* buffer) { |
| #ifdef USE_MINZIP |
| const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str()); |
| if (file_entry == NULL) { |
| printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str()); |
| return false; |
| } |
| if (!mzExtractZipEntryToBuffer(&Zip, file_entry, buffer)) { |
| printf("Failed to read '%s'\n", filename.c_str()); |
| return false; |
| } |
| #else |
| ZipString zip_string(filename.c_str()); |
| ZipEntry file_entry; |
| |
| if (FindEntry(Zip, zip_string, &file_entry) != 0) |
| return false; |
| if (ExtractToMemory(Zip, &file_entry, buffer, file_entry.uncompressed_length) != 0) { |
| printf("Failed to read '%s'\n", filename.c_str()); |
| return false; |
| } |
| #endif |
| return true; |
| } |
| |
| #ifdef USE_MINZIP |
| loff_t ZipWrap::GetEntryOffset(const string& filename) { |
| const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str()); |
| if (file_entry == NULL) { |
| printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str()); |
| return 0; |
| } |
| return mzGetZipEntryOffset(file_entry); |
| } |
| #else |
| off64_t ZipWrap::GetEntryOffset(const string& filename) { |
| ZipString zip_string(filename.c_str()); |
| ZipEntry file_entry; |
| |
| if (FindEntry(Zip, zip_string, &file_entry) != 0) { |
| printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str()); |
| return 0; |
| } |
| return file_entry.offset; |
| } |
| |
| ZipArchiveHandle ZipWrap::GetZipArchiveHandle() { |
| return Zip; |
| } |
| #endif |