summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tar.texi25
m---------paxutils0
-rw-r--r--src/checkpoint.c57
-rw-r--r--src/common.h2
-rw-r--r--src/tar.c25
-rw-r--r--tests/dirrem01.at5
-rw-r--r--tests/dirrem02.at5
-rw-r--r--tests/filerem01.at7
-rw-r--r--tests/filerem02.at7
-rw-r--r--tests/grow.at4
-rw-r--r--tests/sptrcreat.at10
-rw-r--r--tests/sptrdiff00.at5
-rw-r--r--tests/sptrdiff01.at5
-rw-r--r--tests/truncate.at10
14 files changed, 110 insertions, 57 deletions
diff --git a/doc/tar.texi b/doc/tar.texi
index 1362216c..a81851b3 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -2553,6 +2553,12 @@ Wait for @var{time} seconds.
@item ttyout=@var{string}
Output @var{string} on the current console (@file{/dev/tty}).
+
+@item totals
+Print statistics (see @pxref{totals}).
+
+@item wait=@var{signo}
+Wait for signal @var{signo}.
@end table
Several @option{--checkpoint-action} options can be specified. The
@@ -4452,6 +4458,25 @@ checkpoint:
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=sleep=30}
@end smallexample
+@anchor{checkpoint wait}
+@cindex @code{wait}, checkpoint action
+The @code{wait=@var{signo}} action stops further execution until the
+signal @var{signo} is delivered. Valid values for @var{signo} are:
+@code{SIGHUP}, @code{SIGQUIT}, @code{SIGINT}, @code{SIGUSR1} and
+@code{SIGUSR2}. The @samp{SIG} prefix is optional. For example:
+
+@example
+$ @kbd{tar -c -f arc --checkpoint=1000 --checkpoint-action wait=USR1 .}
+@end example
+
+In this example, @GNUTAR{} will stop archivation at each 1000th
+checkpoint. wait until the @samp{SIGUSR1} signal is delivered,
+and resume processing.
+
+This action is used by the @command{genfile} utility to perform
+modifications on the input files upon hitting certain checkpoints
+(@pxref{Exec Mode, genfile}).
+
@anchor{checkpoint exec}
@cindex @code{exec}, checkpoint action
Finally, the @code{exec} action executes a given external command.
diff --git a/paxutils b/paxutils
-Subproject 4ef7f9ab13bcf8483050c932110c88f7ae9c75a
+Subproject 56939847bfa9dbfacb7aebd26f48ea8a64dd8b1
diff --git a/src/checkpoint.c b/src/checkpoint.c
index 4c86b526..a8dc64a0 100644
--- a/src/checkpoint.c
+++ b/src/checkpoint.c
@@ -1,6 +1,6 @@
/* Checkpoint management for tar.
- Copyright 2007, 2013-2014, 2016-2017 Free Software Foundation, Inc.
+ Copyright 2007, 2013-2014, 2016-2018 Free Software Foundation, Inc.
This file is part of GNU tar.
@@ -23,6 +23,7 @@
#include <sys/ioctl.h>
#include <termios.h>
#include "fprintftime.h"
+#include <signal.h>
enum checkpoint_opcode
{
@@ -32,7 +33,8 @@ enum checkpoint_opcode
cop_ttyout,
cop_sleep,
cop_exec,
- cop_totals
+ cop_totals,
+ cop_wait
};
struct checkpoint_action
@@ -43,6 +45,7 @@ struct checkpoint_action
{
time_t time;
char *command;
+ int signal;
} v;
};
@@ -52,6 +55,16 @@ static unsigned checkpoint;
/* List of checkpoint actions */
static struct checkpoint_action *checkpoint_action, *checkpoint_action_tail;
+/* State of the checkpoint system */
+enum {
+ CHKP_INIT, /* Needs initialization */
+ CHKP_COMPILE, /* Actions are being compiled */
+ CHKP_RUN /* Actions are being run */
+};
+static int checkpoint_state;
+/* Blocked signals */
+static sigset_t sigs;
+
static struct checkpoint_action *
alloc_action (enum checkpoint_opcode opcode)
{
@@ -85,6 +98,12 @@ checkpoint_compile_action (const char *str)
{
struct checkpoint_action *act;
+ if (checkpoint_state == CHKP_INIT)
+ {
+ sigemptyset (&sigs);
+ checkpoint_state = CHKP_COMPILE;
+ }
+
if (strcmp (str, ".") == 0 || strcmp (str, "dot") == 0)
alloc_action (cop_dot);
else if (strcmp (str, "bell") == 0)
@@ -117,6 +136,12 @@ checkpoint_compile_action (const char *str)
}
else if (strcmp (str, "totals") == 0)
alloc_action (cop_totals);
+ else if (strncmp (str, "wait=", 5) == 0)
+ {
+ act = alloc_action (cop_wait);
+ act->v.signal = decode_signal (str + 5);
+ sigaddset (&sigs, act->v.signal);
+ }
else
FATAL_ERROR ((0, 0, _("%s: unknown checkpoint action"), str));
}
@@ -124,15 +149,22 @@ checkpoint_compile_action (const char *str)
void
checkpoint_finish_compile (void)
{
- if (checkpoint_option)
+ if (checkpoint_state == CHKP_COMPILE)
{
- if (!checkpoint_action)
- /* Provide a historical default */
- checkpoint_compile_action ("echo");
+ sigprocmask (SIG_BLOCK, &sigs, NULL);
+
+ if (checkpoint_option)
+ {
+ if (!checkpoint_action)
+ /* Provide a historical default */
+ checkpoint_compile_action ("echo");
+ }
+ else if (checkpoint_action)
+ /* Otherwise, set default checkpoint rate */
+ checkpoint_option = DEFAULT_CHECKPOINT;
+
+ checkpoint_state = CHKP_RUN;
}
- else if (checkpoint_action)
- /* Otherwise, set default checkpoint rate */
- checkpoint_option = DEFAULT_CHECKPOINT;
}
static const char *checkpoint_total_format[] = {
@@ -390,6 +422,13 @@ run_checkpoint_actions (bool do_write)
case cop_totals:
compute_duration ();
print_total_stats ();
+ break;
+
+ case cop_wait:
+ {
+ int n;
+ sigwait (&sigs, &n);
+ }
}
}
}
diff --git a/src/common.h b/src/common.h
index 885169fb..a4f6052d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -798,6 +798,8 @@ void set_exit_status (int val);
void request_stdin (const char *option);
+int decode_signal (const char *);
+
/* Where an option comes from: */
enum option_source
{
diff --git a/src/tar.c b/src/tar.c
index 9919e87e..9c939f39 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -976,36 +976,37 @@ stat_on_signal (int signo)
#endif
}
-static void
-set_stat_signal (const char *name)
+int
+decode_signal (const char *name)
{
static struct sigtab
{
char const *name;
int signo;
} const sigtab[] = {
- { "SIGUSR1", SIGUSR1 },
{ "USR1", SIGUSR1 },
- { "SIGUSR2", SIGUSR2 },
{ "USR2", SIGUSR2 },
- { "SIGHUP", SIGHUP },
{ "HUP", SIGHUP },
- { "SIGINT", SIGINT },
{ "INT", SIGINT },
- { "SIGQUIT", SIGQUIT },
{ "QUIT", SIGQUIT }
};
struct sigtab const *p;
+ char const *s = name;
+ if (strncmp (s, "SIG", 3) == 0)
+ s += 3;
for (p = sigtab; p < sigtab + sizeof (sigtab) / sizeof (sigtab[0]); p++)
- if (strcmp (p->name, name) == 0)
- {
- stat_on_signal (p->signo);
- return;
- }
+ if (strcmp (p->name, s) == 0)
+ return p->signo;
FATAL_ERROR ((0, 0, _("Unknown signal name: %s"), name));
}
+static void
+set_stat_signal (const char *name)
+{
+ stat_on_signal (decode_signal (name));
+}
+
struct textual_date
{
diff --git a/tests/dirrem01.at b/tests/dirrem01.at
index dabc206f..b82be02b 100644
--- a/tests/dirrem01.at
+++ b/tests/dirrem01.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2017 Free Software Foundation, Inc.
+# Copyright 2017-2018 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -47,8 +47,7 @@ gnu) CPT=3;;
esac
genfile --run --checkpoint=$CPT --unlink dir/sub/file2 --unlink dir/sub -- \
- tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='echo' \
- --checkpoint-action='sleep=1' -c -f archive.tar \
+ tar --blocking-factor=1 -c -f archive.tar \
--listed-incremental db -v dir >/dev/null
],
[1],
diff --git a/tests/dirrem02.at b/tests/dirrem02.at
index 924454f1..c28989e6 100644
--- a/tests/dirrem02.at
+++ b/tests/dirrem02.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2017 Free Software Foundation, Inc.
+# Copyright 2017-2018 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -44,8 +44,7 @@ gnu) CPT=3;;
esac
genfile --run --checkpoint=$CPT --unlink dir/sub/file2 --unlink dir/sub -- \
- tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='echo' \
- --checkpoint-action='sleep=1' -c -f archive.tar \
+ tar --blocking-factor=1 -c -f archive.tar \
--listed-incremental db -v dir dir/sub >/dev/null
],
[2],
diff --git a/tests/filerem01.at b/tests/filerem01.at
index bf020538..0440277d 100644
--- a/tests/filerem01.at
+++ b/tests/filerem01.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2009, 2013-2014, 2016-2017 Free Software Foundation, Inc.
+# Copyright 2009, 2013-2014, 2016-2018 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -33,7 +33,7 @@
# http://lists.gnu.org/archive/html/bug-tar/2009-03/msg00000.html
#
-AT_SETUP([file removed as we read it (ca. 22 seconds)])
+AT_SETUP([file removed as we read it])
AT_KEYWORDS([create incremental listed filechange filerem filerem01])
AT_TAR_CHECK([
@@ -43,8 +43,7 @@ genfile --file dir/file1
genfile --file dir/sub/file2
genfile --run --checkpoint=3 --unlink dir/file1 -- \
- tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='sleep=1' \
- --checkpoint-action='echo' -c -f archive.tar \
+ tar --blocking-factor=1 -c -f archive.tar \
--listed-incremental db -v dir >/dev/null
],
[1],
diff --git a/tests/filerem02.at b/tests/filerem02.at
index 5e6d1bef..34625d6d 100644
--- a/tests/filerem02.at
+++ b/tests/filerem02.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2009, 2013-2014, 2016-2017 Free Software Foundation, Inc.
+# Copyright 2009, 2013-2014, 2016-2018 Free Software Foundation, Inc.
# This file is part of GNU tar.
@@ -23,7 +23,7 @@
# file or directory disappears that is explicitly mentioned
# in the command line.
-AT_SETUP([toplevel file removed (ca. 24 seconds)])
+AT_SETUP([toplevel file removed])
AT_KEYWORDS([create incremental listed filechange filerem filerem02])
AT_TAR_CHECK([
@@ -35,8 +35,7 @@ mkdir dir2
genfile --file dir2/file1
genfile --run --checkpoint=3 --exec 'rm -rf dir2' -- \
- tar --blocking-factor=1 --checkpoint=1 --checkpoint-action='sleep=1' \
- --checkpoint-action='echo' -c -f archive.tar \
+ tar --blocking-factor=1 -c -f archive.tar \
--listed-incremental db -v --warning=no-new-dir dir dir2 >/dev/null
],
[2],
diff --git a/tests/grow.at b/tests/grow.at
index b04250db..a4a047bf 100644
--- a/tests/grow.at
+++ b/tests/grow.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2006-2007, 2013-2014, 2016-2017 Free Software Foundation,
+# Copyright 2006-2007, 2013-2014, 2016-2018 Free Software Foundation,
# Inc.
# This file is part of GNU tar.
@@ -28,7 +28,7 @@ AT_KEYWORDS([grow filechange])
AT_TAR_CHECK([
genfile --file foo --length 50000k
genfile --file baz
-genfile --run --checkpoint 10 --length 1024 --append foo -- tar --checkpoint -vcf bar foo baz
+genfile --run=10 --checkpoint 10 --length 1024 --append foo -- tar -vcf bar foo baz
],
[1],
[foo
diff --git a/tests/sptrcreat.at b/tests/sptrcreat.at
index 8e28f0e0..cfc9e3b0 100644
--- a/tests/sptrcreat.at
+++ b/tests/sptrcreat.at
@@ -38,21 +38,17 @@ genfile --sparse --block-size=1024 --file foo \
0 ABCDEFGHIJ 1M ABCDEFGHIJ 10M ABCDEFGHIJ 200M ABCDEFGHIJ
genfile --file baz
genfile --run --checkpoint 3 --length 200m --truncate foo -- \
- tar --checkpoint=1 \
- --checkpoint-action=echo \
- --checkpoint-action=sleep=1 \
- --sparse -vcf bar foo baz
+ tar --sparse -vcf bar foo baz
echo Exit status: $?
echo separator
genfile --file foo --seek 200m --length 11575296 --pattern=zeros
-tar dvf bar],
-[1],
+tar dvf bar | sed '/foo: Mod time differs/d'],
+[0],
[foo
baz
Exit status: 1
separator
foo
-foo: Mod time differs
baz
],
[tar: foo: File shrank by 11575296 bytes; padding with zeros
diff --git a/tests/sptrdiff00.at b/tests/sptrdiff00.at
index c4105610..4a8cdc7b 100644
--- a/tests/sptrdiff00.at
+++ b/tests/sptrdiff00.at
@@ -35,10 +35,7 @@ echo creating
tar --sparse -vcf bar foo baz
echo comparing
genfile --run --checkpoint 3 --length 200m --truncate foo -- \
- tar --checkpoint=1 \
- --checkpoint-action=echo='Write checkpoint %u' \
- --checkpoint-action=sleep=1 \
- --sparse -vdf bar
+ tar --sparse -vdf bar
],
[1],
[creating
diff --git a/tests/sptrdiff01.at b/tests/sptrdiff01.at
index 2da22679..53c716b7 100644
--- a/tests/sptrdiff01.at
+++ b/tests/sptrdiff01.at
@@ -35,10 +35,7 @@ echo creating
tar --sparse -vcf bar foo baz
echo comparing
genfile --run --checkpoint 5 --length 221278210 --truncate foo -- \
- tar --checkpoint=1 \
- --checkpoint-action=echo='Write checkpoint %u' \
- --checkpoint-action=sleep=1 \
- --sparse -vdf bar
+ tar --sparse -vdf bar
],
[1],
[creating
diff --git a/tests/truncate.at b/tests/truncate.at
index a743e4b7..7bd1443d 100644
--- a/tests/truncate.at
+++ b/tests/truncate.at
@@ -1,7 +1,7 @@
# Process this file with autom4te to create testsuite. -*- Autotest -*-
# Test suite for GNU tar.
-# Copyright 2005, 2007, 2013-2014, 2016-2017 Free Software Foundation,
+# Copyright 2005, 2007, 2013-2014, 2016-2018 Free Software Foundation,
# Inc.
# This file is part of GNU tar.
@@ -33,18 +33,18 @@ AT_KEYWORDS([truncate filechange])
AT_TAR_CHECK([
genfile --file foo --length 200k
genfile --file baz
-genfile --run --checkpoint 10 --length 195k --truncate foo -- tar --checkpoint --checkpoint-action=echo --checkpoint-action=sleep=1 -vcf bar foo baz
+genfile --run --checkpoint 10 --length 195k --truncate foo -- \
+ tar -vcf bar foo baz
echo Exit status: $?
echo separator
genfile --file foo --seek 195k --length 5k --pattern=zeros
-tar dvf bar],
-[1],
+tar dvf bar|sed '/foo: Mod time differs/d'],
+[0],
[foo
baz
Exit status: 1
separator
foo
-foo: Mod time differs
baz
],
[tar: foo: File shrank by 5120 bytes; padding with zeros