144380Ssos/* gzread.c -- zlib functions for reading gzip files 2230132Suqs * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler 344380Ssos * For conditions of distribution and use, see copyright notice in zlib.h 444380Ssos */ 544380Ssos 644380Ssos/* $FreeBSD: stable/10/contrib/zlib/gzread.c 313796 2017-02-16 06:16:50Z delphij $ */ 744380Ssos 844380Ssos#include "gzguts.h" 944380Ssos#include <unistd.h> 1044380Ssos 1144380Ssos/* Local functions */ 1244380Ssoslocal int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); 1344380Ssoslocal int gz_avail OF((gz_statep)); 1444380Ssoslocal int gz_look OF((gz_statep)); 1544380Ssoslocal int gz_decomp OF((gz_statep)); 1644380Ssoslocal int gz_fetch OF((gz_statep)); 1744380Ssoslocal int gz_skip OF((gz_statep, z_off64_t)); 1844380Ssoslocal z_size_t gz_read OF((gz_statep, voidp, z_size_t)); 1944380Ssos 2044380Ssos/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from 2144380Ssos state->fd, and update state->eof, state->err, and state->msg as appropriate. 2244380Ssos This function needs to loop on read(), since read() is not guaranteed to 2344380Ssos read the number of bytes requested, depending on the type of descriptor. */ 2444380Ssoslocal int gz_load(state, buf, len, have) 2544380Ssos gz_statep state; 2644380Ssos unsigned char *buf; 27119418Sobrien unsigned len; 28119418Sobrien unsigned *have; 29119418Sobrien{ 3044380Ssos int ret; 3144380Ssos unsigned get, max = ((unsigned)-1 >> 2) + 1; 3274302Ssos 3344380Ssos *have = 0; 34144330Ssos do { 35119404Ssos get = len - *have; 36120966Ssos if (get > max) 3774302Ssos get = max; 3845798Ssos ret = read(state->fd, buf + *have, get); 3960041Sphk if (ret <= 0) 4044380Ssos break; 41124534Ssos *have += (unsigned)ret; 42124403Ssos } while (*have < len); 43119404Ssos if (ret < 0) { 44124534Ssos gz_error(state, Z_ERRNO, zstrerror()); 4556558Ssos return -1; 4645798Ssos } 4745798Ssos if (ret == 0) 4845798Ssos state->eof = 1; 4944380Ssos return 0; 50210471Smav} 51144330Ssos 5244380Ssos/* Load up input buffer and set eof flag if last data loaded -- return -1 on 53200171Smav error, 0 otherwise. Note that the eof flag is set when the end of the input 54200171Smav file is reached, even though there may be unused data in the buffer. Once 55200171Smav that data has been used, no more attempts will be made to read the file. 56200171Smav If strm->avail_in != 0, then the current data is moved to the beginning of 57200171Smav the input buffer, and then the remainder of the buffer is loaded with the 58200171Smav available data from the input file. */ 5944380Ssoslocal int gz_avail(state) 60200171Smav gz_statep state; 61200171Smav{ 62249203Smarius unsigned got; 63249203Smarius z_streamp strm = &(state->strm); 64249203Smarius 65249203Smarius if (state->err != Z_OK && state->err != Z_BUF_ERROR) 66249203Smarius return -1; 67249203Smarius if (state->eof == 0) { 68200171Smav if (strm->avail_in) { /* copy what's there to the start */ 69249203Smarius unsigned char *p = state->in; 70214016Smav unsigned const char *q = strm->next_in; 71249203Smarius unsigned n = strm->avail_in; 72249203Smarius do { 7344380Ssos *p++ = *q++; 74122484Ssos } while (--n); 75151897Srwatson } 76146266Ssos if (gz_load(state, state->in + strm->avail_in, 77122484Ssos state->size - strm->avail_in, &got) == -1) 78178278Ssos return -1; 79181753Sphilip strm->avail_in += got; 80122484Ssos strm->next_in = state->in; 8174450Ssos } 82227309Sed return 0; 83181753Sphilip} 84181753Sphilip 85209872Smav/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. 86181753Sphilip If this is the first time in, allocate required memory. state->how will be 87226179Srodrigc left unchanged if there is no more input data available, will be set to COPY 8874450Ssos if there is no gzip header and direct copying will be performed, or it will 89119404Ssos be set to GZIP for decompression. If direct copying, then leftover input 90119404Ssos data from the input buffer will be copied to the output buffer. In that 91119404Ssos case, all further file reads will be directly to either the output buffer or 9266070Ssos a user buffer. If decompressing, the inflate state will be initialized. 9357325Ssos gz_look() will return 0 on success or -1 on failure. */ 9444380Ssoslocal int gz_look(state) 95256326Sgrehan gz_statep state; 96133556Ssos{ 97133556Ssos z_streamp strm = &(state->strm); 98133556Ssos 99133556Ssos /* allocate read buffers and inflate memory */ 100133556Ssos if (state->size == 0) { 101144330Ssos /* allocate buffers */ 102133556Ssos state->in = (unsigned char *)malloc(state->want); 103200171Smav state->out = (unsigned char *)malloc(state->want << 1); 104209664Smav if (state->in == NULL || state->out == NULL) { 105209664Smav free(state->out); 106209664Smav free(state->in); 107133556Ssos gz_error(state, Z_MEM_ERROR, "out of memory"); 108144330Ssos return -1; 109144330Ssos } 110144330Ssos state->size = state->want; 111133556Ssos 11257325Ssos /* allocate inflate memory */ 113119404Ssos state->strm.zalloc = Z_NULL; 114135819Ssos state->strm.zfree = Z_NULL; 115135819Ssos state->strm.opaque = Z_NULL; 116135819Ssos state->strm.avail_in = 0; 117188903Smav state->strm.next_in = Z_NULL; 118200171Smav if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ 119241144Smav free(state->out); 120241144Smav free(state->in); 121241144Smav state->size = 0; 122241144Smav gz_error(state, Z_MEM_ERROR, "out of memory"); 123241144Smav return -1; 124241144Smav } 125241144Smav } 126241144Smav 127241144Smav /* get at least the magic bytes in the input buffer */ 128200171Smav if (strm->avail_in < 2) { 129209664Smav if (gz_avail(state) == -1) 130209664Smav return -1; 131209664Smav if (strm->avail_in == 0) 132209664Smav return 0; 133209664Smav } 134209664Smav 135209664Smav /* look for gzip magic bytes -- if there, do gzip decoding (note: there is 136209664Smav a logical dilemma here when considering the case of a partially written 137209664Smav gzip file, to wit, if a single 31 byte is written, then we cannot tell 138209664Smav whether this is a single-byte file, or just a partially written gzip 139209664Smav file -- for here we assume that if a gzip file is being written, then 140200171Smav the header will be written in a single operation, so that reading a 141200171Smav single byte is sufficient indication that it is not a gzip file) */ 142200171Smav if (strm->avail_in > 1 && 143200171Smav strm->next_in[0] == 31 && strm->next_in[1] == 139) { 144215468Smav inflateReset(strm); 145200171Smav state->how = GZIP; 146249199Smarius state->direct = 0; 147249199Smarius return 0; 148249199Smarius } 149249199Smarius 150249199Smarius /* no gzip header -- if we were decoding gzip before, then this is trailing 151249199Smarius garbage. Ignore the trailing garbage and finish. */ 152249199Smarius if (state->direct == 0) { 153249199Smarius strm->avail_in = 0; 154249199Smarius state->eof = 1; 155200171Smav state->x.have = 0; 156220917Smav return 0; 157112791Ssos } 158179717Ssos 159179717Ssos /* doing raw i/o, copy any leftover input to output -- this assumes that 160179717Ssos the output buffer is larger than the input buffer, which also assures 161179717Ssos space for gzungetc() */ 162144330Ssos state->x.next = state->out; 16372106Ssos if (strm->avail_in) { 164127135Snjl memcpy(state->x.next, strm->next_in, strm->avail_in); 165127135Snjl state->x.have = strm->avail_in; 16690215Ssos strm->avail_in = 0; 167144330Ssos } 16857325Ssos state->how = COPY; 16956255Ssos state->direct = 1; 170166901Spiso return 0; 171188731Smav} 172209944Smav 173144330Ssos/* Decompress from input to the provided next_out and avail_out in the state. 174209944Smav On return, state->x.have and state->x.next point to the just decompressed 17591593Ssos data. If the gzip stream completes, state->how is reset to LOOK to look for 17657325Ssos the next gzip stream or raw data, once state->x.have is depleted. Returns 0 177220917Smav on success, -1 on failure. */ 178220917Smavlocal int gz_decomp(state) 179209944Smav gz_statep state; 180200171Smav{ 181200171Smav int ret = Z_OK; 182200171Smav unsigned had; 183200171Smav z_streamp strm = &(state->strm); 184200171Smav 185200171Smav /* fill output buffer up to end of deflate stream */ 186200171Smav had = strm->avail_out; 187200171Smav do { 188200171Smav /* get more input for inflate() */ 189200171Smav if (strm->avail_in == 0 && gz_avail(state) == -1) 190200171Smav return -1; 191200171Smav if (strm->avail_in == 0) { 192209944Smav gz_error(state, Z_BUF_ERROR, "unexpected end of file"); 193200171Smav break; 194209944Smav } 195200171Smav 196200171Smav /* decompress and handle errors */ 197200171Smav ret = inflate(strm, Z_NO_FLUSH); 198200171Smav if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { 199200171Smav gz_error(state, Z_STREAM_ERROR, 200200171Smav "internal error: inflate stream corrupt"); 201200171Smav return -1; 202200171Smav } 203200171Smav if (ret == Z_MEM_ERROR) { 204200171Smav gz_error(state, Z_MEM_ERROR, "out of memory"); 205200171Smav return -1; 206200171Smav } 207200171Smav if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ 208200171Smav gz_error(state, Z_DATA_ERROR, 209200171Smav strm->msg == NULL ? "compressed data error" : strm->msg); 210200171Smav return -1; 211200171Smav } 212200171Smav } while (strm->avail_out && ret != Z_STREAM_END); 213200171Smav 214209944Smav /* update available output */ 215200171Smav state->x.have = had - strm->avail_out; 216209944Smav state->x.next = strm->next_out - state->x.have; 217200171Smav 218214016Smav /* if the gzip stream completed successfully, look for another */ 219214016Smav if (ret == Z_STREAM_END) 220200171Smav state->how = LOOK; 22144380Ssos 22244380Ssos /* good decompression */ 22373897Ssos return 0; 22457325Ssos} 22556255Ssos 226144330Ssos/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. 227129493Sdes Data is either copied from the input file or decompressed from the input 228150129Ssos file depending on state->how. If state->how is LOOK, then a gzip header is 229144330Ssos looked for to determine whether to copy or decompress. Returns -1 on error, 23057325Ssos otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the 23156255Ssos end of the input file has been reached and all data has been processed. */ 232156003Ssoslocal int gz_fetch(state) 233156003Ssos gz_statep state; 234156003Ssos{ 235156003Ssos z_streamp strm = &(state->strm); 236214016Smav 237214016Smav do { 238156003Ssos switch(state->how) { 239188903Smav case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ 240132030Ssos if (gz_look(state) == -1) 241200171Smav return -1; 242200171Smav if (state->how == LOOK) 243200171Smav return 0; 244200171Smav break; 245200171Smav case COPY: /* -> COPY */ 246209944Smav if (gz_load(state, state->out, state->size << 1, &(state->x.have)) 247200171Smav == -1) 248200171Smav return -1; 249144330Ssos state->x.next = state->out; 25090215Ssos return 0; 25190215Ssos case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ 25290215Ssos strm->avail_out = state->size << 1; 253188763Smav strm->next_out = state->out; 254188763Smav if (gz_decomp(state) == -1) 255188763Smav return -1; 256188763Smav } 257188763Smav } while (state->x.have == 0 && (!state->eof || strm->avail_in)); 258144330Ssos return 0; 259119404Ssos} 260119404Ssos 261119404Ssos/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ 262188903Smavlocal int gz_skip(state, len) 263188903Smav gz_statep state; 264188903Smav z_off64_t len; 265203108Smav{ 266203108Smav unsigned n; 267203108Smav 268188903Smav /* skip over len bytes or reach end-of-file, whichever comes first */ 269203108Smav while (len) 270209944Smav /* skip over whatever is in output buffer */ 271209944Smav if (state->x.have) { 272209944Smav n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? 273209944Smav (unsigned)len : state->x.have; 274203108Smav state->x.have -= n; 275209944Smav state->x.next += n; 276203108Smav state->x.pos += n; 277203108Smav len -= n; 278203108Smav } 279203108Smav 280203108Smav /* output buffer empty -- return if we're at the end of the input */ 281203108Smav else if (state->eof && state->strm.avail_in == 0) 282203108Smav break; 283203108Smav 284209944Smav /* need more data to skip -- load up output buffer */ 285188903Smav else { 286188903Smav /* get more output, looking for header if required */ 287119404Ssos if (gz_fetch(state) == -1) 288144330Ssos return -1; 289119404Ssos } 290144330Ssos return 0; 291150129Ssos} 292129493Sdes 293203108Smav/* Read len bytes into buf from file, or less than len up to the end of the 294200171Smav input. Return the number of bytes read. If zero is returned, either the 295200171Smav end of file was reached, or there was an error. state->err must be 296200171Smav consulted in that case to determine which. */ 297200171Smavlocal z_size_t gz_read(state, buf, len) 298200171Smav gz_statep state; 299200171Smav voidp buf; 300200171Smav z_size_t len; 301200171Smav{ 302200171Smav z_size_t got; 303200171Smav unsigned n; 304200171Smav 305200171Smav /* if len is zero, avoid unnecessary operations */ 306200171Smav if (len == 0) 307200171Smav return 0; 308203108Smav 309200171Smav /* process a skip request */ 31056255Ssos if (state->seek) { 31156255Ssos state->seek = 0; 31273897Ssos if (gz_skip(state, state->skip) == -1) 313114656Ssos return 0; 314114656Ssos } 315114656Ssos 316114656Ssos /* get len bytes to buf, or less than len if at the end */ 317145354Ssos got = 0; 318114656Ssos do { 319114656Ssos /* set n to the maximum amount of len that fits in an unsigned int */ 320133556Ssos n = -1; 321220917Smav if (n > len) 322220917Smav n = len; 323208375Smav 324208375Smav /* first just try copying data from the output buffer */ 325208375Smav if (state->x.have) { 326208375Smav if (state->x.have < n) 327208375Smav n = state->x.have; 328200171Smav memcpy(buf, state->x.next, n); 329114656Ssos state->x.next += n; 330114656Ssos state->x.have -= n; 331114656Ssos } 33257325Ssos 33357325Ssos /* output buffer empty -- return if we're at the end of the input */ 334208375Smav else if (state->eof && state->strm.avail_in == 0) { 335107562Ssos state->past = 1; /* tried to read past end */ 336107562Ssos break; 337145354Ssos } 338208375Smav 339107562Ssos /* need output data -- for small len or new stream load up our output 340107562Ssos buffer */ 341208375Smav else if (state->how == LOOK || n < (state->size << 1)) { 342208375Smav /* get more output, looking for header if required */ 343208375Smav if (gz_fetch(state) == -1) 344208375Smav return 0; 345220917Smav continue; /* no progress yet -- go back to copy above */ 346220917Smav /* the copy above assures that we will leave with space in the 347107562Ssos output buffer, allowing at least one gzungetc() to succeed */ 34857325Ssos } 34957325Ssos 350188731Smav /* large len -- read directly into user buffer */ 351135819Ssos else if (state->how == COPY) { /* read directly */ 352135819Ssos if (gz_load(state, (unsigned char *)buf, n, &n) == -1) 353135819Ssos return 0; 354200171Smav } 355200171Smav 356235333Smav /* large len -- decompress directly into user buffer */ 357200171Smav else { /* state->how == GZIP */ 358235333Smav state->strm.avail_out = n; 359200171Smav state->strm.next_out = (unsigned char *)buf; 360200171Smav if (gz_decomp(state) == -1) 361200171Smav return 0; 362200171Smav n = state->x.have; 363200171Smav state->x.have = 0; 364200171Smav } 365200171Smav 366136486Ssos /* update progress */ 367135819Ssos len -= n; 368136486Ssos buf = (char *)buf + n; 369154507Ssos got += n; 370154507Ssos state->x.pos += n; 371154507Ssos } while (len); 372154507Ssos 373136486Ssos /* return number of bytes read into user buffer */ 374150129Ssos return got; 375136486Ssos} 376135819Ssos 377136486Ssos/* -- see zlib.h -- */ 378135819Ssosint ZEXPORT gzread(file, buf, len) 379154507Ssos gzFile file; 380156003Ssos voidp buf; 381150129Ssos unsigned len; 382136486Ssos{ 383136486Ssos gz_statep state; 384136486Ssos 385144330Ssos /* get internal structure */ 386156486Ssos if (file == NULL) 387145354Ssos return -1; 388144330Ssos state = (gz_statep)file; 389136486Ssos 390135819Ssos /* check that we're reading and that there's no (serious) error */ 391144330Ssos if (state->mode != GZ_READ || 392135819Ssos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 393200171Smav return -1; 394188731Smav 395135819Ssos /* since an int is returned, make sure len fits in one, otherwise return 396136486Ssos with an error (this avoids a flaw in the interface) */ 397135819Ssos if ((int)len < 0) { 398135819Ssos gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); 399214016Smav return -1; 400214016Smav } 401214016Smav 402214016Smav /* read len or fewer bytes to buf */ 403214016Smav len = gz_read(state, buf, len); 404214016Smav 405214016Smav /* check for an error */ 406214016Smav if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) 407214016Smav return -1; 408200171Smav 409200171Smav /* return the number of bytes read (this is assured to fit in an int) */ 410200171Smav return (int)len; 411200171Smav} 412200171Smav 413200171Smav/* -- see zlib.h -- */ 414200171Smavz_size_t ZEXPORT gzfread(buf, size, nitems, file) 415119404Ssos voidp buf; 416119404Ssos z_size_t size; 417119404Ssos z_size_t nitems; 41874302Ssos gzFile file; 419145713Ssos{ 420144707Ssos z_size_t len; 421145713Ssos gz_statep state; 422145713Ssos 423144707Ssos /* get internal structure */ 424144707Ssos if (file == NULL) 425144707Ssos return 0; 426144707Ssos state = (gz_statep)file; 427144707Ssos 428144707Ssos /* check that we're reading and that there's no (serious) error */ 429144707Ssos if (state->mode != GZ_READ || 430144707Ssos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 431144707Ssos return 0; 432144707Ssos 433144707Ssos /* compute bytes to read -- error on overflow */ 434149191Ssos len = nitems * size; 435144330Ssos if (size && len / size != nitems) { 43674302Ssos gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); 437144330Ssos return 0; 438144330Ssos } 439144330Ssos 440144330Ssos /* read len or fewer bytes to buf, return the number of full items read */ 441166909Sjhb return len ? gz_read(state, buf, len) / size : 0; 44274302Ssos} 44390215Ssos 444233282Smarius/* -- see zlib.h -- */ 445249203Smarius#ifdef Z_PREFIX_SET 446249203Smarius# undef z_gzgetc 447249203Smarius#else 448249203Smarius# undef gzgetc 449249203Smarius#endif 450249203Smariusint ZEXPORT gzgetc(file) 451249203Smarius gzFile file; 452249203Smarius{ 453249203Smarius int ret; 454249203Smarius unsigned char buf[1]; 455249203Smarius gz_statep state; 456249203Smarius 457249203Smarius /* get internal structure */ 458249203Smarius if (file == NULL) 459249203Smarius return -1; 460249203Smarius state = (gz_statep)file; 461249203Smarius 462249203Smarius /* check that we're reading and that there's no (serious) error */ 463249203Smarius if (state->mode != GZ_READ || 464249203Smarius (state->err != Z_OK && state->err != Z_BUF_ERROR)) 465249203Smarius return -1; 466249203Smarius 467249203Smarius /* try output buffer (no need to check for skip request) */ 468249203Smarius if (state->x.have) { 469249203Smarius state->x.have--; 470249203Smarius state->x.pos++; 471249203Smarius return *(state->x.next)++; 472249203Smarius } 473249203Smarius 474249203Smarius /* nothing there -- try gz_read() */ 475249203Smarius ret = gz_read(state, buf, 1); 476249203Smarius return ret < 1 ? -1 : buf[0]; 477249203Smarius} 478249203Smarius 479249203Smariusint ZEXPORT gzgetc_(file) 480249203SmariusgzFile file; 481249203Smarius{ 482249203Smarius return gzgetc(file); 483249203Smarius} 484249203Smarius 485249203Smarius/* -- see zlib.h -- */ 486249203Smariusint ZEXPORT gzungetc(c, file) 487249203Smarius int c; 488249203Smarius gzFile file; 489249203Smarius{ 490249203Smarius gz_statep state; 491249203Smarius 492249203Smarius /* get internal structure */ 493249203Smarius if (file == NULL) 494249203Smarius return -1; 495249203Smarius state = (gz_statep)file; 496249203Smarius 497249203Smarius /* check that we're reading and that there's no (serious) error */ 498249203Smarius if (state->mode != GZ_READ || 499249203Smarius (state->err != Z_OK && state->err != Z_BUF_ERROR)) 500249203Smarius return -1; 501249203Smarius 502249203Smarius /* process a skip request */ 503249203Smarius if (state->seek) { 504249203Smarius state->seek = 0; 505249203Smarius if (gz_skip(state, state->skip) == -1) 506249203Smarius return -1; 507249203Smarius } 508249203Smarius 509249203Smarius /* can't push EOF */ 510249203Smarius if (c < 0) 511249203Smarius return -1; 512249203Smarius 513249203Smarius /* if output buffer empty, put byte at end (allows more pushing) */ 514249203Smarius if (state->x.have == 0) { 515249203Smarius state->x.have = 1; 516249203Smarius state->x.next = state->out + (state->size << 1) - 1; 517249203Smarius state->x.next[0] = (unsigned char)c; 518249203Smarius state->x.pos--; 519249203Smarius state->past = 0; 520249203Smarius return c; 521249203Smarius } 522249203Smarius 523249203Smarius /* if no room, give up (must have already done a gzungetc()) */ 524249203Smarius if (state->x.have == (state->size << 1)) { 525249203Smarius gz_error(state, Z_DATA_ERROR, "out of room to push characters"); 526249203Smarius return -1; 527249203Smarius } 528249203Smarius 529249203Smarius /* slide output data if needed and insert byte before existing data */ 530249203Smarius if (state->x.next == state->out) { 531249203Smarius unsigned char *src = state->out + state->x.have; 532249203Smarius unsigned char *dest = state->out + (state->size << 1); 533249203Smarius while (src > state->out) 534249203Smarius *--dest = *--src; 535249203Smarius state->x.next = dest; 536249203Smarius } 537249203Smarius state->x.have++; 538249203Smarius state->x.next--; 539249203Smarius state->x.next[0] = (unsigned char)c; 540249203Smarius state->x.pos--; 541249203Smarius state->past = 0; 542249203Smarius return c; 543249203Smarius} 544249203Smarius 545249203Smarius/* -- see zlib.h -- */ 546249203Smariuschar * ZEXPORT gzgets(file, buf, len) 547249203Smarius gzFile file; 548249203Smarius char *buf; 549249203Smarius int len; 550249203Smarius{ 551249203Smarius unsigned left, n; 552249203Smarius char *str; 553249203Smarius unsigned char *eol; 554249203Smarius gz_statep state; 555249203Smarius 556249203Smarius /* check parameters and get internal structure */ 557249203Smarius if (file == NULL || buf == NULL || len < 1) 558249203Smarius return NULL; 55966070Ssos state = (gz_statep)file; 56057325Ssos 56151520Ssos /* check that we're reading and that there's no (serious) error */ 562149594Ssos if (state->mode != GZ_READ || 56355333Ssos (state->err != Z_OK && state->err != Z_BUF_ERROR)) 56455333Ssos return NULL; 56555333Ssos 56655333Ssos /* process a skip request */ 56755333Ssos if (state->seek) { 568111188Ssos state->seek = 0; 569111188Ssos if (gz_skip(state, state->skip) == -1) 57055333Ssos return NULL; 571111188Ssos } 572111188Ssos 57355333Ssos /* copy output bytes up to new line or len - 1, whichever comes first -- 574111188Ssos append a terminating zero to the string (we don't check for a zero in 57555333Ssos the contents, let the user worry about that) */ 57664307Ssos str = buf; 57784584Ssos left = (unsigned)len - 1; 578115135Ssos if (left) do { 579148992Ssos /* assure that something is in the output buffer */ 580144330Ssos if (state->x.have == 0 && gz_fetch(state) == -1) 581144330Ssos return NULL; /* error */ 582144330Ssos if (state->x.have == 0) { /* end of file */ 583144330Ssos state->past = 1; /* read past end */ 584144330Ssos break; /* return what we have */ 58555333Ssos } 58655333Ssos 58755333Ssos /* look for end-of-line in current output buffer */ 588249203Smarius n = state->x.have > left ? left : state->x.have; 589209664Smav eol = (unsigned char *)memchr(state->x.next, '\n', n); 590209664Smav if (eol != NULL) 591209664Smav n = (unsigned)(eol - state->x.next) + 1; 592209664Smav 593209664Smav /* copy through end-of-line, or remainder if not found */ 594209664Smav memcpy(buf, state->x.next, n); 595209664Smav state->x.have -= n; 596209664Smav state->x.next += n; 597209664Smav state->x.pos += n; 598209664Smav left -= n; 599209664Smav buf += n; 600209664Smav } while (left && eol == NULL); 601209664Smav 602209664Smav /* return terminated string, or if nothing, end of file */ 603209664Smav if (buf == str) 604209664Smav return NULL; 605209664Smav buf[0] = 0; 606209664Smav return str; 607209664Smav} 608209664Smav 609209664Smav/* -- see zlib.h -- */ 610209664Smavint ZEXPORT gzdirect(file) 611209664Smav gzFile file; 612209664Smav{ 613209664Smav gz_statep state; 614209664Smav 615209664Smav /* get internal structure */ 616209664Smav if (file == NULL) 61766070Ssos return 0; 618200459Smarius state = (gz_statep)file; 619183724Ssos 620200459Smarius /* if the state is not known, but we can find out, then do so (this is 621183724Ssos mainly for right after a gzopen() or gzdopen()) */ 622200459Smarius if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) 623183724Ssos (void)gz_look(state); 624183724Ssos 625249203Smarius /* return 1 if transparent, 0 if processing a gzip stream */ 626249203Smarius return state->direct; 627249203Smarius} 628249203Smarius 629249203Smarius/* -- see zlib.h -- */ 630249203Smariusint ZEXPORT gzclose_r(file) 631249203Smarius gzFile file; 632249203Smarius{ 633249203Smarius int ret, err; 634249203Smarius gz_statep state; 635249203Smarius 636249203Smarius /* get internal structure */ 637249203Smarius if (file == NULL) 638249203Smarius return Z_STREAM_ERROR; 639249203Smarius state = (gz_statep)file; 640249203Smarius 641249203Smarius /* check that we're reading */ 642249203Smarius if (state->mode != GZ_READ) 643249203Smarius return Z_STREAM_ERROR; 644249203Smarius 645249203Smarius /* free memory and close file */ 646249203Smarius if (state->size) { 647249203Smarius inflateEnd(&(state->strm)); 648249203Smarius free(state->out); 649249203Smarius free(state->in); 650249203Smarius } 651145676Ssos err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; 652200171Smav gz_error(state, Z_OK, NULL); 653200171Smav free(state->path); 654200171Smav ret = close(state->fd); 655200171Smav free(state); 656145676Ssos return ret ? Z_ERRNO : err; 657200171Smav} 658200171Smav