(root)/
gcc-13.2.0/
zlib/
gzlib.c
       1  /* gzlib.c -- zlib functions common to reading and writing gzip files
       2   * Copyright (C) 2004-2017 Mark Adler
       3   * For conditions of distribution and use, see copyright notice in zlib.h
       4   */
       5  
       6  #include "gzguts.h"
       7  
       8  #if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
       9  #  define LSEEK _lseeki64
      10  #else
      11  #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
      12  #  define LSEEK lseek64
      13  #else
      14  #  define LSEEK lseek
      15  #endif
      16  #endif
      17  
      18  /* Local functions */
      19  local void gz_reset OF((gz_statep));
      20  local gzFile gz_open OF((const void *, int, const char *));
      21  
      22  #if defined UNDER_CE
      23  
      24  /* Map the Windows error number in ERROR to a locale-dependent error message
      25     string and return a pointer to it.  Typically, the values for ERROR come
      26     from GetLastError.
      27  
      28     The string pointed to shall not be modified by the application, but may be
      29     overwritten by a subsequent call to gz_strwinerror
      30  
      31     The gz_strwinerror function does not change the current setting of
      32     GetLastError. */
      33  char ZLIB_INTERNAL *gz_strwinerror (error)
      34       DWORD error;
      35  {
      36      static char buf[1024];
      37  
      38      wchar_t *msgbuf;
      39      DWORD lasterr = GetLastError();
      40      DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
      41          | FORMAT_MESSAGE_ALLOCATE_BUFFER,
      42          NULL,
      43          error,
      44          0, /* Default language */
      45          (LPVOID)&msgbuf,
      46          0,
      47          NULL);
      48      if (chars != 0) {
      49          /* If there is an \r\n appended, zap it.  */
      50          if (chars >= 2
      51              && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
      52              chars -= 2;
      53              msgbuf[chars] = 0;
      54          }
      55  
      56          if (chars > sizeof (buf) - 1) {
      57              chars = sizeof (buf) - 1;
      58              msgbuf[chars] = 0;
      59          }
      60  
      61          wcstombs(buf, msgbuf, chars + 1);
      62          LocalFree(msgbuf);
      63      }
      64      else {
      65          sprintf(buf, "unknown win32 error (%ld)", error);
      66      }
      67  
      68      SetLastError(lasterr);
      69      return buf;
      70  }
      71  
      72  #endif /* UNDER_CE */
      73  
      74  /* Reset gzip file state */
      75  local void gz_reset(state)
      76      gz_statep state;
      77  {
      78      state->x.have = 0;              /* no output data available */
      79      if (state->mode == GZ_READ) {   /* for reading ... */
      80          state->eof = 0;             /* not at end of file */
      81          state->past = 0;            /* have not read past end yet */
      82          state->how = LOOK;          /* look for gzip header */
      83      }
      84      state->seek = 0;                /* no seek request pending */
      85      gz_error(state, Z_OK, NULL);    /* clear error */
      86      state->x.pos = 0;               /* no uncompressed data yet */
      87      state->strm.avail_in = 0;       /* no input data yet */
      88  }
      89  
      90  /* Open a gzip file either by name or file descriptor. */
      91  local gzFile gz_open(path, fd, mode)
      92      const void *path;
      93      int fd;
      94      const char *mode;
      95  {
      96      gz_statep state;
      97      z_size_t len;
      98      int oflag;
      99  #ifdef O_CLOEXEC
     100      int cloexec = 0;
     101  #endif
     102  #ifdef O_EXCL
     103      int exclusive = 0;
     104  #endif
     105  
     106      /* check input */
     107      if (path == NULL)
     108          return NULL;
     109  
     110      /* allocate gzFile structure to return */
     111      state = (gz_statep)malloc(sizeof(gz_state));
     112      if (state == NULL)
     113          return NULL;
     114      state->size = 0;            /* no buffers allocated yet */
     115      state->want = GZBUFSIZE;    /* requested buffer size */
     116      state->msg = NULL;          /* no error message yet */
     117  
     118      /* interpret mode */
     119      state->mode = GZ_NONE;
     120      state->level = Z_DEFAULT_COMPRESSION;
     121      state->strategy = Z_DEFAULT_STRATEGY;
     122      state->direct = 0;
     123      while (*mode) {
     124          if (*mode >= '0' && *mode <= '9')
     125              state->level = *mode - '0';
     126          else
     127              switch (*mode) {
     128              case 'r':
     129                  state->mode = GZ_READ;
     130                  break;
     131  #ifndef NO_GZCOMPRESS
     132              case 'w':
     133                  state->mode = GZ_WRITE;
     134                  break;
     135              case 'a':
     136                  state->mode = GZ_APPEND;
     137                  break;
     138  #endif
     139              case '+':       /* can't read and write at the same time */
     140                  free(state);
     141                  return NULL;
     142              case 'b':       /* ignore -- will request binary anyway */
     143                  break;
     144  #ifdef O_CLOEXEC
     145              case 'e':
     146                  cloexec = 1;
     147                  break;
     148  #endif
     149  #ifdef O_EXCL
     150              case 'x':
     151                  exclusive = 1;
     152                  break;
     153  #endif
     154              case 'f':
     155                  state->strategy = Z_FILTERED;
     156                  break;
     157              case 'h':
     158                  state->strategy = Z_HUFFMAN_ONLY;
     159                  break;
     160              case 'R':
     161                  state->strategy = Z_RLE;
     162                  break;
     163              case 'F':
     164                  state->strategy = Z_FIXED;
     165                  break;
     166              case 'T':
     167                  state->direct = 1;
     168                  break;
     169              default:        /* could consider as an error, but just ignore */
     170                  ;
     171              }
     172          mode++;
     173      }
     174  
     175      /* must provide an "r", "w", or "a" */
     176      if (state->mode == GZ_NONE) {
     177          free(state);
     178          return NULL;
     179      }
     180  
     181      /* can't force transparent read */
     182      if (state->mode == GZ_READ) {
     183          if (state->direct) {
     184              free(state);
     185              return NULL;
     186          }
     187          state->direct = 1;      /* for empty file */
     188      }
     189  
     190      /* save the path name for error messages */
     191  #ifdef WIDECHAR
     192      if (fd == -2) {
     193          len = wcstombs(NULL, path, 0);
     194          if (len == (z_size_t)-1)
     195              len = 0;
     196      }
     197      else
     198  #endif
     199          len = strlen((const char *)path);
     200      state->path = (char *)malloc(len + 1);
     201      if (state->path == NULL) {
     202          free(state);
     203          return NULL;
     204      }
     205  #ifdef WIDECHAR
     206      if (fd == -2)
     207          if (len)
     208              wcstombs(state->path, path, len + 1);
     209          else
     210              *(state->path) = 0;
     211      else
     212  #endif
     213  #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
     214          (void)snprintf(state->path, len + 1, "%s", (const char *)path);
     215  #else
     216          strcpy(state->path, path);
     217  #endif
     218  
     219      /* compute the flags for open() */
     220      oflag =
     221  #ifdef O_LARGEFILE
     222          O_LARGEFILE |
     223  #endif
     224  #ifdef O_BINARY
     225          O_BINARY |
     226  #endif
     227  #ifdef O_CLOEXEC
     228          (cloexec ? O_CLOEXEC : 0) |
     229  #endif
     230          (state->mode == GZ_READ ?
     231           O_RDONLY :
     232           (O_WRONLY | O_CREAT |
     233  #ifdef O_EXCL
     234            (exclusive ? O_EXCL : 0) |
     235  #endif
     236            (state->mode == GZ_WRITE ?
     237             O_TRUNC :
     238             O_APPEND)));
     239  
     240      /* open the file with the appropriate flags (or just use fd) */
     241      state->fd = fd > -1 ? fd : (
     242  #ifdef WIDECHAR
     243          fd == -2 ? _wopen(path, oflag, 0666) :
     244  #endif
     245          open((const char *)path, oflag, 0666));
     246      if (state->fd == -1) {
     247          free(state->path);
     248          free(state);
     249          return NULL;
     250      }
     251      if (state->mode == GZ_APPEND) {
     252          LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
     253          state->mode = GZ_WRITE;         /* simplify later checks */
     254      }
     255  
     256      /* save the current position for rewinding (only if reading) */
     257      if (state->mode == GZ_READ) {
     258          state->start = LSEEK(state->fd, 0, SEEK_CUR);
     259          if (state->start == -1) state->start = 0;
     260      }
     261  
     262      /* initialize stream */
     263      gz_reset(state);
     264  
     265      /* return stream */
     266      return (gzFile)state;
     267  }
     268  
     269  /* -- see zlib.h -- */
     270  gzFile ZEXPORT gzopen(path, mode)
     271      const char *path;
     272      const char *mode;
     273  {
     274      return gz_open(path, -1, mode);
     275  }
     276  
     277  /* -- see zlib.h -- */
     278  gzFile ZEXPORT gzopen64(path, mode)
     279      const char *path;
     280      const char *mode;
     281  {
     282      return gz_open(path, -1, mode);
     283  }
     284  
     285  /* -- see zlib.h -- */
     286  gzFile ZEXPORT gzdopen(fd, mode)
     287      int fd;
     288      const char *mode;
     289  {
     290      char *path;         /* identifier for error messages */
     291      gzFile gz;
     292  
     293      if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
     294          return NULL;
     295  #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
     296      (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
     297  #else
     298      sprintf(path, "<fd:%d>", fd);   /* for debugging */
     299  #endif
     300      gz = gz_open(path, fd, mode);
     301      free(path);
     302      return gz;
     303  }
     304  
     305  /* -- see zlib.h -- */
     306  #ifdef WIDECHAR
     307  gzFile ZEXPORT gzopen_w(path, mode)
     308      const wchar_t *path;
     309      const char *mode;
     310  {
     311      return gz_open(path, -2, mode);
     312  }
     313  #endif
     314  
     315  /* -- see zlib.h -- */
     316  int ZEXPORT gzbuffer(file, size)
     317      gzFile file;
     318      unsigned size;
     319  {
     320      gz_statep state;
     321  
     322      /* get internal structure and check integrity */
     323      if (file == NULL)
     324          return -1;
     325      state = (gz_statep)file;
     326      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     327          return -1;
     328  
     329      /* make sure we haven't already allocated memory */
     330      if (state->size != 0)
     331          return -1;
     332  
     333      /* check and set requested size */
     334      if ((size << 1) < size)
     335          return -1;              /* need to be able to double it */
     336      if (size < 2)
     337          size = 2;               /* need two bytes to check magic header */
     338      state->want = size;
     339      return 0;
     340  }
     341  
     342  /* -- see zlib.h -- */
     343  int ZEXPORT gzrewind(file)
     344      gzFile file;
     345  {
     346      gz_statep state;
     347  
     348      /* get internal structure */
     349      if (file == NULL)
     350          return -1;
     351      state = (gz_statep)file;
     352  
     353      /* check that we're reading and that there's no error */
     354      if (state->mode != GZ_READ ||
     355              (state->err != Z_OK && state->err != Z_BUF_ERROR))
     356          return -1;
     357  
     358      /* back up and start over */
     359      if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
     360          return -1;
     361      gz_reset(state);
     362      return 0;
     363  }
     364  
     365  /* -- see zlib.h -- */
     366  z_off64_t ZEXPORT gzseek64(file, offset, whence)
     367      gzFile file;
     368      z_off64_t offset;
     369      int whence;
     370  {
     371      unsigned n;
     372      z_off64_t ret;
     373      gz_statep state;
     374  
     375      /* get internal structure and check integrity */
     376      if (file == NULL)
     377          return -1;
     378      state = (gz_statep)file;
     379      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     380          return -1;
     381  
     382      /* check that there's no error */
     383      if (state->err != Z_OK && state->err != Z_BUF_ERROR)
     384          return -1;
     385  
     386      /* can only seek from start or relative to current position */
     387      if (whence != SEEK_SET && whence != SEEK_CUR)
     388          return -1;
     389  
     390      /* normalize offset to a SEEK_CUR specification */
     391      if (whence == SEEK_SET)
     392          offset -= state->x.pos;
     393      else if (state->seek)
     394          offset += state->skip;
     395      state->seek = 0;
     396  
     397      /* if within raw area while reading, just go there */
     398      if (state->mode == GZ_READ && state->how == COPY &&
     399              state->x.pos + offset >= 0) {
     400          ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
     401          if (ret == -1)
     402              return -1;
     403          state->x.have = 0;
     404          state->eof = 0;
     405          state->past = 0;
     406          state->seek = 0;
     407          gz_error(state, Z_OK, NULL);
     408          state->strm.avail_in = 0;
     409          state->x.pos += offset;
     410          return state->x.pos;
     411      }
     412  
     413      /* calculate skip amount, rewinding if needed for back seek when reading */
     414      if (offset < 0) {
     415          if (state->mode != GZ_READ)         /* writing -- can't go backwards */
     416              return -1;
     417          offset += state->x.pos;
     418          if (offset < 0)                     /* before start of file! */
     419              return -1;
     420          if (gzrewind(file) == -1)           /* rewind, then skip to offset */
     421              return -1;
     422      }
     423  
     424      /* if reading, skip what's in output buffer (one less gzgetc() check) */
     425      if (state->mode == GZ_READ) {
     426          n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
     427              (unsigned)offset : state->x.have;
     428          state->x.have -= n;
     429          state->x.next += n;
     430          state->x.pos += n;
     431          offset -= n;
     432      }
     433  
     434      /* request skip (if not zero) */
     435      if (offset) {
     436          state->seek = 1;
     437          state->skip = offset;
     438      }
     439      return state->x.pos + offset;
     440  }
     441  
     442  /* -- see zlib.h -- */
     443  z_off_t ZEXPORT gzseek(file, offset, whence)
     444      gzFile file;
     445      z_off_t offset;
     446      int whence;
     447  {
     448      z_off64_t ret;
     449  
     450      ret = gzseek64(file, (z_off64_t)offset, whence);
     451      return ret == (z_off_t)ret ? (z_off_t)ret : -1;
     452  }
     453  
     454  /* -- see zlib.h -- */
     455  z_off64_t ZEXPORT gztell64(file)
     456      gzFile file;
     457  {
     458      gz_statep state;
     459  
     460      /* get internal structure and check integrity */
     461      if (file == NULL)
     462          return -1;
     463      state = (gz_statep)file;
     464      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     465          return -1;
     466  
     467      /* return position */
     468      return state->x.pos + (state->seek ? state->skip : 0);
     469  }
     470  
     471  /* -- see zlib.h -- */
     472  z_off_t ZEXPORT gztell(file)
     473      gzFile file;
     474  {
     475      z_off64_t ret;
     476  
     477      ret = gztell64(file);
     478      return ret == (z_off_t)ret ? (z_off_t)ret : -1;
     479  }
     480  
     481  /* -- see zlib.h -- */
     482  z_off64_t ZEXPORT gzoffset64(file)
     483      gzFile file;
     484  {
     485      z_off64_t offset;
     486      gz_statep state;
     487  
     488      /* get internal structure and check integrity */
     489      if (file == NULL)
     490          return -1;
     491      state = (gz_statep)file;
     492      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     493          return -1;
     494  
     495      /* compute and return effective offset in file */
     496      offset = LSEEK(state->fd, 0, SEEK_CUR);
     497      if (offset == -1)
     498          return -1;
     499      if (state->mode == GZ_READ)             /* reading */
     500          offset -= state->strm.avail_in;     /* don't count buffered input */
     501      return offset;
     502  }
     503  
     504  /* -- see zlib.h -- */
     505  z_off_t ZEXPORT gzoffset(file)
     506      gzFile file;
     507  {
     508      z_off64_t ret;
     509  
     510      ret = gzoffset64(file);
     511      return ret == (z_off_t)ret ? (z_off_t)ret : -1;
     512  }
     513  
     514  /* -- see zlib.h -- */
     515  int ZEXPORT gzeof(file)
     516      gzFile file;
     517  {
     518      gz_statep state;
     519  
     520      /* get internal structure and check integrity */
     521      if (file == NULL)
     522          return 0;
     523      state = (gz_statep)file;
     524      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     525          return 0;
     526  
     527      /* return end-of-file state */
     528      return state->mode == GZ_READ ? state->past : 0;
     529  }
     530  
     531  /* -- see zlib.h -- */
     532  const char * ZEXPORT gzerror(file, errnum)
     533      gzFile file;
     534      int *errnum;
     535  {
     536      gz_statep state;
     537  
     538      /* get internal structure and check integrity */
     539      if (file == NULL)
     540          return NULL;
     541      state = (gz_statep)file;
     542      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     543          return NULL;
     544  
     545      /* return error information */
     546      if (errnum != NULL)
     547          *errnum = state->err;
     548      return state->err == Z_MEM_ERROR ? "out of memory" :
     549                                         (state->msg == NULL ? "" : state->msg);
     550  }
     551  
     552  /* -- see zlib.h -- */
     553  void ZEXPORT gzclearerr(file)
     554      gzFile file;
     555  {
     556      gz_statep state;
     557  
     558      /* get internal structure and check integrity */
     559      if (file == NULL)
     560          return;
     561      state = (gz_statep)file;
     562      if (state->mode != GZ_READ && state->mode != GZ_WRITE)
     563          return;
     564  
     565      /* clear error and end-of-file */
     566      if (state->mode == GZ_READ) {
     567          state->eof = 0;
     568          state->past = 0;
     569      }
     570      gz_error(state, Z_OK, NULL);
     571  }
     572  
     573  /* Create an error message in allocated memory and set state->err and
     574     state->msg accordingly.  Free any previous error message already there.  Do
     575     not try to free or allocate space if the error is Z_MEM_ERROR (out of
     576     memory).  Simply save the error message as a static string.  If there is an
     577     allocation failure constructing the error message, then convert the error to
     578     out of memory. */
     579  void ZLIB_INTERNAL gz_error(state, err, msg)
     580      gz_statep state;
     581      int err;
     582      const char *msg;
     583  {
     584      /* free previously allocated message and clear */
     585      if (state->msg != NULL) {
     586          if (state->err != Z_MEM_ERROR)
     587              free(state->msg);
     588          state->msg = NULL;
     589      }
     590  
     591      /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
     592      if (err != Z_OK && err != Z_BUF_ERROR)
     593          state->x.have = 0;
     594  
     595      /* set error code, and if no message, then done */
     596      state->err = err;
     597      if (msg == NULL)
     598          return;
     599  
     600      /* for an out of memory error, return literal string when requested */
     601      if (err == Z_MEM_ERROR)
     602          return;
     603  
     604      /* construct error message with path */
     605      if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
     606              NULL) {
     607          state->err = Z_MEM_ERROR;
     608          return;
     609      }
     610  #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
     611      (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
     612                     "%s%s%s", state->path, ": ", msg);
     613  #else
     614      strcpy(state->msg, state->path);
     615      strcat(state->msg, ": ");
     616      strcat(state->msg, msg);
     617  #endif
     618  }
     619  
     620  #ifndef INT_MAX
     621  /* portably return maximum value for an int (when limits.h presumed not
     622     available) -- we need to do this to cover cases where 2's complement not
     623     used, since C standard permits 1's complement and sign-bit representations,
     624     otherwise we could just use ((unsigned)-1) >> 1 */
     625  unsigned ZLIB_INTERNAL gz_intmax()
     626  {
     627      unsigned p, q;
     628  
     629      p = 1;
     630      do {
     631          q = p;
     632          p <<= 1;
     633          p++;
     634      } while (p > q);
     635      return q >> 1;
     636  }
     637  #endif