1c3423655Schristos /* gzread.c -- zlib functions for reading gzip files 2ec47cc4bSchristos * Copyright (C) 2004-2017 Mark Adler 3c3423655Schristos * For conditions of distribution and use, see copyright notice in zlib.h 4c3423655Schristos */ 5c3423655Schristos 6c3423655Schristos #include "gzguts.h" 7c3423655Schristos 8c3423655Schristos /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 9c3423655Schristos state->fd, and update state->eof, state->err, and state->msg as appropriate. 10c3423655Schristos This function needs to loop on read(), since read() is not guaranteed to 11c3423655Schristos read the number of bytes requested, depending on the type of descriptor. */ 12*b175d1c2Schristos local int gz_load(gz_statep state, unsigned char *buf, unsigned len, 13*b175d1c2Schristos unsigned *have) { 14c3423655Schristos int ret; 15c3423655Schristos unsigned get, max = ((unsigned)-1 >> 2) + 1; 16c3423655Schristos 17c3423655Schristos *have = 0; 18c3423655Schristos do { 19c3423655Schristos get = len - *have; 20c3423655Schristos if (get > max) 21c3423655Schristos get = max; 22c3423655Schristos ret = read(state->fd, buf + *have, get); 23c3423655Schristos if (ret <= 0) 24c3423655Schristos break; 25c3423655Schristos *have += (unsigned)ret; 26c3423655Schristos } while (*have < len); 27c3423655Schristos if (ret < 0) { 28c3423655Schristos gz_error(state, Z_ERRNO, zstrerror()); 29c3423655Schristos return -1; 30c3423655Schristos } 31c3423655Schristos if (ret == 0) 32c3423655Schristos state->eof = 1; 33c3423655Schristos return 0; 34c3423655Schristos } 35c3423655Schristos 36c3423655Schristos /* Load up input buffer and set eof flag if last data loaded -- return -1 on 37c3423655Schristos error, 0 otherwise. Note that the eof flag is set when the end of the input 38c3423655Schristos file is reached, even though there may be unused data in the buffer. Once 39c3423655Schristos that data has been used, no more attempts will be made to read the file. 40c3423655Schristos If strm->avail_in != 0, then the current data is moved to the beginning of 41c3423655Schristos the input buffer, and then the remainder of the buffer is loaded with the 42c3423655Schristos available data from the input file. */ 43*b175d1c2Schristos local int gz_avail(gz_statep state) { 44c3423655Schristos unsigned got; 45c3423655Schristos z_streamp strm = &(state->strm); 46c3423655Schristos 47c3423655Schristos if (state->err != Z_OK && state->err != Z_BUF_ERROR) 48c3423655Schristos return -1; 49c3423655Schristos if (state->eof == 0) { 50c3423655Schristos if (strm->avail_in) { /* copy what's there to the start */ 51c3423655Schristos unsigned char *p = state->in; 52c3423655Schristos unsigned const char *q = strm->next_in; 53c3423655Schristos unsigned n = strm->avail_in; 54c3423655Schristos do { 55c3423655Schristos *p++ = *q++; 56c3423655Schristos } while (--n); 57c3423655Schristos } 58c3423655Schristos if (gz_load(state, state->in + strm->avail_in, 59c3423655Schristos state->size - strm->avail_in, &got) == -1) 60c3423655Schristos return -1; 61c3423655Schristos strm->avail_in += got; 62c3423655Schristos strm->next_in = state->in; 63c3423655Schristos } 64c3423655Schristos return 0; 65c3423655Schristos } 66c3423655Schristos 67c3423655Schristos /* Look for gzip header, set up for inflate or copy. state->x.have must be 0. 68c3423655Schristos If this is the first time in, allocate required memory. state->how will be 69c3423655Schristos left unchanged if there is no more input data available, will be set to COPY 70c3423655Schristos if there is no gzip header and direct copying will be performed, or it will 71c3423655Schristos be set to GZIP for decompression. If direct copying, then leftover input 72c3423655Schristos data from the input buffer will be copied to the output buffer. In that 73c3423655Schristos case, all further file reads will be directly to either the output buffer or 74c3423655Schristos a user buffer. If decompressing, the inflate state will be initialized. 75c3423655Schristos gz_look() will return 0 on success or -1 on failure. */ 76*b175d1c2Schristos local int gz_look(gz_statep state) { 77c3423655Schristos z_streamp strm = &(state->strm); 78c3423655Schristos 79c3423655Schristos /* allocate read buffers and inflate memory */ 80c3423655Schristos if (state->size == 0) { 81c3423655Schristos /* allocate buffers */ 82c3423655Schristos state->in = (unsigned char *)malloc(state->want); 83c3423655Schristos state->out = (unsigned char *)malloc(state->want << 1); 84c3423655Schristos if (state->in == NULL || state->out == NULL) { 85c3423655Schristos free(state->out); 86c3423655Schristos free(state->in); 87c3423655Schristos gz_error(state, Z_MEM_ERROR, "out of memory"); 88c3423655Schristos return -1; 89c3423655Schristos } 90c3423655Schristos state->size = state->want; 91c3423655Schristos 92c3423655Schristos /* allocate inflate memory */ 93c3423655Schristos state->strm.zalloc = Z_NULL; 94c3423655Schristos state->strm.zfree = Z_NULL; 95c3423655Schristos state->strm.opaque = Z_NULL; 96c3423655Schristos state->strm.avail_in = 0; 97c3423655Schristos state->strm.next_in = Z_NULL; 98c3423655Schristos if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ 99c3423655Schristos free(state->out); 100c3423655Schristos free(state->in); 101c3423655Schristos state->size = 0; 102c3423655Schristos gz_error(state, Z_MEM_ERROR, "out of memory"); 103c3423655Schristos return -1; 104c3423655Schristos } 105c3423655Schristos } 106c3423655Schristos 107c3423655Schristos /* get at least the magic bytes in the input buffer */ 108c3423655Schristos if (strm->avail_in < 2) { 109c3423655Schristos if (gz_avail(state) == -1) 110c3423655Schristos return -1; 111c3423655Schristos if (strm->avail_in == 0) 112c3423655Schristos return 0; 113c3423655Schristos } 114c3423655Schristos 115c3423655Schristos /* look for gzip magic bytes -- if there, do gzip decoding (note: there is 116c3423655Schristos a logical dilemma here when considering the case of a partially written 117c3423655Schristos gzip file, to wit, if a single 31 byte is written, then we cannot tell 118c3423655Schristos whether this is a single-byte file, or just a partially written gzip 119c3423655Schristos file -- for here we assume that if a gzip file is being written, then 120c3423655Schristos the header will be written in a single operation, so that reading a 121c3423655Schristos single byte is sufficient indication that it is not a gzip file) */ 122c3423655Schristos if (strm->avail_in > 1 && 123c3423655Schristos strm->next_in[0] == 31 && strm->next_in[1] == 139) { 124c3423655Schristos inflateReset(strm); 125c3423655Schristos state->how = GZIP; 126c3423655Schristos state->direct = 0; 127c3423655Schristos return 0; 128c3423655Schristos } 129c3423655Schristos 130c3423655Schristos /* no gzip header -- if we were decoding gzip before, then this is trailing 131c3423655Schristos garbage. Ignore the trailing garbage and finish. */ 132c3423655Schristos if (state->direct == 0) { 133c3423655Schristos strm->avail_in = 0; 134c3423655Schristos state->eof = 1; 135c3423655Schristos state->x.have = 0; 136c3423655Schristos return 0; 137c3423655Schristos } 138c3423655Schristos 139c3423655Schristos /* doing raw i/o, copy any leftover input to output -- this assumes that 140c3423655Schristos the output buffer is larger than the input buffer, which also assures 141c3423655Schristos space for gzungetc() */ 142c3423655Schristos state->x.next = state->out; 143c3423655Schristos memcpy(state->x.next, strm->next_in, strm->avail_in); 144c3423655Schristos state->x.have = strm->avail_in; 145c3423655Schristos strm->avail_in = 0; 146c3423655Schristos state->how = COPY; 147c3423655Schristos state->direct = 1; 148c3423655Schristos return 0; 149c3423655Schristos } 150c3423655Schristos 151c3423655Schristos /* Decompress from input to the provided next_out and avail_out in the state. 152c3423655Schristos On return, state->x.have and state->x.next point to the just decompressed 153c3423655Schristos data. If the gzip stream completes, state->how is reset to LOOK to look for 154c3423655Schristos the next gzip stream or raw data, once state->x.have is depleted. Returns 0 155c3423655Schristos on success, -1 on failure. */ 156*b175d1c2Schristos local int gz_decomp(gz_statep state) { 157c3423655Schristos int ret = Z_OK; 158c3423655Schristos unsigned had; 159c3423655Schristos z_streamp strm = &(state->strm); 160c3423655Schristos 161c3423655Schristos /* fill output buffer up to end of deflate stream */ 162c3423655Schristos had = strm->avail_out; 163c3423655Schristos do { 164c3423655Schristos /* get more input for inflate() */ 165c3423655Schristos if (strm->avail_in == 0 && gz_avail(state) == -1) 166c3423655Schristos return -1; 167c3423655Schristos if (strm->avail_in == 0) { 168c3423655Schristos gz_error(state, Z_BUF_ERROR, "unexpected end of file"); 169c3423655Schristos break; 170c3423655Schristos } 171c3423655Schristos 172c3423655Schristos /* decompress and handle errors */ 173c3423655Schristos ret = inflate(strm, Z_NO_FLUSH); 174c3423655Schristos if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 175c3423655Schristos gz_error(state, Z_STREAM_ERROR, 176c3423655Schristos "internal error: inflate stream corrupt"); 177c3423655Schristos return -1; 178c3423655Schristos } 179c3423655Schristos if (ret == Z_MEM_ERROR) { 180c3423655Schristos gz_error(state, Z_MEM_ERROR, "out of memory"); 181c3423655Schristos return -1; 182c3423655Schristos } 183c3423655Schristos if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ 184c3423655Schristos gz_error(state, Z_DATA_ERROR, 185c3423655Schristos strm->msg == NULL ? "compressed data error" : strm->msg); 186c3423655Schristos return -1; 187c3423655Schristos } 188c3423655Schristos } while (strm->avail_out && ret != Z_STREAM_END); 189c3423655Schristos 190c3423655Schristos /* update available output */ 191c3423655Schristos state->x.have = had - strm->avail_out; 192c3423655Schristos state->x.next = strm->next_out - state->x.have; 193c3423655Schristos 194c3423655Schristos /* if the gzip stream completed successfully, look for another */ 195c3423655Schristos if (ret == Z_STREAM_END) 196c3423655Schristos state->how = LOOK; 197c3423655Schristos 198c3423655Schristos /* good decompression */ 199c3423655Schristos return 0; 200c3423655Schristos } 201c3423655Schristos 202c3423655Schristos /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. 203c3423655Schristos Data is either copied from the input file or decompressed from the input 204c3423655Schristos file depending on state->how. If state->how is LOOK, then a gzip header is 205c3423655Schristos looked for to determine whether to copy or decompress. Returns -1 on error, 206c3423655Schristos otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the 207c3423655Schristos end of the input file has been reached and all data has been processed. */ 208*b175d1c2Schristos local int gz_fetch(gz_statep state) { 209c3423655Schristos z_streamp strm = &(state->strm); 210c3423655Schristos 211c3423655Schristos do { 212c3423655Schristos switch(state->how) { 213c3423655Schristos case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ 214c3423655Schristos if (gz_look(state) == -1) 215c3423655Schristos return -1; 216c3423655Schristos if (state->how == LOOK) 217c3423655Schristos return 0; 218c3423655Schristos break; 219c3423655Schristos case COPY: /* -> COPY */ 220c3423655Schristos if (gz_load(state, state->out, state->size << 1, &(state->x.have)) 221c3423655Schristos == -1) 222c3423655Schristos return -1; 223c3423655Schristos state->x.next = state->out; 224c3423655Schristos return 0; 225c3423655Schristos case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ 226c3423655Schristos strm->avail_out = state->size << 1; 227c3423655Schristos strm->next_out = state->out; 228c3423655Schristos if (gz_decomp(state) == -1) 229c3423655Schristos return -1; 230c3423655Schristos } 231c3423655Schristos } while (state->x.have == 0 && (!state->eof || strm->avail_in)); 232c3423655Schristos return 0; 233c3423655Schristos } 234c3423655Schristos 235c3423655Schristos /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 236*b175d1c2Schristos local int gz_skip(gz_statep state, z_off64_t len) { 237c3423655Schristos unsigned n; 238c3423655Schristos 239c3423655Schristos /* skip over len bytes or reach end-of-file, whichever comes first */ 240c3423655Schristos while (len) 241c3423655Schristos /* skip over whatever is in output buffer */ 242c3423655Schristos if (state->x.have) { 243c3423655Schristos n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? 244c3423655Schristos (unsigned)len : state->x.have; 245c3423655Schristos state->x.have -= n; 246c3423655Schristos state->x.next += n; 247c3423655Schristos state->x.pos += n; 248c3423655Schristos len -= n; 249c3423655Schristos } 250c3423655Schristos 251c3423655Schristos /* output buffer empty -- return if we're at the end of the input */ 252c3423655Schristos else if (state->eof && state->strm.avail_in == 0) 253c3423655Schristos break; 254c3423655Schristos 255c3423655Schristos /* need more data to skip -- load up output buffer */ 256c3423655Schristos else { 257c3423655Schristos /* get more output, looking for header if required */ 258c3423655Schristos if (gz_fetch(state) == -1) 259c3423655Schristos return -1; 260c3423655Schristos } 261c3423655Schristos return 0; 262c3423655Schristos } 263c3423655Schristos 264c3423655Schristos /* Read len bytes into buf from file, or less than len up to the end of the 265c3423655Schristos input. Return the number of bytes read. If zero is returned, either the 266c3423655Schristos end of file was reached, or there was an error. state->err must be 267c3423655Schristos consulted in that case to determine which. */ 268*b175d1c2Schristos local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) { 269c3423655Schristos z_size_t got; 270c3423655Schristos unsigned n; 271c3423655Schristos 272c3423655Schristos /* if len is zero, avoid unnecessary operations */ 273c3423655Schristos if (len == 0) 274c3423655Schristos return 0; 275c3423655Schristos 276c3423655Schristos /* process a skip request */ 277c3423655Schristos if (state->seek) { 278c3423655Schristos state->seek = 0; 279c3423655Schristos if (gz_skip(state, state->skip) == -1) 280c3423655Schristos return 0; 281c3423655Schristos } 282c3423655Schristos 283c3423655Schristos /* get len bytes to buf, or less than len if at the end */ 284c3423655Schristos got = 0; 285c3423655Schristos do { 286c3423655Schristos /* set n to the maximum amount of len that fits in an unsigned int */ 287ec47cc4bSchristos n = (unsigned)-1; 288c3423655Schristos if (n > len) 289ec47cc4bSchristos n = (unsigned)len; 290c3423655Schristos 291c3423655Schristos /* first just try copying data from the output buffer */ 292c3423655Schristos if (state->x.have) { 293c3423655Schristos if (state->x.have < n) 294c3423655Schristos n = state->x.have; 295c3423655Schristos memcpy(buf, state->x.next, n); 296c3423655Schristos state->x.next += n; 297c3423655Schristos state->x.have -= n; 298c3423655Schristos } 299c3423655Schristos 300c3423655Schristos /* output buffer empty -- return if we're at the end of the input */ 301c3423655Schristos else if (state->eof && state->strm.avail_in == 0) { 302c3423655Schristos state->past = 1; /* tried to read past end */ 303c3423655Schristos break; 304c3423655Schristos } 305c3423655Schristos 306c3423655Schristos /* need output data -- for small len or new stream load up our output 307c3423655Schristos buffer */ 308c3423655Schristos else if (state->how == LOOK || n < (state->size << 1)) { 309c3423655Schristos /* get more output, looking for header if required */ 310c3423655Schristos if (gz_fetch(state) == -1) 311c3423655Schristos return 0; 312c3423655Schristos continue; /* no progress yet -- go back to copy above */ 313c3423655Schristos /* the copy above assures that we will leave with space in the 314c3423655Schristos output buffer, allowing at least one gzungetc() to succeed */ 315c3423655Schristos } 316c3423655Schristos 317c3423655Schristos /* large len -- read directly into user buffer */ 318c3423655Schristos else if (state->how == COPY) { /* read directly */ 319c3423655Schristos if (gz_load(state, (unsigned char *)buf, n, &n) == -1) 320c3423655Schristos return 0; 321c3423655Schristos } 322c3423655Schristos 323c3423655Schristos /* large len -- decompress directly into user buffer */ 324c3423655Schristos else { /* state->how == GZIP */ 325c3423655Schristos state->strm.avail_out = n; 326c3423655Schristos state->strm.next_out = (unsigned char *)buf; 327c3423655Schristos if (gz_decomp(state) == -1) 328c3423655Schristos return 0; 329c3423655Schristos n = state->x.have; 330c3423655Schristos state->x.have = 0; 331c3423655Schristos } 332c3423655Schristos 333c3423655Schristos /* update progress */ 334c3423655Schristos len -= n; 335c3423655Schristos buf = (char *)buf + n; 336c3423655Schristos got += n; 337c3423655Schristos state->x.pos += n; 338c3423655Schristos } while (len); 339c3423655Schristos 340c3423655Schristos /* return number of bytes read into user buffer */ 341c3423655Schristos return got; 342c3423655Schristos } 343c3423655Schristos 344c3423655Schristos /* -- see zlib.h -- */ 345*b175d1c2Schristos int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) { 346c3423655Schristos gz_statep state; 347c3423655Schristos 348c3423655Schristos /* get internal structure */ 349c3423655Schristos if (file == NULL) 350c3423655Schristos return -1; 351c3423655Schristos state = (gz_statep)file; 352c3423655Schristos 353c3423655Schristos /* check that we're reading and that there's no (serious) error */ 354c3423655Schristos if (state->mode != GZ_READ || 355c3423655Schristos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 356c3423655Schristos return -1; 357c3423655Schristos 358c3423655Schristos /* since an int is returned, make sure len fits in one, otherwise return 359c3423655Schristos with an error (this avoids a flaw in the interface) */ 360c3423655Schristos if ((int)len < 0) { 361c3423655Schristos gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); 362c3423655Schristos return -1; 363c3423655Schristos } 364c3423655Schristos 365c3423655Schristos /* read len or fewer bytes to buf */ 366ec47cc4bSchristos len = (unsigned)gz_read(state, buf, len); 367c3423655Schristos 368c3423655Schristos /* check for an error */ 369c3423655Schristos if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) 370c3423655Schristos return -1; 371c3423655Schristos 372c3423655Schristos /* return the number of bytes read (this is assured to fit in an int) */ 373c3423655Schristos return (int)len; 374c3423655Schristos } 375c3423655Schristos 376c3423655Schristos /* -- see zlib.h -- */ 377*b175d1c2Schristos z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) { 378c3423655Schristos z_size_t len; 379c3423655Schristos gz_statep state; 380c3423655Schristos 381c3423655Schristos /* get internal structure */ 382c3423655Schristos if (file == NULL) 383c3423655Schristos return 0; 384c3423655Schristos state = (gz_statep)file; 385c3423655Schristos 386c3423655Schristos /* check that we're reading and that there's no (serious) error */ 387c3423655Schristos if (state->mode != GZ_READ || 388c3423655Schristos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 389c3423655Schristos return 0; 390c3423655Schristos 391c3423655Schristos /* compute bytes to read -- error on overflow */ 392c3423655Schristos len = nitems * size; 393c3423655Schristos if (size && len / size != nitems) { 394c3423655Schristos gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); 395c3423655Schristos return 0; 396c3423655Schristos } 397c3423655Schristos 398c3423655Schristos /* read len or fewer bytes to buf, return the number of full items read */ 399c3423655Schristos return len ? gz_read(state, buf, len) / size : 0; 400c3423655Schristos } 401c3423655Schristos 402c3423655Schristos /* -- see zlib.h -- */ 403c3423655Schristos #ifdef Z_PREFIX_SET 404c3423655Schristos # undef z_gzgetc 405c3423655Schristos #else 406c3423655Schristos # undef gzgetc 407c3423655Schristos #endif 408*b175d1c2Schristos int ZEXPORT gzgetc(gzFile file) { 409c3423655Schristos unsigned char buf[1]; 410c3423655Schristos gz_statep state; 411c3423655Schristos 412c3423655Schristos /* get internal structure */ 413c3423655Schristos if (file == NULL) 414c3423655Schristos return -1; 415c3423655Schristos state = (gz_statep)file; 416c3423655Schristos 417c3423655Schristos /* check that we're reading and that there's no (serious) error */ 418c3423655Schristos if (state->mode != GZ_READ || 419c3423655Schristos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 420c3423655Schristos return -1; 421c3423655Schristos 422c3423655Schristos /* try output buffer (no need to check for skip request) */ 423c3423655Schristos if (state->x.have) { 424c3423655Schristos state->x.have--; 425c3423655Schristos state->x.pos++; 426c3423655Schristos return *(state->x.next)++; 427c3423655Schristos } 428c3423655Schristos 429c3423655Schristos /* nothing there -- try gz_read() */ 430ec47cc4bSchristos return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; 431c3423655Schristos } 432c3423655Schristos 433*b175d1c2Schristos int ZEXPORT gzgetc_(gzFile file) { 434c3423655Schristos return gzgetc(file); 435c3423655Schristos } 436c3423655Schristos 437c3423655Schristos /* -- see zlib.h -- */ 438*b175d1c2Schristos int ZEXPORT gzungetc(int c, gzFile file) { 439c3423655Schristos gz_statep state; 440c3423655Schristos 441c3423655Schristos /* get internal structure */ 442c3423655Schristos if (file == NULL) 443c3423655Schristos return -1; 444c3423655Schristos state = (gz_statep)file; 445c3423655Schristos 446*b175d1c2Schristos /* in case this was just opened, set up the input buffer */ 447*b175d1c2Schristos if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) 448*b175d1c2Schristos (void)gz_look(state); 449*b175d1c2Schristos 450c3423655Schristos /* check that we're reading and that there's no (serious) error */ 451c3423655Schristos if (state->mode != GZ_READ || 452c3423655Schristos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 453c3423655Schristos return -1; 454c3423655Schristos 455c3423655Schristos /* process a skip request */ 456c3423655Schristos if (state->seek) { 457c3423655Schristos state->seek = 0; 458c3423655Schristos if (gz_skip(state, state->skip) == -1) 459c3423655Schristos return -1; 460c3423655Schristos } 461c3423655Schristos 462c3423655Schristos /* can't push EOF */ 463c3423655Schristos if (c < 0) 464c3423655Schristos return -1; 465c3423655Schristos 466c3423655Schristos /* if output buffer empty, put byte at end (allows more pushing) */ 467c3423655Schristos if (state->x.have == 0) { 468c3423655Schristos state->x.have = 1; 469c3423655Schristos state->x.next = state->out + (state->size << 1) - 1; 470c3423655Schristos state->x.next[0] = (unsigned char)c; 471c3423655Schristos state->x.pos--; 472c3423655Schristos state->past = 0; 473c3423655Schristos return c; 474c3423655Schristos } 475c3423655Schristos 476c3423655Schristos /* if no room, give up (must have already done a gzungetc()) */ 477c3423655Schristos if (state->x.have == (state->size << 1)) { 478c3423655Schristos gz_error(state, Z_DATA_ERROR, "out of room to push characters"); 479c3423655Schristos return -1; 480c3423655Schristos } 481c3423655Schristos 482c3423655Schristos /* slide output data if needed and insert byte before existing data */ 483c3423655Schristos if (state->x.next == state->out) { 484c3423655Schristos unsigned char *src = state->out + state->x.have; 485c3423655Schristos unsigned char *dest = state->out + (state->size << 1); 486c3423655Schristos while (src > state->out) 487c3423655Schristos *--dest = *--src; 488c3423655Schristos state->x.next = dest; 489c3423655Schristos } 490c3423655Schristos state->x.have++; 491c3423655Schristos state->x.next--; 492c3423655Schristos state->x.next[0] = (unsigned char)c; 493c3423655Schristos state->x.pos--; 494c3423655Schristos state->past = 0; 495c3423655Schristos return c; 496c3423655Schristos } 497c3423655Schristos 498c3423655Schristos /* -- see zlib.h -- */ 499*b175d1c2Schristos char * ZEXPORT gzgets(gzFile file, char *buf, int len) { 500c3423655Schristos unsigned left, n; 501c3423655Schristos char *str; 502c3423655Schristos unsigned char *eol; 503c3423655Schristos gz_statep state; 504c3423655Schristos 505c3423655Schristos /* check parameters and get internal structure */ 506c3423655Schristos if (file == NULL || buf == NULL || len < 1) 507c3423655Schristos return NULL; 508c3423655Schristos state = (gz_statep)file; 509c3423655Schristos 510c3423655Schristos /* check that we're reading and that there's no (serious) error */ 511c3423655Schristos if (state->mode != GZ_READ || 512c3423655Schristos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 513c3423655Schristos return NULL; 514c3423655Schristos 515c3423655Schristos /* process a skip request */ 516c3423655Schristos if (state->seek) { 517c3423655Schristos state->seek = 0; 518c3423655Schristos if (gz_skip(state, state->skip) == -1) 519c3423655Schristos return NULL; 520c3423655Schristos } 521c3423655Schristos 522c3423655Schristos /* copy output bytes up to new line or len - 1, whichever comes first -- 523c3423655Schristos append a terminating zero to the string (we don't check for a zero in 524c3423655Schristos the contents, let the user worry about that) */ 525c3423655Schristos str = buf; 526c3423655Schristos left = (unsigned)len - 1; 527c3423655Schristos if (left) do { 528c3423655Schristos /* assure that something is in the output buffer */ 529c3423655Schristos if (state->x.have == 0 && gz_fetch(state) == -1) 530c3423655Schristos return NULL; /* error */ 531c3423655Schristos if (state->x.have == 0) { /* end of file */ 532c3423655Schristos state->past = 1; /* read past end */ 533c3423655Schristos break; /* return what we have */ 534c3423655Schristos } 535c3423655Schristos 536c3423655Schristos /* look for end-of-line in current output buffer */ 537c3423655Schristos n = state->x.have > left ? left : state->x.have; 538c3423655Schristos eol = (unsigned char *)memchr(state->x.next, '\n', n); 539c3423655Schristos if (eol != NULL) 540c3423655Schristos n = (unsigned)(eol - state->x.next) + 1; 541c3423655Schristos 542c3423655Schristos /* copy through end-of-line, or remainder if not found */ 543c3423655Schristos memcpy(buf, state->x.next, n); 544c3423655Schristos state->x.have -= n; 545c3423655Schristos state->x.next += n; 546c3423655Schristos state->x.pos += n; 547c3423655Schristos left -= n; 548c3423655Schristos buf += n; 549c3423655Schristos } while (left && eol == NULL); 550c3423655Schristos 551c3423655Schristos /* return terminated string, or if nothing, end of file */ 552c3423655Schristos if (buf == str) 553c3423655Schristos return NULL; 554c3423655Schristos buf[0] = 0; 555c3423655Schristos return str; 556c3423655Schristos } 557c3423655Schristos 558c3423655Schristos /* -- see zlib.h -- */ 559*b175d1c2Schristos int ZEXPORT gzdirect(gzFile file) { 560c3423655Schristos gz_statep state; 561c3423655Schristos 562c3423655Schristos /* get internal structure */ 563c3423655Schristos if (file == NULL) 564c3423655Schristos return 0; 565c3423655Schristos state = (gz_statep)file; 566c3423655Schristos 567c3423655Schristos /* if the state is not known, but we can find out, then do so (this is 568c3423655Schristos mainly for right after a gzopen() or gzdopen()) */ 569c3423655Schristos if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) 570c3423655Schristos (void)gz_look(state); 571c3423655Schristos 572c3423655Schristos /* return 1 if transparent, 0 if processing a gzip stream */ 573c3423655Schristos return state->direct; 574c3423655Schristos } 575c3423655Schristos 576c3423655Schristos /* -- see zlib.h -- */ 577*b175d1c2Schristos int ZEXPORT gzclose_r(gzFile file) { 578c3423655Schristos int ret, err; 579c3423655Schristos gz_statep state; 580c3423655Schristos 581c3423655Schristos /* get internal structure */ 582c3423655Schristos if (file == NULL) 583c3423655Schristos return Z_STREAM_ERROR; 584c3423655Schristos state = (gz_statep)file; 585c3423655Schristos 586c3423655Schristos /* check that we're reading */ 587c3423655Schristos if (state->mode != GZ_READ) 588c3423655Schristos return Z_STREAM_ERROR; 589c3423655Schristos 590c3423655Schristos /* free memory and close file */ 591c3423655Schristos if (state->size) { 592c3423655Schristos inflateEnd(&(state->strm)); 593c3423655Schristos free(state->out); 594c3423655Schristos free(state->in); 595c3423655Schristos } 596c3423655Schristos err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; 597c3423655Schristos gz_error(state, Z_OK, NULL); 598c3423655Schristos free(state->path); 599c3423655Schristos ret = close(state->fd); 600c3423655Schristos free(state); 601c3423655Schristos return ret ? Z_ERRNO : err; 602c3423655Schristos } 603