]> Dogcows Code - chaz/tar/blobdiff - src/checkpoint.c
Update copyright years.
[chaz/tar] / src / checkpoint.c
index 76374524a1f9d340cdc5fe2f73a907dadb9d43d9..46f4702b5b1c6f67e89d6f9f421e7160fad3bedb 100644 (file)
@@ -1,6 +1,6 @@
 /* Checkpoint management for tar.
 
-   Copyright 2007, 2013 Free Software Foundation, Inc.
+   Copyright 2007, 2013-2014 Free Software Foundation, Inc.
 
    This file is part of GNU tar.
 
@@ -134,14 +134,14 @@ checkpoint_finish_compile (void)
     checkpoint_option = DEFAULT_CHECKPOINT;
 }
 
-static char *checkpoint_total_format[] = {
+static const char *checkpoint_total_format[] = {
   "R",
   "W",
   "D"
 };
 
 static int
-getwidth(FILE *fp)
+getwidth (FILE *fp)
 {
   struct winsize ws;
 
@@ -183,16 +183,20 @@ getarg (const char *input, const char ** endp, char **argbuf, size_t *arglen)
   return NULL;
 }
 
+static int tty_cleanup;
 
-static void
-format_checkpoint_string (FILE *fp, const char *input, bool do_write,
+static const char *def_format =
+  "%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r";
+
+static int
+format_checkpoint_string (FILE *fp, size_t len,
+                         const char *input, bool do_write,
                          unsigned cpn)
 {
   const char *opstr = do_write ? gettext ("write") : gettext ("read");
   char uintbuf[UINTMAX_STRSIZE_BOUND];
   char *cps = STRINGIFY_BIGINT (cpn, uintbuf);
   const char *ip;
-  size_t len = 0;
 
   static char *argbuf = NULL;
   static size_t arglen = 0;
@@ -231,6 +235,11 @@ format_checkpoint_string (FILE *fp, const char *input, bool do_write,
            }
          switch (*ip)
            {
+           case 'c':
+             len += format_checkpoint_string (fp, len, def_format, do_write,
+                                              cpn);
+             break;
+             
            case 'u':
              fputs (cps, fp);
              len += strlen (cps);
@@ -246,15 +255,40 @@ format_checkpoint_string (FILE *fp, const char *input, bool do_write,
              break;
              
            case 'T':
-             compute_duration ();
-             len += format_total_stats (fp, checkpoint_total_format, ',', 0);
+             {
+               const char **fmt = checkpoint_total_format, *fmtbuf[3];
+               struct wordsplit ws;
+               compute_duration ();
+               
+               if (arg)
+                 {
+                   ws.ws_delim = ",";
+                   if (wordsplit (arg, &ws, WRDSF_NOVAR | WRDSF_NOCMD |
+                                          WRDSF_QUOTE | WRDSF_DELIM))
+                     ERROR ((0, 0, _("cannot split string '%s': %s"),
+                             arg, wordsplit_strerror (&ws)));
+                   else
+                     {
+                       int i;
+
+                       for (i = 0; i < ws.ws_wordc; i++)
+                         fmtbuf[i] = ws.ws_wordv[i];
+                       for (; i < 3; i++)
+                         fmtbuf[i] = NULL;
+                       fmt = fmtbuf;
+                     }
+                 }
+               len += format_total_stats (fp, fmt, ',', 0);
+               if (arg)
+                 wordsplit_free (&ws);
+             }
              break;
 
            case 't':
              {
                struct timeval tv;
                struct tm *tm;
-               char *fmt = arg ? arg : "%c";
+               const char *fmt = arg ? arg : "%c";
 
                gettimeofday (&tv, NULL);
                tm = localtime (&tv.tv_sec);
@@ -282,19 +316,24 @@ format_checkpoint_string (FILE *fp, const char *input, bool do_write,
        {
          fputc (*ip, fp);
          if (*ip == '\r')
-           len = 0;
+           {
+             len = 0;
+             tty_cleanup = 1;
+           }
          else
            len++;
        }
     }
   fflush (fp);
+  return len;
 }
 
+static FILE *tty = NULL;
+
 static void
 run_checkpoint_actions (bool do_write)
 {
   struct checkpoint_action *p;
-  FILE *tty = NULL;
 
   for (p = checkpoint_action; p; p = p->next)
     {
@@ -316,20 +355,20 @@ run_checkpoint_actions (bool do_write)
          break;
 
        case cop_echo:
-         fprintf (stderr, "%s: ", program_name);
-         format_checkpoint_string (stderr, p->v.command, do_write, checkpoint);
-         fputc ('\n', stderr);
+         {
+           int n = fprintf (stderr, "%s: ", program_name);
+           format_checkpoint_string (stderr, n, p->v.command, do_write,
+                                     checkpoint);
+           fputc ('\n', stderr);
+         }
          break;
 
        case cop_ttyout:
          if (!tty)
            tty = fopen ("/dev/tty", "w");
          if (tty)
-           {
-             format_checkpoint_string (tty, p->v.command, do_write,
-                                       checkpoint);
-             fflush (tty);
-           }
+           format_checkpoint_string (tty, 0, p->v.command, do_write,
+                                     checkpoint);
          break;
 
        case cop_sleep:
@@ -347,8 +386,31 @@ run_checkpoint_actions (bool do_write)
          print_total_stats ();
        }
     }
-  if (tty)
-    fclose (tty);
+}
+
+void
+checkpoint_flush_actions (void)
+{
+  struct checkpoint_action *p;
+  
+  for (p = checkpoint_action; p; p = p->next)
+    {
+      switch (p->opcode)
+       {
+       case cop_ttyout:
+         if (tty && tty_cleanup)
+           {
+             int w = getwidth (tty);
+             while (w--)
+               fputc (' ', tty);
+             fputc ('\r', tty);
+             fflush (tty);
+           }
+         break;
+       default:
+         /* nothing */;
+       }
+    }
 }
 
 void
@@ -357,3 +419,14 @@ checkpoint_run (bool do_write)
   if (checkpoint_option && !(++checkpoint % checkpoint_option))
     run_checkpoint_actions (do_write);
 }
+
+void
+checkpoint_finish (void)
+{
+  if (checkpoint_option)
+    {
+      checkpoint_flush_actions ();
+      if (tty)
+       fclose (tty);
+    }
+}
This page took 0.030286 seconds and 4 git commands to generate.