install-sh: be stricter in catching invalid usages
authorStefano Lattarini <stefano.lattarini@gmail.com>
Wed, 25 Dec 2013 23:07:27 +0000 (00:07 +0100)
committerStefano Lattarini <stefano.lattarini@gmail.com>
Wed, 25 Dec 2013 23:07:27 +0000 (00:07 +0100)
Such usages (which are rejected by GNU install as well) are:

  - options -d and -t used together;

  - argument passed to option -t must be a directory;

  - if there are two or more SOURCEFILE arguments, the
    DESTINATION argument must be a directory.

Note that we still allow the use of options -d and -T together, by
making -d take the precedence; this is for compatibility with GNU
install.

This change fixes, among other things, automake bug#15376.

* lib/install-sh: Adjust.
* t/install-sh-unittests.sh: Enhance.
* NEWS: Update.
* THANKS: Add reporter of bug#15376.

Helped-by: Tobias Hansen <thansen@debian.org>
Signed-off-by: Stefano Lattarini <stefano.lattarini@gmail.com>
NEWS
THANKS
lib/install-sh
t/install-sh-unittests.sh

diff --git a/NEWS b/NEWS
index a6e197946e8ab55b8a983e7265646882374d96b3..8d902c07c8a2030903a879ca66fc9095df8e516e 100644 (file)
--- a/NEWS
+++ b/NEWS
 
 New in 1.15:
 
-* Cleanups and modernizations:
+* Improvements and refactorings in the install-sh script:
 
-  - The install-sh script has been modernized, and now makes the following
-    assumptions *unconditionally*:
+  - It has been modernized, and now makes the following assumptions
+    *unconditionally*:
     (1) a working 'dirname' program is available;
     (2) the ${var:-value} shell parameters substitution works;
     (3) the "set -f" and "set +f" shell commands work, and, respectively,
         disable and enable shell globbing.
 
+  - The script implements stricter error checking, an it will now complain
+    and bail out if:
+    (1) the options -d and -t are used together;
+    (2) the argument passed to option -t must be a directory;
+    (3) if there are two or more SOURCEFILE arguments, the
+        DESTINATION argument must be a directory.
+
 * Automake-generated testsuites:
 
   - The default test-driver used by the Automake-generates testsuites now
diff --git a/THANKS b/THANKS
index e4f70f322b966b27473f5850c1e57e8ef22481e9..2b4f8eeec745f5f7aa29d72921de0d7e33df2da8 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -401,6 +401,7 @@ Tim Mooney                      mooney@dogbert.cc.ndsu.NoDak.edu
 Tim Retout                      diocles@debian.org
 Tim Rice                        tim@multitalents.net
 Tim Van Holder                  tim.van.holder@pandora.be
+Tobias Hansen                   thansen@debian.org
 Toshio Kuratomi                 toshio@tiki-lounge.com
 Tom Epperly                     tepperly@llnl.gov
 Tom Rini                        tom_rini@mentor.com
index 04367377519aa95e9c254662e9d81362a13f1b10..d8de87f3061c481074a1b136d37da2d42c9e6119 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2013-10-30.23; # UTC
+scriptversion=2013-12-25.23; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -82,7 +82,7 @@ dir_arg=
 dst_arg=
 
 copy_on_change=false
-no_target_directory=
+is_target_a_directory=possibly
 
 usage="\
 Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
@@ -139,14 +139,16 @@ while test $# -ne 0; do
 
     -s) stripcmd=$stripprog;;
 
-    -t) dst_arg=$2
+    -t)
+        is_target_a_directory=always
+        dst_arg=$2
         # Protect names problematic for 'test' and other utilities.
         case $dst_arg in
           -* | [=\(\)!]) dst_arg=./$dst_arg;;
         esac
         shift;;
 
-    -T) no_target_directory=true;;
+    -T) is_target_a_directory=never;;
 
     --version) echo "$0 $scriptversion"; exit $?;;
 
@@ -161,6 +163,16 @@ while test $# -ne 0; do
   shift
 done
 
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+  if test -n "$dst_arg"; then
+    echo "$0: target directory not allowed when installing a directory." >&2
+    exit 1
+  fi
+fi
+
 if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
   # When -d is used, all remaining arguments are directories to create.
   # When -t is used, the destination is already specified.
@@ -181,6 +193,15 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
   done
 fi
 
+if test -z "$dir_arg"; then
+  if test $# -gt 1 || test "$is_target_a_directory" = always; then
+    if test ! -d "$dst_arg"; then
+      echo "$0: $dst_arg: Is not a directory." >&2
+      exit 1
+    fi
+  fi
+fi
+
 if test $# -eq 0; then
   if test -z "$dir_arg"; then
     echo "$0: no input file specified." >&2
@@ -253,7 +274,7 @@ do
     # If destination is a directory, append the input filename; won't work
     # if double slashes aren't ignored.
     if test -d "$dst"; then
-      if test -n "$no_target_directory"; then
+      if test "$is_target_a_directory" = never; then
         echo "$0: $dst_arg: Is a directory" >&2
         exit 1
       fi
index 8a60d7435799bd42f7fb04aa742417436c9e20d5..1b85c9ce38573371d7e2a4b9c644420a7336ba92 100644 (file)
@@ -25,26 +25,46 @@ get_shell_script install-sh
 ./install-sh && exit 1
 ./install-sh -m 644 dest && exit 1
 
-# Directories.
+# Incorrect usages.
+: > bar
+: > baz
+: > qux
+./install-sh -d -t foo && exit 1
+./install-sh -d -t foo bar && exit 1
+./install-sh -t foo bar && exit 1
+./install-sh bar baz foo && exit 1
+mkdir foo
+./install-sh -d -t foo && exit 1
+./install-sh -d -t foo bar && exit 1
+rmdir foo
+rm -f bar baz qux
 
-# It should be OK to create no directory.  We sometimes need
-# this when directory are conditionally defined.
-./install-sh -d
-# One directory.
-./install-sh -d d0
-test -d d0
-# Multiple directories (for make installdirs).
-./install-sh -d d1 d2 d3 d4
-test -d d1
-test -d d2
-test -d d3
-test -d d4
-# Subdirectories.
-./install-sh -d p1/p2/p3 p4//p5//p6//
-test -d p1/p2/p3
-test -d p4/p5/p6
+# Directories.
+for opts in '-d' '-d -T' '-T -d' '-d -T -d' '-T -d -T -d -T'; do
+  # It should be OK to create no directory.  We sometimes need
+  # this when directory are conditionally defined.
+  ./install-sh $opts
+  # One directory.
+  ./install-sh $opts d0
+  test -d d0
+  # Multiple directories (for make installdirs).
+  ./install-sh $opts d1 d2 d3 d4
+  test -d d1
+  test -d d2
+  test -d d3
+  test -d d4
+  rmdir d[0-9]
+  # Subdirectories.
+  ./install-sh $opts p1/p2/p3 p4//p5//p6//
+  test -d p1/p2/p3
+  test -d p4/p5/p6
+  rmdir p[0-9]/p[0-9]/p[0-9]
+  rmdir p[0-9]/p[0-9]
+  rmdir p[0-9]
+done
 
 # Files.
+mkdir d0 d1 d2 d3 d4
 : > x
 ./install-sh -c -m 644 x y
 test -f x