install-sh revision 94c9ab7b
18440cca4Smrg#!/bin/sh
28440cca4Smrg# install - install a program, script, or datafile
3d1c293acSmrg
494c9ab7bSmrgscriptversion=2020-11-14.01; # UTC
5d1c293acSmrg
68440cca4Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
78440cca4Smrg# later released in X11R6 (xc/config/util/install.sh) with the
88440cca4Smrg# following copyright and license.
98440cca4Smrg#
108440cca4Smrg# Copyright (C) 1994 X Consortium
118440cca4Smrg#
128440cca4Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
138440cca4Smrg# of this software and associated documentation files (the "Software"), to
148440cca4Smrg# deal in the Software without restriction, including without limitation the
158440cca4Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
168440cca4Smrg# sell copies of the Software, and to permit persons to whom the Software is
178440cca4Smrg# furnished to do so, subject to the following conditions:
188440cca4Smrg#
198440cca4Smrg# The above copyright notice and this permission notice shall be included in
208440cca4Smrg# all copies or substantial portions of the Software.
218440cca4Smrg#
228440cca4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
238440cca4Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
248440cca4Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
258440cca4Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
268440cca4Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
278440cca4Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
288440cca4Smrg#
298440cca4Smrg# Except as contained in this notice, the name of the X Consortium shall not
308440cca4Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
318440cca4Smrg# ings in this Software without prior written authorization from the X Consor-
328440cca4Smrg# tium.
338440cca4Smrg#
348440cca4Smrg#
358440cca4Smrg# FSF changes to this file are in the public domain.
368440cca4Smrg#
378440cca4Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3804449c54Smrg# 'make' implicit rules from creating a file called install from it
398440cca4Smrg# when there is no Makefile.
408440cca4Smrg#
418440cca4Smrg# This script is compatible with the BSD install script, but was written
42d1c293acSmrg# from scratch.
438440cca4Smrg
4404449c54Smrgtab='	'
45d1c293acSmrgnl='
46d1c293acSmrg'
4704449c54SmrgIFS=" $tab$nl"
488440cca4Smrg
4904449c54Smrg# Set DOITPROG to "echo" to test this script.
508440cca4Smrg
51d1c293acSmrgdoit=${DOITPROG-}
5204449c54Smrgdoit_exec=${doit:-exec}
538440cca4Smrg
54d1c293acSmrg# Put in absolute file names if you don't have them in your path;
55d1c293acSmrg# or use environment vars.
56d1c293acSmrg
57d1c293acSmrgchgrpprog=${CHGRPPROG-chgrp}
58d1c293acSmrgchmodprog=${CHMODPROG-chmod}
59d1c293acSmrgchownprog=${CHOWNPROG-chown}
60d1c293acSmrgcmpprog=${CMPPROG-cmp}
61d1c293acSmrgcpprog=${CPPROG-cp}
62d1c293acSmrgmkdirprog=${MKDIRPROG-mkdir}
63d1c293acSmrgmvprog=${MVPROG-mv}
64d1c293acSmrgrmprog=${RMPROG-rm}
65d1c293acSmrgstripprog=${STRIPPROG-strip}
66d1c293acSmrg
67d1c293acSmrgposix_mkdir=
68d1c293acSmrg
69d1c293acSmrg# Desired mode of installed file.
70d1c293acSmrgmode=0755
71d1c293acSmrg
7294c9ab7bSmrg# Create dirs (including intermediate dirs) using mode 755.
7394c9ab7bSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7494c9ab7bSmrgmkdir_umask=22
7594c9ab7bSmrg
7694c9ab7bSmrgbackupsuffix=
77d1c293acSmrgchgrpcmd=
78d1c293acSmrgchmodcmd=$chmodprog
79d1c293acSmrgchowncmd=
80d1c293acSmrgmvcmd=$mvprog
81d1c293acSmrgrmcmd="$rmprog -f"
82d1c293acSmrgstripcmd=
838440cca4Smrg
84d1c293acSmrgsrc=
85d1c293acSmrgdst=
86d1c293acSmrgdir_arg=
87d1c293acSmrgdst_arg=
888440cca4Smrg
89d1c293acSmrgcopy_on_change=false
9004449c54Smrgis_target_a_directory=possibly
918440cca4Smrg
92d1c293acSmrgusage="\
93d1c293acSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94d1c293acSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95d1c293acSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96d1c293acSmrg   or: $0 [OPTION]... -d DIRECTORIES...
978440cca4Smrg
98d1c293acSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99d1c293acSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100d1c293acSmrgIn the 4th, create DIRECTORIES.
1018440cca4Smrg
102d1c293acSmrgOptions:
103d1c293acSmrg     --help     display this help and exit.
104d1c293acSmrg     --version  display version info and exit.
1058440cca4Smrg
106d1c293acSmrg  -c            (ignored)
10794c9ab7bSmrg  -C            install only if different (preserve data modification time)
108d1c293acSmrg  -d            create directories instead of installing files.
109d1c293acSmrg  -g GROUP      $chgrpprog installed files to GROUP.
110d1c293acSmrg  -m MODE       $chmodprog installed files to MODE.
111d1c293acSmrg  -o USER       $chownprog installed files to USER.
11294c9ab7bSmrg  -p            pass -p to $cpprog.
113d1c293acSmrg  -s            $stripprog installed files.
11494c9ab7bSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115d1c293acSmrg  -t DIRECTORY  install into DIRECTORY.
116d1c293acSmrg  -T            report an error if DSTFILE is a directory.
1178440cca4Smrg
118d1c293acSmrgEnvironment variables override the default commands:
119d1c293acSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120d1c293acSmrg  RMPROG STRIPPROG
12194c9ab7bSmrg
12294c9ab7bSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12394c9ab7bSmrgit's up to you to specify -f if you want it.
12494c9ab7bSmrg
12594c9ab7bSmrgIf -S is not specified, no backups are attempted.
12694c9ab7bSmrg
12794c9ab7bSmrgEmail bug reports to bug-automake@gnu.org.
12894c9ab7bSmrgAutomake home page: https://www.gnu.org/software/automake/
129d1c293acSmrg"
1308440cca4Smrg
131d1c293acSmrgwhile test $# -ne 0; do
132d1c293acSmrg  case $1 in
133d1c293acSmrg    -c) ;;
1348440cca4Smrg
135d1c293acSmrg    -C) copy_on_change=true;;
1368440cca4Smrg
137d1c293acSmrg    -d) dir_arg=true;;
1388440cca4Smrg
139d1c293acSmrg    -g) chgrpcmd="$chgrpprog $2"
14004449c54Smrg        shift;;
1418440cca4Smrg
142d1c293acSmrg    --help) echo "$usage"; exit $?;;
1438440cca4Smrg
144d1c293acSmrg    -m) mode=$2
14504449c54Smrg        case $mode in
14604449c54Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14704449c54Smrg            echo "$0: invalid mode: $mode" >&2
14804449c54Smrg            exit 1;;
14904449c54Smrg        esac
15004449c54Smrg        shift;;
1518440cca4Smrg
152d1c293acSmrg    -o) chowncmd="$chownprog $2"
15304449c54Smrg        shift;;
1548440cca4Smrg
15594c9ab7bSmrg    -p) cpprog="$cpprog -p";;
15694c9ab7bSmrg
157d1c293acSmrg    -s) stripcmd=$stripprog;;
1588440cca4Smrg
15994c9ab7bSmrg    -S) backupsuffix="$2"
16094c9ab7bSmrg        shift;;
16194c9ab7bSmrg
16204449c54Smrg    -t)
16304449c54Smrg        is_target_a_directory=always
16404449c54Smrg        dst_arg=$2
16504449c54Smrg        # Protect names problematic for 'test' and other utilities.
16604449c54Smrg        case $dst_arg in
16704449c54Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16804449c54Smrg        esac
16904449c54Smrg        shift;;
1708440cca4Smrg
17104449c54Smrg    -T) is_target_a_directory=never;;
1728440cca4Smrg
173d1c293acSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1748440cca4Smrg
17504449c54Smrg    --) shift
17604449c54Smrg        break;;
1778440cca4Smrg
17804449c54Smrg    -*) echo "$0: invalid option: $1" >&2
17904449c54Smrg        exit 1;;
1808440cca4Smrg
181d1c293acSmrg    *)  break;;
182d1c293acSmrg  esac
183d1c293acSmrg  shift
184d1c293acSmrgdone
1858440cca4Smrg
18604449c54Smrg# We allow the use of options -d and -T together, by making -d
18704449c54Smrg# take the precedence; this is for compatibility with GNU install.
18804449c54Smrg
18904449c54Smrgif test -n "$dir_arg"; then
19004449c54Smrg  if test -n "$dst_arg"; then
19104449c54Smrg    echo "$0: target directory not allowed when installing a directory." >&2
19204449c54Smrg    exit 1
19304449c54Smrg  fi
19404449c54Smrgfi
19504449c54Smrg
196d1c293acSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197d1c293acSmrg  # When -d is used, all remaining arguments are directories to create.
198d1c293acSmrg  # When -t is used, the destination is already specified.
199d1c293acSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200d1c293acSmrg  for arg
201d1c293acSmrg  do
202d1c293acSmrg    if test -n "$dst_arg"; then
203d1c293acSmrg      # $@ is not empty: it contains at least $arg.
204d1c293acSmrg      set fnord "$@" "$dst_arg"
205d1c293acSmrg      shift # fnord
206d1c293acSmrg    fi
207d1c293acSmrg    shift # arg
208d1c293acSmrg    dst_arg=$arg
20904449c54Smrg    # Protect names problematic for 'test' and other utilities.
21020915927Smrg    case $dst_arg in
21120915927Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21220915927Smrg    esac
213d1c293acSmrg  done
214d1c293acSmrgfi
2158440cca4Smrg
216d1c293acSmrgif test $# -eq 0; then
217d1c293acSmrg  if test -z "$dir_arg"; then
218d1c293acSmrg    echo "$0: no input file specified." >&2
219d1c293acSmrg    exit 1
220d1c293acSmrg  fi
22104449c54Smrg  # It's OK to call 'install-sh -d' without argument.
222d1c293acSmrg  # This can happen when creating conditional directories.
223d1c293acSmrg  exit 0
224d1c293acSmrgfi
2258440cca4Smrg
22604449c54Smrgif test -z "$dir_arg"; then
22704449c54Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22804449c54Smrg    if test ! -d "$dst_arg"; then
22904449c54Smrg      echo "$0: $dst_arg: Is not a directory." >&2
23004449c54Smrg      exit 1
23104449c54Smrg    fi
23204449c54Smrg  fi
23304449c54Smrgfi
23404449c54Smrg
235d1c293acSmrgif test -z "$dir_arg"; then
23620915927Smrg  do_exit='(exit $ret); exit $ret'
23720915927Smrg  trap "ret=129; $do_exit" 1
23820915927Smrg  trap "ret=130; $do_exit" 2
23920915927Smrg  trap "ret=141; $do_exit" 13
24020915927Smrg  trap "ret=143; $do_exit" 15
241d1c293acSmrg
242d1c293acSmrg  # Set umask so as not to create temps with too-generous modes.
243d1c293acSmrg  # However, 'strip' requires both read and write access to temps.
244d1c293acSmrg  case $mode in
245d1c293acSmrg    # Optimize common cases.
246d1c293acSmrg    *644) cp_umask=133;;
247d1c293acSmrg    *755) cp_umask=22;;
248d1c293acSmrg
249d1c293acSmrg    *[0-7])
250d1c293acSmrg      if test -z "$stripcmd"; then
25104449c54Smrg        u_plus_rw=
252d1c293acSmrg      else
25304449c54Smrg        u_plus_rw='% 200'
254d1c293acSmrg      fi
255d1c293acSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256d1c293acSmrg    *)
257d1c293acSmrg      if test -z "$stripcmd"; then
25804449c54Smrg        u_plus_rw=
259d1c293acSmrg      else
26004449c54Smrg        u_plus_rw=,u+rw
261d1c293acSmrg      fi
262d1c293acSmrg      cp_umask=$mode$u_plus_rw;;
263d1c293acSmrg  esac
264d1c293acSmrgfi
2658440cca4Smrg
266d1c293acSmrgfor src
267d1c293acSmrgdo
26804449c54Smrg  # Protect names problematic for 'test' and other utilities.
269d1c293acSmrg  case $src in
27020915927Smrg    -* | [=\(\)!]) src=./$src;;
271d1c293acSmrg  esac
272d1c293acSmrg
273d1c293acSmrg  if test -n "$dir_arg"; then
274d1c293acSmrg    dst=$src
275d1c293acSmrg    dstdir=$dst
276d1c293acSmrg    test -d "$dstdir"
277d1c293acSmrg    dstdir_status=$?
27894c9ab7bSmrg    # Don't chown directories that already exist.
27994c9ab7bSmrg    if test $dstdir_status = 0; then
28094c9ab7bSmrg      chowncmd=""
28194c9ab7bSmrg    fi
282d1c293acSmrg  else
283d1c293acSmrg
284d1c293acSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285d1c293acSmrg    # might cause directories to be created, which would be especially bad
286d1c293acSmrg    # if $src (and thus $dsttmp) contains '*'.
287d1c293acSmrg    if test ! -f "$src" && test ! -d "$src"; then
288d1c293acSmrg      echo "$0: $src does not exist." >&2
289d1c293acSmrg      exit 1
290d1c293acSmrg    fi
291d1c293acSmrg
292d1c293acSmrg    if test -z "$dst_arg"; then
293d1c293acSmrg      echo "$0: no destination specified." >&2
294d1c293acSmrg      exit 1
295d1c293acSmrg    fi
296d1c293acSmrg    dst=$dst_arg
2978440cca4Smrg
29894c9ab7bSmrg    # If destination is a directory, append the input filename.
299d1c293acSmrg    if test -d "$dst"; then
30004449c54Smrg      if test "$is_target_a_directory" = never; then
30104449c54Smrg        echo "$0: $dst_arg: Is a directory" >&2
30204449c54Smrg        exit 1
303d1c293acSmrg      fi
304d1c293acSmrg      dstdir=$dst
30594c9ab7bSmrg      dstbase=`basename "$src"`
30694c9ab7bSmrg      case $dst in
30794c9ab7bSmrg	*/) dst=$dst$dstbase;;
30894c9ab7bSmrg	*)  dst=$dst/$dstbase;;
30994c9ab7bSmrg      esac
310d1c293acSmrg      dstdir_status=0
311d1c293acSmrg    else
31204449c54Smrg      dstdir=`dirname "$dst"`
313d1c293acSmrg      test -d "$dstdir"
314d1c293acSmrg      dstdir_status=$?
315d1c293acSmrg    fi
316d1c293acSmrg  fi
317d1c293acSmrg
31894c9ab7bSmrg  case $dstdir in
31994c9ab7bSmrg    */) dstdirslash=$dstdir;;
32094c9ab7bSmrg    *)  dstdirslash=$dstdir/;;
32194c9ab7bSmrg  esac
32294c9ab7bSmrg
323d1c293acSmrg  obsolete_mkdir_used=false
324d1c293acSmrg
325d1c293acSmrg  if test $dstdir_status != 0; then
326d1c293acSmrg    case $posix_mkdir in
327d1c293acSmrg      '')
32804449c54Smrg        # With -d, create the new directory with the user-specified mode.
32904449c54Smrg        # Otherwise, rely on $mkdir_umask.
33004449c54Smrg        if test -n "$dir_arg"; then
33104449c54Smrg          mkdir_mode=-m$mode
33204449c54Smrg        else
33304449c54Smrg          mkdir_mode=
33404449c54Smrg        fi
33504449c54Smrg
33604449c54Smrg        posix_mkdir=false
33794c9ab7bSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33894c9ab7bSmrg	# here however when possible just to lower collision chance.
33994c9ab7bSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34094c9ab7bSmrg
34194c9ab7bSmrg	trap '
34294c9ab7bSmrg	  ret=$?
34394c9ab7bSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34494c9ab7bSmrg	  exit $ret
34594c9ab7bSmrg	' 0
34694c9ab7bSmrg
34794c9ab7bSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
34894c9ab7bSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
34994c9ab7bSmrg	# directory is successfully created first before we actually test
35094c9ab7bSmrg	# 'mkdir -p'.
35194c9ab7bSmrg	if (umask $mkdir_umask &&
35294c9ab7bSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35394c9ab7bSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35494c9ab7bSmrg	then
35594c9ab7bSmrg	  if test -z "$dir_arg" || {
35694c9ab7bSmrg	       # Check for POSIX incompatibilities with -m.
35794c9ab7bSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35894c9ab7bSmrg	       # other-writable bit of parent directory when it shouldn't.
35994c9ab7bSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36094c9ab7bSmrg	       test_tmpdir="$tmpdir/a"
36194c9ab7bSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36294c9ab7bSmrg	       case $ls_ld_tmpdir in
36394c9ab7bSmrg		 d????-?r-*) different_mode=700;;
36494c9ab7bSmrg		 d????-?--*) different_mode=755;;
36594c9ab7bSmrg		 *) false;;
36694c9ab7bSmrg	       esac &&
36794c9ab7bSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36894c9ab7bSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36994c9ab7bSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37094c9ab7bSmrg	       }
37194c9ab7bSmrg	     }
37294c9ab7bSmrg	  then posix_mkdir=:
37394c9ab7bSmrg	  fi
37494c9ab7bSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
37594c9ab7bSmrg	else
37694c9ab7bSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
37794c9ab7bSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37894c9ab7bSmrg	fi
37994c9ab7bSmrg	trap '' 0;;
380d1c293acSmrg    esac
3818440cca4Smrg
382d1c293acSmrg    if
383d1c293acSmrg      $posix_mkdir && (
38404449c54Smrg        umask $mkdir_umask &&
38504449c54Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386d1c293acSmrg      )
387d1c293acSmrg    then :
388d1c293acSmrg    else
389d1c293acSmrg
39094c9ab7bSmrg      # mkdir does not conform to POSIX,
391d1c293acSmrg      # or it failed possibly due to a race condition.  Create the
392d1c293acSmrg      # directory the slow way, step by step, checking for races as we go.
393d1c293acSmrg
394d1c293acSmrg      case $dstdir in
39504449c54Smrg        /*) prefix='/';;
39604449c54Smrg        [-=\(\)!]*) prefix='./';;
39704449c54Smrg        *)  prefix='';;
398d1c293acSmrg      esac
399d1c293acSmrg
400d1c293acSmrg      oIFS=$IFS
401d1c293acSmrg      IFS=/
40204449c54Smrg      set -f
403d1c293acSmrg      set fnord $dstdir
404d1c293acSmrg      shift
40504449c54Smrg      set +f
406d1c293acSmrg      IFS=$oIFS
407d1c293acSmrg
408d1c293acSmrg      prefixes=
409d1c293acSmrg
410d1c293acSmrg      for d
411d1c293acSmrg      do
41204449c54Smrg        test X"$d" = X && continue
41304449c54Smrg
41404449c54Smrg        prefix=$prefix$d
41504449c54Smrg        if test -d "$prefix"; then
41604449c54Smrg          prefixes=
41704449c54Smrg        else
41804449c54Smrg          if $posix_mkdir; then
41994c9ab7bSmrg            (umask $mkdir_umask &&
42004449c54Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42104449c54Smrg            # Don't fail if two instances are running concurrently.
42204449c54Smrg            test -d "$prefix" || exit 1
42304449c54Smrg          else
42404449c54Smrg            case $prefix in
42504449c54Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42604449c54Smrg              *) qprefix=$prefix;;
42704449c54Smrg            esac
42804449c54Smrg            prefixes="$prefixes '$qprefix'"
42904449c54Smrg          fi
43004449c54Smrg        fi
43104449c54Smrg        prefix=$prefix/
432d1c293acSmrg      done
433d1c293acSmrg
434d1c293acSmrg      if test -n "$prefixes"; then
43504449c54Smrg        # Don't fail if two instances are running concurrently.
43604449c54Smrg        (umask $mkdir_umask &&
43704449c54Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43804449c54Smrg          test -d "$dstdir" || exit 1
43904449c54Smrg        obsolete_mkdir_used=true
440d1c293acSmrg      fi
441d1c293acSmrg    fi
442d1c293acSmrg  fi
443d1c293acSmrg
444d1c293acSmrg  if test -n "$dir_arg"; then
445d1c293acSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446d1c293acSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447d1c293acSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448d1c293acSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449d1c293acSmrg  else
450d1c293acSmrg
451d1c293acSmrg    # Make a couple of temp file names in the proper directory.
45294c9ab7bSmrg    dsttmp=${dstdirslash}_inst.$$_
45394c9ab7bSmrg    rmtmp=${dstdirslash}_rm.$$_
454d1c293acSmrg
455d1c293acSmrg    # Trap to clean up those temp files at exit.
456d1c293acSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457d1c293acSmrg
458d1c293acSmrg    # Copy the file name to the temp name.
45994c9ab7bSmrg    (umask $cp_umask &&
46094c9ab7bSmrg     { test -z "$stripcmd" || {
46194c9ab7bSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46294c9ab7bSmrg	 # which would cause strip to fail.
46394c9ab7bSmrg	 if test -z "$doit"; then
46494c9ab7bSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46594c9ab7bSmrg	 else
46694c9ab7bSmrg	   $doit touch "$dsttmp"
46794c9ab7bSmrg	 fi
46894c9ab7bSmrg       }
46994c9ab7bSmrg     } &&
47094c9ab7bSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471d1c293acSmrg
472d1c293acSmrg    # and set any options; do chmod last to preserve setuid bits.
473d1c293acSmrg    #
474d1c293acSmrg    # If any of these fail, we abort the whole thing.  If we want to
475d1c293acSmrg    # ignore errors from any of these, just make sure not to ignore
476d1c293acSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477d1c293acSmrg    #
478d1c293acSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479d1c293acSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480d1c293acSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481d1c293acSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482d1c293acSmrg
483d1c293acSmrg    # If -C, don't bother to copy if it wouldn't change the file.
484d1c293acSmrg    if $copy_on_change &&
48504449c54Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48604449c54Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48704449c54Smrg       set -f &&
488d1c293acSmrg       set X $old && old=:$2:$4:$5:$6 &&
489d1c293acSmrg       set X $new && new=:$2:$4:$5:$6 &&
49004449c54Smrg       set +f &&
491d1c293acSmrg       test "$old" = "$new" &&
492d1c293acSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493d1c293acSmrg    then
494d1c293acSmrg      rm -f "$dsttmp"
495d1c293acSmrg    else
49694c9ab7bSmrg      # If $backupsuffix is set, and the file being installed
49794c9ab7bSmrg      # already exists, attempt a backup.  Don't worry if it fails,
49894c9ab7bSmrg      # e.g., if mv doesn't support -f.
49994c9ab7bSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
50094c9ab7bSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50194c9ab7bSmrg      fi
50294c9ab7bSmrg
503d1c293acSmrg      # Rename the file to the real destination.
504d1c293acSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505d1c293acSmrg
506d1c293acSmrg      # The rename failed, perhaps because mv can't rename something else
507d1c293acSmrg      # to itself, or perhaps because mv is so ancient that it does not
508d1c293acSmrg      # support -f.
509d1c293acSmrg      {
51004449c54Smrg        # Now remove or move aside any old file at destination location.
51104449c54Smrg        # We try this two ways since rm can't unlink itself on some
51204449c54Smrg        # systems and the destination file might be busy for other
51304449c54Smrg        # reasons.  In this case, the final cleanup might fail but the new
51404449c54Smrg        # file should still install successfully.
51504449c54Smrg        {
51604449c54Smrg          test ! -f "$dst" ||
51794c9ab7bSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
51804449c54Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51994c9ab7bSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52004449c54Smrg          } ||
52104449c54Smrg          { echo "$0: cannot unlink or rename $dst" >&2
52204449c54Smrg            (exit 1); exit 1
52304449c54Smrg          }
52404449c54Smrg        } &&
52504449c54Smrg
52604449c54Smrg        # Now rename the file to the real destination.
52704449c54Smrg        $doit $mvcmd "$dsttmp" "$dst"
528d1c293acSmrg      }
529d1c293acSmrg    fi || exit 1
530d1c293acSmrg
531d1c293acSmrg    trap '' 0
532d1c293acSmrg  fi
533d1c293acSmrgdone
5348440cca4Smrg
535d1c293acSmrg# Local variables:
53694c9ab7bSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
537d1c293acSmrg# time-stamp-start: "scriptversion="
538d1c293acSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53994c9ab7bSmrg# time-stamp-time-zone: "UTC0"
540d1c293acSmrg# time-stamp-end: "; # UTC"
541d1c293acSmrg# End:
542