Exemple #1
0
/* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
   Data is either copied from the input file or decompressed from the input
   file depending on state->how.  If state->how is LOOK, then a gzip header is
   looked for to determine whether to copy or decompress.  Returns -1 on error,
   otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
   end of the input file has been reached and all data has been processed.  */
local int
gz_fetch (gz_statep state)
{
  z_streamp strm = &(state->strm);

  do
    {
      switch (state->how)
	{
	case LOOK:		/* -> LOOK, COPY (only if never GZIP), or GZIP */
	  if (gz_look (state) == -1)
	    return -1;
	  if (state->how == LOOK)
	    return 0;
	  break;
	case COPY:		/* -> COPY */
	  if (gz_load (state, state->out, state->size << 1, &(state->x.have))
	      == -1)
	    return -1;
	  state->x.next = state->out;
	  return 0;
	case GZIP:		/* -> GZIP or LOOK (if end of gzip stream) */
	  strm->avail_out = state->size << 1;
	  strm->next_out = state->out;
	  if (gz_decomp (state) == -1)
	    return -1;
	}
    }
  while (state->x.have == 0 && (!state->eof || strm->avail_in));
  return 0;
}
Exemple #2
0
/* Make data and put in the output buffer.  Assumes that state->have == 0.
   Data is either copied from the input file or decompressed from the input
   file depending on state->how.  If state->how is LOOK, then a gzip header is
   looked for (and skipped if found) to determine wither to copy or decompress.
   Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
   or GZIP unless the end of the input file has been reached and all data has
   been processed.  */
local int gz_make(gz_statep state)
{
    z_streamp strm = &(state->strm);

    if (state->how == LOOK) {           /* look for gzip header */
        if (gz_head(state) == -1)
            return -1;
        if (state->have)                /* got some data from gz_head() */
            return 0;
    }
    if (state->how == COPY) {           /* straight copy */
        if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
            return -1;
        state->next = state->out;
    }
    else if (state->how == GZIP) {      /* decompress */
        strm->avail_out = state->size << 1;
        strm->next_out = state->out;
        if (gz_decomp(state) == -1)
            return -1;
    }
    return 0;
}
Exemple #3
0
/* -- see zlib.h -- */
int ZEXPORT
gzread (gzFile file, voidp buf, unsigned len)
{
  unsigned got, n;
  gz_statep state;
  z_streamp strm;

  /* get internal structure */
  if (file == NULL)
    return -1;
  state = (gz_statep) file;
  strm = &(state->strm);

  /* check that we're reading and that there's no (serious) error */
  if (state->mode != GZ_READ ||
      (state->err != Z_OK && state->err != Z_BUF_ERROR))
    return -1;

  /* since an int is returned, make sure len fits in one, otherwise return
     with an error (this avoids the flaw in the interface) */
  if ((int) len < 0)
    {
      gz_error (state, Z_DATA_ERROR, "requested length does not fit in int");
      return -1;
    }

  /* if len is zero, avoid unnecessary operations */
  if (len == 0)
    return 0;

  /* process a skip request */
  if (state->seek)
    {
      state->seek = 0;
      if (gz_skip (state, state->skip) == -1)
	return -1;
    }

  /* get len bytes to buf, or less than len if at the end */
  got = 0;
  do
    {
      /* first just try copying data from the output buffer */
      if (state->x.have)
	{
	  n = state->x.have > len ? len : state->x.have;
	  memcpy (buf, state->x.next, n);
	  state->x.next += n;
	  state->x.have -= n;
	}

      /* output buffer empty -- return if we're at the end of the input */
      else if (state->eof && strm->avail_in == 0)
	{
	  state->past = 1;	/* tried to read past end */
	  break;
	}

      /* need output data -- for small len or new stream load up our output
         buffer */
      else if (state->how == LOOK || len < (state->size << 1))
	{
	  /* get more output, looking for header if required */
	  if (gz_fetch (state) == -1)
	    return -1;
	  continue;		/* no progress yet -- go back to copy above */
	  /* the copy above assures that we will leave with space in the
	     output buffer, allowing at least one gzungetc() to succeed */
	}

      /* large len -- read directly into user buffer */
      else if (state->how == COPY)
	{			/* read directly */
	  if (gz_load (state, (unsigned char *) buf, len, &n) == -1)
	    return -1;
	}

      /* large len -- decompress directly into user buffer */
      else
	{			/* state->how == GZIP */
	  strm->avail_out = len;
	  strm->next_out = (unsigned char *) buf;
	  if (gz_decomp (state) == -1)
	    return -1;
	  n = state->x.have;
	  state->x.have = 0;
	}

      /* update progress */
      len -= n;
      buf = (char *) buf + n;
      got += n;
      state->x.pos += n;
    }
  while (len);

  /* return number of bytes read into user buffer (will fit in int) */
  return (int) got;
}