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