Fossil SCM

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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button