tests: unpack-invalid: correct and clean up a test
[debian/gzip] / gzip.c
diff --git a/gzip.c b/gzip.c
index 707a190943995df1a93703fa968308c9c9384438..637b7913ec9e5d7fa18a822846fa07ab2bc3be07 100644 (file)
--- a/gzip.c
+++ b/gzip.c
  */
 
 static char const *const license_msg[] = {
-"Copyright (C) 2016 Free Software Foundation, Inc.",
+"Copyright (C) 2017 Free Software Foundation, Inc.",
 "Copyright (C) 1993 Jean-loup Gailly.",
 "This is free software.  You may redistribute copies of it under the terms of",
-"the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.",
+"the GNU General Public License <https://www.gnu.org/licenses/gpl.html>.",
 "There is NO WARRANTY, to the extent permitted by law.",
 0};
 
@@ -77,6 +77,7 @@ static char const *const license_msg[] = {
 #include "ignore-value.h"
 #include "stat-time.h"
 #include "version.h"
+#include "xalloc.h"
 #include "yesno.h"
 
                 /* configuration */
@@ -194,10 +195,12 @@ static char *env;            /* contents of GZIP env variable */
 static char const *z_suffix; /* default suffix (can be set with --suffix) */
 static size_t z_len;         /* strlen(z_suffix) */
 
-/* The original time stamp (modification time).  Its tv_nsec component
-   is negative if the original time is unknown or is out of time_t
-   range; the latter can happen on hosts with 32-bit signed time_t
-   because the gzip format's MTIME is 32-bit unsigned.  */
+/* The original timestamp (modification time).  If the original is
+   unknown, TIME_STAMP.tv_nsec is negative.  If the original is
+   greater than struct timespec range, TIME_STAMP is the maximal
+   struct timespec value; this can happen on hosts with 32-bit signed
+   time_t because the gzip format's MTIME is 32-bit unsigned.
+   The original cannot be less than struct timespec range.  */
 struct timespec time_stamp;
 
 /* The set of signals that are caught.  */
@@ -365,8 +368,8 @@ local void help()
  "  -m                do not save or restore the original modification time",
  "  -M, --time        save or restore the original modification time",
 #endif
- "  -n, --no-name     do not save or restore the original name and time stamp",
- "  -N, --name        save or restore the original name and time stamp",
+ "  -n, --no-name     do not save or restore the original name and timestamp",
+ "  -N, --name        save or restore the original name and timestamp",
  "  -q, --quiet       suppress all warnings",
 #if ! NO_DIR
  "  -r, --recursive   operate recursively on directories",
@@ -599,7 +602,7 @@ int main (int argc, char **argv)
         case '4' + ENV_OPTION:  case '5' + ENV_OPTION:  case '6' + ENV_OPTION:
         case '7' + ENV_OPTION:  case '8' + ENV_OPTION:  case '9' + ENV_OPTION:
             optc -= ENV_OPTION;
-            /* Fall through.  */
+            FALLTHROUGH;
         case '1':  case '2':  case '3':  case '4':
         case '5':  case '6':  case '7':  case '8':  case '9':
             level = optc - '0';
@@ -752,7 +755,7 @@ local void treat_stdin()
     strcpy(ifname, "stdin");
     strcpy(ofname, "stdout");
 
-    /* Get the file's time stamp and size.  */
+    /* Get the file's timestamp and size.  */
     if (fstat (STDIN_FILENO, &istat) != 0)
       {
         progerror ("standard input");
@@ -1180,9 +1183,12 @@ local char *get_suffix(name)
             break;
           }
       }
+
+    char *z_lower = xstrdup(z_suffix);
+    strlwr(z_lower);
     known_suffixes[suffix_of_builtin
                    ? sizeof known_suffixes / sizeof *known_suffixes - 2
-                   : 0] = z_suffix;
+                   : 0] = z_lower;
     suf = known_suffixes + suffix_of_builtin;
 
     nlen = strlen(name);
@@ -1193,15 +1199,18 @@ local char *get_suffix(name)
     }
     strlwr(suffix);
     slen = strlen(suffix);
+    char *match = NULL;
     do {
        int s = strlen(*suf);
        if (slen > s && ! ISSLASH (suffix[slen - s - 1])
            && strequ(suffix + slen - s, *suf)) {
-           return name+nlen-s;
+           match = name+nlen-s;
+           break;
        }
     } while (*++suf != NULL);
+    free(z_lower);
 
-    return NULL;
+    return match;
 }
 
 
@@ -1479,7 +1488,7 @@ local int get_method(in)
     uch magic[10]; /* magic header */
     int imagic0;   /* first magic byte or EOF */
     int imagic1;   /* like magic[1], but can represent EOF */
-    ulg stamp;     /* time stamp */
+    ulg stamp;     /* timestamp */
 
     /* If --force and --stdout, zcat == cat, so do not complain about
      * premature end of file: use try_byte instead of get_byte.
@@ -1539,10 +1548,21 @@ local int get_method(in)
         stamp |= ((ulg)get_byte()) << 8;
         stamp |= ((ulg)get_byte()) << 16;
         stamp |= ((ulg)get_byte()) << 24;
-        if (!no_time && 0 < stamp && stamp <= TYPE_MAXIMUM (time_t))
+        if (stamp != 0 && !no_time)
           {
-            time_stamp.tv_sec = stamp;
-            time_stamp.tv_nsec = 0;
+            if (stamp <= TYPE_MAXIMUM (time_t))
+              {
+                time_stamp.tv_sec = stamp;
+                time_stamp.tv_nsec = 0;
+              }
+            else
+              {
+                WARN ((stderr,
+                       "%s: %s: MTIME %lu out of range for this platform\n",
+                       program_name, ifname, stamp));
+                time_stamp.tv_sec = TYPE_MAXIMUM (time_t);
+                time_stamp.tv_nsec = TIMESPEC_RESOLUTION - 1;
+              }
           }
 
         magic[8] = get_byte ();  /* Ignore extra flags.  */
@@ -1771,9 +1791,7 @@ local void do_list(ifd, method)
         static char const month_abbr[][4]
           = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-        struct tm *tm = (time_stamp.tv_nsec < 0
-                         ? NULL
-                         : localtime (&time_stamp.tv_sec));
+        struct tm *tm = localtime (&time_stamp.tv_sec);
         printf ("%5s %08lx ", methods[method], crc);
         if (tm)
           printf ("%s%3d %02d:%02d ", month_abbr[tm->tm_mon],
@@ -1932,7 +1950,7 @@ local void copy_stat(ifstat)
     if (fdutimens (ofd, ofname, timespec) == 0)
       {
         if (restoring && 1 < verbose) {
-            fprintf(stderr, "%s: time stamp restored\n", ofname);
+            fprintf(stderr, "%s: timestamp restored\n", ofname);
         }
       }
     else