• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/zlib/gzwrite.c

00001 /* gzwrite.c -- zlib functions for writing gzip files
00002  * Copyright (C) 2004, 2005, 2010 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 #include "gzguts.h"
00007 
00008 /* Local functions */
00009 local int gz_init OF((gz_statep));
00010 local int gz_comp OF((gz_statep, int));
00011 local int gz_zero OF((gz_statep, z_off64_t));
00012 
00013 /* Initialize state for writing a gzip file.  Mark initialization by setting
00014    state->size to non-zero.  Return -1 on failure or 0 on success. */
00015 local int gz_init(state)
00016     gz_statep state;
00017 {
00018     int ret;
00019     z_streamp strm = &(state->strm);
00020 
00021     /* allocate input and output buffers */
00022     state->in = malloc(state->want);
00023     state->out = malloc(state->want);
00024     if (state->in == NULL || state->out == NULL) {
00025         if (state->out != NULL)
00026             free(state->out);
00027         if (state->in != NULL)
00028             free(state->in);
00029         gz_error(state, Z_MEM_ERROR, "out of memory");
00030         return -1;
00031     }
00032 
00033     /* allocate deflate memory, set up for gzip compression */
00034     strm->zalloc = Z_NULL;
00035     strm->zfree = Z_NULL;
00036     strm->opaque = Z_NULL;
00037     ret = deflateInit2(strm, state->level, Z_DEFLATED,
00038                        15 + 16, 8, state->strategy);
00039     if (ret != Z_OK) {
00040         free(state->in);
00041         gz_error(state, Z_MEM_ERROR, "out of memory");
00042         return -1;
00043     }
00044 
00045     /* mark state as initialized */
00046     state->size = state->want;
00047 
00048     /* initialize write buffer */
00049     strm->avail_out = state->size;
00050     strm->next_out = state->out;
00051     state->next = strm->next_out;
00052     return 0;
00053 }
00054 
00055 /* Compress whatever is at avail_in and next_in and write to the output file.
00056    Return -1 if there is an error writing to the output file, otherwise 0.
00057    flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
00058    then the deflate() state is reset to start a new gzip stream. */
00059 local int gz_comp(state, flush)
00060     gz_statep state;
00061     int flush;
00062 {
00063     int ret, got;
00064     unsigned have;
00065     z_streamp strm = &(state->strm);
00066 
00067     /* allocate memory if this is the first time through */
00068     if (state->size == 0 && gz_init(state) == -1)
00069         return -1;
00070 
00071     /* run deflate() on provided input until it produces no more output */
00072     ret = Z_OK;
00073     do {
00074         /* write out current buffer contents if full, or if flushing, but if
00075            doing Z_FINISH then don't write until we get to Z_STREAM_END */
00076         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
00077             (flush != Z_FINISH || ret == Z_STREAM_END))) {
00078             have = (unsigned)(strm->next_out - state->next);
00079             if (have && ((got = write(state->fd, state->next, have)) < 0 ||
00080                          (unsigned)got != have)) {
00081                 gz_error(state, Z_ERRNO, zstrerror());
00082                 return -1;
00083             }
00084             if (strm->avail_out == 0) {
00085                 strm->avail_out = state->size;
00086                 strm->next_out = state->out;
00087             }
00088             state->next = strm->next_out;
00089         }
00090 
00091         /* compress */
00092         have = strm->avail_out;
00093         ret = deflate(strm, flush);
00094         if (ret == Z_STREAM_ERROR) {
00095             gz_error(state, Z_STREAM_ERROR,
00096                       "internal error: deflate stream corrupt");
00097             return -1;
00098         }
00099         have -= strm->avail_out;
00100     } while (have);
00101 
00102     /* if that completed a deflate stream, allow another to start */
00103     if (flush == Z_FINISH)
00104         deflateReset(strm);
00105 
00106     /* all done, no errors */
00107     return 0;
00108 }
00109 
00110 /* Compress len zeros to output.  Return -1 on error, 0 on success. */
00111 local int gz_zero(state, len)
00112     gz_statep state;
00113     z_off64_t len;
00114 {
00115     int first;
00116     unsigned n;
00117     z_streamp strm = &(state->strm);
00118 
00119     /* consume whatever's left in the input buffer */
00120     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00121         return -1;
00122 
00123     /* compress len zeros (len guaranteed > 0) */
00124     first = 1;
00125     while (len) {
00126         n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
00127             (unsigned)len : state->size;
00128         if (first) {
00129             memset(state->in, 0, n);
00130             first = 0;
00131         }
00132         strm->avail_in = n;
00133         strm->next_in = state->in;
00134         state->pos += n;
00135         if (gz_comp(state, Z_NO_FLUSH) == -1)
00136             return -1;
00137         len -= n;
00138     }
00139     return 0;
00140 }
00141 
00142 /* -- see zlib.h -- */
00143 int ZEXPORT gzwrite(file, buf, len)
00144     gzFile file;
00145     voidpc buf;
00146     unsigned len;
00147 {
00148     unsigned put = len;
00149     unsigned n;
00150     gz_statep state;
00151     z_streamp strm;
00152 
00153     /* get internal structure */
00154     if (file == NULL)
00155         return 0;
00156     state = (gz_statep)file;
00157     strm = &(state->strm);
00158 
00159     /* check that we're writing and that there's no error */
00160     if (state->mode != GZ_WRITE || state->err != Z_OK)
00161         return 0;
00162 
00163     /* since an int is returned, make sure len fits in one, otherwise return
00164        with an error (this avoids the flaw in the interface) */
00165     if ((int)len < 0) {
00166         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
00167         return 0;
00168     }
00169 
00170     /* if len is zero, avoid unnecessary operations */
00171     if (len == 0)
00172         return 0;
00173 
00174     /* allocate memory if this is the first time through */
00175     if (state->size == 0 && gz_init(state) == -1)
00176         return 0;
00177 
00178     /* check for seek request */
00179     if (state->seek) {
00180         state->seek = 0;
00181         if (gz_zero(state, state->skip) == -1)
00182             return 0;
00183     }
00184 
00185     /* for small len, copy to input buffer, otherwise compress directly */
00186     if (len < state->size) {
00187         /* copy to input buffer, compress when full */
00188         do {
00189             if (strm->avail_in == 0)
00190                 strm->next_in = state->in;
00191             n = state->size - strm->avail_in;
00192             if (n > len)
00193                 n = len;
00194             memcpy(strm->next_in + strm->avail_in, buf, n);
00195             strm->avail_in += n;
00196             state->pos += n;
00197             buf = (char *)buf + n;
00198             len -= n;
00199             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
00200                 return 0;
00201         } while (len);
00202     }
00203     else {
00204         /* consume whatever's left in the input buffer */
00205         if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00206             return 0;
00207 
00208         /* directly compress user buffer to file */
00209         strm->avail_in = len;
00210         strm->next_in = (voidp)buf;
00211         state->pos += len;
00212         if (gz_comp(state, Z_NO_FLUSH) == -1)
00213             return 0;
00214     }
00215 
00216     /* input was all buffered or compressed (put will fit in int) */
00217     return (int)put;
00218 }
00219 
00220 /* -- see zlib.h -- */
00221 int ZEXPORT gzputc(file, c)
00222     gzFile file;
00223     int c;
00224 {
00225     unsigned char buf[1];
00226     gz_statep state;
00227     z_streamp strm;
00228 
00229     /* get internal structure */
00230     if (file == NULL)
00231         return -1;
00232     state = (gz_statep)file;
00233     strm = &(state->strm);
00234 
00235     /* check that we're writing and that there's no error */
00236     if (state->mode != GZ_WRITE || state->err != Z_OK)
00237         return -1;
00238 
00239     /* check for seek request */
00240     if (state->seek) {
00241         state->seek = 0;
00242         if (gz_zero(state, state->skip) == -1)
00243             return -1;
00244     }
00245 
00246     /* try writing to input buffer for speed (state->size == 0 if buffer not
00247        initialized) */
00248     if (strm->avail_in < state->size) {
00249         if (strm->avail_in == 0)
00250             strm->next_in = state->in;
00251         strm->next_in[strm->avail_in++] = c;
00252         state->pos++;
00253         return c;
00254     }
00255 
00256     /* no room in buffer or not initialized, use gz_write() */
00257     buf[0] = c;
00258     if (gzwrite(file, buf, 1) != 1)
00259         return -1;
00260     return c;
00261 }
00262 
00263 /* -- see zlib.h -- */
00264 int ZEXPORT gzputs(file, str)
00265     gzFile file;
00266     const char *str;
00267 {
00268     int ret;
00269     unsigned len;
00270 
00271     /* write string */
00272     len = (unsigned)strlen(str);
00273     ret = gzwrite(file, str, len);
00274     return ret == 0 && len != 0 ? -1 : ret;
00275 }
00276 
00277 #ifdef STDC
00278 #include <stdarg.h>
00279 
00280 /* -- see zlib.h -- */
00281 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
00282 {
00283     int size, len;
00284     gz_statep state;
00285     z_streamp strm;
00286     va_list va;
00287 
00288     /* get internal structure */
00289     if (file == NULL)
00290         return -1;
00291     state = (gz_statep)file;
00292     strm = &(state->strm);
00293 
00294     /* check that we're writing and that there's no error */
00295     if (state->mode != GZ_WRITE || state->err != Z_OK)
00296         return 0;
00297 
00298     /* make sure we have some buffer space */
00299     if (state->size == 0 && gz_init(state) == -1)
00300         return 0;
00301 
00302     /* check for seek request */
00303     if (state->seek) {
00304         state->seek = 0;
00305         if (gz_zero(state, state->skip) == -1)
00306             return 0;
00307     }
00308 
00309     /* consume whatever's left in the input buffer */
00310     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00311         return 0;
00312 
00313     /* do the printf() into the input buffer, put length in len */
00314     size = (int)(state->size);
00315     state->in[size - 1] = 0;
00316     va_start(va, format);
00317 #ifdef NO_vsnprintf
00318 #  ifdef HAS_vsprintf_void
00319     (void)vsprintf(state->in, format, va);
00320     va_end(va);
00321     for (len = 0; len < size; len++)
00322         if (state->in[len] == 0) break;
00323 #  else
00324     len = vsprintf(state->in, format, va);
00325     va_end(va);
00326 #  endif
00327 #else
00328 #  ifdef HAS_vsnprintf_void
00329     (void)vsnprintf(state->in, size, format, va);
00330     va_end(va);
00331     len = strlen(state->in);
00332 #  else
00333     len = vsnprintf((char *)(state->in), size, format, va);
00334     va_end(va);
00335 #  endif
00336 #endif
00337 
00338     /* check that printf() results fit in buffer */
00339     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
00340         return 0;
00341 
00342     /* update buffer and position, defer compression until needed */
00343     strm->avail_in = (unsigned)len;
00344     strm->next_in = state->in;
00345     state->pos += len;
00346     return len;
00347 }
00348 
00349 #else /* !STDC */
00350 
00351 /* -- see zlib.h -- */
00352 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00353                        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
00354     gzFile file;
00355     const char *format;
00356     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
00357         a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
00358 {
00359     int size, len;
00360     gz_statep state;
00361     z_streamp strm;
00362 
00363     /* get internal structure */
00364     if (file == NULL)
00365         return -1;
00366     state = (gz_statep)file;
00367     strm = &(state->strm);
00368 
00369     /* check that we're writing and that there's no error */
00370     if (state->mode != GZ_WRITE || state->err != Z_OK)
00371         return 0;
00372 
00373     /* make sure we have some buffer space */
00374     if (state->size == 0 && gz_init(state) == -1)
00375         return 0;
00376 
00377     /* check for seek request */
00378     if (state->seek) {
00379         state->seek = 0;
00380         if (gz_zero(state, state->skip) == -1)
00381             return 0;
00382     }
00383 
00384     /* consume whatever's left in the input buffer */
00385     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
00386         return 0;
00387 
00388     /* do the printf() into the input buffer, put length in len */
00389     size = (int)(state->size);
00390     state->in[size - 1] = 0;
00391 #ifdef NO_snprintf
00392 #  ifdef HAS_sprintf_void
00393     sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
00394             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00395     for (len = 0; len < size; len++)
00396         if (state->in[len] == 0) break;
00397 #  else
00398     len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
00399                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00400 #  endif
00401 #else
00402 #  ifdef HAS_snprintf_void
00403     snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
00404              a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00405     len = strlen(state->in);
00406 #  else
00407     len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
00408                  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
00409 #  endif
00410 #endif
00411 
00412     /* check that printf() results fit in buffer */
00413     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
00414         return 0;
00415 
00416     /* update buffer and position, defer compression until needed */
00417     strm->avail_in = (unsigned)len;
00418     strm->next_in = state->in;
00419     state->pos += len;
00420     return len;
00421 }
00422 
00423 #endif
00424 
00425 /* -- see zlib.h -- */
00426 int ZEXPORT gzflush(file, flush)
00427     gzFile file;
00428     int flush;
00429 {
00430     gz_statep state;
00431 
00432     /* get internal structure */
00433     if (file == NULL)
00434         return -1;
00435     state = (gz_statep)file;
00436 
00437     /* check that we're writing and that there's no error */
00438     if (state->mode != GZ_WRITE || state->err != Z_OK)
00439         return Z_STREAM_ERROR;
00440 
00441     /* check flush parameter */
00442     if (flush < 0 || flush > Z_FINISH)
00443         return Z_STREAM_ERROR;
00444 
00445     /* check for seek request */
00446     if (state->seek) {
00447         state->seek = 0;
00448         if (gz_zero(state, state->skip) == -1)
00449             return -1;
00450     }
00451 
00452     /* compress remaining data with requested flush */
00453     gz_comp(state, flush);
00454     return state->err;
00455 }
00456 
00457 /* -- see zlib.h -- */
00458 int ZEXPORT gzsetparams(file, level, strategy)
00459     gzFile file;
00460     int level;
00461     int strategy;
00462 {
00463     gz_statep state;
00464     z_streamp strm;
00465 
00466     /* get internal structure */
00467     if (file == NULL)
00468         return Z_STREAM_ERROR;
00469     state = (gz_statep)file;
00470     strm = &(state->strm);
00471 
00472     /* check that we're writing and that there's no error */
00473     if (state->mode != GZ_WRITE || state->err != Z_OK)
00474         return Z_STREAM_ERROR;
00475 
00476     /* if no change is requested, then do nothing */
00477     if (level == state->level && strategy == state->strategy)
00478         return Z_OK;
00479 
00480     /* check for seek request */
00481     if (state->seek) {
00482         state->seek = 0;
00483         if (gz_zero(state, state->skip) == -1)
00484             return -1;
00485     }
00486 
00487     /* change compression parameters for subsequent input */
00488     if (state->size) {
00489         /* flush previous input with previous parameters before changing */
00490         if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
00491             return state->err;
00492         deflateParams(strm, level, strategy);
00493     }
00494     state->level = level;
00495     state->strategy = strategy;
00496     return Z_OK;
00497 }
00498 
00499 /* -- see zlib.h -- */
00500 int ZEXPORT gzclose_w(file)
00501     gzFile file;
00502 {
00503     int ret = 0;
00504     gz_statep state;
00505 
00506     /* get internal structure */
00507     if (file == NULL)
00508         return Z_STREAM_ERROR;
00509     state = (gz_statep)file;
00510 
00511     /* check that we're writing */
00512     if (state->mode != GZ_WRITE)
00513         return Z_STREAM_ERROR;
00514 
00515     /* check for seek request */
00516     if (state->seek) {
00517         state->seek = 0;
00518         ret += gz_zero(state, state->skip);
00519     }
00520 
00521     /* flush, free memory, and close file */
00522     ret += gz_comp(state, Z_FINISH);
00523     (void)deflateEnd(&(state->strm));
00524     free(state->out);
00525     free(state->in);
00526     gz_error(state, Z_OK, NULL);
00527     free(state->path);
00528     ret += close(state->fd);
00529     free(state);
00530     return ret ? Z_ERRNO : Z_OK;
00531 }

Generated on Wed Oct 20 2010 11:12:18 for APBS by  doxygen 1.7.2