]> Dogcows Code - chaz/tar/blobdiff - src/list.c
(max): New macro.
[chaz/tar] / src / list.c
index 2109d8fe36e370e36633e1ff69d868175f6b9db8..474651c5c1cbb4273ad9c30a85f4fca8723e8e2b 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "common.h"
 
+#define max(a, b) ((a) < (b) ? (b) : (a))
+
 union block *current_header;   /* points to current archive header */
 struct stat current_stat;      /* stat struct corresponding */
 enum archive_format current_format; /* recognized format */
@@ -512,19 +514,22 @@ from_chars (char const *where0, size_t digs, char const *type,
   char const *lim = where + digs;
   int negative = 0;
 
-  /* Accommodate older tars, which output leading spaces, and at least one
-     buggy tar, which outputs leading NUL if the previous field overflows.  */
+  /* Accommodate buggy tar of unknown vintage, which outputs leading
+     NUL if the previous field overflows.  */
+  where += !*where;
+
+  /* Accommodate older tars, which output leading spaces.  */
   for (;;)
     {
       if (where == lim)
        {
          if (type)
            ERROR ((0, 0,
-                   _("Empty header where numeric %s value expected"),
+                   _("Blanks in header where numeric %s value expected"),
                    type));
          return -1;
        }
-      if (!ISSPACE ((unsigned char) *where) && *where)
+      if (!ISSPACE ((unsigned char) *where))
        break;
       where++;
     }
@@ -703,20 +708,34 @@ stringify_uintmax_t_backwards (uintmax_t o, char *buf)
 
 /* Also, see http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html.  */
 
-static char *
-isotime (const time_t *time)
+static char const *
+isotime (time_t time)
 {
-  static char buffer[INT_STRLEN_BOUND (int) + 16];
-  struct tm *tm = localtime (time);
+  static char buffer[max (UINTMAX_STRSIZE_BOUND + 1,
+                         INT_STRLEN_BOUND (int) + 16)];
+  struct tm *tm = localtime (&time);
   if (tm)
-    sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d",
-            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-            tm->tm_hour, tm->tm_min, tm->tm_sec);
+    {
+      sprintf (buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+              tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+              tm->tm_hour, tm->tm_min, tm->tm_sec);
+      return buffer;
+    }
   else
-    /* Interpose %s between ?? and - to avoid ANSI C trigraph brain damage.  */
-    sprintf (buffer, "????%s-??%s-?? ??:??:??", "", "");
-
-  return buffer;
+    {
+      /* The timestamp cannot be broken down, most likely because it
+        is a huge timestamp.  Convert it as an integer,
+        right-adjusted in a field with the same width as the usual
+        19-byte 4-year ISO time format.  */
+      uintmax_t abstime = time < 0 ? - (uintmax_t) time : time;
+      char *p = stringify_uintmax_t_backwards (abstime,
+                                              buffer + sizeof buffer);
+      if (time < 0)
+       *--p = '-';
+      while (buffer + sizeof buffer - 19 - 1 < p)
+       *--p = ' ';
+      return p;
+    }
 }
 
 #endif /* not USE_OLD_CTIME */
@@ -883,7 +902,7 @@ print_header (void)
          timestamp = "??? ?? ??:?? ????";
       }
 #else
-      timestamp = isotime (&longie);
+      timestamp = isotime (longie);
 #endif
 
       /* User and group names.  */
@@ -910,9 +929,11 @@ print_header (void)
        {
        case CHRTYPE:
        case BLKTYPE:
-         sprintf (size, "%lu,%lu",
-                  (unsigned long) major (current_stat.st_rdev),
-                  (unsigned long) minor (current_stat.st_rdev));
+         strcpy (size,
+                 STRINGIFY_BIGINT (major (current_stat.st_rdev), uintbuf));
+         strcat (size, ",");
+         strcat (size,
+                 STRINGIFY_BIGINT (minor (current_stat.st_rdev), uintbuf));
          break;
        case GNUTYPE_SPARSE:
          strcpy (size,
This page took 0.028123 seconds and 4 git commands to generate.