1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Original code used in this source file:
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * https://github.com/PerBothner/DomTerm.git @912add15f3d0aec
7*1c60b9acSAndroid Build Coastguard Worker *
8*1c60b9acSAndroid Build Coastguard Worker * ./lws-term/io.c
9*1c60b9acSAndroid Build Coastguard Worker * ./lws-term/junzip.c
10*1c60b9acSAndroid Build Coastguard Worker *
11*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2017 Per Bothner <[email protected]>
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * MIT License
14*1c60b9acSAndroid Build Coastguard Worker *
15*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
16*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to deal
17*1c60b9acSAndroid Build Coastguard Worker * in the Software without restriction, including without limitation the rights
18*1c60b9acSAndroid Build Coastguard Worker * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19*1c60b9acSAndroid Build Coastguard Worker * ( copies of the Software, and to permit persons to whom the Software is
20*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
21*1c60b9acSAndroid Build Coastguard Worker *
22*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
23*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
24*1c60b9acSAndroid Build Coastguard Worker *
25*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30*1c60b9acSAndroid Build Coastguard Worker * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31*1c60b9acSAndroid Build Coastguard Worker * SOFTWARE.
32*1c60b9acSAndroid Build Coastguard Worker *
33*1c60b9acSAndroid Build Coastguard Worker * Somewhat rewritten by AG
34*1c60b9acSAndroid Build Coastguard Worker */
35*1c60b9acSAndroid Build Coastguard Worker
36*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_MINIZ)
39*1c60b9acSAndroid Build Coastguard Worker #include <miniz.h>
40*1c60b9acSAndroid Build Coastguard Worker #else
41*1c60b9acSAndroid Build Coastguard Worker #include <zlib.h>
42*1c60b9acSAndroid Build Coastguard Worker #endif
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard Worker /*
45*1c60b9acSAndroid Build Coastguard Worker * This code works with zip format containers which may have files compressed
46*1c60b9acSAndroid Build Coastguard Worker * with gzip deflate (type 8) or store uncompressed (type 0).
47*1c60b9acSAndroid Build Coastguard Worker *
48*1c60b9acSAndroid Build Coastguard Worker * Linux zip produces such zipfiles by default, eg
49*1c60b9acSAndroid Build Coastguard Worker *
50*1c60b9acSAndroid Build Coastguard Worker * $ zip ../myzip.zip file1 file2 file3
51*1c60b9acSAndroid Build Coastguard Worker */
52*1c60b9acSAndroid Build Coastguard Worker
53*1c60b9acSAndroid Build Coastguard Worker #define ZIP_COMPRESSION_METHOD_STORE 0
54*1c60b9acSAndroid Build Coastguard Worker #define ZIP_COMPRESSION_METHOD_DEFLATE 8
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker typedef struct {
57*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t filename_start;
58*1c60b9acSAndroid Build Coastguard Worker uint32_t crc32;
59*1c60b9acSAndroid Build Coastguard Worker uint32_t comp_size;
60*1c60b9acSAndroid Build Coastguard Worker uint32_t uncomp_size;
61*1c60b9acSAndroid Build Coastguard Worker uint32_t offset;
62*1c60b9acSAndroid Build Coastguard Worker uint32_t mod_time;
63*1c60b9acSAndroid Build Coastguard Worker uint16_t filename_len;
64*1c60b9acSAndroid Build Coastguard Worker uint16_t extra;
65*1c60b9acSAndroid Build Coastguard Worker uint16_t method;
66*1c60b9acSAndroid Build Coastguard Worker uint16_t file_com_len;
67*1c60b9acSAndroid Build Coastguard Worker } lws_fops_zip_hdr_t;
68*1c60b9acSAndroid Build Coastguard Worker
69*1c60b9acSAndroid Build Coastguard Worker typedef struct {
70*1c60b9acSAndroid Build Coastguard Worker struct lws_fop_fd fop_fd; /* MUST BE FIRST logical fop_fd into
71*1c60b9acSAndroid Build Coastguard Worker * file inside zip: fops_zip fops */
72*1c60b9acSAndroid Build Coastguard Worker lws_fop_fd_t zip_fop_fd; /* logical fop fd on to zip file
73*1c60b9acSAndroid Build Coastguard Worker * itself: using platform fops */
74*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_hdr_t hdr;
75*1c60b9acSAndroid Build Coastguard Worker z_stream inflate;
76*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t content_start;
77*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t exp_uncomp_pos;
78*1c60b9acSAndroid Build Coastguard Worker union {
79*1c60b9acSAndroid Build Coastguard Worker uint8_t trailer8[8];
80*1c60b9acSAndroid Build Coastguard Worker uint32_t trailer32[2];
81*1c60b9acSAndroid Build Coastguard Worker } u;
82*1c60b9acSAndroid Build Coastguard Worker uint8_t rbuf[128]; /* decompression chunk size */
83*1c60b9acSAndroid Build Coastguard Worker int entry_count;
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker unsigned int decompress:1; /* 0 = direct from file */
86*1c60b9acSAndroid Build Coastguard Worker unsigned int add_gzip_container:1;
87*1c60b9acSAndroid Build Coastguard Worker } *lws_fops_zip_t;
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker struct lws_plat_file_ops fops_zip;
90*1c60b9acSAndroid Build Coastguard Worker #define fop_fd_to_priv(FD) ((lws_fops_zip_t)(FD))
91*1c60b9acSAndroid Build Coastguard Worker
92*1c60b9acSAndroid Build Coastguard Worker static const uint8_t hd[] = { 31, 139, 8, 0, 0, 0, 0, 0, 0, 3 };
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker enum {
95*1c60b9acSAndroid Build Coastguard Worker ZC_SIGNATURE = 0,
96*1c60b9acSAndroid Build Coastguard Worker ZC_VERSION_MADE_BY = 4,
97*1c60b9acSAndroid Build Coastguard Worker ZC_VERSION_NEEDED_TO_EXTRACT = 6,
98*1c60b9acSAndroid Build Coastguard Worker ZC_GENERAL_PURPOSE_BIT_FLAG = 8,
99*1c60b9acSAndroid Build Coastguard Worker ZC_COMPRESSION_METHOD = 10,
100*1c60b9acSAndroid Build Coastguard Worker ZC_LAST_MOD_FILE_TIME = 12,
101*1c60b9acSAndroid Build Coastguard Worker ZC_LAST_MOD_FILE_DATE = 14,
102*1c60b9acSAndroid Build Coastguard Worker ZC_CRC32 = 16,
103*1c60b9acSAndroid Build Coastguard Worker ZC_COMPRESSED_SIZE = 20,
104*1c60b9acSAndroid Build Coastguard Worker ZC_UNCOMPRESSED_SIZE = 24,
105*1c60b9acSAndroid Build Coastguard Worker ZC_FILE_NAME_LENGTH = 28,
106*1c60b9acSAndroid Build Coastguard Worker ZC_EXTRA_FIELD_LENGTH = 30,
107*1c60b9acSAndroid Build Coastguard Worker
108*1c60b9acSAndroid Build Coastguard Worker ZC_FILE_COMMENT_LENGTH = 32,
109*1c60b9acSAndroid Build Coastguard Worker ZC_DISK_NUMBER_START = 34,
110*1c60b9acSAndroid Build Coastguard Worker ZC_INTERNAL_FILE_ATTRIBUTES = 36,
111*1c60b9acSAndroid Build Coastguard Worker ZC_EXTERNAL_FILE_ATTRIBUTES = 38,
112*1c60b9acSAndroid Build Coastguard Worker ZC_REL_OFFSET_LOCAL_HEADER = 42,
113*1c60b9acSAndroid Build Coastguard Worker ZC_DIRECTORY_LENGTH = 46,
114*1c60b9acSAndroid Build Coastguard Worker
115*1c60b9acSAndroid Build Coastguard Worker ZE_SIGNATURE_OFFSET = 0,
116*1c60b9acSAndroid Build Coastguard Worker ZE_DESK_NUMBER = 4,
117*1c60b9acSAndroid Build Coastguard Worker ZE_CENTRAL_DIRECTORY_DISK_NUMBER = 6,
118*1c60b9acSAndroid Build Coastguard Worker ZE_NUM_ENTRIES_THIS_DISK = 8,
119*1c60b9acSAndroid Build Coastguard Worker ZE_NUM_ENTRIES = 10,
120*1c60b9acSAndroid Build Coastguard Worker ZE_CENTRAL_DIRECTORY_SIZE = 12,
121*1c60b9acSAndroid Build Coastguard Worker ZE_CENTRAL_DIR_OFFSET = 16,
122*1c60b9acSAndroid Build Coastguard Worker ZE_ZIP_COMMENT_LENGTH = 20,
123*1c60b9acSAndroid Build Coastguard Worker ZE_DIRECTORY_LENGTH = 22,
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard Worker ZL_REL_OFFSET_CONTENT = 28,
126*1c60b9acSAndroid Build Coastguard Worker ZL_HEADER_LENGTH = 30,
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_SEEK_END_RECORD = 1,
129*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_READ_END_RECORD,
130*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_END_RECORD_MAGIC,
131*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_END_RECORD_SANITY,
132*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_CENTRAL_SEEK,
133*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_CENTRAL_READ,
134*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_CENTRAL_SANITY,
135*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_NAME_TOO_LONG,
136*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_NAME_SEEK,
137*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_NAME_READ,
138*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_CONTENT_SANITY,
139*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_CONTENT_SEEK,
140*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_SCAN_SEEK,
141*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_NOT_FOUND,
142*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_ZLIB_INIT,
143*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_READ_CONTENT,
144*1c60b9acSAndroid Build Coastguard Worker LWS_FZ_ERR_SEEK_COMPRESSED,
145*1c60b9acSAndroid Build Coastguard Worker };
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker #define eff_size(_priv) (_priv->hdr.method == ZIP_COMPRESSION_METHOD_STORE ? \
148*1c60b9acSAndroid Build Coastguard Worker _priv->hdr.uncomp_size : _priv->hdr.comp_size)
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker static uint16_t
get_u16(void * p)151*1c60b9acSAndroid Build Coastguard Worker get_u16(void *p)
152*1c60b9acSAndroid Build Coastguard Worker {
153*1c60b9acSAndroid Build Coastguard Worker const uint8_t *c = (const uint8_t *)p;
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker return (uint16_t)((c[0] | (c[1] << 8)));
156*1c60b9acSAndroid Build Coastguard Worker }
157*1c60b9acSAndroid Build Coastguard Worker
158*1c60b9acSAndroid Build Coastguard Worker static uint32_t
get_u32(void * p)159*1c60b9acSAndroid Build Coastguard Worker get_u32(void *p)
160*1c60b9acSAndroid Build Coastguard Worker {
161*1c60b9acSAndroid Build Coastguard Worker const uint8_t *c = (const uint8_t *)p;
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker return (uint32_t)((c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)));
164*1c60b9acSAndroid Build Coastguard Worker }
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard Worker int
lws_fops_zip_scan(lws_fops_zip_t priv,const char * name,int len)167*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_scan(lws_fops_zip_t priv, const char *name, int len)
168*1c60b9acSAndroid Build Coastguard Worker {
169*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t amount;
170*1c60b9acSAndroid Build Coastguard Worker uint8_t buf[96];
171*1c60b9acSAndroid Build Coastguard Worker int i;
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_end(priv->zip_fop_fd, -ZE_DIRECTORY_LENGTH) < 0)
174*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_SEEK_END_RECORD;
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf,
177*1c60b9acSAndroid Build Coastguard Worker ZE_DIRECTORY_LENGTH))
178*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_READ_END_RECORD;
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker if (amount != ZE_DIRECTORY_LENGTH)
181*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_READ_END_RECORD;
182*1c60b9acSAndroid Build Coastguard Worker
183*1c60b9acSAndroid Build Coastguard Worker /*
184*1c60b9acSAndroid Build Coastguard Worker * We require the zip to have the last record right at the end
185*1c60b9acSAndroid Build Coastguard Worker * Linux zip always does this if no zip comment.
186*1c60b9acSAndroid Build Coastguard Worker */
187*1c60b9acSAndroid Build Coastguard Worker if (buf[0] != 'P' || buf[1] != 'K' || buf[2] != 5 || buf[3] != 6)
188*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_END_RECORD_MAGIC;
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker i = get_u16(buf + ZE_NUM_ENTRIES);
191*1c60b9acSAndroid Build Coastguard Worker
192*1c60b9acSAndroid Build Coastguard Worker if (get_u16(buf + ZE_DESK_NUMBER) ||
193*1c60b9acSAndroid Build Coastguard Worker get_u16(buf + ZE_CENTRAL_DIRECTORY_DISK_NUMBER) ||
194*1c60b9acSAndroid Build Coastguard Worker i != get_u16(buf + ZE_NUM_ENTRIES_THIS_DISK))
195*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_END_RECORD_SANITY;
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker /* end record is OK... look for our file in the central dir */
198*1c60b9acSAndroid Build Coastguard Worker
199*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_set(priv->zip_fop_fd,
200*1c60b9acSAndroid Build Coastguard Worker get_u32(buf + ZE_CENTRAL_DIR_OFFSET)) < 0)
201*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CENTRAL_SEEK;
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker while (i--) {
204*1c60b9acSAndroid Build Coastguard Worker priv->content_start = lws_vfs_tell(priv->zip_fop_fd);
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_read(priv->zip_fop_fd, &amount, buf,
207*1c60b9acSAndroid Build Coastguard Worker ZC_DIRECTORY_LENGTH))
208*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CENTRAL_READ;
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker if (amount != ZC_DIRECTORY_LENGTH)
211*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CENTRAL_READ;
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker if (get_u32(buf + ZC_SIGNATURE) != 0x02014B50)
214*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CENTRAL_SANITY;
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("cstart 0x%lx\n", (unsigned long)priv->content_start);
217*1c60b9acSAndroid Build Coastguard Worker
218*1c60b9acSAndroid Build Coastguard Worker priv->hdr.filename_len = get_u16(buf + ZC_FILE_NAME_LENGTH);
219*1c60b9acSAndroid Build Coastguard Worker priv->hdr.extra = get_u16(buf + ZC_EXTRA_FIELD_LENGTH);
220*1c60b9acSAndroid Build Coastguard Worker priv->hdr.filename_start = lws_vfs_tell(priv->zip_fop_fd);
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker priv->hdr.method = get_u16(buf + ZC_COMPRESSION_METHOD);
223*1c60b9acSAndroid Build Coastguard Worker priv->hdr.crc32 = get_u32(buf + ZC_CRC32);
224*1c60b9acSAndroid Build Coastguard Worker priv->hdr.comp_size = get_u32(buf + ZC_COMPRESSED_SIZE);
225*1c60b9acSAndroid Build Coastguard Worker priv->hdr.uncomp_size = get_u32(buf + ZC_UNCOMPRESSED_SIZE);
226*1c60b9acSAndroid Build Coastguard Worker priv->hdr.offset = get_u32(buf + ZC_REL_OFFSET_LOCAL_HEADER);
227*1c60b9acSAndroid Build Coastguard Worker priv->hdr.mod_time = get_u32(buf + ZC_LAST_MOD_FILE_TIME);
228*1c60b9acSAndroid Build Coastguard Worker priv->hdr.file_com_len = get_u16(buf + ZC_FILE_COMMENT_LENGTH);
229*1c60b9acSAndroid Build Coastguard Worker
230*1c60b9acSAndroid Build Coastguard Worker if (priv->hdr.filename_len != len)
231*1c60b9acSAndroid Build Coastguard Worker goto next;
232*1c60b9acSAndroid Build Coastguard Worker
233*1c60b9acSAndroid Build Coastguard Worker if (len >= (int)sizeof(buf) - 1)
234*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_TOO_LONG;
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
237*1c60b9acSAndroid Build Coastguard Worker &amount, buf, (unsigned int)len))
238*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_READ;
239*1c60b9acSAndroid Build Coastguard Worker if ((int)amount != len)
240*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_READ;
241*1c60b9acSAndroid Build Coastguard Worker
242*1c60b9acSAndroid Build Coastguard Worker buf[len] = '\0';
243*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("check %s vs %s\n", buf, name);
244*1c60b9acSAndroid Build Coastguard Worker
245*1c60b9acSAndroid Build Coastguard Worker if (strcmp((const char *)buf, name))
246*1c60b9acSAndroid Build Coastguard Worker goto next;
247*1c60b9acSAndroid Build Coastguard Worker
248*1c60b9acSAndroid Build Coastguard Worker /* we found a match */
249*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_set(priv->zip_fop_fd, priv->hdr.offset) < 0)
250*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_SEEK;
251*1c60b9acSAndroid Build Coastguard Worker if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
252*1c60b9acSAndroid Build Coastguard Worker &amount, buf,
253*1c60b9acSAndroid Build Coastguard Worker ZL_HEADER_LENGTH))
254*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_READ;
255*1c60b9acSAndroid Build Coastguard Worker if (amount != ZL_HEADER_LENGTH)
256*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NAME_READ;
257*1c60b9acSAndroid Build Coastguard Worker
258*1c60b9acSAndroid Build Coastguard Worker priv->content_start = priv->hdr.offset +
259*1c60b9acSAndroid Build Coastguard Worker ZL_HEADER_LENGTH +
260*1c60b9acSAndroid Build Coastguard Worker priv->hdr.filename_len +
261*1c60b9acSAndroid Build Coastguard Worker get_u16(buf + ZL_REL_OFFSET_CONTENT);
262*1c60b9acSAndroid Build Coastguard Worker
263*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("content supposed to start at 0x%lx\n",
264*1c60b9acSAndroid Build Coastguard Worker (unsigned long)priv->content_start);
265*1c60b9acSAndroid Build Coastguard Worker
266*1c60b9acSAndroid Build Coastguard Worker if (priv->content_start > priv->zip_fop_fd->len)
267*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CONTENT_SANITY;
268*1c60b9acSAndroid Build Coastguard Worker
269*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_set(priv->zip_fop_fd,
270*1c60b9acSAndroid Build Coastguard Worker (lws_fileofs_t)priv->content_start) < 0)
271*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CONTENT_SEEK;
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker /* we are aligned at the start of the content */
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker priv->exp_uncomp_pos = 0;
276*1c60b9acSAndroid Build Coastguard Worker
277*1c60b9acSAndroid Build Coastguard Worker return 0;
278*1c60b9acSAndroid Build Coastguard Worker
279*1c60b9acSAndroid Build Coastguard Worker next:
280*1c60b9acSAndroid Build Coastguard Worker if (i && lws_vfs_file_seek_set(priv->zip_fop_fd,
281*1c60b9acSAndroid Build Coastguard Worker (lws_fileofs_t)priv->content_start +
282*1c60b9acSAndroid Build Coastguard Worker (ZC_DIRECTORY_LENGTH +
283*1c60b9acSAndroid Build Coastguard Worker priv->hdr.filename_len +
284*1c60b9acSAndroid Build Coastguard Worker priv->hdr.extra +
285*1c60b9acSAndroid Build Coastguard Worker priv->hdr.file_com_len)) < 0)
286*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_SCAN_SEEK;
287*1c60b9acSAndroid Build Coastguard Worker }
288*1c60b9acSAndroid Build Coastguard Worker
289*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_NOT_FOUND;
290*1c60b9acSAndroid Build Coastguard Worker }
291*1c60b9acSAndroid Build Coastguard Worker
292*1c60b9acSAndroid Build Coastguard Worker static int
lws_fops_zip_reset_inflate(lws_fops_zip_t priv)293*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_reset_inflate(lws_fops_zip_t priv)
294*1c60b9acSAndroid Build Coastguard Worker {
295*1c60b9acSAndroid Build Coastguard Worker if (priv->decompress)
296*1c60b9acSAndroid Build Coastguard Worker inflateEnd(&priv->inflate);
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker priv->inflate.zalloc = Z_NULL;
299*1c60b9acSAndroid Build Coastguard Worker priv->inflate.zfree = Z_NULL;
300*1c60b9acSAndroid Build Coastguard Worker priv->inflate.opaque = Z_NULL;
301*1c60b9acSAndroid Build Coastguard Worker priv->inflate.avail_in = 0;
302*1c60b9acSAndroid Build Coastguard Worker priv->inflate.next_in = Z_NULL;
303*1c60b9acSAndroid Build Coastguard Worker
304*1c60b9acSAndroid Build Coastguard Worker if (inflateInit2(&priv->inflate, -MAX_WBITS) != Z_OK) {
305*1c60b9acSAndroid Build Coastguard Worker lwsl_err("inflate init failed\n");
306*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_ZLIB_INIT;
307*1c60b9acSAndroid Build Coastguard Worker }
308*1c60b9acSAndroid Build Coastguard Worker
309*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_seek_set(priv->zip_fop_fd, (lws_fileofs_t)priv->content_start) < 0)
310*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_CONTENT_SEEK;
311*1c60b9acSAndroid Build Coastguard Worker
312*1c60b9acSAndroid Build Coastguard Worker priv->exp_uncomp_pos = 0;
313*1c60b9acSAndroid Build Coastguard Worker
314*1c60b9acSAndroid Build Coastguard Worker return 0;
315*1c60b9acSAndroid Build Coastguard Worker }
316*1c60b9acSAndroid Build Coastguard Worker
317*1c60b9acSAndroid Build Coastguard Worker static lws_fop_fd_t
lws_fops_zip_open(const struct lws_plat_file_ops * fops,const char * vfs_path,const char * vpath,lws_fop_flags_t * flags)318*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_open(const struct lws_plat_file_ops *fops, const char *vfs_path,
319*1c60b9acSAndroid Build Coastguard Worker const char *vpath, lws_fop_flags_t *flags)
320*1c60b9acSAndroid Build Coastguard Worker {
321*1c60b9acSAndroid Build Coastguard Worker lws_fop_flags_t local_flags = 0;
322*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_t priv;
323*1c60b9acSAndroid Build Coastguard Worker char rp[192];
324*1c60b9acSAndroid Build Coastguard Worker int m;
325*1c60b9acSAndroid Build Coastguard Worker
326*1c60b9acSAndroid Build Coastguard Worker /*
327*1c60b9acSAndroid Build Coastguard Worker * vpath points at the / after the fops signature in vfs_path, eg
328*1c60b9acSAndroid Build Coastguard Worker * with a vfs_path "/var/www/docs/manual.zip/index.html", vpath
329*1c60b9acSAndroid Build Coastguard Worker * will come pointing at "/index.html"
330*1c60b9acSAndroid Build Coastguard Worker */
331*1c60b9acSAndroid Build Coastguard Worker
332*1c60b9acSAndroid Build Coastguard Worker priv = lws_zalloc(sizeof(*priv), "fops_zip priv");
333*1c60b9acSAndroid Build Coastguard Worker if (!priv)
334*1c60b9acSAndroid Build Coastguard Worker return NULL;
335*1c60b9acSAndroid Build Coastguard Worker
336*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.fops = &fops_zip;
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker m = sizeof(rp) - 1;
339*1c60b9acSAndroid Build Coastguard Worker if ((vpath - vfs_path - 1) < m)
340*1c60b9acSAndroid Build Coastguard Worker m = lws_ptr_diff(vpath, vfs_path) - 1;
341*1c60b9acSAndroid Build Coastguard Worker lws_strncpy(rp, vfs_path, (unsigned int)m + 1);
342*1c60b9acSAndroid Build Coastguard Worker
343*1c60b9acSAndroid Build Coastguard Worker /* open the zip file itself using the incoming fops, not fops_zip */
344*1c60b9acSAndroid Build Coastguard Worker
345*1c60b9acSAndroid Build Coastguard Worker priv->zip_fop_fd = fops->LWS_FOP_OPEN(fops, rp, NULL, &local_flags);
346*1c60b9acSAndroid Build Coastguard Worker if (!priv->zip_fop_fd) {
347*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unable to open zip %s\n", __func__, rp);
348*1c60b9acSAndroid Build Coastguard Worker goto bail1;
349*1c60b9acSAndroid Build Coastguard Worker }
350*1c60b9acSAndroid Build Coastguard Worker
351*1c60b9acSAndroid Build Coastguard Worker if (*vpath == '/')
352*1c60b9acSAndroid Build Coastguard Worker vpath++;
353*1c60b9acSAndroid Build Coastguard Worker
354*1c60b9acSAndroid Build Coastguard Worker m = lws_fops_zip_scan(priv, vpath, (int)strlen(vpath));
355*1c60b9acSAndroid Build Coastguard Worker if (m) {
356*1c60b9acSAndroid Build Coastguard Worker lwsl_err("unable to find record matching '%s' %d\n", vpath, m);
357*1c60b9acSAndroid Build Coastguard Worker goto bail2;
358*1c60b9acSAndroid Build Coastguard Worker }
359*1c60b9acSAndroid Build Coastguard Worker
360*1c60b9acSAndroid Build Coastguard Worker /* the directory metadata tells us modification time, so pass it on */
361*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.mod_time = priv->hdr.mod_time;
362*1c60b9acSAndroid Build Coastguard Worker *flags |= LWS_FOP_FLAG_MOD_TIME_VALID | LWS_FOP_FLAG_VIRTUAL;
363*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.flags = *flags;
364*1c60b9acSAndroid Build Coastguard Worker
365*1c60b9acSAndroid Build Coastguard Worker /* The zip fop_fd is left pointing at the start of the content.
366*1c60b9acSAndroid Build Coastguard Worker *
367*1c60b9acSAndroid Build Coastguard Worker * 1) Content could be uncompressed (STORE), and we can always serve
368*1c60b9acSAndroid Build Coastguard Worker * that directly
369*1c60b9acSAndroid Build Coastguard Worker *
370*1c60b9acSAndroid Build Coastguard Worker * 2) Content could be compressed (GZIP), and the client can handle
371*1c60b9acSAndroid Build Coastguard Worker * receiving GZIP... we can wrap it in a GZIP header and trailer
372*1c60b9acSAndroid Build Coastguard Worker * and serve the content part directly. The flag indicating we
373*1c60b9acSAndroid Build Coastguard Worker * are providing GZIP directly is set so lws will send the right
374*1c60b9acSAndroid Build Coastguard Worker * headers.
375*1c60b9acSAndroid Build Coastguard Worker *
376*1c60b9acSAndroid Build Coastguard Worker * 3) Content could be compressed (GZIP) but the client can't handle
377*1c60b9acSAndroid Build Coastguard Worker * receiving GZIP... we can decompress it and serve as it is
378*1c60b9acSAndroid Build Coastguard Worker * inflated piecemeal.
379*1c60b9acSAndroid Build Coastguard Worker *
380*1c60b9acSAndroid Build Coastguard Worker * 4) Content may be compressed some unknown way... fail
381*1c60b9acSAndroid Build Coastguard Worker *
382*1c60b9acSAndroid Build Coastguard Worker */
383*1c60b9acSAndroid Build Coastguard Worker if (priv->hdr.method == ZIP_COMPRESSION_METHOD_STORE) {
384*1c60b9acSAndroid Build Coastguard Worker /*
385*1c60b9acSAndroid Build Coastguard Worker * it is stored uncompressed, leave it indicated as
386*1c60b9acSAndroid Build Coastguard Worker * uncompressed, and just serve it from inside the
387*1c60b9acSAndroid Build Coastguard Worker * zip with no gzip container;
388*1c60b9acSAndroid Build Coastguard Worker */
389*1c60b9acSAndroid Build Coastguard Worker
390*1c60b9acSAndroid Build Coastguard Worker lwsl_info("direct zip serving (stored)\n");
391*1c60b9acSAndroid Build Coastguard Worker
392*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.len = priv->hdr.uncomp_size;
393*1c60b9acSAndroid Build Coastguard Worker
394*1c60b9acSAndroid Build Coastguard Worker return &priv->fop_fd;
395*1c60b9acSAndroid Build Coastguard Worker }
396*1c60b9acSAndroid Build Coastguard Worker
397*1c60b9acSAndroid Build Coastguard Worker if ((*flags & LWS_FOP_FLAG_COMPR_ACCEPTABLE_GZIP) &&
398*1c60b9acSAndroid Build Coastguard Worker priv->hdr.method == ZIP_COMPRESSION_METHOD_DEFLATE) {
399*1c60b9acSAndroid Build Coastguard Worker
400*1c60b9acSAndroid Build Coastguard Worker /*
401*1c60b9acSAndroid Build Coastguard Worker * We can serve the gzipped file contents directly as gzip
402*1c60b9acSAndroid Build Coastguard Worker * from inside the zip container; client says it is OK.
403*1c60b9acSAndroid Build Coastguard Worker *
404*1c60b9acSAndroid Build Coastguard Worker * To convert to standalone gzip, we have to add a 10-byte
405*1c60b9acSAndroid Build Coastguard Worker * constant header and a variable 8-byte trailer around the
406*1c60b9acSAndroid Build Coastguard Worker * content.
407*1c60b9acSAndroid Build Coastguard Worker *
408*1c60b9acSAndroid Build Coastguard Worker * The 8-byte trailer is prepared now and held in the priv.
409*1c60b9acSAndroid Build Coastguard Worker */
410*1c60b9acSAndroid Build Coastguard Worker
411*1c60b9acSAndroid Build Coastguard Worker lwsl_info("direct zip serving (gzipped)\n");
412*1c60b9acSAndroid Build Coastguard Worker
413*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.len = sizeof(hd) + priv->hdr.comp_size +
414*1c60b9acSAndroid Build Coastguard Worker sizeof(priv->u);
415*1c60b9acSAndroid Build Coastguard Worker
416*1c60b9acSAndroid Build Coastguard Worker if (lws_is_be()) {
417*1c60b9acSAndroid Build Coastguard Worker uint8_t *p = priv->u.trailer8;
418*1c60b9acSAndroid Build Coastguard Worker
419*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)priv->hdr.crc32;
420*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(priv->hdr.crc32 >> 8);
421*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(priv->hdr.crc32 >> 16);
422*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(priv->hdr.crc32 >> 24);
423*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)priv->hdr.uncomp_size;
424*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(priv->hdr.uncomp_size >> 8);
425*1c60b9acSAndroid Build Coastguard Worker *p++ = (uint8_t)(priv->hdr.uncomp_size >> 16);
426*1c60b9acSAndroid Build Coastguard Worker *p = (uint8_t)(priv->hdr.uncomp_size >> 24);
427*1c60b9acSAndroid Build Coastguard Worker } else {
428*1c60b9acSAndroid Build Coastguard Worker priv->u.trailer32[0] = priv->hdr.crc32;
429*1c60b9acSAndroid Build Coastguard Worker priv->u.trailer32[1] = priv->hdr.uncomp_size;
430*1c60b9acSAndroid Build Coastguard Worker }
431*1c60b9acSAndroid Build Coastguard Worker
432*1c60b9acSAndroid Build Coastguard Worker *flags |= LWS_FOP_FLAG_COMPR_IS_GZIP;
433*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.flags = *flags;
434*1c60b9acSAndroid Build Coastguard Worker priv->add_gzip_container = 1;
435*1c60b9acSAndroid Build Coastguard Worker
436*1c60b9acSAndroid Build Coastguard Worker return &priv->fop_fd;
437*1c60b9acSAndroid Build Coastguard Worker }
438*1c60b9acSAndroid Build Coastguard Worker
439*1c60b9acSAndroid Build Coastguard Worker if (priv->hdr.method == ZIP_COMPRESSION_METHOD_DEFLATE) {
440*1c60b9acSAndroid Build Coastguard Worker
441*1c60b9acSAndroid Build Coastguard Worker /* we must decompress it to serve it */
442*1c60b9acSAndroid Build Coastguard Worker
443*1c60b9acSAndroid Build Coastguard Worker lwsl_info("decompressed zip serving\n");
444*1c60b9acSAndroid Build Coastguard Worker
445*1c60b9acSAndroid Build Coastguard Worker priv->fop_fd.len = priv->hdr.uncomp_size;
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker if (lws_fops_zip_reset_inflate(priv)) {
448*1c60b9acSAndroid Build Coastguard Worker lwsl_err("inflate init failed\n");
449*1c60b9acSAndroid Build Coastguard Worker goto bail2;
450*1c60b9acSAndroid Build Coastguard Worker }
451*1c60b9acSAndroid Build Coastguard Worker
452*1c60b9acSAndroid Build Coastguard Worker priv->decompress = 1;
453*1c60b9acSAndroid Build Coastguard Worker
454*1c60b9acSAndroid Build Coastguard Worker return &priv->fop_fd;
455*1c60b9acSAndroid Build Coastguard Worker }
456*1c60b9acSAndroid Build Coastguard Worker
457*1c60b9acSAndroid Build Coastguard Worker /* we can't handle it ... */
458*1c60b9acSAndroid Build Coastguard Worker
459*1c60b9acSAndroid Build Coastguard Worker lwsl_err("zipped file %s compressed in unknown way (%d)\n", vfs_path,
460*1c60b9acSAndroid Build Coastguard Worker priv->hdr.method);
461*1c60b9acSAndroid Build Coastguard Worker
462*1c60b9acSAndroid Build Coastguard Worker bail2:
463*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&priv->zip_fop_fd);
464*1c60b9acSAndroid Build Coastguard Worker bail1:
465*1c60b9acSAndroid Build Coastguard Worker free(priv);
466*1c60b9acSAndroid Build Coastguard Worker
467*1c60b9acSAndroid Build Coastguard Worker return NULL;
468*1c60b9acSAndroid Build Coastguard Worker }
469*1c60b9acSAndroid Build Coastguard Worker
470*1c60b9acSAndroid Build Coastguard Worker /* ie, we are closing the fop_fd for the file inside the gzip */
471*1c60b9acSAndroid Build Coastguard Worker
472*1c60b9acSAndroid Build Coastguard Worker static int
lws_fops_zip_close(lws_fop_fd_t * fd)473*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_close(lws_fop_fd_t *fd)
474*1c60b9acSAndroid Build Coastguard Worker {
475*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_t priv = fop_fd_to_priv(*fd);
476*1c60b9acSAndroid Build Coastguard Worker
477*1c60b9acSAndroid Build Coastguard Worker if (priv->decompress)
478*1c60b9acSAndroid Build Coastguard Worker inflateEnd(&priv->inflate);
479*1c60b9acSAndroid Build Coastguard Worker
480*1c60b9acSAndroid Build Coastguard Worker lws_vfs_file_close(&priv->zip_fop_fd); /* close the gzip fop_fd */
481*1c60b9acSAndroid Build Coastguard Worker
482*1c60b9acSAndroid Build Coastguard Worker free(priv);
483*1c60b9acSAndroid Build Coastguard Worker *fd = NULL;
484*1c60b9acSAndroid Build Coastguard Worker
485*1c60b9acSAndroid Build Coastguard Worker return 0;
486*1c60b9acSAndroid Build Coastguard Worker }
487*1c60b9acSAndroid Build Coastguard Worker
488*1c60b9acSAndroid Build Coastguard Worker static lws_fileofs_t
lws_fops_zip_seek_cur(lws_fop_fd_t fd,lws_fileofs_t offset_from_cur_pos)489*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_seek_cur(lws_fop_fd_t fd, lws_fileofs_t offset_from_cur_pos)
490*1c60b9acSAndroid Build Coastguard Worker {
491*1c60b9acSAndroid Build Coastguard Worker fd->pos = (lws_filepos_t)((lws_fileofs_t)fd->pos + offset_from_cur_pos);
492*1c60b9acSAndroid Build Coastguard Worker
493*1c60b9acSAndroid Build Coastguard Worker return (lws_fileofs_t)fd->pos;
494*1c60b9acSAndroid Build Coastguard Worker }
495*1c60b9acSAndroid Build Coastguard Worker
496*1c60b9acSAndroid Build Coastguard Worker static int
lws_fops_zip_read(lws_fop_fd_t fd,lws_filepos_t * amount,uint8_t * buf,lws_filepos_t len)497*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_read(lws_fop_fd_t fd, lws_filepos_t *amount, uint8_t *buf,
498*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t len)
499*1c60b9acSAndroid Build Coastguard Worker {
500*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_t priv = fop_fd_to_priv(fd);
501*1c60b9acSAndroid Build Coastguard Worker lws_filepos_t ramount, rlen, cur = lws_vfs_tell(fd);
502*1c60b9acSAndroid Build Coastguard Worker int ret;
503*1c60b9acSAndroid Build Coastguard Worker
504*1c60b9acSAndroid Build Coastguard Worker if (priv->decompress) {
505*1c60b9acSAndroid Build Coastguard Worker
506*1c60b9acSAndroid Build Coastguard Worker if (priv->exp_uncomp_pos != fd->pos) {
507*1c60b9acSAndroid Build Coastguard Worker /*
508*1c60b9acSAndroid Build Coastguard Worker * there has been a seek in the uncompressed fop_fd
509*1c60b9acSAndroid Build Coastguard Worker * we have to restart the decompression and loop eating
510*1c60b9acSAndroid Build Coastguard Worker * the decompressed data up to the seek point
511*1c60b9acSAndroid Build Coastguard Worker */
512*1c60b9acSAndroid Build Coastguard Worker lwsl_info("seek in decompressed\n");
513*1c60b9acSAndroid Build Coastguard Worker
514*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_reset_inflate(priv);
515*1c60b9acSAndroid Build Coastguard Worker
516*1c60b9acSAndroid Build Coastguard Worker while (priv->exp_uncomp_pos != fd->pos) {
517*1c60b9acSAndroid Build Coastguard Worker rlen = len;
518*1c60b9acSAndroid Build Coastguard Worker if (rlen > fd->pos - priv->exp_uncomp_pos)
519*1c60b9acSAndroid Build Coastguard Worker rlen = fd->pos - priv->exp_uncomp_pos;
520*1c60b9acSAndroid Build Coastguard Worker if (lws_fops_zip_read(fd, amount, buf, rlen))
521*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_SEEK_COMPRESSED;
522*1c60b9acSAndroid Build Coastguard Worker }
523*1c60b9acSAndroid Build Coastguard Worker *amount = 0;
524*1c60b9acSAndroid Build Coastguard Worker }
525*1c60b9acSAndroid Build Coastguard Worker
526*1c60b9acSAndroid Build Coastguard Worker priv->inflate.avail_out = (unsigned int)len;
527*1c60b9acSAndroid Build Coastguard Worker priv->inflate.next_out = buf;
528*1c60b9acSAndroid Build Coastguard Worker
529*1c60b9acSAndroid Build Coastguard Worker spin:
530*1c60b9acSAndroid Build Coastguard Worker if (!priv->inflate.avail_in) {
531*1c60b9acSAndroid Build Coastguard Worker rlen = sizeof(priv->rbuf);
532*1c60b9acSAndroid Build Coastguard Worker if (rlen > eff_size(priv) - (cur - priv->content_start))
533*1c60b9acSAndroid Build Coastguard Worker rlen = eff_size(priv) - (cur - priv->content_start);
534*1c60b9acSAndroid Build Coastguard Worker
535*1c60b9acSAndroid Build Coastguard Worker if (priv->zip_fop_fd->fops->LWS_FOP_READ(
536*1c60b9acSAndroid Build Coastguard Worker priv->zip_fop_fd, &ramount, priv->rbuf,
537*1c60b9acSAndroid Build Coastguard Worker rlen))
538*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_READ_CONTENT;
539*1c60b9acSAndroid Build Coastguard Worker
540*1c60b9acSAndroid Build Coastguard Worker cur += ramount;
541*1c60b9acSAndroid Build Coastguard Worker
542*1c60b9acSAndroid Build Coastguard Worker priv->inflate.avail_in = (unsigned int)ramount;
543*1c60b9acSAndroid Build Coastguard Worker priv->inflate.next_in = priv->rbuf;
544*1c60b9acSAndroid Build Coastguard Worker }
545*1c60b9acSAndroid Build Coastguard Worker
546*1c60b9acSAndroid Build Coastguard Worker ret = inflate(&priv->inflate, Z_NO_FLUSH);
547*1c60b9acSAndroid Build Coastguard Worker if (ret == Z_STREAM_ERROR)
548*1c60b9acSAndroid Build Coastguard Worker return ret;
549*1c60b9acSAndroid Build Coastguard Worker
550*1c60b9acSAndroid Build Coastguard Worker switch (ret) {
551*1c60b9acSAndroid Build Coastguard Worker case Z_NEED_DICT:
552*1c60b9acSAndroid Build Coastguard Worker ret = Z_DATA_ERROR;
553*1c60b9acSAndroid Build Coastguard Worker /* fallthru */
554*1c60b9acSAndroid Build Coastguard Worker case Z_DATA_ERROR:
555*1c60b9acSAndroid Build Coastguard Worker case Z_MEM_ERROR:
556*1c60b9acSAndroid Build Coastguard Worker
557*1c60b9acSAndroid Build Coastguard Worker return ret;
558*1c60b9acSAndroid Build Coastguard Worker }
559*1c60b9acSAndroid Build Coastguard Worker
560*1c60b9acSAndroid Build Coastguard Worker if (!priv->inflate.avail_in && priv->inflate.avail_out &&
561*1c60b9acSAndroid Build Coastguard Worker cur != priv->content_start + priv->hdr.comp_size)
562*1c60b9acSAndroid Build Coastguard Worker goto spin;
563*1c60b9acSAndroid Build Coastguard Worker
564*1c60b9acSAndroid Build Coastguard Worker *amount = len - priv->inflate.avail_out;
565*1c60b9acSAndroid Build Coastguard Worker
566*1c60b9acSAndroid Build Coastguard Worker priv->exp_uncomp_pos += *amount;
567*1c60b9acSAndroid Build Coastguard Worker fd->pos += *amount;
568*1c60b9acSAndroid Build Coastguard Worker
569*1c60b9acSAndroid Build Coastguard Worker return 0;
570*1c60b9acSAndroid Build Coastguard Worker }
571*1c60b9acSAndroid Build Coastguard Worker
572*1c60b9acSAndroid Build Coastguard Worker if (priv->add_gzip_container) {
573*1c60b9acSAndroid Build Coastguard Worker
574*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: gzip + container\n", __func__);
575*1c60b9acSAndroid Build Coastguard Worker *amount = 0;
576*1c60b9acSAndroid Build Coastguard Worker
577*1c60b9acSAndroid Build Coastguard Worker /* place the canned header at the start */
578*1c60b9acSAndroid Build Coastguard Worker
579*1c60b9acSAndroid Build Coastguard Worker if (len && fd->pos < sizeof(hd)) {
580*1c60b9acSAndroid Build Coastguard Worker rlen = sizeof(hd) - fd->pos;
581*1c60b9acSAndroid Build Coastguard Worker if (rlen > len)
582*1c60b9acSAndroid Build Coastguard Worker rlen = len;
583*1c60b9acSAndroid Build Coastguard Worker /* provide stuff from canned header */
584*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, hd + fd->pos, (size_t)rlen);
585*1c60b9acSAndroid Build Coastguard Worker fd->pos += rlen;
586*1c60b9acSAndroid Build Coastguard Worker buf += rlen;
587*1c60b9acSAndroid Build Coastguard Worker len -= rlen;
588*1c60b9acSAndroid Build Coastguard Worker *amount += rlen;
589*1c60b9acSAndroid Build Coastguard Worker }
590*1c60b9acSAndroid Build Coastguard Worker
591*1c60b9acSAndroid Build Coastguard Worker /* serve gzipped data direct from zipfile */
592*1c60b9acSAndroid Build Coastguard Worker
593*1c60b9acSAndroid Build Coastguard Worker if (len && fd->pos >= sizeof(hd) &&
594*1c60b9acSAndroid Build Coastguard Worker fd->pos < priv->hdr.comp_size + sizeof(hd)) {
595*1c60b9acSAndroid Build Coastguard Worker
596*1c60b9acSAndroid Build Coastguard Worker rlen = priv->hdr.comp_size - (priv->zip_fop_fd->pos -
597*1c60b9acSAndroid Build Coastguard Worker priv->content_start);
598*1c60b9acSAndroid Build Coastguard Worker if (rlen > len)
599*1c60b9acSAndroid Build Coastguard Worker rlen = len;
600*1c60b9acSAndroid Build Coastguard Worker
601*1c60b9acSAndroid Build Coastguard Worker if (rlen &&
602*1c60b9acSAndroid Build Coastguard Worker priv->zip_fop_fd->pos < (priv->hdr.comp_size +
603*1c60b9acSAndroid Build Coastguard Worker priv->content_start)) {
604*1c60b9acSAndroid Build Coastguard Worker if (lws_vfs_file_read(priv->zip_fop_fd,
605*1c60b9acSAndroid Build Coastguard Worker &ramount, buf, rlen))
606*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_READ_CONTENT;
607*1c60b9acSAndroid Build Coastguard Worker *amount += ramount;
608*1c60b9acSAndroid Build Coastguard Worker fd->pos += ramount; // virtual pos
609*1c60b9acSAndroid Build Coastguard Worker buf += ramount;
610*1c60b9acSAndroid Build Coastguard Worker len -= ramount;
611*1c60b9acSAndroid Build Coastguard Worker }
612*1c60b9acSAndroid Build Coastguard Worker }
613*1c60b9acSAndroid Build Coastguard Worker
614*1c60b9acSAndroid Build Coastguard Worker /* place the prepared trailer at the end */
615*1c60b9acSAndroid Build Coastguard Worker
616*1c60b9acSAndroid Build Coastguard Worker if (len && fd->pos >= priv->hdr.comp_size + sizeof(hd) &&
617*1c60b9acSAndroid Build Coastguard Worker fd->pos < priv->hdr.comp_size + sizeof(hd) +
618*1c60b9acSAndroid Build Coastguard Worker sizeof(priv->u)) {
619*1c60b9acSAndroid Build Coastguard Worker cur = fd->pos - priv->hdr.comp_size - sizeof(hd);
620*1c60b9acSAndroid Build Coastguard Worker rlen = sizeof(priv->u) - cur;
621*1c60b9acSAndroid Build Coastguard Worker if (rlen > len)
622*1c60b9acSAndroid Build Coastguard Worker rlen = len;
623*1c60b9acSAndroid Build Coastguard Worker
624*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, priv->u.trailer8 + cur, (size_t)rlen);
625*1c60b9acSAndroid Build Coastguard Worker
626*1c60b9acSAndroid Build Coastguard Worker *amount += rlen;
627*1c60b9acSAndroid Build Coastguard Worker fd->pos += rlen;
628*1c60b9acSAndroid Build Coastguard Worker }
629*1c60b9acSAndroid Build Coastguard Worker
630*1c60b9acSAndroid Build Coastguard Worker return 0;
631*1c60b9acSAndroid Build Coastguard Worker }
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: store\n", __func__);
634*1c60b9acSAndroid Build Coastguard Worker
635*1c60b9acSAndroid Build Coastguard Worker if (len > eff_size(priv) - cur)
636*1c60b9acSAndroid Build Coastguard Worker len = eff_size(priv) - cur;
637*1c60b9acSAndroid Build Coastguard Worker
638*1c60b9acSAndroid Build Coastguard Worker if (priv->zip_fop_fd->fops->LWS_FOP_READ(priv->zip_fop_fd,
639*1c60b9acSAndroid Build Coastguard Worker amount, buf, len))
640*1c60b9acSAndroid Build Coastguard Worker return LWS_FZ_ERR_READ_CONTENT;
641*1c60b9acSAndroid Build Coastguard Worker
642*1c60b9acSAndroid Build Coastguard Worker fd->pos += *amount;
643*1c60b9acSAndroid Build Coastguard Worker
644*1c60b9acSAndroid Build Coastguard Worker return 0;
645*1c60b9acSAndroid Build Coastguard Worker }
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker struct lws_plat_file_ops fops_zip = {
648*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_open,
649*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_close,
650*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_seek_cur,
651*1c60b9acSAndroid Build Coastguard Worker lws_fops_zip_read,
652*1c60b9acSAndroid Build Coastguard Worker NULL,
653*1c60b9acSAndroid Build Coastguard Worker { { ".zip/", 5 }, { ".jar/", 5 }, { ".war/", 5 } },
654*1c60b9acSAndroid Build Coastguard Worker NULL,
655*1c60b9acSAndroid Build Coastguard Worker };
656