blob: 8cb199375bc528244c2c6fcfc76cc92bad33bc4f [file] [log] [blame]
Brian Carlstromb0460ea2011-07-29 10:08:05 -07001/*
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
Elliott Hughes3b6baaa2011-10-14 19:13:56 -070019#include <vector>
20
Brian Carlstromb0460ea2011-07-29 10:08:05 -070021#include <fcntl.h>
Ian Rogers8d31bbd2013-10-13 10:44:14 -070022#include <stdio.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -070023#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26
Ian Rogers8d31bbd2013-10-13 10:44:14 -070027#include "base/stringprintf.h"
Elliott Hughes76160052012-12-12 16:31:20 -080028#include "base/unix_file/fd_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070029#include "UniquePtr.h"
30
Brian Carlstromb0460ea2011-07-29 10:08:05 -070031namespace art {
32
Brian Carlstromb0460ea2011-07-29 10:08:05 -070033uint32_t ZipEntry::GetUncompressedLength() {
Narayan Kamath92572be2013-11-28 14:06:24 +000034 return zip_entry_->uncompressed_length;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070035}
36
37uint32_t ZipEntry::GetCrc32() {
Narayan Kamath92572be2013-11-28 14:06:24 +000038 return zip_entry_->crc32;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070039}
40
Brian Carlstromb0460ea2011-07-29 10:08:05 -070041
Ian Rogers8d31bbd2013-10-13 10:44:14 -070042bool ZipEntry::ExtractToFile(File& file, std::string* error_msg) {
Narayan Kamath92572be2013-11-28 14:06:24 +000043 const int32_t error = ExtractEntryToFile(handle_, zip_entry_, file.Fd());
44 if (error) {
45 *error_msg = std::string(ErrorCodeString(error));
Brian Carlstrom89521892011-12-07 22:05:07 -080046 return false;
47 }
48
Narayan Kamath92572be2013-11-28 14:06:24 +000049 return true;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070050}
51
Ian Rogers8d31bbd2013-10-13 10:44:14 -070052MemMap* ZipEntry::ExtractToMemMap(const char* entry_filename, std::string* error_msg) {
Brian Carlstrom4922e9d2013-07-09 17:18:47 -070053 std::string name(entry_filename);
54 name += " extracted in memory from ";
55 name += entry_filename;
56 UniquePtr<MemMap> map(MemMap::MapAnonymous(name.c_str(),
Narayan Kamath92572be2013-11-28 14:06:24 +000057 NULL, GetUncompressedLength(),
Ian Rogers8d31bbd2013-10-13 10:44:14 -070058 PROT_READ | PROT_WRITE, error_msg));
59 if (map.get() == nullptr) {
60 DCHECK(!error_msg->empty());
Narayan Kamath92572be2013-11-28 14:06:24 +000061 return nullptr;
Brian Carlstrom4922e9d2013-07-09 17:18:47 -070062 }
63
Narayan Kamath92572be2013-11-28 14:06:24 +000064 const int32_t error = ExtractToMemory(handle_, zip_entry_,
65 map->Begin(), map->Size());
66 if (error) {
67 *error_msg = std::string(ErrorCodeString(error));
68 return nullptr;
Brian Carlstrom4922e9d2013-07-09 17:18:47 -070069 }
70
71 return map.release();
72}
73
Elliott Hughesad6c9c32012-01-19 17:39:12 -080074static void SetCloseOnExec(int fd) {
75 // This dance is more portable than Linux's O_CLOEXEC open(2) flag.
76 int flags = fcntl(fd, F_GETFD);
77 if (flags == -1) {
78 PLOG(WARNING) << "fcntl(" << fd << ", F_GETFD) failed";
79 return;
80 }
81 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
82 if (rc == -1) {
83 PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed";
84 return;
85 }
86}
87
Ian Rogers8d31bbd2013-10-13 10:44:14 -070088ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) {
89 DCHECK(filename != nullptr);
Narayan Kamath92572be2013-11-28 14:06:24 +000090
91 ZipArchiveHandle handle;
92 const int32_t error = OpenArchive(filename, &handle);
93 if (error) {
94 *error_msg = std::string(ErrorCodeString(error));
95 CloseArchive(handle);
96 return nullptr;
Brian Carlstromb0460ea2011-07-29 10:08:05 -070097 }
Narayan Kamath92572be2013-11-28 14:06:24 +000098
99 SetCloseOnExec(GetFileDescriptor(handle));
100 return new ZipArchive(handle);
Brian Carlstromb7bbba42011-10-13 14:58:47 -0700101}
102
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700103ZipArchive* ZipArchive::OpenFromFd(int fd, const char* filename, std::string* error_msg) {
Narayan Kamath92572be2013-11-28 14:06:24 +0000104 DCHECK(filename != nullptr);
105 DCHECK_GT(fd, 0);
106
107 ZipArchiveHandle handle;
108 const int32_t error = OpenArchiveFd(fd, filename, &handle);
109 if (error) {
110 *error_msg = std::string(ErrorCodeString(error));
111 CloseArchive(handle);
112 return nullptr;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700113 }
Narayan Kamath92572be2013-11-28 14:06:24 +0000114
115 SetCloseOnExec(GetFileDescriptor(handle));
116 return new ZipArchive(handle);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700117}
118
Narayan Kamath92572be2013-11-28 14:06:24 +0000119ZipEntry* ZipArchive::Find(const char* name, std::string* error_msg) const {
120 DCHECK(name != nullptr);
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700121
Narayan Kamath92572be2013-11-28 14:06:24 +0000122 // Resist the urge to delete the space. <: is a bigraph sequence.
123 UniquePtr< ::ZipEntry> zip_entry(new ::ZipEntry);
124 const int32_t error = FindEntry(handle_, name, zip_entry.get());
125 if (error) {
126 *error_msg = std::string(ErrorCodeString(error));
127 return nullptr;
Kenny Root72fcca22013-09-19 09:25:34 -0700128 }
129
Narayan Kamath92572be2013-11-28 14:06:24 +0000130 return new ZipEntry(handle_, zip_entry.release());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700131}
132
133} // namespace art