[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