]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Implement the "wait" checkpoint action.
authorSergey Poznyakoff <gray@gnu.org>
Fri, 28 Dec 2018 11:17:44 +0000 (13:17 +0200)
committerSergey Poznyakoff <gray@gnu.org>
Fri, 28 Dec 2018 11:27:02 +0000 (13:27 +0200)
This action instructs tar to pause until given signal is delivered.
The newer genfile tool uses this action for communication between
genfile and tar in exec mode. This eliminates race conitions and
speeds up the tests based on exec mode.

* doc/tar.texi: Document changes.
* paxutils: Upgrade.
* src/checkpoint.c: Implement the wait action.
* src/common.h (decode_signal): New proto.
* src/tar.c (decode_signal): New function.
(set_stat_signal): Rewrite.
* tests/dirrem01.at: Adjust genfile and tar command line arguments
to use the new feature.
* tests/dirrem02.at: Likewise.
* tests/filerem01.at: Likewise.
* tests/filerem02.at: Likewise.
* tests/grow.at: Likewise.
* tests/sptrcreat.at: Likewise.
* tests/sptrdiff00.at: Likewise.
* tests/sptrdiff01.at: Likewise.
* tests/truncate.at: Likewise.

14 files changed:
doc/tar.texi
paxutils
src/checkpoint.c
src/common.h
src/tar.c
tests/dirrem01.at
tests/dirrem02.at
tests/filerem01.at
tests/filerem02.at
tests/grow.at
tests/sptrcreat.at
tests/sptrdiff00.at
tests/sptrdiff01.at
tests/truncate.at

index 1362216c97cf3adf79b8e311d047c917d1e22bb2..a81851b3c0260ba1c95dce114cd2d754f8c538a4 100644 (file)
@@ -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.
index 4ef7f9ab13bcf8483050c932110c88f7ae9c75a7..56939847bfa9dbfacb7aebd26f48ea8a64dd8b1d 160000 (submodule)
--- a/paxutils
+++ b/paxutils
@@ -1 +1 @@
-Subproject commit 4ef7f9ab13bcf8483050c932110c88f7ae9c75a7
+Subproject commit 56939847bfa9dbfacb7aebd26f48ea8a64dd8b1d
index 4c86b52601de52a573c5c114f03d08dd984f0afd..a8dc64a07683a2483c925b908367c11f728a32c3 100644 (file)
@@ -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);
+         }
        }
     }
 }
index 885169fb82e67eb14db221c484bd5bda02d1f69e..a4f6052d835e3096d3c6c3c06ddf45c40239af84 100644 (file)
@@ -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
   {
index 9919e87ec517afdf45d0e0033bbddb5ffd885b50..9c939f39f2103fcac4b4f7c3726da8dcbed6dd83 100644 (file)
--- 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));
+}
+
 \f
 struct textual_date
 {
index dabc206f64de91741c0d294ba8032c7011b4f962..b82be02b4d844ddd89dc7341c730cf90b98fcebe 100644 (file)
@@ -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],
index 924454f167429f154b4ab3299be7425fe438b42c..c28989e6f896233d19be265da3919df39efd36d2 100644 (file)
@@ -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],
index bf02053843f693567a0cfd9188450aab01c75dd6..0440277d3b1b1cc2a8abe678927d0b847c1017d9 100644 (file)
@@ -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],
index 5e6d1beff8eccdf53986a3468250d47442bc4e1e..34625d6d86c3250cb03a491c4bf6fd95702f3aa3 100644 (file)
@@ -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],
index b04250dbd4e95640cb56601a4cd9e8c5f305f107..a4a047bf7d0222930ceb594aa84dc9f834e61f84 100644 (file)
@@ -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
index 8e28f0e000f6dc573e0aa7571f31f7d3810feb2e..cfc9e3b007a4cb4c13dbe4ac555a0de45832aef4 100644 (file)
@@ -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
index c41056108eaefa944025860510a343874df0a9f0..4a8cdc7b29aeb73a5b41ff8794d96495352cd2fc 100644 (file)
@@ -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
index 2da226793d259487e51db181af363da59c966287..53c716b7fc5311abf6442324c54170f9c260402b 100644 (file)
@@ -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
index a743e4b796efe52b9906bfb713ac1e619593224a..7bd1443de29cc10617262b11a6fdf63449d948e8 100644 (file)
@@ -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