bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-tar] [PATCH] clarification on variable expansion and best pract


From: Stephane Chazelas
Subject: Re: [Bug-tar] [PATCH] clarification on variable expansion and best practice fixes in examples.
Date: Thu, 14 Apr 2016 10:27:12 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

2016-04-14 11:55:29 +0300, Sergey Poznyakoff:
> Stephane Chazelas <address@hidden> ha escrit:
> 
> > That was with 1.28, but I can reproduce with the latest git
> > master from savannah.
> 
> Indeed.  That behavior was broken in v. 1.27.  I've pushed a patch to
> fix it.
> 
> Thanks for bringing my attention to it.
[...]

Thanks.

Updated documentation patch below. Note that you forgot to quote
the variables in your latest change to the doc.

You may want to read
https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells
if you're not familiar with the need to quote variables in
shells.


diff --git a/doc/tar.texi b/doc/tar.texi
index a8969e0..4d7db4f 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -4482,12 +4482,13 @@ command, provided that they are properly escaped, for 
example:
 
 @smallexample
 @kbd{tar -c -f arc.tar \
-     --checkpoint-action='exec=/sbin/cpoint $TAR_CHECKPOINT'}
+     --checkpoint-action='exec=/sbin/cpoint "$TAR_CHECKPOINT"'}
 @end smallexample
 
 @noindent
 Notice single quotes to prevent variable names from being expanded by
-the shell when invoking @command{tar}.
+the shell when invoking @command{tar}. And the double quotes to prevent
+word splitting or filename generation by the shell invoked by @command{tar}.
 
 Any number of actions can be defined, by supplying several
 @option{--checkpoint-action} options in the command line.  For
@@ -4721,12 +4722,8 @@ feature is the @option{-I} option, which allows you to 
supply the
 program to use for compressing or decompressing the archive
 (@pxref{use-compress-program}).
 
-Whenever such operation is requested, @command{tar} first splits the
-supplied command into words much like the shell does.  It then treats
-the first word as the name of the program or the shell script to execute
-and the rest of words as its command line arguments.  The program,
-unless given as an absolute file name, is searched in the shell's
address@hidden
address@hidden invokes a shell (@command{/bin/sh}) to parse the supplied
+command line.
 
 Any additional information is normally supplied to external commands
 in environment variables, specific to each particular operation.  For
@@ -4737,7 +4734,7 @@ command line of the external command.  For example:
 
 @smallexample
 $ @kbd{tar -x -f archive.tar \
-    --checkpoint-action=exec='printf "%04d in %32s\r" $TAR_CHECKPOINT 
$TAR_ARCHIVE'}
+    --checkpoint-action=exec='printf "%04d in %32s\r" "$TAR_CHECKPOINT" 
"$TAR_ARCHIVE"'}
 @end smallexample
 
 @noindent
@@ -4747,6 +4744,25 @@ archive, using the same output line on the screen.
 Notice the use of single quotes to prevent variable names from being
 expanded by the shell when invoking @command{tar}.
 
+And the double quotes to prevent word splitting and filename generation
+by the shell invoked by @command{tar}.
+
+Note that while a shell is now invoked to parse that command line, but
+note that versions 1.27 and 1.28 of @command{tar} used not to but
+instead used a simplified command line parser that did not support shell
+redirection or expansions other than simple variable expansion.
+
+If writing a script to be compatible with those earlier versions, you
+can use this approach to make sure a shell is always invoked to parse
+the command line regardless of the version of @command{tar}.
+
address@hidden
+$ @kbd{SH_CODE='
+   printf "%04d in %32s\r" "$TAR_CHECKPOINT" "$TAR_ARCHIVE" |
+     tee -a ~/some-file
+   ' tar -x -f archive.tar --checkpoint=exec='sh -c "$SH_CODE"'}
address@hidden smallexample
+
 @node operations
 @chapter @GNUTAR{} Operations
 
@@ -6282,12 +6298,14 @@ could do:
 
 @smallexample
 $ @kbd{tar -x -f archive.tar \
-       --to-command='proc $TAR_FILENAME $TAR_SIZE'}
+       --to-command='proc "$TAR_FILENAME" "$TAR_SIZE"'}
 @end smallexample
 
 @noindent
 Notice single quotes to prevent variable names from being expanded by
-the shell when invoking @command{tar}.
+the shell when invoking @command{tar}. And the double quotes to prevent
+word splitting and filename generation by the shell invoked by
address@hidden
 
 If @var{command} exits with a non-0 status, @command{tar} will print
 an error message similar to the following:
@@ -6499,7 +6517,7 @@ link-structure of all the files therein.  In this case, 
the transfer
 medium is a @dfn{pipe}:
 
 @smallexample
-$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)}
+$ @kbd{(cd sourcedir && tar -cf - .) | (cd targetdir && tar -xf -)}
 @end smallexample
 
 @noindent
@@ -6514,8 +6532,8 @@ The command also works using long option forms:
 
 @smallexample
 @group
-$ @kbd{(cd sourcedir; tar --create --file=- . ) \
-       | (cd targetdir; tar --extract --file=-)}
+$ @kbd{(cd sourcedir && tar --create --file=- . ) \
+       | (cd targetdir && tar --extract --file=-)}
 @end group
 @end smallexample
 
@@ -7246,7 +7264,7 @@ RSH_COMMAND=/usr/bin/ssh
 
 # Override MT_STATUS function:
 my_status() @{
-      mts -t $TAPE_FILE
+      mts -t "$TAPE_FILE"
 @}
 MT_STATUS=my_status
 
@@ -7543,7 +7561,7 @@ The following example is a convenient way of copying 
directory
 hierarchy from @file{sourcedir} to @file{targetdir}.
 
 @smallexample
-$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xpf -)}
+$ @kbd{(cd sourcedir && tar -cf - .) | (cd targetdir && tar -xpf -)}
 @end smallexample
 
 The @option{-C} option allows to avoid using subshells:
@@ -12251,21 +12269,21 @@ archive being created (as given by @option{--file} 
option) and
 
 @smallexample
 @group
-#! /bin/bash
+#! /bin/bash -
 # For this script it's advisable to use a shell, such as Bash,
 # that supports a TAR_FD value greater than 9.
 
-echo Preparing volume $TAR_VOLUME of $TAR_ARCHIVE.
+echo "Preparing volume $TAR_VOLUME of $TAR_ARCHIVE."
 
-name=`expr $TAR_ARCHIVE : '\(.*\)-.*'`
address@hidden@}
 case $TAR_SUBCOMMAND in
 -c)       ;;
--d|-x|-t) test -r address@hidden:address@hidden || exit 1
+-d|-x|-t) test -r "$name-$TAR_VOLUME" || exit 1
           ;;
 *)        exit 1
 esac
 
-echo address@hidden:address@hidden >&$TAR_FD
+printf '%s\n' "$name-$TAR_VOLUME" >&$TAR_FD
 @end group
 @end smallexample
 
-- 
Stephane



reply via email to

[Prev in Thread] Current Thread [Next in Thread]