Annotation of embedaddon/sudo/zlib/gzwrite.c, revision 1.1.1.2

1.1       misho       1: /* gzwrite.c -- zlib functions for writing gzip files
1.1.1.2 ! misho       2:  * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
1.1       misho       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: 
1.1.1.2 ! misho      21:     /* allocate input buffer */
1.1       misho      22:     state->in = malloc(state->want);
1.1.1.2 ! misho      23:     if (state->in == NULL) {
1.1       misho      24:         gz_error(state, Z_MEM_ERROR, "out of memory");
                     25:         return -1;
                     26:     }
                     27: 
1.1.1.2 ! misho      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:         }
1.1       misho      50:     }
                     51: 
                     52:     /* mark state as initialized */
                     53:     state->size = state->want;
                     54: 
1.1.1.2 ! misho      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:     }
1.1       misho      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,
1.1.1.2 ! misho      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. */
1.1       misho      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: 
1.1.1.2 ! misho      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: 
1.1       misho      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))) {
1.1.1.2 ! misho     100:             have = (unsigned)(strm->next_out - state->x.next);
        !           101:             if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
1.1       misho     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:             }
1.1.1.2 ! misho     110:             state->x.next = strm->next_out;
1.1       misho     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;
1.1.1.2 ! misho     156:         state->x.pos += n;
1.1       misho     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) {
1.1.1.2 ! misho     188:         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
1.1       misho     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;
1.1.1.2 ! misho     218:             state->x.pos += n;
1.1       misho     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;
1.1.1.2 ! misho     233:         state->x.pos += len;
1.1       misho     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;
1.1.1.2 ! misho     274:         state->x.pos++;
        !           275:         return c & 0xff;
1.1       misho     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;
1.1.1.2 ! misho     282:     return c & 0xff;
1.1       misho     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: 
1.1.1.2 ! misho     299: #if defined(STDC) || defined(Z_HAVE_STDARG_H)
1.1       misho     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;
1.1.1.2 ! misho     367:     state->x.pos += len;
1.1       misho     368:     return len;
                    369: }
                    370: 
1.1.1.2 ! misho     371: #else /* !STDC && !Z_HAVE_STDARG_H */
1.1       misho     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: 
1.1.1.2 ! misho     391:     /* check that can really pass pointer in ints */
        !           392:     if (sizeof(int) != sizeof(void *))
        !           393:         return 0;
        !           394: 
1.1       misho     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;
1.1.1.2 ! misho     445:     state->x.pos += len;
1.1       misho     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: {
1.1.1.2 ! misho     529:     int ret = Z_OK;
1.1       misho     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;
1.1.1.2 ! misho     544:         if (gz_zero(state, state->skip) == -1)
        !           545:             ret = state->err;
1.1       misho     546:     }
                    547: 
                    548:     /* flush, free memory, and close file */
1.1.1.2 ! misho     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:     }
1.1       misho     555:     free(state->in);
                    556:     gz_error(state, Z_OK, NULL);
                    557:     free(state->path);
1.1.1.2 ! misho     558:     if (close(state->fd) == -1)
        !           559:         ret = Z_ERRNO;
1.1       misho     560:     free(state);
1.1.1.2 ! misho     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;
1.1       misho     593: }

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