checkpoint actions: further improvements.

* 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
This commit is contained in:
Sergey Poznyakoff 2014-01-22 17:19:55 +02:00
parent 717a07e208
commit eb7e2aa933
6 changed files with 87 additions and 41 deletions

21
NEWS
View File

@ -1,4 +1,4 @@
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>
@ -11,14 +11,19 @@ total number of bytes transferred at each checkpoint.
* Extended checkpoint format specification.
New conversion specifiers are implemented:
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
%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.
%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"
version 1.27.1 - Sergey Poznyakoff, 2013-11-17

View File

@ -3975,7 +3975,10 @@ tar: Hit write checkpoint #20
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
@ -3984,17 +3987,18 @@ Print type of the checkpoint (@samp{write} or @samp{read}).
@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
@ -4012,6 +4016,10 @@ for the current locale.
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

View File

@ -492,20 +492,20 @@ open_compressed_archive (void)
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
@ -524,27 +524,28 @@ format_total_stats (FILE *fp, const char **formats, int eor, int eol)
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));

View File

@ -185,7 +185,8 @@ getarg (const char *input, const char ** endp, char **argbuf, size_t *arglen)
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,
@ -254,8 +255,33 @@ 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':
@ -362,11 +388,11 @@ run_checkpoint_actions (bool do_write)
}
}
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)
@ -378,14 +404,13 @@ finish_checkpoint_actions (void)
while (w--)
fputc (' ', tty);
fputc ('\r', tty);
fflush (tty);
}
break;
default:
/* nothing */;
}
}
if (tty)
fclose (tty);
}
void
@ -399,5 +424,9 @@ void
checkpoint_finish (void)
{
if (checkpoint_option)
finish_checkpoint_actions ();
{
checkpoint_flush_actions ();
if (tty)
fclose (tty);
}
}

View File

@ -862,6 +862,7 @@ void checkpoint_compile_action (const char *str);
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

View File

@ -2623,6 +2623,8 @@ main (int argc, char **argv)
exit_failure = TAREXIT_FAILURE;
exit_status = TAREXIT_SUCCESS;
error_hook = checkpoint_flush_actions;
filename_terminator = '\n';
set_quoting_style (0, DEFAULT_QUOTING_STYLE);