Example #1
0
/* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
local int
gz_skip (gz_statep state, z_off64_t len)
{
  unsigned n;

  /* skip over len bytes or reach end-of-file, whichever comes first */
  while (len)
    /* skip over whatever is in output buffer */
    if (state->x.have)
      {
	n = GT_OFF (state->x.have) || (z_off64_t) state->x.have > len ?
	  (unsigned) len : state->x.have;
	state->x.have -= n;
	state->x.next += n;
	state->x.pos += n;
	len -= n;
      }

  /* output buffer empty -- return if we're at the end of the input */
    else if (state->eof && state->strm.avail_in == 0)
      break;

  /* need more data to skip -- load up output buffer */
    else
      {
	/* get more output, looking for header if required */
	if (gz_fetch (state) == -1)
	  return -1;
      }
  return 0;
}
Example #2
0
char * ZEXPORT gzgets(gzFile file, char *buf, int len)
{
   unsigned left, n;
   char *str;
   unsigned char *eol;
   gz_statep state;

   /* check parameters and get internal structure */
   if (file == NULL || buf == NULL || len < 1)
      return NULL;
   state = (gz_statep)file;

   /* 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 NULL;

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

   /* copy output bytes up to new line or len - 1, whichever comes first --
      append a terminating zero to the string (we don't check for a zero in
      the contents, let the user worry about that) */
   str = buf;
   left = (unsigned)len - 1;
   if (left) do {
      /* assure that something is in the output buffer */
      if (state->x.have == 0 && gz_fetch(state) == -1)
         return NULL;                /* error */
      if (state->x.have == 0) {       /* end of file */
         state->past = 1;            /* read past end */
         break;                      /* return what we have */
      }

      /* look for end-of-line in current output buffer */
      n = state->x.have > left ? left : state->x.have;
      eol = (unsigned char *)memchr(state->x.next, '\n', n);
      if (eol != NULL)
         n = (unsigned)(eol - state->x.next) + 1;

      /* copy through end-of-line, or remainder if not found */
      memcpy(buf, state->x.next, n);
      state->x.have -= n;
      state->x.next += n;
      state->x.pos += n;
      left -= n;
      buf += n;
   } while (left && eol == NULL);

   /* return terminated string, or if nothing, end of file */
   if (buf == str)
      return NULL;
   buf[0] = 0;
   return str;
}
Example #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;
}