* NEWS: Update.
* doc/tar.texi: Update.
* src/buffer.c (print_stats): Avoid use of additional string buffer.
Allow for text to be NULL.
Call gettext if it is not.
(format_total_stats): Don't use gettext when calling print_stats.
* src/checkpoint.c (def_format): Change default format.
(format_checkpoint_string): Implement optional arguments for
T conversion.
(finish_checkpoint_actions): Rename to checkpoint_flush_actions,
make extern. All uses changed.
* src/common.h (checkpoint_flush_actions): New proto.
* src/tar.c (main): Set error_hook
-GNU tar NEWS - User visible changes. 2014-01-21
+GNU tar NEWS - User visible changes. 2014-01-22
Please send GNU tar bug reports to <bug-tar@gnu.org>
\f
* Extended checkpoint format specification.
-New conversion specifiers are implemented:
-
- %d - output number of seconds since tar started
- %T - output I/O totals
- %{FMT}t - output current local time using FMT as strftime(3) format
- If {FMT} is omitted, use %c
- %{N}* - pad output with spaces to the Nth column, or to the
- current screen width, if {N} is not given.
+New conversion specifiers are implemented. Some of them take
+optional arguments, supplied in curly braces between the percent
+sign and the specifier letter.
+
+ %d - output number of seconds since tar started
+ %{r,w,d}T - output I/O totals; optional arguments supply prefixes
+ to be used before number of bytes read, written and
+ deleted, correspondingly.
+ %{FMT}t - output current local time using FMT as strftime(3) format
+ If {FMT} is omitted, use %c
+ %{N}* - pad output with spaces to the Nth column, or to the
+ current screen width, if {N} is not given.
+ %c - a shortcut for "%{%Y-%m-%d %H:%M:%S}t: %ds, %{read,wrote}T%*\r"
\f
version 1.27.1 - Sergey Poznyakoff, 2013-11-17
tar: Hit write checkpoint #30
@end smallexample
-The complete list of available format specifiers follows:
+The complete list of available format specifiers follows. Some of
+them can take optional arguments. These arguments, if given, are
+supplied in curly braces between the percent sign and the specifier
+letter.
@table @samp
@item %s
@item %u
Print number of the checkpoint.
-@item %T
+@item %@{r,w,d@}T
Print number of bytes transferred so far and approximate transfer
-speed. The number is preceded by @samp{W:}, when writing and by
-@samp{R:} when reading. If @command{tar} is performing delete
-operation (@pxref{delete}), three numbers are printed: number of bytes
-read, written and deleted, each of them prefixed by @samp{R:},
-@samp{W:} and @samp{D:} correspondingy. For example:
+speed. Optional arguments supply prefixes to be used before number
+of bytes read, written and deleted, correspondingly. If absent,
+they default to @samp{R}. @samp{W}, @samp{D}. Any or all of them can
+be omitted, so, that e.g. @samp{%@{@}T} means to print corresponding
+statistics without any prefixes. Any surplus arguments, if present,
+are silently ignored.
@example
$ @kbd{tar --delete -f f.tar --checkpoint-action=echo="#%u: %T" main.c}
-tar: #1: R: 0 (0B, ?/s),W: 0 (0B, ?/s),D: 0
+tar: #1: R: 0 (0B, 0B/s),W: 0 (0B, 0B/s),D: 0
tar: #2: R: 10240 (10KiB, 19MiB/s),W: 0 (0B, 0B/s),D: 10240
@end example
Pad output with spaces to the @var{n}th column. If the
@samp{@{@var{n}@}} part is omitted, the current screen width
is assumed.
+
+@item %@var{c}
+This is a shortcut for @samp{%@{%Y-%m-%d %H:%M:%S@}t: %ds, %@{read,wrote@}T%*\r},
+intended mainly for use with @samp{ttyout} action (see below).
@end table
Aside from format expansion, the message string is subject to
static int
print_stats (FILE *fp, const char *text, tarlong numbytes)
{
- char bytes[sizeof (tarlong) * CHAR_BIT];
char abbr[LONGEST_HUMAN_READABLE + 1];
char rate[LONGEST_HUMAN_READABLE + 1];
-
+ int n = 0;
+
int human_opts = human_autoscale | human_base_1024 | human_SI | human_B;
- sprintf (bytes, TARLONG_FORMAT, numbytes);
-
- return fprintf (fp, "%s: %s (%s, %s/s)",
- text, bytes,
- human_readable (numbytes, abbr, human_opts, 1, 1),
- (0 < duration && numbytes / duration < (uintmax_t) -1
- ? human_readable (numbytes / duration, rate, human_opts, 1, 1)
- : "?"));
+ if (text && text[0])
+ n += fprintf (fp, "%s: ", gettext (text));
+ return n + fprintf (fp, TARLONG_FORMAT " (%s, %s/s)",
+ numbytes,
+ human_readable (numbytes, abbr, human_opts, 1, 1),
+ (0 < duration && numbytes / duration < (uintmax_t) -1
+ ? human_readable (numbytes / duration, rate, human_opts, 1, 1)
+ : "?"));
}
/* Format totals to file FP. FORMATS is an array of strings to output
case CAT_SUBCOMMAND:
case UPDATE_SUBCOMMAND:
case APPEND_SUBCOMMAND:
- n = print_stats (fp, _(formats[TF_WRITE]),
+ n = print_stats (fp, formats[TF_WRITE],
prev_written + bytes_written);
break;
case DELETE_SUBCOMMAND:
{
char buf[UINTMAX_STRSIZE_BOUND];
- n = print_stats (fp, _(formats[TF_READ]),
+ n = print_stats (fp, formats[TF_READ],
records_read * record_size);
fputc (eor, fp);
n++;
- n += print_stats (fp, _(formats[TF_WRITE]),
+ n += print_stats (fp, formats[TF_WRITE],
prev_written + bytes_written);
fputc (eor, fp);
n++;
-
- n += fprintf (fp, "%s: %s",
- _(formats[TF_DELETED]),
+
+ if (formats[TF_DELETED] && formats[TF_DELETED][0])
+ n += fprintf (fp, "%s: ", gettext (formats[TF_DELETED]));
+ n += fprintf (fp, "%s",
STRINGIFY_BIGINT ((records_read - records_skipped)
* record_size
- (prev_written + bytes_written), buf));
static int tty_cleanup;
-static const char *def_format = "%s: %t: %T%*\r";
+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,
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':
}
}
-static void
-finish_checkpoint_actions (void)
+void
+checkpoint_flush_actions (void)
{
struct checkpoint_action *p;
-
+
for (p = checkpoint_action; p; p = p->next)
{
switch (p->opcode)
while (w--)
fputc (' ', tty);
fputc ('\r', tty);
+ fflush (tty);
}
break;
default:
/* nothing */;
}
}
- if (tty)
- fclose (tty);
}
void
checkpoint_finish (void)
{
if (checkpoint_option)
- finish_checkpoint_actions ();
+ {
+ checkpoint_flush_actions ();
+ if (tty)
+ fclose (tty);
+ }
}
void checkpoint_finish_compile (void);
void checkpoint_run (bool do_write);
void checkpoint_finish (void);
+void checkpoint_flush_actions (void);
/* Module warning.c */
#define WARN_ALONE_ZERO_BLOCK 0x00000001
exit_failure = TAREXIT_FAILURE;
exit_status = TAREXIT_SUCCESS;
+ error_hook = checkpoint_flush_actions;
+
filename_terminator = '\n';
set_quoting_style (0, DEFAULT_QUOTING_STYLE);