This source file includes following definitions.
- zip_source_window
- _zip_source_window_new
- _zip_source_set_source_archive
- _zip_source_invalidate
- window_read
- _zip_deregister_source
- _zip_register_source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include "zipint.h"
39
40 struct window {
41 zip_uint64_t start;
42 zip_uint64_t end;
43 zip_uint64_t offset;
44 zip_stat_t stat;
45 zip_error_t error;
46 zip_int64_t supports;
47 bool needs_seek;
48 };
49
50 static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
51
52
53 zip_source_t *
54 zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len)
55 {
56 return _zip_source_window_new(src, start, len, NULL, &za->error);
57 }
58
59
60 zip_source_t *
61 _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_error_t *error)
62 {
63 struct window *ctx;
64
65 if (src == NULL || start + length < start) {
66 zip_error_set(error, ZIP_ER_INVAL, 0);
67 return NULL;
68 }
69
70 if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) {
71 zip_error_set(error, ZIP_ER_MEMORY, 0);
72 return NULL;
73 }
74
75 ctx->start = start;
76 ctx->end = start + length;
77 zip_stat_init(&ctx->stat);
78 zip_error_init(&ctx->error);
79 ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
80 ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false;
81
82 if (st) {
83 if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
84 free(ctx);
85 return NULL;
86 }
87 }
88
89 return zip_source_layered_create(src, window_read, ctx, error);
90 }
91
92
93 int
94 _zip_source_set_source_archive(zip_source_t *src, zip_t *za)
95 {
96 src->source_archive = za;
97 return _zip_register_source(za, src);
98 }
99
100
101
102 void
103 _zip_source_invalidate(zip_source_t *src)
104 {
105 src->source_closed = 1;
106
107 if (zip_error_code_zip(&src->error) == ZIP_ER_OK) {
108 zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0);
109 }
110 }
111
112
113 static zip_int64_t
114 window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
115 {
116 struct window *ctx;
117 zip_int64_t ret;
118 zip_uint64_t n, i;
119 char b[8192];
120
121 ctx = (struct window *)_ctx;
122
123 switch (cmd) {
124 case ZIP_SOURCE_CLOSE:
125 return 0;
126
127 case ZIP_SOURCE_ERROR:
128 return zip_error_to_data(&ctx->error, data, len);
129
130 case ZIP_SOURCE_FREE:
131 free(ctx);
132 return 0;
133
134 case ZIP_SOURCE_OPEN:
135 if (!ctx->needs_seek) {
136 for (n=0; n<ctx->start; n+=(zip_uint64_t)ret) {
137 i = (ctx->start-n > sizeof(b) ? sizeof(b) : ctx->start-n);
138 if ((ret=zip_source_read(src, b, i)) < 0) {
139 _zip_error_set_from_source(&ctx->error, src);
140 return -1;
141 }
142 if (ret==0) {
143 zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
144 return -1;
145 }
146 }
147
148 }
149 ctx->offset = ctx->start;
150 return 0;
151
152 case ZIP_SOURCE_READ:
153 if (len > ctx->end - ctx->offset)
154 len = ctx->end - ctx->offset;
155
156 if (len == 0)
157 return 0;
158
159 if (ctx->needs_seek) {
160 if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) {
161 _zip_error_set_from_source(&ctx->error, src);
162 return -1;
163 }
164 }
165
166 if ((ret=zip_source_read(src, data, len)) < 0) {
167 zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
168 return -1;
169 }
170
171 ctx->offset += (zip_uint64_t)ret;
172
173 if (ret == 0) {
174 if (ctx->offset < ctx->end) {
175 zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
176 return -1;
177 }
178 }
179 return ret;
180
181 case ZIP_SOURCE_SEEK:
182 {
183 zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error);
184
185 if (new_offset < 0) {
186 return -1;
187 }
188
189 ctx->offset = (zip_uint64_t)new_offset + ctx->start;
190 return 0;
191 }
192
193 case ZIP_SOURCE_STAT:
194 {
195 zip_stat_t *st;
196
197 st = (zip_stat_t *)data;
198
199 if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
200 return -1;
201 }
202 return 0;
203 }
204
205 case ZIP_SOURCE_SUPPORTS:
206 return ctx->supports;
207
208 case ZIP_SOURCE_TELL:
209 return (zip_int64_t)(ctx->offset - ctx->start);
210
211 default:
212 zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
213 return -1;
214 }
215 }
216
217
218 void
219 _zip_deregister_source(zip_t *za, zip_source_t *src)
220 {
221 unsigned int i;
222
223 for (i=0; i<za->nopen_source; i++) {
224 if (za->open_source[i] == src) {
225 za->open_source[i] = za->open_source[za->nopen_source-1];
226 za->nopen_source--;
227 break;
228 }
229 }
230 }
231
232
233 int
234 _zip_register_source(zip_t *za, zip_source_t *src)
235 {
236 zip_source_t **open_source;
237
238 if (za->nopen_source+1 >= za->nopen_source_alloc) {
239 unsigned int n;
240 n = za->nopen_source_alloc + 10;
241 open_source = (zip_source_t **)realloc(za->open_source, n*sizeof(zip_source_t *));
242 if (open_source == NULL) {
243 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
244 return -1;
245 }
246 za->nopen_source_alloc = n;
247 za->open_source = open_source;
248 }
249
250 za->open_source[za->nopen_source++] = src;
251
252 return 0;
253 }