(root)/
binutils-2.41/
zlib/
gzwrite.c
       1  /* gzwrite.c -- zlib functions for 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  /* Local functions */
       9  local int gz_init OF((gz_statep));
      10  local int gz_comp OF((gz_statep, int));
      11  local int gz_zero OF((gz_statep, z_off64_t));
      12  local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
      13  
      14  /* Initialize state for writing a gzip file.  Mark initialization by setting
      15     state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
      16     success. */
      17  local int gz_init(state)
      18      gz_statep state;
      19  {
      20      int ret;
      21      z_streamp strm = &(state->strm);
      22  
      23      /* allocate input buffer (double size for gzprintf) */
      24      state->in = (unsigned char *)malloc(state->want << 1);
      25      if (state->in == NULL) {
      26          gz_error(state, Z_MEM_ERROR, "out of memory");
      27          return -1;
      28      }
      29  
      30      /* only need output buffer and deflate state if compressing */
      31      if (!state->direct) {
      32          /* allocate output buffer */
      33          state->out = (unsigned char *)malloc(state->want);
      34          if (state->out == NULL) {
      35              free(state->in);
      36              gz_error(state, Z_MEM_ERROR, "out of memory");
      37              return -1;
      38          }
      39  
      40          /* allocate deflate memory, set up for gzip compression */
      41          strm->zalloc = Z_NULL;
      42          strm->zfree = Z_NULL;
      43          strm->opaque = Z_NULL;
      44          ret = deflateInit2(strm, state->level, Z_DEFLATED,
      45                             MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
      46          if (ret != Z_OK) {
      47              free(state->out);
      48              free(state->in);
      49              gz_error(state, Z_MEM_ERROR, "out of memory");
      50              return -1;
      51          }
      52          strm->next_in = NULL;
      53      }
      54  
      55      /* mark state as initialized */
      56      state->size = state->want;
      57  
      58      /* initialize write buffer if compressing */
      59      if (!state->direct) {
      60          strm->avail_out = state->size;
      61          strm->next_out = state->out;
      62          state->x.next = strm->next_out;
      63      }
      64      return 0;
      65  }
      66  
      67  /* Compress whatever is at avail_in and next_in and write to the output file.
      68     Return -1 if there is an error writing to the output file or if gz_init()
      69     fails to allocate memory, otherwise 0.  flush is assumed to be a valid
      70     deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
      71     reset to start a new gzip stream.  If gz->direct is true, then simply write
      72     to the output file without compressing, and ignore flush. */
      73  local int gz_comp(state, flush)
      74      gz_statep state;
      75      int flush;
      76  {
      77      int ret, writ;
      78      unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
      79      z_streamp strm = &(state->strm);
      80  
      81      /* allocate memory if this is the first time through */
      82      if (state->size == 0 && gz_init(state) == -1)
      83          return -1;
      84  
      85      /* write directly if requested */
      86      if (state->direct) {
      87          while (strm->avail_in) {
      88              put = strm->avail_in > max ? max : strm->avail_in;
      89              writ = write(state->fd, strm->next_in, put);
      90              if (writ < 0) {
      91                  gz_error(state, Z_ERRNO, zstrerror());
      92                  return -1;
      93              }
      94              strm->avail_in -= (unsigned)writ;
      95              strm->next_in += writ;
      96          }
      97          return 0;
      98      }
      99  
     100      /* check for a pending reset */
     101      if (state->reset) {
     102          /* don't start a new gzip member unless there is data to write */
     103          if (strm->avail_in == 0)
     104              return 0;
     105          deflateReset(strm);
     106          state->reset = 0;
     107      }
     108  
     109      /* run deflate() on provided input until it produces no more output */
     110      ret = Z_OK;
     111      do {
     112          /* write out current buffer contents if full, or if flushing, but if
     113             doing Z_FINISH then don't write until we get to Z_STREAM_END */
     114          if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
     115              (flush != Z_FINISH || ret == Z_STREAM_END))) {
     116              while (strm->next_out > state->x.next) {
     117                  put = strm->next_out - state->x.next > (int)max ? max :
     118                        (unsigned)(strm->next_out - state->x.next);
     119                  writ = write(state->fd, state->x.next, put);
     120                  if (writ < 0) {
     121                      gz_error(state, Z_ERRNO, zstrerror());
     122                      return -1;
     123                  }
     124                  state->x.next += writ;
     125              }
     126              if (strm->avail_out == 0) {
     127                  strm->avail_out = state->size;
     128                  strm->next_out = state->out;
     129                  state->x.next = state->out;
     130              }
     131          }
     132  
     133          /* compress */
     134          have = strm->avail_out;
     135          ret = deflate(strm, flush);
     136          if (ret == Z_STREAM_ERROR) {
     137              gz_error(state, Z_STREAM_ERROR,
     138                        "internal error: deflate stream corrupt");
     139              return -1;
     140          }
     141          have -= strm->avail_out;
     142      } while (have);
     143  
     144      /* if that completed a deflate stream, allow another to start */
     145      if (flush == Z_FINISH)
     146          state->reset = 1;
     147  
     148      /* all done, no errors */
     149      return 0;
     150  }
     151  
     152  /* Compress len zeros to output.  Return -1 on a write error or memory
     153     allocation failure by gz_comp(), or 0 on success. */
     154  local int gz_zero(state, len)
     155      gz_statep state;
     156      z_off64_t len;
     157  {
     158      int first;
     159      unsigned n;
     160      z_streamp strm = &(state->strm);
     161  
     162      /* consume whatever's left in the input buffer */
     163      if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
     164          return -1;
     165  
     166      /* compress len zeros (len guaranteed > 0) */
     167      first = 1;
     168      while (len) {
     169          n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
     170              (unsigned)len : state->size;
     171          if (first) {
     172              memset(state->in, 0, n);
     173              first = 0;
     174          }
     175          strm->avail_in = n;
     176          strm->next_in = state->in;
     177          state->x.pos += n;
     178          if (gz_comp(state, Z_NO_FLUSH) == -1)
     179              return -1;
     180          len -= n;
     181      }
     182      return 0;
     183  }
     184  
     185  /* Write len bytes from buf to file.  Return the number of bytes written.  If
     186     the returned value is less than len, then there was an error. */
     187  local z_size_t gz_write(state, buf, len)
     188      gz_statep state;
     189      voidpc buf;
     190      z_size_t len;
     191  {
     192      z_size_t put = len;
     193  
     194      /* if len is zero, avoid unnecessary operations */
     195      if (len == 0)
     196          return 0;
     197  
     198      /* allocate memory if this is the first time through */
     199      if (state->size == 0 && gz_init(state) == -1)
     200          return 0;
     201  
     202      /* check for seek request */
     203      if (state->seek) {
     204          state->seek = 0;
     205          if (gz_zero(state, state->skip) == -1)
     206              return 0;
     207      }
     208  
     209      /* for small len, copy to input buffer, otherwise compress directly */
     210      if (len < state->size) {
     211          /* copy to input buffer, compress when full */
     212          do {
     213              unsigned have, copy;
     214  
     215              if (state->strm.avail_in == 0)
     216                  state->strm.next_in = state->in;
     217              have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
     218                                state->in);
     219              copy = state->size - have;
     220              if (copy > len)
     221                  copy = (unsigned)len;
     222              memcpy(state->in + have, buf, copy);
     223              state->strm.avail_in += copy;
     224              state->x.pos += copy;
     225              buf = (const char *)buf + copy;
     226              len -= copy;
     227              if (len && gz_comp(state, Z_NO_FLUSH) == -1)
     228                  return 0;
     229          } while (len);
     230      }
     231      else {
     232          /* consume whatever's left in the input buffer */
     233          if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
     234              return 0;
     235  
     236          /* directly compress user buffer to file */
     237          state->strm.next_in = (z_const Bytef *)buf;
     238          do {
     239              unsigned n = (unsigned)-1;
     240              if (n > len)
     241                  n = (unsigned)len;
     242              state->strm.avail_in = n;
     243              state->x.pos += n;
     244              if (gz_comp(state, Z_NO_FLUSH) == -1)
     245                  return 0;
     246              len -= n;
     247          } while (len);
     248      }
     249  
     250      /* input was all buffered or compressed */
     251      return put;
     252  }
     253  
     254  /* -- see zlib.h -- */
     255  int ZEXPORT gzwrite(file, buf, len)
     256      gzFile file;
     257      voidpc buf;
     258      unsigned len;
     259  {
     260      gz_statep state;
     261  
     262      /* get internal structure */
     263      if (file == NULL)
     264          return 0;
     265      state = (gz_statep)file;
     266  
     267      /* check that we're writing and that there's no error */
     268      if (state->mode != GZ_WRITE || state->err != Z_OK)
     269          return 0;
     270  
     271      /* since an int is returned, make sure len fits in one, otherwise return
     272         with an error (this avoids a flaw in the interface) */
     273      if ((int)len < 0) {
     274          gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
     275          return 0;
     276      }
     277  
     278      /* write len bytes from buf (the return value will fit in an int) */
     279      return (int)gz_write(state, buf, len);
     280  }
     281  
     282  /* -- see zlib.h -- */
     283  z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
     284      voidpc buf;
     285      z_size_t size;
     286      z_size_t nitems;
     287      gzFile file;
     288  {
     289      z_size_t len;
     290      gz_statep state;
     291  
     292      /* get internal structure */
     293      if (file == NULL)
     294          return 0;
     295      state = (gz_statep)file;
     296  
     297      /* check that we're writing and that there's no error */
     298      if (state->mode != GZ_WRITE || state->err != Z_OK)
     299          return 0;
     300  
     301      /* compute bytes to read -- error on overflow */
     302      len = nitems * size;
     303      if (size && len / size != nitems) {
     304          gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
     305          return 0;
     306      }
     307  
     308      /* write len bytes to buf, return the number of full items written */
     309      return len ? gz_write(state, buf, len) / size : 0;
     310  }
     311  
     312  /* -- see zlib.h -- */
     313  int ZEXPORT gzputc(file, c)
     314      gzFile file;
     315      int c;
     316  {
     317      unsigned have;
     318      unsigned char buf[1];
     319      gz_statep state;
     320      z_streamp strm;
     321  
     322      /* get internal structure */
     323      if (file == NULL)
     324          return -1;
     325      state = (gz_statep)file;
     326      strm = &(state->strm);
     327  
     328      /* check that we're writing and that there's no error */
     329      if (state->mode != GZ_WRITE || state->err != Z_OK)
     330          return -1;
     331  
     332      /* check for seek request */
     333      if (state->seek) {
     334          state->seek = 0;
     335          if (gz_zero(state, state->skip) == -1)
     336              return -1;
     337      }
     338  
     339      /* try writing to input buffer for speed (state->size == 0 if buffer not
     340         initialized) */
     341      if (state->size) {
     342          if (strm->avail_in == 0)
     343              strm->next_in = state->in;
     344          have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
     345          if (have < state->size) {
     346              state->in[have] = (unsigned char)c;
     347              strm->avail_in++;
     348              state->x.pos++;
     349              return c & 0xff;
     350          }
     351      }
     352  
     353      /* no room in buffer or not initialized, use gz_write() */
     354      buf[0] = (unsigned char)c;
     355      if (gz_write(state, buf, 1) != 1)
     356          return -1;
     357      return c & 0xff;
     358  }
     359  
     360  /* -- see zlib.h -- */
     361  int ZEXPORT gzputs(file, s)
     362      gzFile file;
     363      const char *s;
     364  {
     365      z_size_t len, put;
     366      gz_statep state;
     367  
     368      /* get internal structure */
     369      if (file == NULL)
     370          return -1;
     371      state = (gz_statep)file;
     372  
     373      /* check that we're writing and that there's no error */
     374      if (state->mode != GZ_WRITE || state->err != Z_OK)
     375          return -1;
     376  
     377      /* write string */
     378      len = strlen(s);
     379      if ((int)len < 0 || (unsigned)len != len) {
     380          gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
     381          return -1;
     382      }
     383      put = gz_write(state, s, len);
     384      return put < len ? -1 : (int)len;
     385  }
     386  
     387  #if defined(STDC) || defined(Z_HAVE_STDARG_H)
     388  #include <stdarg.h>
     389  
     390  /* -- see zlib.h -- */
     391  int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
     392  {
     393      int len;
     394      unsigned left;
     395      char *next;
     396      gz_statep state;
     397      z_streamp strm;
     398  
     399      /* get internal structure */
     400      if (file == NULL)
     401          return Z_STREAM_ERROR;
     402      state = (gz_statep)file;
     403      strm = &(state->strm);
     404  
     405      /* check that we're writing and that there's no error */
     406      if (state->mode != GZ_WRITE || state->err != Z_OK)
     407          return Z_STREAM_ERROR;
     408  
     409      /* make sure we have some buffer space */
     410      if (state->size == 0 && gz_init(state) == -1)
     411          return state->err;
     412  
     413      /* check for seek request */
     414      if (state->seek) {
     415          state->seek = 0;
     416          if (gz_zero(state, state->skip) == -1)
     417              return state->err;
     418      }
     419  
     420      /* do the printf() into the input buffer, put length in len -- the input
     421         buffer is double-sized just for this function, so there is guaranteed to
     422         be state->size bytes available after the current contents */
     423      if (strm->avail_in == 0)
     424          strm->next_in = state->in;
     425      next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
     426      next[state->size - 1] = 0;
     427  #ifdef NO_vsnprintf
     428  #  ifdef HAS_vsprintf_void
     429      (void)vsprintf(next, format, va);
     430      for (len = 0; len < state->size; len++)
     431          if (next[len] == 0) break;
     432  #  else
     433      len = vsprintf(next, format, va);
     434  #  endif
     435  #else
     436  #  ifdef HAS_vsnprintf_void
     437      (void)vsnprintf(next, state->size, format, va);
     438      len = strlen(next);
     439  #  else
     440      len = vsnprintf(next, state->size, format, va);
     441  #  endif
     442  #endif
     443  
     444      /* check that printf() results fit in buffer */
     445      if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
     446          return 0;
     447  
     448      /* update buffer and position, compress first half if past that */
     449      strm->avail_in += (unsigned)len;
     450      state->x.pos += len;
     451      if (strm->avail_in >= state->size) {
     452          left = strm->avail_in - state->size;
     453          strm->avail_in = state->size;
     454          if (gz_comp(state, Z_NO_FLUSH) == -1)
     455              return state->err;
     456          memmove(state->in, state->in + state->size, left);
     457          strm->next_in = state->in;
     458          strm->avail_in = left;
     459      }
     460      return len;
     461  }
     462  
     463  int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
     464  {
     465      va_list va;
     466      int ret;
     467  
     468      va_start(va, format);
     469      ret = gzvprintf(file, format, va);
     470      va_end(va);
     471      return ret;
     472  }
     473  
     474  #else /* !STDC && !Z_HAVE_STDARG_H */
     475  
     476  /* -- see zlib.h -- */
     477  int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
     478                         a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
     479      gzFile file;
     480      const char *format;
     481      int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
     482          a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
     483  {
     484      unsigned len, left;
     485      char *next;
     486      gz_statep state;
     487      z_streamp strm;
     488  
     489      /* get internal structure */
     490      if (file == NULL)
     491          return Z_STREAM_ERROR;
     492      state = (gz_statep)file;
     493      strm = &(state->strm);
     494  
     495      /* check that can really pass pointer in ints */
     496      if (sizeof(int) != sizeof(void *))
     497          return Z_STREAM_ERROR;
     498  
     499      /* check that we're writing and that there's no error */
     500      if (state->mode != GZ_WRITE || state->err != Z_OK)
     501          return Z_STREAM_ERROR;
     502  
     503      /* make sure we have some buffer space */
     504      if (state->size == 0 && gz_init(state) == -1)
     505          return state->error;
     506  
     507      /* check for seek request */
     508      if (state->seek) {
     509          state->seek = 0;
     510          if (gz_zero(state, state->skip) == -1)
     511              return state->error;
     512      }
     513  
     514      /* do the printf() into the input buffer, put length in len -- the input
     515         buffer is double-sized just for this function, so there is guaranteed to
     516         be state->size bytes available after the current contents */
     517      if (strm->avail_in == 0)
     518          strm->next_in = state->in;
     519      next = (char *)(strm->next_in + strm->avail_in);
     520      next[state->size - 1] = 0;
     521  #ifdef NO_snprintf
     522  #  ifdef HAS_sprintf_void
     523      sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
     524              a13, a14, a15, a16, a17, a18, a19, a20);
     525      for (len = 0; len < size; len++)
     526          if (next[len] == 0)
     527              break;
     528  #  else
     529      len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
     530                    a12, a13, a14, a15, a16, a17, a18, a19, a20);
     531  #  endif
     532  #else
     533  #  ifdef HAS_snprintf_void
     534      snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
     535               a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     536      len = strlen(next);
     537  #  else
     538      len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
     539                     a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
     540  #  endif
     541  #endif
     542  
     543      /* check that printf() results fit in buffer */
     544      if (len == 0 || len >= state->size || next[state->size - 1] != 0)
     545          return 0;
     546  
     547      /* update buffer and position, compress first half if past that */
     548      strm->avail_in += len;
     549      state->x.pos += len;
     550      if (strm->avail_in >= state->size) {
     551          left = strm->avail_in - state->size;
     552          strm->avail_in = state->size;
     553          if (gz_comp(state, Z_NO_FLUSH) == -1)
     554              return state->err;
     555          memmove(state->in, state->in + state->size, left);
     556          strm->next_in = state->in;
     557          strm->avail_in = left;
     558      }
     559      return (int)len;
     560  }
     561  
     562  #endif
     563  
     564  /* -- see zlib.h -- */
     565  int ZEXPORT gzflush(file, flush)
     566      gzFile file;
     567      int flush;
     568  {
     569      gz_statep state;
     570  
     571      /* get internal structure */
     572      if (file == NULL)
     573          return Z_STREAM_ERROR;
     574      state = (gz_statep)file;
     575  
     576      /* check that we're writing and that there's no error */
     577      if (state->mode != GZ_WRITE || state->err != Z_OK)
     578          return Z_STREAM_ERROR;
     579  
     580      /* check flush parameter */
     581      if (flush < 0 || flush > Z_FINISH)
     582          return Z_STREAM_ERROR;
     583  
     584      /* check for seek request */
     585      if (state->seek) {
     586          state->seek = 0;
     587          if (gz_zero(state, state->skip) == -1)
     588              return state->err;
     589      }
     590  
     591      /* compress remaining data with requested flush */
     592      (void)gz_comp(state, flush);
     593      return state->err;
     594  }
     595  
     596  /* -- see zlib.h -- */
     597  int ZEXPORT gzsetparams(file, level, strategy)
     598      gzFile file;
     599      int level;
     600      int strategy;
     601  {
     602      gz_statep state;
     603      z_streamp strm;
     604  
     605      /* get internal structure */
     606      if (file == NULL)
     607          return Z_STREAM_ERROR;
     608      state = (gz_statep)file;
     609      strm = &(state->strm);
     610  
     611      /* check that we're writing and that there's no error */
     612      if (state->mode != GZ_WRITE || state->err != Z_OK)
     613          return Z_STREAM_ERROR;
     614  
     615      /* if no change is requested, then do nothing */
     616      if (level == state->level && strategy == state->strategy)
     617          return Z_OK;
     618  
     619      /* check for seek request */
     620      if (state->seek) {
     621          state->seek = 0;
     622          if (gz_zero(state, state->skip) == -1)
     623              return state->err;
     624      }
     625  
     626      /* change compression parameters for subsequent input */
     627      if (state->size) {
     628          /* flush previous input with previous parameters before changing */
     629          if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
     630              return state->err;
     631          deflateParams(strm, level, strategy);
     632      }
     633      state->level = level;
     634      state->strategy = strategy;
     635      return Z_OK;
     636  }
     637  
     638  /* -- see zlib.h -- */
     639  int ZEXPORT gzclose_w(file)
     640      gzFile file;
     641  {
     642      int ret = Z_OK;
     643      gz_statep state;
     644  
     645      /* get internal structure */
     646      if (file == NULL)
     647          return Z_STREAM_ERROR;
     648      state = (gz_statep)file;
     649  
     650      /* check that we're writing */
     651      if (state->mode != GZ_WRITE)
     652          return Z_STREAM_ERROR;
     653  
     654      /* check for seek request */
     655      if (state->seek) {
     656          state->seek = 0;
     657          if (gz_zero(state, state->skip) == -1)
     658              ret = state->err;
     659      }
     660  
     661      /* flush, free memory, and close file */
     662      if (gz_comp(state, Z_FINISH) == -1)
     663          ret = state->err;
     664      if (state->size) {
     665          if (!state->direct) {
     666              (void)deflateEnd(&(state->strm));
     667              free(state->out);
     668          }
     669          free(state->in);
     670      }
     671      gz_error(state, Z_OK, NULL);
     672      free(state->path);
     673      if (close(state->fd) == -1)
     674          ret = Z_ERRNO;
     675      free(state);
     676      return ret;
     677  }