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