X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=util.c;h=c4c7f70532d6b14ff492dcecec25f542f500003f;hb=da37b5c8754bc3b8af89693ab1e67690cb702727;hp=f08c2c7d41419bec7f375f5b50c727045ee22ba1;hpb=dc0ab95dbae38577efebe2283fc9b76e92ef4233;p=debian%2Fgzip diff --git a/util.c b/util.c index f08c2c7..c4c7f70 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,6 @@ /* util.c -- utility functions for gzip support - Copyright (C) 1997-1999, 2001-2002, 2006, 2009-2010 Free Software + Copyright (C) 1997-1999, 2001-2002, 2006, 2009-2013 Free Software Foundation, Inc. Copyright (C) 1992-1993 Jean-loup Gailly @@ -31,34 +31,37 @@ #include #include "gzip.h" -#include "crypt.h" #include #ifndef CHAR_BIT # define CHAR_BIT 8 #endif -static int write_buffer OF((int, voidp, unsigned int)); +static int write_buffer (int, voidp, unsigned int); -extern ulg crc_32_tab[]; /* crc table, defined below */ +static const ulg crc_32_tab[]; /* crc table, defined below */ /* =========================================================================== * Copy input to output unchanged: zcat == cat with --force. - * IN assertion: insize bytes have already been read in inbuf. + * IN assertion: insize bytes have already been read in inbuf and inptr bytes + * already processed or copied. */ int copy(in, out) int in, out; /* input and output file descriptors */ { + int got; + errno = 0; - while (insize != 0 && (int)insize != -1) { - write_buf(out, (char*)inbuf, insize); - bytes_out += insize; - insize = read_buffer (in, (char *) inbuf, INBUFSIZ); - } - if ((int)insize == -1) { - read_error(); + while (insize > inptr) { + write_buf(out, (char*)inbuf + inptr, insize - inptr); + bytes_out += insize - inptr; + got = read_buffer (in, (char *) inbuf, INBUFSIZ); + if (got == -1) + read_error(); + bytes_in += got; + insize = (unsigned)got; + inptr = 0; } - bytes_in = bytes_out; return OK; } @@ -76,9 +79,9 @@ ulg updcrc(s, n) static ulg crc = (ulg)0xffffffffL; /* shift register contents */ if (s == NULL) { - c = 0xffffffffL; + c = 0xffffffffL; } else { - c = crc; + c = crc; if (n) do { c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8); } while (--n); @@ -108,20 +111,20 @@ int fill_inbuf(eof_ok) /* Read as much as possible */ insize = 0; do { - len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize); - if (len == 0) break; - if (len == -1) { - read_error(); - break; - } - insize += len; + len = read_buffer (ifd, (char *) inbuf + insize, INBUFSIZ - insize); + if (len == 0) break; + if (len == -1) { + read_error(); + break; + } + insize += len; } while (insize < INBUFSIZ); if (insize == 0) { - if (eof_ok) return EOF; - flush_window(); - errno = 0; - read_error(); + if (eof_ok) return EOF; + flush_window(); + errno = 0; + read_error(); } bytes_in += (off_t)insize; inptr = 1; @@ -129,16 +132,35 @@ int fill_inbuf(eof_ok) } /* Like the standard read function, except do not attempt to read more - than SSIZE_MAX bytes at a time. */ + than INT_MAX bytes at a time. */ int read_buffer (fd, buf, cnt) int fd; voidp buf; unsigned int cnt; { + int len; if (INT_MAX < cnt) cnt = INT_MAX; - return read (fd, buf, cnt); + len = read (fd, buf, cnt); + +#if defined F_SETFL && O_NONBLOCK && defined EAGAIN + /* Input files are opened O_NONBLOCK for security reasons. On some + file systems this can cause read to fail with errno == EAGAIN. */ + if (len < 0 && errno == EAGAIN) + { + int flags = fcntl (fd, F_GETFL); + if (0 <= flags) + { + if (! (flags & O_NONBLOCK)) + errno = EAGAIN; + else if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1) + len = read (fd, buf, cnt); + } + } +#endif + + return len; } /* Likewise for 'write'. */ @@ -176,7 +198,7 @@ void flush_window() updcrc(window, outcnt); if (!test) { - write_buf(ofd, (char *)window, outcnt); + write_buf(ofd, (char *)window, outcnt); } bytes_out += (off_t)outcnt; outcnt = 0; @@ -194,11 +216,11 @@ void write_buf(fd, buf, cnt) unsigned n; while ((n = write_buffer (fd, buf, cnt)) != cnt) { - if (n == (unsigned)(-1)) { - write_error(); - } - cnt -= n; - buf = (voidp)((char*)buf+n); + if (n == (unsigned)(-1)) { + write_error(); + } + cnt -= n; + buf = (voidp)((char*)buf+n); } } @@ -252,10 +274,10 @@ int xunlink (filename) { int e = errno; if (chmod (filename, S_IWUSR) != 0) - { - errno = e; - return -1; - } + { + errno = e; + return -1; + } r = unlink (filename); } @@ -308,15 +330,15 @@ char *add_envopt( env_val = xstrdup (env_val); for (p = env_val; *p; nargc++ ) { /* move through env_val */ - p += strspn(p, SEPARATOR); /* skip leading separators */ - if (*p == '\0') break; + p += strspn(p, SEPARATOR); /* skip leading separators */ + if (*p == '\0') break; - p += strcspn(p, SEPARATOR); /* find end of word */ - if (*p) *p++ = '\0'; /* mark it */ + p += strcspn(p, SEPARATOR); /* find end of word */ + if (*p) *p++ = '\0'; /* mark it */ } if (nargc == 0) { - free(env_val); - return NULL; + free(env_val); + return NULL; } *argcp += nargc; /* Allocate the new argv array, with an extra element just in case @@ -333,9 +355,9 @@ char *add_envopt( /* Then copy the environment args */ for (p = env_val; nargc > 0; nargc--) { - p += strspn(p, SEPARATOR); /* skip separators */ - *(nargv++) = p; /* store start */ - while (*p++) ; /* skip over word */ + p += strspn(p, SEPARATOR); /* skip separators */ + *(nargv++) = p; /* store start */ + while (*p++) ; /* skip over word */ } /* Finally copy the old args and add a NULL (usual convention) */ @@ -371,10 +393,10 @@ void read_error() int e = errno; fprintf (stderr, "\n%s: ", program_name); if (e != 0) { - errno = e; - perror(ifname); + errno = e; + perror(ifname); } else { - fprintf(stderr, "%s: unexpected end of file\n", ifname); + fprintf(stderr, "%s: unexpected end of file\n", ifname); } abort_gzip(); } @@ -413,29 +435,29 @@ void fprint_off(file, offset, width) /* Don't negate offset here; it might overflow. */ if (offset < 0) { - do - *--p = '0' - offset % 10; - while ((offset /= 10) != 0); + do + *--p = '0' - offset % 10; + while ((offset /= 10) != 0); - *--p = '-'; + *--p = '-'; } else { - do - *--p = '0' + offset % 10; - while ((offset /= 10) != 0); + do + *--p = '0' + offset % 10; + while ((offset /= 10) != 0); } width -= buf + sizeof buf - p; while (0 < width--) { - putc (' ', file); + putc (' ', file); } for (; p < buf + sizeof buf; p++) - putc (*p, file); + putc (*p, file); } /* ======================================================================== * Table of CRC-32's of all single-byte values (made by makecrc.c) */ -ulg crc_32_tab[] = { +static const ulg crc_32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,