]> 4ch.mooo.com Git - 16.git/blob - src/lib/dl/ext/zlib/gzwrite.c
meh did some cleanings and i will work on mapread to mm thingy sometime soon! oops...
[16.git] / src / lib / dl / ext / zlib / gzwrite.c
1 /* gzwrite.c -- zlib functions for writing gzip files
2  * Copyright (C) 2004, 2005, 2010 Mark Adler
3  * For conditions of distribution and use, see copyright notice in zlib.h
4  */
5
6 #include "gzguts.h"
7 #include "zutil.h"
8
9 #if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__)
10 # include <dos.h>
11 #endif
12
13 /* Local functions */
14 local int gz_init OF((gz_statep));
15 local int gz_comp OF((gz_statep, int));
16 local int gz_zero OF((gz_statep, z_off64_t));
17
18 /* Initialize state for writing a gzip file.  Mark initialization by setting
19    state->size to non-zero.  Return -1 on failure or 0 on success. */
20 local int gz_init(state)
21     gz_statep state;
22 {
23     int ret;
24     z_streamp strm = &(state->strm);
25
26     /* allocate input and output buffers */
27 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
28     state->in = _fmalloc(state->want);
29     state->out = _fmalloc(state->want);
30 #else
31     state->in = malloc(state->want);
32     state->out = malloc(state->want);
33 #endif
34     if (state->in == NULL || state->out == NULL) {
35         fprintf(stderr,"Unable to malloc(%u x 2 = %lu)\n",
36                 state->want,
37                 (unsigned long)state->want * 2UL);
38 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
39         if (state->out != NULL)
40             _ffree(state->out);
41         if (state->in != NULL)
42             _ffree(state->in);
43 #else
44         if (state->out != NULL)
45             free(state->out);
46         if (state->in != NULL)
47             free(state->in);
48 #endif
49         gz_error(state, Z_MEM_ERROR, "out of memory");
50         return -1;
51     }
52
53     /* allocate deflate memory, set up for gzip compression */
54     strm->zalloc = Z_NULL;
55     strm->zfree = Z_NULL;
56     strm->opaque = Z_NULL;
57     ret = deflateInit2(strm, state->level, Z_DEFLATED,
58                        15 + 16, 8, state->strategy);
59     if (ret != Z_OK) {
60 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
61         _ffree(state->in);
62 #else
63         free(state->in);
64 #endif
65         gz_error(state, Z_MEM_ERROR, "out of memory");
66         return -1;
67     }
68
69     /* mark state as initialized */
70     state->size = state->want;
71
72     /* initialize write buffer */
73     strm->avail_out = state->size;
74     strm->next_out = state->out;
75     state->next = strm->next_out;
76     return 0;
77 }
78
79 /* Compress whatever is at avail_in and next_in and write to the output file.
80    Return -1 if there is an error writing to the output file, otherwise 0.
81    flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
82    then the deflate() state is reset to start a new gzip stream. */
83 local int gz_comp(state, flush)
84     gz_statep state;
85     int flush;
86 {
87     int ret, got;
88     unsigned have;
89     z_streamp strm = &(state->strm);
90
91     /* allocate memory if this is the first time through */
92     if (state->size == 0 && gz_init(state) == -1)
93         return -1;
94
95     /* run deflate() on provided input until it produces no more output */
96     ret = Z_OK;
97     do {
98         /* write out current buffer contents if full, or if flushing, but if
99            doing Z_FINISH then don't write until we get to Z_STREAM_END */
100         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
101             (flush != Z_FINISH || ret == Z_STREAM_END))) {
102             have = (unsigned)(strm->next_out - state->next);
103 #if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__)
104             got = 0;
105             if (have && (_dos_write(state->fd, state->next, have, (unsigned*)(&got)) != 0 ||
106                          (unsigned)got != have)) {
107 #else
108             if (have && ((got = write(state->fd, state->next, have)) < 0 ||
109                          (unsigned)got != have)) {
110 #endif
111                 gz_error(state, Z_ERRNO, zstrerror());
112                 return -1;
113             }
114             if (strm->avail_out == 0) {
115                 strm->avail_out = state->size;
116                 strm->next_out = state->out;
117             }
118             state->next = strm->next_out;
119         }
120
121         /* compress */
122         have = strm->avail_out;
123         ret = deflate(strm, flush);
124         if (ret == Z_STREAM_ERROR) {
125             gz_error(state, Z_STREAM_ERROR,
126                       "internal error: deflate stream corrupt");
127             return -1;
128         }
129         have -= strm->avail_out;
130     } while (have);
131
132     /* if that completed a deflate stream, allow another to start */
133     if (flush == Z_FINISH)
134         deflateReset(strm);
135
136     /* all done, no errors */
137     return 0;
138 }
139
140 /* Compress len zeros to output.  Return -1 on error, 0 on success. */
141 local int gz_zero(state, len)
142     gz_statep state;
143     z_off64_t len;
144 {
145     int first;
146     unsigned n;
147     z_streamp strm = &(state->strm);
148
149     /* consume whatever's left in the input buffer */
150     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
151         return -1;
152
153     /* compress len zeros (len guaranteed > 0) */
154     first = 1;
155     while (len) {
156         n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
157             (unsigned)len : state->size;
158         if (first) {
159             zmemzero(state->in, n);
160             first = 0;
161         }
162         strm->avail_in = n;
163         strm->next_in = state->in;
164         state->pos += n;
165         if (gz_comp(state, Z_NO_FLUSH) == -1)
166             return -1;
167         len -= n;
168     }
169     return 0;
170 }
171
172 /* -- see zlib.h -- */
173 int ZEXPORT gzwrite(file, buf, len)
174     gzFile file;
175     voidpcf buf;
176     unsigned len;
177 {
178     unsigned put = len;
179     unsigned n;
180     gz_statep state;
181     z_streamp strm;
182
183     /* get internal structure */
184     if (file == NULL)
185         return 0;
186     state = (gz_statep)file;
187     strm = &(state->strm);
188
189     /* check that we're writing and that there's no error */
190     if (state->mode != GZ_WRITE || state->err != Z_OK)
191         return 0;
192
193     /* since an int is returned, make sure len fits in one, otherwise return
194        with an error (this avoids the flaw in the interface) */
195     if ((int)len < 0) {
196         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
197         return 0;
198     }
199
200     /* if len is zero, avoid unnecessary operations */
201     if (len == 0)
202         return 0;
203
204     /* allocate memory if this is the first time through */
205     if (state->size == 0 && gz_init(state) == -1)
206         return 0;
207
208     /* check for seek request */
209     if (state->seek) {
210         state->seek = 0;
211         if (gz_zero(state, state->skip) == -1)
212             return 0;
213     }
214
215     /* for small len, copy to input buffer, otherwise compress directly */
216     if (len < state->size) {
217         /* copy to input buffer, compress when full */
218         do {
219             if (strm->avail_in == 0)
220                 strm->next_in = state->in;
221             n = state->size - strm->avail_in;
222             if (n > len)
223                 n = len;
224             zmemcpy(strm->next_in + strm->avail_in, buf, n);
225             strm->avail_in += n;
226             state->pos += n;
227             buf = (char *)buf + n;
228             len -= n;
229             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
230                 return 0;
231         } while (len);
232     }
233     else {
234         /* consume whatever's left in the input buffer */
235         if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
236             return 0;
237
238         /* directly compress user buffer to file */
239         strm->avail_in = len;
240         strm->next_in = (voidp)buf;
241         state->pos += len;
242         if (gz_comp(state, Z_NO_FLUSH) == -1)
243             return 0;
244     }
245
246     /* input was all buffered or compressed (put will fit in int) */
247     return (int)put;
248 }
249
250 /* -- see zlib.h -- */
251 int ZEXPORT gzputc(file, c)
252     gzFile file;
253     int c;
254 {
255     unsigned char buf[1];
256     gz_statep state;
257     z_streamp strm;
258
259     /* get internal structure */
260     if (file == NULL)
261         return -1;
262     state = (gz_statep)file;
263     strm = &(state->strm);
264
265     /* check that we're writing and that there's no error */
266     if (state->mode != GZ_WRITE || state->err != Z_OK)
267         return -1;
268
269     /* check for seek request */
270     if (state->seek) {
271         state->seek = 0;
272         if (gz_zero(state, state->skip) == -1)
273             return -1;
274     }
275
276     /* try writing to input buffer for speed (state->size == 0 if buffer not
277        initialized) */
278     if (strm->avail_in < state->size) {
279         if (strm->avail_in == 0)
280             strm->next_in = state->in;
281         strm->next_in[strm->avail_in++] = c;
282         state->pos++;
283         return c;
284     }
285
286     /* no room in buffer or not initialized, use gz_write() */
287     buf[0] = c;
288     if (gzwrite(file, buf, 1) != 1)
289         return -1;
290     return c;
291 }
292
293 /* -- see zlib.h -- */
294 int ZEXPORT gzputs(file, str)
295     gzFile file;
296     const char *str;
297 {
298     int ret;
299     unsigned len;
300
301     /* write string */
302     len = (unsigned)strlen(str);
303     ret = gzwrite(file, str, len);
304     return ret == 0 && len != 0 ? -1 : ret;
305 }
306
307 #ifdef STDC
308 #include <stdarg.h>
309
310 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
311 static unsigned char __gzprintf_buffer[1024];
312 #endif
313
314 /* -- see zlib.h -- */
315 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
316 {
317     int size, len;
318     gz_statep state;
319     z_streamp strm;
320     va_list va;
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 0;
331
332     /* make sure we have some buffer space */
333     if (state->size == 0 && gz_init(state) == -1)
334         return 0;
335
336     /* check for seek request */
337     if (state->seek) {
338         state->seek = 0;
339         if (gz_zero(state, state->skip) == -1)
340             return 0;
341     }
342
343     /* consume whatever's left in the input buffer */
344     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
345         return 0;
346
347     /* do the printf() into the input buffer, put length in len */
348     size = (int)(state->size);
349     state->in[size - 1] = 0;
350     va_start(va, format);
351 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
352     /* there is no vsprintf() that writes to a FAR pointer, so we have to vsprintf to a temp buffer */
353     len = vsnprintf((char*)__gzprintf_buffer,sizeof(__gzprintf_buffer),format,va);
354     if (len != 0) _fmemcpy(state->in,__gzprintf_buffer,len);
355     va_end(va);
356 #else
357 # ifdef NO_vsnprintf
358 #   ifdef HAS_vsprintf_void
359     (void)vsprintf(state->in, format, va);
360     va_end(va);
361     for (len = 0; len < size; len++)
362         if (state->in[len] == 0) break;
363 #   else
364     len = vsprintf(state->in, format, va);
365     va_end(va);
366 #   endif
367 # else
368 #   ifdef HAS_vsnprintf_void
369     (void)vsnprintf(state->in, size, format, va);
370     va_end(va);
371     len = strlen(state->in);
372 #   else
373     len = vsnprintf((char *)(state->in), size, format, va);
374     va_end(va);
375 #   endif
376 # endif
377 #endif
378
379     /* check that printf() results fit in buffer */
380     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
381         return 0;
382
383     /* update buffer and position, defer compression until needed */
384     strm->avail_in = (unsigned)len;
385     strm->next_in = state->in;
386     state->pos += len;
387     return len;
388 }
389
390 #else /* !STDC */
391
392 /* -- see zlib.h -- */
393 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
394                        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
395     gzFile file;
396     const char *format;
397     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
398         a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
399 {
400     int size, len;
401     gz_statep state;
402     z_streamp strm;
403
404     /* get internal structure */
405     if (file == NULL)
406         return -1;
407     state = (gz_statep)file;
408     strm = &(state->strm);
409
410     /* check that we're writing and that there's no error */
411     if (state->mode != GZ_WRITE || state->err != Z_OK)
412         return 0;
413
414     /* make sure we have some buffer space */
415     if (state->size == 0 && gz_init(state) == -1)
416         return 0;
417
418     /* check for seek request */
419     if (state->seek) {
420         state->seek = 0;
421         if (gz_zero(state, state->skip) == -1)
422             return 0;
423     }
424
425     /* consume whatever's left in the input buffer */
426     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
427         return 0;
428
429     /* do the printf() into the input buffer, put length in len */
430     size = (int)(state->size);
431     state->in[size - 1] = 0;
432 #ifdef NO_snprintf
433 #  ifdef HAS_sprintf_void
434     sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
435             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
436     for (len = 0; len < size; len++)
437         if (state->in[len] == 0) break;
438 #  else
439     len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
440                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
441 #  endif
442 #else
443 #  ifdef HAS_snprintf_void
444     snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
445              a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
446     len = strlen(state->in);
447 #  else
448     len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
449                  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
450 #  endif
451 #endif
452
453     /* check that printf() results fit in buffer */
454     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
455         return 0;
456
457     /* update buffer and position, defer compression until needed */
458     strm->avail_in = (unsigned)len;
459     strm->next_in = state->in;
460     state->pos += len;
461     return len;
462 }
463
464 #endif
465
466 /* -- see zlib.h -- */
467 int ZEXPORT gzflush(file, flush)
468     gzFile file;
469     int flush;
470 {
471     gz_statep state;
472
473     /* get internal structure */
474     if (file == NULL)
475         return -1;
476     state = (gz_statep)file;
477
478     /* check that we're writing and that there's no error */
479     if (state->mode != GZ_WRITE || state->err != Z_OK)
480         return Z_STREAM_ERROR;
481
482     /* check flush parameter */
483     if (flush < 0 || flush > Z_FINISH)
484         return Z_STREAM_ERROR;
485
486     /* check for seek request */
487     if (state->seek) {
488         state->seek = 0;
489         if (gz_zero(state, state->skip) == -1)
490             return -1;
491     }
492
493     /* compress remaining data with requested flush */
494     gz_comp(state, flush);
495     return state->err;
496 }
497
498 /* -- see zlib.h -- */
499 int ZEXPORT gzsetparams(file, level, strategy)
500     gzFile file;
501     int level;
502     int strategy;
503 {
504     gz_statep state;
505     z_streamp strm;
506
507     /* get internal structure */
508     if (file == NULL)
509         return Z_STREAM_ERROR;
510     state = (gz_statep)file;
511     strm = &(state->strm);
512
513     /* check that we're writing and that there's no error */
514     if (state->mode != GZ_WRITE || state->err != Z_OK)
515         return Z_STREAM_ERROR;
516
517     /* if no change is requested, then do nothing */
518     if (level == state->level && strategy == state->strategy)
519         return Z_OK;
520
521     /* check for seek request */
522     if (state->seek) {
523         state->seek = 0;
524         if (gz_zero(state, state->skip) == -1)
525             return -1;
526     }
527
528     /* change compression parameters for subsequent input */
529     if (state->size) {
530         /* flush previous input with previous parameters before changing */
531         if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
532             return state->err;
533         deflateParams(strm, level, strategy);
534     }
535     state->level = level;
536     state->strategy = strategy;
537     return Z_OK;
538 }
539
540 /* -- see zlib.h -- */
541 int ZEXPORT gzclose_w(file)
542     gzFile file;
543 {
544     int ret = 0;
545     gz_statep state;
546
547     /* get internal structure */
548     if (file == NULL)
549         return Z_STREAM_ERROR;
550     state = (gz_statep)file;
551
552     /* check that we're writing */
553     if (state->mode != GZ_WRITE)
554         return Z_STREAM_ERROR;
555
556     /* check for seek request */
557     if (state->seek) {
558         state->seek = 0;
559         ret += gz_zero(state, state->skip);
560     }
561
562     /* flush, free memory, and close file */
563     ret += gz_comp(state, Z_FINISH);
564     (void)deflateEnd(&(state->strm));
565 #if TARGET_MSDOS == 16 && defined(SMALL_MEDIUM) && defined(__WATCOMC__)
566     _ffree(state->out);
567     _ffree(state->in);
568 #else
569     free(state->out);
570     free(state->in);
571 #endif
572     gz_error(state, Z_OK, NULL);
573     free(state->path);
574     ret += close(state->fd);
575     free(state);
576     return ret ? Z_ERRNO : Z_OK;
577 }