-/*
- * Actually print it.
- *
- * Plain and fancy file header block logging.
- * Non-verbose just prints the name, e.g. for "tar t" or "tar x".
- * This should just contain file names, so it can be fed back into tar
- * with xargs or the "-T" option. The verbose option can give a bunch
- * of info, one line per file. I doubt anybody tries to parse its
- * format, or if they do, they shouldn't. Unix tar is pretty random here
- * anyway.
- *
- * Note that print_header uses the globals <head>, <hstat>, and
- * <head_standard>, which must be set up in advance. This is not very clean
- * and should be cleaned up. FIXME.
- */
-#define UGSWIDTH 18 /* min width of User, group, size */
-/* UGSWIDTH of 18 means that with user and group names <= 8 chars the columns
- never shift during the listing. */
-#define DATEWIDTH 19 /* Last mod date */
-static int ugswidth = UGSWIDTH; /* Max width encountered so far */
+time_t
+time_from_header (const char *p, size_t s)
+{
+ return from_header (p, s, "time_t",
+ - (uintmax_t) TYPE_MINIMUM (time_t),
+ (uintmax_t) TYPE_MAXIMUM (time_t), false, false);
+}
+
+uid_t
+uid_from_header (const char *p, size_t s)
+{
+ return from_header (p, s, "uid_t",
+ - (uintmax_t) TYPE_MINIMUM (uid_t),
+ (uintmax_t) TYPE_MAXIMUM (uid_t), false, false);
+}
+
+uintmax_t
+uintmax_from_header (const char *p, size_t s)
+{
+ return from_header (p, s, "uintmax_t", (uintmax_t) 0,
+ TYPE_MAXIMUM (uintmax_t), false, false);
+}
+
+
+/* Return a printable representation of T. The result points to
+ static storage that can be reused in the next call to this
+ function, to ctime, or to asctime. If FULL_TIME, then output the
+ time stamp to its full resolution; otherwise, just output it to
+ 1-minute resolution. */
+char const *
+tartime (struct timespec t, bool full_time)
+{
+ enum { fraclen = sizeof ".FFFFFFFFF" - 1 };
+ static char buffer[max (UINTMAX_STRSIZE_BOUND + 1,
+ INT_STRLEN_BOUND (int) + 16)
+ + fraclen];
+ struct tm *tm;
+ time_t s = t.tv_sec;
+ int ns = t.tv_nsec;
+ bool negative = s < 0;
+ char *p;
+
+ if (negative && ns != 0)
+ {
+ s++;
+ ns = 1000000000 - ns;
+ }
+
+ tm = utc_option ? gmtime (&s) : localtime (&s);
+ if (tm)
+ {
+ if (full_time)
+ {
+ sprintf (buffer, "%04ld-%02d-%02d %02d:%02d:%02d",
+ tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ code_ns_fraction (ns, buffer + strlen (buffer));
+ }
+ else
+ sprintf (buffer, "%04ld-%02d-%02d %02d:%02d",
+ tm->tm_year + 1900L, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min);
+ return buffer;
+ }
+
+ /* The time stamp cannot be broken down, most likely because it
+ is out of range. Convert it as an integer,
+ right-adjusted in a field with the same width as the usual
+ 4-year ISO time format. */
+ p = umaxtostr (negative ? - (uintmax_t) s : s,
+ buffer + sizeof buffer - UINTMAX_STRSIZE_BOUND - fraclen);
+ if (negative)
+ *--p = '-';
+ while ((buffer + sizeof buffer - sizeof "YYYY-MM-DD HH:MM"
+ + (full_time ? sizeof ":SS.FFFFFFFFF" - 1 : 0))
+ < p)
+ *--p = ' ';
+ if (full_time)
+ code_ns_fraction (ns, buffer + sizeof buffer - 1 - fraclen);
+ return p;
+}
+
+/* Actually print it.
+
+ Plain and fancy file header block logging. Non-verbose just prints
+ the name, e.g. for "tar t" or "tar x". This should just contain
+ file names, so it can be fed back into tar with xargs or the "-T"
+ option. The verbose option can give a bunch of info, one line per
+ file. I doubt anybody tries to parse its format, or if they do,
+ they shouldn't. Unix tar is pretty random here anyway. */
+
+
+/* FIXME: Note that print_header uses the globals HEAD, HSTAT, and
+ HEAD_STANDARD, which must be set up in advance. Not very clean.. */
+
+/* Width of "user/group size", with initial value chosen
+ heuristically. This grows as needed, though this may cause some
+ stairstepping in the output. Make it too small and the output will
+ almost always look ragged. Make it too large and the output will
+ be spaced out too far. */
+static int ugswidth = 19;
+
+/* Width of printed time stamps. It grows if longer time stamps are
+ found (typically, those with nanosecond resolution). Like
+ USGWIDTH, some stairstepping may occur. */
+static int datewidth = sizeof "YYYY-MM-DD HH:MM" - 1;