1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "zip_archive.h" 18 19 #include <fcntl.h> 20 #include <stdio.h> 21 #include <sys/stat.h> 22 #include <sys/types.h> 23 #include <unistd.h> 24 #include <vector> 25 26 #include "base/stringprintf.h" 27 #include "base/unix_file/fd_file.h" 28 29 namespace art { 30 31 uint32_t ZipEntry::GetUncompressedLength() { 32 return zip_entry_->uncompressed_length; 33 } 34 35 uint32_t ZipEntry::GetCrc32() { 36 return zip_entry_->crc32; 37 } 38 39 ZipEntry::~ZipEntry() { 40 delete zip_entry_; 41 } 42 43 bool ZipEntry::ExtractToFile(File& file, std::string* error_msg) { 44 const int32_t error = ExtractEntryToFile(handle_, zip_entry_, file.Fd()); 45 if (error) { 46 *error_msg = std::string(ErrorCodeString(error)); 47 return false; 48 } 49 50 return true; 51 } 52 53 MemMap* ZipEntry::ExtractToMemMap(const char* zip_filename, const char* entry_filename, 54 std::string* error_msg) { 55 std::string name(entry_filename); 56 name += " extracted in memory from "; 57 name += zip_filename; 58 std::unique_ptr<MemMap> map(MemMap::MapAnonymous(name.c_str(), 59 nullptr, GetUncompressedLength(), 60 PROT_READ | PROT_WRITE, false, false, 61 error_msg)); 62 if (map.get() == nullptr) { 63 DCHECK(!error_msg->empty()); 64 return nullptr; 65 } 66 67 const int32_t error = ExtractToMemory(handle_, zip_entry_, 68 map->Begin(), map->Size()); 69 if (error) { 70 *error_msg = std::string(ErrorCodeString(error)); 71 return nullptr; 72 } 73 74 return map.release(); 75 } 76 77 static void SetCloseOnExec(int fd) { 78 // This dance is more portable than Linux's O_CLOEXEC open(2) flag. 79 int flags = fcntl(fd, F_GETFD); 80 if (flags == -1) { 81 PLOG(WARNING) << "fcntl(" << fd << ", F_GETFD) failed"; 82 return; 83 } 84 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 85 if (rc == -1) { 86 PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed"; 87 return; 88 } 89 } 90 91 ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) { 92 DCHECK(filename != nullptr); 93 94 ZipArchiveHandle handle; 95 const int32_t error = OpenArchive(filename, &handle); 96 if (error) { 97 *error_msg = std::string(ErrorCodeString(error)); 98 CloseArchive(handle); 99 return nullptr; 100 } 101 102 SetCloseOnExec(GetFileDescriptor(handle)); 103 return new ZipArchive(handle); 104 } 105 106 ZipArchive* ZipArchive::OpenFromFd(int fd, const char* filename, std::string* error_msg) { 107 DCHECK(filename != nullptr); 108 DCHECK_GT(fd, 0); 109 110 ZipArchiveHandle handle; 111 const int32_t error = OpenArchiveFd(fd, filename, &handle); 112 if (error) { 113 *error_msg = std::string(ErrorCodeString(error)); 114 CloseArchive(handle); 115 return nullptr; 116 } 117 118 SetCloseOnExec(GetFileDescriptor(handle)); 119 return new ZipArchive(handle); 120 } 121 122 ZipEntry* ZipArchive::Find(const char* name, std::string* error_msg) const { 123 DCHECK(name != nullptr); 124 125 // Resist the urge to delete the space. <: is a bigraph sequence. 126 std::unique_ptr< ::ZipEntry> zip_entry(new ::ZipEntry); 127 const int32_t error = FindEntry(handle_, ZipString(name), zip_entry.get()); 128 if (error) { 129 *error_msg = std::string(ErrorCodeString(error)); 130 return nullptr; 131 } 132 133 return new ZipEntry(handle_, zip_entry.release()); 134 } 135 136 ZipArchive::~ZipArchive() { 137 CloseArchive(handle_); 138 } 139 140 } // namespace art 141