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