File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / zlib / gzwrite.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 10:46:14 2013 UTC (10 years, 11 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_8p0, v1_8_8, v1_8_7p0, v1_8_7, v1_8_5p1, v1_8_10p3_0, v1_8_10p3, HEAD
1.8.7

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>