VirtualBox

source: vbox/trunk/src/libs/zlib-1.3.1/gzwrite.c

最後變更 在這個檔案是 108382,由 vboxsync 提交於 3 週 前

zlib-1.3.1: Applied and adjusted our zlib changes to 1.3.1. jiraref:VBP-1328

  • 屬性 svn:eol-style 設為 native
檔案大小: 22.4 KB
 
1/* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004-2019 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6#include "gzguts.h"
7
8/* Initialize state for writing a gzip file. Mark initialization by setting
9 state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
10 success. */
11local int gz_init(gz_statep state) {
12 int ret;
13 z_streamp strm = &(state->strm);
14
15 /* allocate input buffer (double size for gzprintf) */
16 state->in = (unsigned char *)malloc(state->want << 1);
17 if (state->in == NULL) {
18 gz_error(state, Z_MEM_ERROR, "out of memory");
19 return -1;
20 }
21
22 /* only need output buffer and deflate state if compressing */
23 if (!state->direct) {
24 /* allocate output buffer */
25 state->out = (unsigned char *)malloc(state->want);
26 if (state->out == NULL) {
27 free(state->in);
28 gz_error(state, Z_MEM_ERROR, "out of memory");
29 return -1;
30 }
31
32 /* allocate deflate memory, set up for gzip compression */
33 strm->zalloc = Z_NULL;
34 strm->zfree = Z_NULL;
35 strm->opaque = Z_NULL;
36 ret = deflateInit2(strm, state->level, Z_DEFLATED,
37 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
38 if (ret != Z_OK) {
39 free(state->out);
40 free(state->in);
41 gz_error(state, Z_MEM_ERROR, "out of memory");
42 return -1;
43 }
44 strm->next_in = NULL;
45 }
46
47 /* mark state as initialized */
48 state->size = state->want;
49
50 /* initialize write buffer if compressing */
51 if (!state->direct) {
52 strm->avail_out = state->size;
53 strm->next_out = state->out;
54 state->x.next = strm->next_out;
55 }
56 return 0;
57}
58
59#ifdef IPRT_NO_CRT /* VBox */
60DECLINLINE(int) gz_write_wrap(gz_statep state, void const *pvSrc, size_t cbToWrite) /* VBox */
61{ /* VBox */
62 size_t cbWritten; /* VBox */
63 int ret = RTFileWrite(state->fd, pvSrc, cbToWrite, &cbWritten); /* VBox */
64 if (RT_SUCCESS(ret)) /* VBox */
65 ret = (int)cbWritten; /* VBox */
66 else { /* VBox */
67 char szDefine[80]; /* VBox */
68 RTErrQueryDefine(ret, szDefine, sizeof(szDefine), false); /* VBox */
69 gz_error(state, Z_ERRNO, szDefine); /* VBox */
70 ret = -1; /* VBox */
71 } /* VBox */
72 return ret; /* VBox */
73} /* VBox */
74#endif /* IPRT_NO_CRT */ /* VBox */
75
76/* Compress whatever is at avail_in and next_in and write to the output file.
77 Return -1 if there is an error writing to the output file or if gz_init()
78 fails to allocate memory, otherwise 0. flush is assumed to be a valid
79 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
80 reset to start a new gzip stream. If gz->direct is true, then simply write
81 to the output file without compressing, and ignore flush. */
82local int gz_comp(gz_statep state, int flush) {
83 int ret, writ;
84 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
85 z_streamp strm = &(state->strm);
86
87 /* allocate memory if this is the first time through */
88 if (state->size == 0 && gz_init(state) == -1)
89 return -1;
90
91 /* write directly if requested */
92 if (state->direct) {
93 while (strm->avail_in) {
94 put = strm->avail_in > max ? max : strm->avail_in;
95#ifndef IPRT_NO_CRT /* VBox */
96 writ = write(state->fd, strm->next_in, put);
97 if (writ < 0) {
98 gz_error(state, Z_ERRNO, zstrerror());
99 return -1;
100 }
101#else /* VBox */
102 writ = gz_write_wrap(state, strm->next_in, put); /* VBox */
103 if (writ < 0) /* VBox */
104 return -1; /* VBox */
105#endif /* VBox */
106 strm->avail_in -= (unsigned)writ;
107 strm->next_in += writ;
108 }
109 return 0;
110 }
111
112 /* check for a pending reset */
113 if (state->reset) {
114 /* don't start a new gzip member unless there is data to write */
115 if (strm->avail_in == 0)
116 return 0;
117 deflateReset(strm);
118 state->reset = 0;
119 }
120
121 /* run deflate() on provided input until it produces no more output */
122 ret = Z_OK;
123 do {
124 /* write out current buffer contents if full, or if flushing, but if
125 doing Z_FINISH then don't write until we get to Z_STREAM_END */
126 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
127 (flush != Z_FINISH || ret == Z_STREAM_END))) {
128 while (strm->next_out > state->x.next) {
129 put = strm->next_out - state->x.next > (int)max ? max :
130 (unsigned)(strm->next_out - state->x.next);
131#ifndef IPRT_NO_CRT /* VBox */
132 writ = write(state->fd, state->x.next, put);
133 if (writ < 0) {
134 gz_error(state, Z_ERRNO, zstrerror());
135 return -1;
136 }
137#else /* VBox */
138 writ = gz_write_wrap(state, state->x.next, put); /* VBox */
139 if (writ < 0) /* VBox */
140 return -1; /* VBox */
141#endif /* VBox */
142 state->x.next += writ;
143 }
144 if (strm->avail_out == 0) {
145 strm->avail_out = state->size;
146 strm->next_out = state->out;
147 state->x.next = state->out;
148 }
149 }
150
151 /* compress */
152 have = strm->avail_out;
153 ret = deflate(strm, flush);
154 if (ret == Z_STREAM_ERROR) {
155 gz_error(state, Z_STREAM_ERROR,
156 "internal error: deflate stream corrupt");
157 return -1;
158 }
159 have -= strm->avail_out;
160 } while (have);
161
162 /* if that completed a deflate stream, allow another to start */
163 if (flush == Z_FINISH)
164 state->reset = 1;
165
166 /* all done, no errors */
167 return 0;
168}
169
170/* Compress len zeros to output. Return -1 on a write error or memory
171 allocation failure by gz_comp(), or 0 on success. */
172local int gz_zero(gz_statep state, z_off64_t len) {
173 int first;
174 unsigned n;
175 z_streamp strm = &(state->strm);
176
177 /* consume whatever's left in the input buffer */
178 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
179 return -1;
180
181 /* compress len zeros (len guaranteed > 0) */
182 first = 1;
183 while (len) {
184 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
185 (unsigned)len : state->size;
186 if (first) {
187 memset(state->in, 0, n);
188 first = 0;
189 }
190 strm->avail_in = n;
191 strm->next_in = state->in;
192 state->x.pos += n;
193 if (gz_comp(state, Z_NO_FLUSH) == -1)
194 return -1;
195 len -= n;
196 }
197 return 0;
198}
199
200/* Write len bytes from buf to file. Return the number of bytes written. If
201 the returned value is less than len, then there was an error. */
202local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
203 z_size_t put = len;
204
205 /* if len is zero, avoid unnecessary operations */
206 if (len == 0)
207 return 0;
208
209 /* allocate memory if this is the first time through */
210 if (state->size == 0 && gz_init(state) == -1)
211 return 0;
212
213 /* check for seek request */
214 if (state->seek) {
215 state->seek = 0;
216 if (gz_zero(state, state->skip) == -1)
217 return 0;
218 }
219
220 /* for small len, copy to input buffer, otherwise compress directly */
221 if (len < state->size) {
222 /* copy to input buffer, compress when full */
223 do {
224 unsigned have, copy;
225
226 if (state->strm.avail_in == 0)
227 state->strm.next_in = state->in;
228 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
229 state->in);
230 copy = state->size - have;
231 if (copy > len)
232 copy = (unsigned)len;
233 memcpy(state->in + have, buf, copy);
234 state->strm.avail_in += copy;
235 state->x.pos += copy;
236 buf = (const char *)buf + copy;
237 len -= copy;
238 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
239 return 0;
240 } while (len);
241 }
242 else {
243 /* consume whatever's left in the input buffer */
244 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
245 return 0;
246
247 /* directly compress user buffer to file */
248 state->strm.next_in = (z_const Bytef *)buf;
249 do {
250 unsigned n = (unsigned)-1;
251 if (n > len)
252 n = (unsigned)len;
253 state->strm.avail_in = n;
254 state->x.pos += n;
255 if (gz_comp(state, Z_NO_FLUSH) == -1)
256 return 0;
257 len -= n;
258 } while (len);
259 }
260
261 /* input was all buffered or compressed */
262 return put;
263}
264
265/* -- see zlib.h -- */
266int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
267 gz_statep state;
268
269 /* get internal structure */
270 if (file == NULL)
271 return 0;
272 state = (gz_statep)file;
273
274 /* check that we're writing and that there's no error */
275 if (state->mode != GZ_WRITE || state->err != Z_OK)
276 return 0;
277
278 /* since an int is returned, make sure len fits in one, otherwise return
279 with an error (this avoids a flaw in the interface) */
280 if ((int)len < 0) {
281 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
282 return 0;
283 }
284
285 /* write len bytes from buf (the return value will fit in an int) */
286 return (int)gz_write(state, buf, len);
287}
288
289/* -- see zlib.h -- */
290z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
291 gzFile file) {
292 z_size_t len;
293 gz_statep state;
294
295 /* get internal structure */
296 if (file == NULL)
297 return 0;
298 state = (gz_statep)file;
299
300 /* check that we're writing and that there's no error */
301 if (state->mode != GZ_WRITE || state->err != Z_OK)
302 return 0;
303
304 /* compute bytes to read -- error on overflow */
305 len = nitems * size;
306 if (size && len / size != nitems) {
307 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
308 return 0;
309 }
310
311 /* write len bytes to buf, return the number of full items written */
312 return len ? gz_write(state, buf, len) / size : 0;
313}
314
315/* -- see zlib.h -- */
316int ZEXPORT gzputc(gzFile file, int c) {
317 unsigned have;
318 unsigned char buf[1];
319 gz_statep state;
320 z_streamp strm;
321
322 /* get internal structure */
323 if (file == NULL)
324 return -1;
325 state = (gz_statep)file;
326 strm = &(state->strm);
327
328 /* check that we're writing and that there's no error */
329 if (state->mode != GZ_WRITE || state->err != Z_OK)
330 return -1;
331
332 /* check for seek request */
333 if (state->seek) {
334 state->seek = 0;
335 if (gz_zero(state, state->skip) == -1)
336 return -1;
337 }
338
339 /* try writing to input buffer for speed (state->size == 0 if buffer not
340 initialized) */
341 if (state->size) {
342 if (strm->avail_in == 0)
343 strm->next_in = state->in;
344 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
345 if (have < state->size) {
346 state->in[have] = (unsigned char)c;
347 strm->avail_in++;
348 state->x.pos++;
349 return c & 0xff;
350 }
351 }
352
353 /* no room in buffer or not initialized, use gz_write() */
354 buf[0] = (unsigned char)c;
355 if (gz_write(state, buf, 1) != 1)
356 return -1;
357 return c & 0xff;
358}
359
360/* -- see zlib.h -- */
361int ZEXPORT gzputs(gzFile file, const char *s) {
362 z_size_t len, put;
363 gz_statep state;
364
365 /* get internal structure */
366 if (file == NULL)
367 return -1;
368 state = (gz_statep)file;
369
370 /* check that we're writing and that there's no error */
371 if (state->mode != GZ_WRITE || state->err != Z_OK)
372 return -1;
373
374 /* write string */
375 len = strlen(s);
376 if ((int)len < 0 || (unsigned)len != len) {
377 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
378 return -1;
379 }
380 put = gz_write(state, s, len);
381 return put < len ? -1 : (int)len;
382}
383
384#if defined(STDC) || defined(Z_HAVE_STDARG_H)
385#include <stdarg.h>
386
387/* -- see zlib.h -- */
388int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
389 int len;
390 unsigned left;
391 char *next;
392 gz_statep state;
393 z_streamp strm;
394
395 /* get internal structure */
396 if (file == NULL)
397 return Z_STREAM_ERROR;
398 state = (gz_statep)file;
399 strm = &(state->strm);
400
401 /* check that we're writing and that there's no error */
402 if (state->mode != GZ_WRITE || state->err != Z_OK)
403 return Z_STREAM_ERROR;
404
405 /* make sure we have some buffer space */
406 if (state->size == 0 && gz_init(state) == -1)
407 return state->err;
408
409 /* check for seek request */
410 if (state->seek) {
411 state->seek = 0;
412 if (gz_zero(state, state->skip) == -1)
413 return state->err;
414 }
415
416 /* do the printf() into the input buffer, put length in len -- the input
417 buffer is double-sized just for this function, so there is guaranteed to
418 be state->size bytes available after the current contents */
419 if (strm->avail_in == 0)
420 strm->next_in = state->in;
421 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
422 next[state->size - 1] = 0;
423#ifdef NO_vsnprintf
424# ifdef HAS_vsprintf_void
425 (void)vsprintf(next, format, va);
426 for (len = 0; len < state->size; len++)
427 if (next[len] == 0) break;
428# else
429 len = vsprintf(next, format, va);
430# endif
431#else
432# ifdef HAS_vsnprintf_void
433 (void)vsnprintf(next, state->size, format, va);
434 len = strlen(next);
435# else
436 len = vsnprintf(next, state->size, format, va);
437# endif
438#endif
439
440 /* check that printf() results fit in buffer */
441 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
442 return 0;
443
444 /* update buffer and position, compress first half if past that */
445 strm->avail_in += (unsigned)len;
446 state->x.pos += len;
447 if (strm->avail_in >= state->size) {
448 left = strm->avail_in - state->size;
449 strm->avail_in = state->size;
450 if (gz_comp(state, Z_NO_FLUSH) == -1)
451 return state->err;
452 memmove(state->in, state->in + state->size, left);
453 strm->next_in = state->in;
454 strm->avail_in = left;
455 }
456 return len;
457}
458
459int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
460 va_list va;
461 int ret;
462
463 va_start(va, format);
464 ret = gzvprintf(file, format, va);
465 va_end(va);
466 return ret;
467}
468
469#else /* !STDC && !Z_HAVE_STDARG_H */
470
471/* -- see zlib.h -- */
472int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
473 int a4, int a5, int a6, int a7, int a8, int a9, int a10,
474 int a11, int a12, int a13, int a14, int a15, int a16,
475 int a17, int a18, int a19, int a20) {
476 unsigned len, left;
477 char *next;
478 gz_statep state;
479 z_streamp strm;
480
481 /* get internal structure */
482 if (file == NULL)
483 return Z_STREAM_ERROR;
484 state = (gz_statep)file;
485 strm = &(state->strm);
486
487 /* check that can really pass pointer in ints */
488 if (sizeof(int) != sizeof(void *))
489 return Z_STREAM_ERROR;
490
491 /* check that we're writing and that there's no error */
492 if (state->mode != GZ_WRITE || state->err != Z_OK)
493 return Z_STREAM_ERROR;
494
495 /* make sure we have some buffer space */
496 if (state->size == 0 && gz_init(state) == -1)
497 return state->error;
498
499 /* check for seek request */
500 if (state->seek) {
501 state->seek = 0;
502 if (gz_zero(state, state->skip) == -1)
503 return state->error;
504 }
505
506 /* do the printf() into the input buffer, put length in len -- the input
507 buffer is double-sized just for this function, so there is guaranteed to
508 be state->size bytes available after the current contents */
509 if (strm->avail_in == 0)
510 strm->next_in = state->in;
511 next = (char *)(strm->next_in + strm->avail_in);
512 next[state->size - 1] = 0;
513#ifdef NO_snprintf
514# ifdef HAS_sprintf_void
515 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
516 a13, a14, a15, a16, a17, a18, a19, a20);
517 for (len = 0; len < size; len++)
518 if (next[len] == 0)
519 break;
520# else
521 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
522 a12, a13, a14, a15, a16, a17, a18, a19, a20);
523# endif
524#else
525# ifdef HAS_snprintf_void
526 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
527 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
528 len = strlen(next);
529# else
530 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
531 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
532# endif
533#endif
534
535 /* check that printf() results fit in buffer */
536 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
537 return 0;
538
539 /* update buffer and position, compress first half if past that */
540 strm->avail_in += len;
541 state->x.pos += len;
542 if (strm->avail_in >= state->size) {
543 left = strm->avail_in - state->size;
544 strm->avail_in = state->size;
545 if (gz_comp(state, Z_NO_FLUSH) == -1)
546 return state->err;
547 memmove(state->in, state->in + state->size, left);
548 strm->next_in = state->in;
549 strm->avail_in = left;
550 }
551 return (int)len;
552}
553
554#endif
555
556/* -- see zlib.h -- */
557int ZEXPORT gzflush(gzFile file, int flush) {
558 gz_statep state;
559
560 /* get internal structure */
561 if (file == NULL)
562 return Z_STREAM_ERROR;
563 state = (gz_statep)file;
564
565 /* check that we're writing and that there's no error */
566 if (state->mode != GZ_WRITE || state->err != Z_OK)
567 return Z_STREAM_ERROR;
568
569 /* check flush parameter */
570 if (flush < 0 || flush > Z_FINISH)
571 return Z_STREAM_ERROR;
572
573 /* check for seek request */
574 if (state->seek) {
575 state->seek = 0;
576 if (gz_zero(state, state->skip) == -1)
577 return state->err;
578 }
579
580 /* compress remaining data with requested flush */
581 (void)gz_comp(state, flush);
582 return state->err;
583}
584
585/* -- see zlib.h -- */
586int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
587 gz_statep state;
588 z_streamp strm;
589
590 /* get internal structure */
591 if (file == NULL)
592 return Z_STREAM_ERROR;
593 state = (gz_statep)file;
594 strm = &(state->strm);
595
596 /* check that we're writing and that there's no error */
597 if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
598 return Z_STREAM_ERROR;
599
600 /* if no change is requested, then do nothing */
601 if (level == state->level && strategy == state->strategy)
602 return Z_OK;
603
604 /* check for seek request */
605 if (state->seek) {
606 state->seek = 0;
607 if (gz_zero(state, state->skip) == -1)
608 return state->err;
609 }
610
611 /* change compression parameters for subsequent input */
612 if (state->size) {
613 /* flush previous input with previous parameters before changing */
614 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
615 return state->err;
616 deflateParams(strm, level, strategy);
617 }
618 state->level = level;
619 state->strategy = strategy;
620 return Z_OK;
621}
622
623/* -- see zlib.h -- */
624int ZEXPORT gzclose_w(gzFile file) {
625 int ret = Z_OK;
626 gz_statep state;
627
628 /* get internal structure */
629 if (file == NULL)
630 return Z_STREAM_ERROR;
631 state = (gz_statep)file;
632
633 /* check that we're writing */
634 if (state->mode != GZ_WRITE)
635 return Z_STREAM_ERROR;
636
637 /* check for seek request */
638 if (state->seek) {
639 state->seek = 0;
640 if (gz_zero(state, state->skip) == -1)
641 ret = state->err;
642 }
643
644 /* flush, free memory, and close file */
645 if (gz_comp(state, Z_FINISH) == -1)
646 ret = state->err;
647 if (state->size) {
648 if (!state->direct) {
649 (void)deflateEnd(&(state->strm));
650 free(state->out);
651 }
652 free(state->in);
653 }
654 gz_error(state, Z_OK, NULL);
655 free(state->path);
656#ifndef IPRT_NO_CRT /* VBox */
657 if (close(state->fd) == -1)
658#else /* VBox */
659 if (RT_FAILURE(RTFileClose(state->fd))) /* VBox */
660#endif /* VBox */
661 ret = Z_ERRNO;
662 free(state);
663 return ret;
664}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette