File: | libexec/got-read-tree/../../lib/inflate.c |
Warning: | line 399, column 3 Value stored to 'err' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2018 Stefan Sperling <stsp@openbsd.org> |
3 | * |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above |
6 | * copyright notice and this permission notice appear in all copies. |
7 | * |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ |
16 | |
17 | #include <sys/queue.h> |
18 | |
19 | #include <errno(*__errno()).h> |
20 | #include <stdio.h> |
21 | #include <stdlib.h> |
22 | #include <string.h> |
23 | #include <sha1.h> |
24 | #include <unistd.h> |
25 | #include <zlib.h> |
26 | #include <time.h> |
27 | |
28 | #include "got_error.h" |
29 | #include "got_object.h" |
30 | #include "got_path.h" |
31 | |
32 | #include "got_lib_inflate.h" |
33 | |
34 | #ifndef MIN |
35 | #define MIN(_a,_b)((_a) < (_b) ? (_a) : (_b)) ((_a) < (_b) ? (_a) : (_b)) |
36 | #endif |
37 | |
38 | const struct got_error * |
39 | got_inflate_init(struct got_inflate_buf *zb, uint8_t *outbuf, size_t bufsize, |
40 | struct got_inflate_checksum *csum) |
41 | { |
42 | const struct got_error *err = NULL((void *)0); |
43 | int zerr; |
44 | |
45 | memset(&zb->z, 0, sizeof(zb->z)); |
46 | |
47 | zb->z.zalloc = Z_NULL0; |
48 | zb->z.zfree = Z_NULL0; |
49 | zerr = inflateInit(&zb->z)inflateInit_((&zb->z), "1.2.3", sizeof(z_stream)); |
50 | if (zerr != Z_OK0) { |
51 | if (zerr == Z_ERRNO(-1)) |
52 | return got_error_from_errno("inflateInit"); |
53 | if (zerr == Z_MEM_ERROR(-4)) { |
54 | errno(*__errno()) = ENOMEM12; |
55 | return got_error_from_errno("inflateInit"); |
56 | } |
57 | return got_error(GOT_ERR_DECOMPRESSION8); |
58 | } |
59 | |
60 | zb->inlen = zb->outlen = bufsize; |
61 | |
62 | zb->inbuf = calloc(1, zb->inlen); |
63 | if (zb->inbuf == NULL((void *)0)) { |
64 | err = got_error_from_errno("calloc"); |
65 | goto done; |
66 | } |
67 | |
68 | zb->flags = 0; |
69 | if (outbuf == NULL((void *)0)) { |
70 | zb->outbuf = calloc(1, zb->outlen); |
71 | if (zb->outbuf == NULL((void *)0)) { |
72 | err = got_error_from_errno("calloc"); |
73 | goto done; |
74 | } |
75 | zb->flags |= GOT_INFLATE_F_OWN_OUTBUF0x02; |
76 | } else |
77 | zb->outbuf = outbuf; |
78 | |
79 | zb->csum = csum; |
80 | done: |
81 | if (err) |
82 | got_inflate_end(zb); |
83 | return err; |
84 | } |
85 | |
86 | static void |
87 | csum_input(struct got_inflate_checksum *csum, const char *buf, size_t len) |
88 | { |
89 | if (csum->input_crc) |
90 | *csum->input_crc = crc32(*csum->input_crc, buf, len); |
91 | |
92 | if (csum->input_sha1) |
93 | SHA1Update(csum->input_sha1, buf, len); |
94 | } |
95 | |
96 | const struct got_error * |
97 | got_inflate_read(struct got_inflate_buf *zb, FILE *f, size_t *outlenp, |
98 | size_t *consumed) |
99 | { |
100 | size_t last_total_out = zb->z.total_out; |
101 | size_t last_total_in = zb->z.total_in; |
102 | z_stream *z = &zb->z; |
103 | int ret = Z_ERRNO(-1); |
104 | |
105 | z->next_out = zb->outbuf; |
106 | z->avail_out = zb->outlen; |
107 | |
108 | *outlenp = 0; |
109 | if (consumed) |
110 | *consumed = 0; |
111 | do { |
112 | char *csum_in = NULL((void *)0); |
113 | size_t csum_avail = 0; |
114 | |
115 | if (z->avail_in == 0) { |
116 | size_t n = fread(zb->inbuf, 1, zb->inlen, f); |
117 | if (n == 0) { |
118 | if (ferror(f)(!__isthreaded ? (((f)->_flags & 0x0040) != 0) : (ferror )(f))) |
119 | return got_ferror(f, GOT_ERR_IO6); |
120 | /* EOF */ |
121 | ret = Z_STREAM_END1; |
122 | break; |
123 | } |
124 | z->next_in = zb->inbuf; |
125 | z->avail_in = n; |
126 | } |
127 | if (zb->csum) { |
128 | csum_in = z->next_in; |
129 | csum_avail = z->avail_in; |
130 | } |
131 | ret = inflate(z, Z_SYNC_FLUSH2); |
132 | if (zb->csum) |
133 | csum_input(zb->csum, csum_in, csum_avail - z->avail_in); |
134 | } while (ret == Z_OK0 && z->avail_out > 0); |
135 | |
136 | if (ret == Z_OK0 || ret == Z_BUF_ERROR(-5)) { |
137 | zb->flags |= GOT_INFLATE_F_HAVE_MORE0x01; |
138 | } else { |
139 | if (ret != Z_STREAM_END1) |
140 | return got_error(GOT_ERR_DECOMPRESSION8); |
141 | zb->flags &= ~GOT_INFLATE_F_HAVE_MORE0x01; |
142 | } |
143 | |
144 | *outlenp = z->total_out - last_total_out; |
145 | if (consumed) |
146 | *consumed += z->total_in - last_total_in; |
147 | return NULL((void *)0); |
148 | } |
149 | |
150 | const struct got_error * |
151 | got_inflate_read_fd(struct got_inflate_buf *zb, int fd, size_t *outlenp, |
152 | size_t *consumed) |
153 | { |
154 | size_t last_total_out = zb->z.total_out; |
155 | size_t last_total_in = zb->z.total_in; |
156 | z_stream *z = &zb->z; |
157 | int ret = Z_ERRNO(-1); |
158 | |
159 | z->next_out = zb->outbuf; |
160 | z->avail_out = zb->outlen; |
161 | |
162 | *outlenp = 0; |
163 | if (consumed) |
164 | *consumed = 0; |
165 | do { |
166 | char *csum_in = NULL((void *)0); |
167 | size_t csum_avail = 0; |
168 | |
169 | if (z->avail_in == 0) { |
170 | ssize_t n = read(fd, zb->inbuf, zb->inlen); |
171 | if (n < 0) |
172 | return got_error_from_errno("read"); |
173 | else if (n == 0) { |
174 | /* EOF */ |
175 | ret = Z_STREAM_END1; |
176 | break; |
177 | } |
178 | z->next_in = zb->inbuf; |
179 | z->avail_in = n; |
180 | } |
181 | if (zb->csum) { |
182 | csum_in = z->next_in; |
183 | csum_avail = z->avail_in; |
184 | } |
185 | ret = inflate(z, Z_SYNC_FLUSH2); |
186 | if (zb->csum) |
187 | csum_input(zb->csum, csum_in, csum_avail - z->avail_in); |
188 | } while (ret == Z_OK0 && z->avail_out > 0); |
189 | |
190 | if (ret == Z_OK0 || ret == Z_BUF_ERROR(-5)) { |
191 | zb->flags |= GOT_INFLATE_F_HAVE_MORE0x01; |
192 | } else { |
193 | if (ret != Z_STREAM_END1) |
194 | return got_error(GOT_ERR_DECOMPRESSION8); |
195 | zb->flags &= ~GOT_INFLATE_F_HAVE_MORE0x01; |
196 | } |
197 | |
198 | *outlenp = z->total_out - last_total_out; |
199 | if (consumed) |
200 | *consumed += z->total_in - last_total_in; |
201 | return NULL((void *)0); |
202 | } |
203 | |
204 | const struct got_error * |
205 | got_inflate_read_mmap(struct got_inflate_buf *zb, uint8_t *map, size_t offset, |
206 | size_t len, size_t *outlenp, size_t *consumed) |
207 | { |
208 | size_t last_total_out = zb->z.total_out; |
209 | z_stream *z = &zb->z; |
210 | int ret = Z_ERRNO(-1); |
211 | |
212 | z->next_out = zb->outbuf; |
213 | z->avail_out = zb->outlen; |
214 | |
215 | *outlenp = 0; |
216 | *consumed = 0; |
217 | |
218 | do { |
219 | char *csum_in = NULL((void *)0); |
220 | size_t csum_avail = 0; |
221 | size_t last_total_in = zb->z.total_in; |
222 | |
223 | if (z->avail_in == 0) { |
224 | if (len == 0) { |
225 | /* EOF */ |
226 | ret = Z_STREAM_END1; |
227 | break; |
228 | } |
229 | z->next_in = map + offset + *consumed; |
230 | z->avail_in = len - *consumed; |
231 | } |
232 | if (zb->csum) { |
233 | csum_in = z->next_in; |
234 | csum_avail = z->avail_in; |
235 | } |
236 | ret = inflate(z, Z_SYNC_FLUSH2); |
237 | if (zb->csum) |
238 | csum_input(zb->csum, csum_in, csum_avail - z->avail_in); |
239 | *consumed += z->total_in - last_total_in; |
240 | } while (ret == Z_OK0 && z->avail_out > 0); |
241 | |
242 | if (ret == Z_OK0 || ret == Z_BUF_ERROR(-5)) { |
243 | zb->flags |= GOT_INFLATE_F_HAVE_MORE0x01; |
244 | } else { |
245 | if (ret != Z_STREAM_END1) |
246 | return got_error(GOT_ERR_DECOMPRESSION8); |
247 | zb->flags &= ~GOT_INFLATE_F_HAVE_MORE0x01; |
248 | } |
249 | |
250 | *outlenp = z->total_out - last_total_out; |
251 | return NULL((void *)0); |
252 | } |
253 | |
254 | void |
255 | got_inflate_end(struct got_inflate_buf *zb) |
256 | { |
257 | free(zb->inbuf); |
258 | if (zb->flags & GOT_INFLATE_F_OWN_OUTBUF0x02) |
259 | free(zb->outbuf); |
260 | inflateEnd(&zb->z); |
261 | } |
262 | |
263 | const struct got_error * |
264 | got_inflate_to_mem(uint8_t **outbuf, size_t *outlen, |
265 | size_t *consumed_total, FILE *f) |
266 | { |
267 | const struct got_error *err; |
268 | size_t avail, consumed; |
269 | struct got_inflate_buf zb; |
270 | void *newbuf; |
271 | int nbuf = 1; |
272 | |
273 | if (outbuf) { |
274 | *outbuf = malloc(GOT_INFLATE_BUFSIZE32768); |
275 | if (*outbuf == NULL((void *)0)) |
276 | return got_error_from_errno("malloc"); |
277 | err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE32768, NULL((void *)0)); |
278 | } else |
279 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, NULL((void *)0)); |
280 | if (err) |
281 | return err; |
282 | |
283 | *outlen = 0; |
284 | if (consumed_total) |
285 | *consumed_total = 0; |
286 | |
287 | do { |
288 | err = got_inflate_read(&zb, f, &avail, &consumed); |
289 | if (err) |
290 | goto done; |
291 | *outlen += avail; |
292 | if (consumed_total) |
293 | *consumed_total += consumed; |
294 | if (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01) { |
295 | if (outbuf == NULL((void *)0)) |
296 | continue; |
297 | zb.outlen = (nbuf * GOT_INFLATE_BUFSIZE32768) - *outlen; |
298 | newbuf = reallocarray(*outbuf, ++nbuf, |
299 | GOT_INFLATE_BUFSIZE32768); |
300 | if (newbuf == NULL((void *)0)) { |
301 | err = got_error_from_errno("reallocarray"); |
302 | free(*outbuf); |
303 | *outbuf = NULL((void *)0); |
304 | *outlen = 0; |
305 | goto done; |
306 | } |
307 | *outbuf = newbuf; |
308 | zb.outbuf = newbuf + *outlen; |
309 | } |
310 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
311 | |
312 | done: |
313 | got_inflate_end(&zb); |
314 | return err; |
315 | } |
316 | |
317 | const struct got_error * |
318 | got_inflate_to_mem_fd(uint8_t **outbuf, size_t *outlen, |
319 | size_t *consumed_total, struct got_inflate_checksum *csum, |
320 | size_t expected_size, int infd) |
321 | { |
322 | const struct got_error *err; |
323 | size_t avail, consumed; |
324 | struct got_inflate_buf zb; |
325 | void *newbuf; |
326 | int nbuf = 1; |
327 | size_t bufsize = GOT_INFLATE_BUFSIZE32768; |
328 | |
329 | /* Optimize buffer size in case short reads should suffice. */ |
330 | if (expected_size > 0 && expected_size < bufsize) |
331 | bufsize = expected_size; |
332 | |
333 | if (outbuf) { |
334 | *outbuf = malloc(bufsize); |
335 | if (*outbuf == NULL((void *)0)) |
336 | return got_error_from_errno("malloc"); |
337 | err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE32768, csum); |
338 | } else |
339 | err = got_inflate_init(&zb, NULL((void *)0), bufsize, csum); |
340 | if (err) |
341 | goto done; |
342 | |
343 | *outlen = 0; |
344 | if (consumed_total) |
345 | *consumed_total = 0; |
346 | |
347 | do { |
348 | err = got_inflate_read_fd(&zb, infd, &avail, &consumed); |
349 | if (err) |
350 | goto done; |
351 | *outlen += avail; |
352 | if (consumed_total) |
353 | *consumed_total += consumed; |
354 | if (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01) { |
355 | if (outbuf == NULL((void *)0)) |
356 | continue; |
357 | zb.outlen = (nbuf * GOT_INFLATE_BUFSIZE32768) - *outlen; |
358 | newbuf = reallocarray(*outbuf, ++nbuf, |
359 | GOT_INFLATE_BUFSIZE32768); |
360 | if (newbuf == NULL((void *)0)) { |
361 | err = got_error_from_errno("reallocarray"); |
362 | free(*outbuf); |
363 | *outbuf = NULL((void *)0); |
364 | *outlen = 0; |
365 | goto done; |
366 | } |
367 | *outbuf = newbuf; |
368 | zb.outbuf = newbuf + *outlen; |
369 | } |
370 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
371 | |
372 | done: |
373 | got_inflate_end(&zb); |
374 | return err; |
375 | } |
376 | |
377 | const struct got_error * |
378 | got_inflate_to_mem_mmap(uint8_t **outbuf, size_t *outlen, |
379 | size_t *consumed_total, struct got_inflate_checksum *csum, uint8_t *map, |
380 | size_t offset, size_t len) |
381 | { |
382 | const struct got_error *err; |
383 | size_t avail, consumed; |
384 | struct got_inflate_buf zb; |
385 | void *newbuf; |
386 | int nbuf = 1; |
387 | |
388 | if (outbuf) { |
389 | *outbuf = malloc(GOT_INFLATE_BUFSIZE32768); |
390 | if (*outbuf == NULL((void *)0)) |
391 | return got_error_from_errno("malloc"); |
392 | err = got_inflate_init(&zb, *outbuf, GOT_INFLATE_BUFSIZE32768, csum); |
393 | if (err) { |
394 | free(*outbuf); |
395 | *outbuf = NULL((void *)0); |
396 | return err; |
397 | } |
398 | } else { |
399 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, csum); |
Value stored to 'err' is never read | |
400 | } |
401 | |
402 | *outlen = 0; |
403 | if (consumed_total) |
404 | *consumed_total = 0; |
405 | do { |
406 | err = got_inflate_read_mmap(&zb, map, offset, len, &avail, |
407 | &consumed); |
408 | if (err) |
409 | goto done; |
410 | offset += consumed; |
411 | if (consumed_total) |
412 | *consumed_total += consumed; |
413 | len -= consumed; |
414 | *outlen += avail; |
415 | if (len == 0) |
416 | break; |
417 | if (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01) { |
418 | if (outbuf == NULL((void *)0)) |
419 | continue; |
420 | newbuf = reallocarray(*outbuf, ++nbuf, |
421 | GOT_INFLATE_BUFSIZE32768); |
422 | if (newbuf == NULL((void *)0)) { |
423 | err = got_error_from_errno("reallocarray"); |
424 | free(*outbuf); |
425 | *outbuf = NULL((void *)0); |
426 | *outlen = 0; |
427 | goto done; |
428 | } |
429 | *outbuf = newbuf; |
430 | zb.outbuf = newbuf + *outlen; |
431 | zb.outlen = (nbuf * GOT_INFLATE_BUFSIZE32768) - *outlen; |
432 | } |
433 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
434 | done: |
435 | got_inflate_end(&zb); |
436 | return err; |
437 | } |
438 | |
439 | const struct got_error * |
440 | got_inflate_to_fd(size_t *outlen, FILE *infile, int outfd) |
441 | { |
442 | const struct got_error *err = NULL((void *)0); |
443 | size_t avail; |
444 | struct got_inflate_buf zb; |
445 | |
446 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, NULL((void *)0)); |
447 | if (err) |
448 | goto done; |
449 | |
450 | *outlen = 0; |
451 | |
452 | do { |
453 | err = got_inflate_read(&zb, infile, &avail, NULL((void *)0)); |
454 | if (err) |
455 | goto done; |
456 | if (avail > 0) { |
457 | ssize_t n; |
458 | n = write(outfd, zb.outbuf, avail); |
459 | if (n != avail) { |
460 | err = got_error_from_errno("write"); |
461 | goto done; |
462 | } |
463 | *outlen += avail; |
464 | } |
465 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
466 | |
467 | done: |
468 | if (err == NULL((void *)0)) { |
469 | if (lseek(outfd, SEEK_SET0, 0) == -1) |
470 | err = got_error_from_errno("lseek"); |
471 | } |
472 | got_inflate_end(&zb); |
473 | return err; |
474 | } |
475 | |
476 | const struct got_error * |
477 | got_inflate_to_file(size_t *outlen, FILE *infile, FILE *outfile) |
478 | { |
479 | const struct got_error *err; |
480 | size_t avail; |
481 | struct got_inflate_buf zb; |
482 | |
483 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, NULL((void *)0)); |
484 | if (err) |
485 | goto done; |
486 | |
487 | *outlen = 0; |
488 | |
489 | do { |
490 | err = got_inflate_read(&zb, infile, &avail, NULL((void *)0)); |
491 | if (err) |
492 | goto done; |
493 | if (avail > 0) { |
494 | size_t n; |
495 | n = fwrite(zb.outbuf, avail, 1, outfile); |
496 | if (n != 1) { |
497 | err = got_ferror(outfile, GOT_ERR_IO6); |
498 | goto done; |
499 | } |
500 | *outlen += avail; |
501 | } |
502 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
503 | |
504 | done: |
505 | if (err == NULL((void *)0)) |
506 | rewind(outfile); |
507 | got_inflate_end(&zb); |
508 | return err; |
509 | } |
510 | |
511 | const struct got_error * |
512 | got_inflate_to_file_fd(size_t *outlen, size_t *consumed_total, |
513 | struct got_inflate_checksum *csum, int infd, FILE *outfile) |
514 | { |
515 | const struct got_error *err; |
516 | size_t avail, consumed; |
517 | struct got_inflate_buf zb; |
518 | |
519 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, csum); |
520 | if (err) |
521 | goto done; |
522 | |
523 | *outlen = 0; |
524 | if (consumed_total) |
525 | *consumed_total = 0; |
526 | do { |
527 | err = got_inflate_read_fd(&zb, infd, &avail, &consumed); |
528 | if (err) |
529 | goto done; |
530 | if (avail > 0) { |
531 | size_t n; |
532 | n = fwrite(zb.outbuf, avail, 1, outfile); |
533 | if (n != 1) { |
534 | err = got_ferror(outfile, GOT_ERR_IO6); |
535 | goto done; |
536 | } |
537 | *outlen += avail; |
538 | if (consumed_total) |
539 | *consumed_total += consumed; |
540 | } |
541 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
542 | |
543 | done: |
544 | if (err == NULL((void *)0)) |
545 | rewind(outfile); |
546 | got_inflate_end(&zb); |
547 | return err; |
548 | } |
549 | |
550 | const struct got_error * |
551 | got_inflate_to_file_mmap(size_t *outlen, size_t *consumed_total, |
552 | struct got_inflate_checksum *csum, uint8_t *map, size_t offset, |
553 | size_t len, FILE *outfile) |
554 | { |
555 | const struct got_error *err; |
556 | size_t avail, consumed; |
557 | struct got_inflate_buf zb; |
558 | |
559 | err = got_inflate_init(&zb, NULL((void *)0), GOT_INFLATE_BUFSIZE32768, csum); |
560 | if (err) |
561 | goto done; |
562 | |
563 | *outlen = 0; |
564 | if (consumed_total) |
565 | *consumed_total = 0; |
566 | do { |
567 | err = got_inflate_read_mmap(&zb, map, offset, len, &avail, |
568 | &consumed); |
569 | if (err) |
570 | goto done; |
571 | offset += consumed; |
572 | if (consumed_total) |
573 | *consumed_total += consumed; |
574 | len -= consumed; |
575 | if (avail > 0) { |
576 | size_t n; |
577 | n = fwrite(zb.outbuf, avail, 1, outfile); |
578 | if (n != 1) { |
579 | err = got_ferror(outfile, GOT_ERR_IO6); |
580 | goto done; |
581 | } |
582 | *outlen += avail; |
583 | } |
584 | } while (zb.flags & GOT_INFLATE_F_HAVE_MORE0x01); |
585 | |
586 | done: |
587 | if (err == NULL((void *)0)) |
588 | rewind(outfile); |
589 | got_inflate_end(&zb); |
590 | return err; |
591 | } |