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 NULL, GetUncompressedLength(), 60 PROT_READ | PROT_WRITE, false, error_msg)); 61 if (map.get() == nullptr) { 62 DCHECK(!error_msg->empty()); 63 return nullptr; 64 } 65 66 const int32_t error = ExtractToMemory(handle_, zip_entry_, 67 map->Begin(), map->Size()); 68 if (error) { 69 *error_msg = std::string(ErrorCodeString(error)); 70 return nullptr; 71 } 72 73 return map.release(); 74 } 75 76 static void SetCloseOnExec(int fd) { 77 // This dance is more portable than Linux's O_CLOEXEC open(2) flag. 78 int flags = fcntl(fd, F_GETFD); 79 if (flags == -1) { 80 PLOG(WARNING) << "fcntl(" << fd << ", F_GETFD) failed"; 81 return; 82 } 83 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 84 if (rc == -1) { 85 PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed"; 86 return; 87 } 88 } 89 90 ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) { 91 DCHECK(filename != nullptr); 92 93 ZipArchiveHandle handle; 94 const int32_t error = OpenArchive(filename, &handle); 95 if (error) { 96 *error_msg = std::string(ErrorCodeString(error)); 97 CloseArchive(handle); 98 return nullptr; 99 } 100 101 SetCloseOnExec(GetFileDescriptor(handle)); 102 return new ZipArchive(handle); 103 } 104 105 ZipArchive* ZipArchive::OpenFromFd(int fd, const char* filename, std::string* error_msg) { 106 DCHECK(filename != nullptr); 107 DCHECK_GT(fd, 0); 108 109 ZipArchiveHandle handle; 110 const int32_t error = OpenArchiveFd(fd, filename, &handle); 111 if (error) { 112 *error_msg = std::string(ErrorCodeString(error)); 113 CloseArchive(handle); 114 return nullptr; 115 } 116 117 SetCloseOnExec(GetFileDescriptor(handle)); 118 return new ZipArchive(handle); 119 } 120 121 ZipEntry* ZipArchive::Find(const char* name, std::string* error_msg) const { 122 DCHECK(name != nullptr); 123 124 // Resist the urge to delete the space. <: is a bigraph sequence. 125 std::unique_ptr< ::ZipEntry> zip_entry(new ::ZipEntry); 126 const int32_t error = FindEntry(handle_, name, zip_entry.get()); 127 if (error) { 128 *error_msg = std::string(ErrorCodeString(error)); 129 return nullptr; 130 } 131 132 return new ZipEntry(handle_, zip_entry.release()); 133 } 134 135 } // namespace art 136