xref: /aosp_15_r20/external/sandboxed-api/contrib/libzip/wrapper/wrapper_zip.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "contrib/libzip/wrapper/wrapper_zip.h"
16 
17 #include <fcntl.h>
18 #include <unistd.h>
19 
20 #include <iostream>
21 
22 #include "absl/cleanup/cleanup.h"
23 
24 constexpr size_t kFileMaxSize = 1024 * 1024 * 1024;  // 1GB
25 
zip_source_filefd(zip_t * archive,int fd,const char * mode,zip_uint64_t start,zip_int64_t len)26 void* zip_source_filefd(zip_t* archive, int fd, const char* mode,
27                         zip_uint64_t start, zip_int64_t len) {
28   FILE* pfile;
29 
30   // The file stream is closed when the source is being freed,
31   // usually by zip_close(3).
32   pfile = fdopen(fd, mode);
33   if (pfile == nullptr) {
34     return nullptr;
35   }
36 
37   return zip_source_filep(archive, pfile, start, len);
38 }
39 
zip_source_filefd_create(int fd,const char * mode,zip_uint64_t start,zip_int64_t len,zip_error_t * ze)40 void* zip_source_filefd_create(int fd, const char* mode, zip_uint64_t start,
41                                zip_int64_t len, zip_error_t* ze) {
42   FILE* pfile;
43 
44   pfile = fdopen(fd, mode);
45   if (pfile == nullptr) {
46     return nullptr;
47   }
48 
49   return zip_source_filep_create(pfile, start, len, ze);
50 }
51 
FDGetSize(int fd)52 off_t FDGetSize(int fd) {
53   off_t size = lseek(fd, 0, SEEK_END);
54   if (size < 0) {
55     return -1;
56   }
57   if (lseek(fd, 0, SEEK_SET) < 0) {
58     return -1;
59   }
60 
61   return size;
62 }
63 
zip_read_fd_to_source(int fd,zip_error_t * ze)64 void* zip_read_fd_to_source(int fd, zip_error_t* ze) {
65   off_t sizein = FDGetSize(fd);
66   if (sizein > kFileMaxSize) {
67     return nullptr;
68   }
69 
70   int8_t* buf = reinterpret_cast<int8_t*>(malloc(sizein));
71   if (buf == nullptr) {
72     return nullptr;
73   }
74 
75   if (read(fd, buf, sizein) != sizein) {
76     free(buf);
77     return nullptr;
78   }
79 
80   zip_source_t* src = zip_source_buffer_create(buf, sizein, 1, ze);
81   if (src == nullptr) {
82     free(buf);
83     return nullptr;
84   }
85 
86   return src;
87 }
88 
89 // This function is not atomic. Maybe it should be?
zip_source_to_fd(zip_source_t * src,int fd)90 bool zip_source_to_fd(zip_source_t* src, int fd) {
91   if (lseek(fd, 0, SEEK_SET) < 0) {
92     return false;
93   }
94   if (ftruncate(fd, 0) < 0) {
95     return false;
96   }
97 
98   if (zip_source_open(src) < 0) {
99     return false;
100   }
101   absl::Cleanup src_cleanup = [&src] { zip_source_close(src); };
102 
103   if (zip_source_seek(src, 0, SEEK_SET) < 0) {
104     return false;
105   }
106 
107   int8_t buf[4096];
108   size_t size;
109   while (true) {
110     size = zip_source_read(src, &buf, sizeof(buf));
111     if (size <= 0) {
112       break;
113     }
114     if (write(fd, &buf, size) != size) {
115       return false;
116     }
117   }
118 
119   return size == 0;
120 }
121