1c76ae52dSmrg#!/bin/sh
2c76ae52dSmrg# install - install a program, script, or datafile
3c76ae52dSmrg
425420f97Smrgscriptversion=2020-11-14.01; # UTC
5c76ae52dSmrg
6c76ae52dSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7c76ae52dSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8c76ae52dSmrg# following copyright and license.
9c76ae52dSmrg#
10c76ae52dSmrg# Copyright (C) 1994 X Consortium
11c76ae52dSmrg#
12c76ae52dSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13c76ae52dSmrg# of this software and associated documentation files (the "Software"), to
14c76ae52dSmrg# deal in the Software without restriction, including without limitation the
15c76ae52dSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16c76ae52dSmrg# sell copies of the Software, and to permit persons to whom the Software is
17c76ae52dSmrg# furnished to do so, subject to the following conditions:
18c76ae52dSmrg#
19c76ae52dSmrg# The above copyright notice and this permission notice shall be included in
20c76ae52dSmrg# all copies or substantial portions of the Software.
21c76ae52dSmrg#
22c76ae52dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c76ae52dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c76ae52dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25c76ae52dSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26c76ae52dSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27c76ae52dSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28c76ae52dSmrg#
29c76ae52dSmrg# Except as contained in this notice, the name of the X Consortium shall not
30c76ae52dSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31c76ae52dSmrg# ings in this Software without prior written authorization from the X Consor-
32c76ae52dSmrg# tium.
33c76ae52dSmrg#
34c76ae52dSmrg#
35c76ae52dSmrg# FSF changes to this file are in the public domain.
36c76ae52dSmrg#
37c76ae52dSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38dff01e5aSmrg# 'make' implicit rules from creating a file called install from it
39c76ae52dSmrg# when there is no Makefile.
40c76ae52dSmrg#
41c76ae52dSmrg# This script is compatible with the BSD install script, but was written
420d590c07Smrg# from scratch.
430d590c07Smrg
448292847cSmrgtab='	'
450d590c07Smrgnl='
460d590c07Smrg'
478292847cSmrgIFS=" $tab$nl"
48c76ae52dSmrg
498292847cSmrg# Set DOITPROG to "echo" to test this script.
50c76ae52dSmrg
510d590c07Smrgdoit=${DOITPROG-}
528292847cSmrgdoit_exec=${doit:-exec}
53c76ae52dSmrg
540d590c07Smrg# Put in absolute file names if you don't have them in your path;
550d590c07Smrg# or use environment vars.
560d590c07Smrg
570d590c07Smrgchgrpprog=${CHGRPPROG-chgrp}
580d590c07Smrgchmodprog=${CHMODPROG-chmod}
590d590c07Smrgchownprog=${CHOWNPROG-chown}
600d590c07Smrgcmpprog=${CMPPROG-cmp}
610d590c07Smrgcpprog=${CPPROG-cp}
620d590c07Smrgmkdirprog=${MKDIRPROG-mkdir}
630d590c07Smrgmvprog=${MVPROG-mv}
640d590c07Smrgrmprog=${RMPROG-rm}
650d590c07Smrgstripprog=${STRIPPROG-strip}
660d590c07Smrg
670d590c07Smrgposix_mkdir=
680d590c07Smrg
690d590c07Smrg# Desired mode of installed file.
700d590c07Smrgmode=0755
71c76ae52dSmrg
7225420f97Smrg# Create dirs (including intermediate dirs) using mode 755.
7325420f97Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7425420f97Smrgmkdir_umask=22
7525420f97Smrg
7625420f97Smrgbackupsuffix=
77c76ae52dSmrgchgrpcmd=
780d590c07Smrgchmodcmd=$chmodprog
790d590c07Smrgchowncmd=
800d590c07Smrgmvcmd=$mvprog
81c76ae52dSmrgrmcmd="$rmprog -f"
820d590c07Smrgstripcmd=
830d590c07Smrg
84c76ae52dSmrgsrc=
85c76ae52dSmrgdst=
86c76ae52dSmrgdir_arg=
870d590c07Smrgdst_arg=
880d590c07Smrg
890d590c07Smrgcopy_on_change=false
908292847cSmrgis_target_a_directory=possibly
91c76ae52dSmrg
920d590c07Smrgusage="\
930d590c07SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94c76ae52dSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95c76ae52dSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96c76ae52dSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97c76ae52dSmrg
98c76ae52dSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99c76ae52dSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100c76ae52dSmrgIn the 4th, create DIRECTORIES.
101c76ae52dSmrg
102c76ae52dSmrgOptions:
1030d590c07Smrg     --help     display this help and exit.
1040d590c07Smrg     --version  display version info and exit.
1050d590c07Smrg
1060d590c07Smrg  -c            (ignored)
10725420f97Smrg  -C            install only if different (preserve data modification time)
1080d590c07Smrg  -d            create directories instead of installing files.
1090d590c07Smrg  -g GROUP      $chgrpprog installed files to GROUP.
1100d590c07Smrg  -m MODE       $chmodprog installed files to MODE.
1110d590c07Smrg  -o USER       $chownprog installed files to USER.
11225420f97Smrg  -p            pass -p to $cpprog.
1130d590c07Smrg  -s            $stripprog installed files.
11425420f97Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
1150d590c07Smrg  -t DIRECTORY  install into DIRECTORY.
1160d590c07Smrg  -T            report an error if DSTFILE is a directory.
117c76ae52dSmrg
118c76ae52dSmrgEnvironment variables override the default commands:
1190d590c07Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1200d590c07Smrg  RMPROG STRIPPROG
12125420f97Smrg
12225420f97SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12325420f97Smrgit's up to you to specify -f if you want it.
12425420f97Smrg
12525420f97SmrgIf -S is not specified, no backups are attempted.
12625420f97Smrg
12725420f97SmrgEmail bug reports to bug-automake@gnu.org.
12825420f97SmrgAutomake home page: https://www.gnu.org/software/automake/
129c76ae52dSmrg"
130c76ae52dSmrg
1310d590c07Smrgwhile test $# -ne 0; do
132c76ae52dSmrg  case $1 in
1330d590c07Smrg    -c) ;;
1340d590c07Smrg
1350d590c07Smrg    -C) copy_on_change=true;;
136c76ae52dSmrg
1370d590c07Smrg    -d) dir_arg=true;;
138c76ae52dSmrg
139c76ae52dSmrg    -g) chgrpcmd="$chgrpprog $2"
1408292847cSmrg        shift;;
141c76ae52dSmrg
142c76ae52dSmrg    --help) echo "$usage"; exit $?;;
143c76ae52dSmrg
1440d590c07Smrg    -m) mode=$2
1458292847cSmrg        case $mode in
1468292847cSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1478292847cSmrg            echo "$0: invalid mode: $mode" >&2
1488292847cSmrg            exit 1;;
1498292847cSmrg        esac
1508292847cSmrg        shift;;
151c76ae52dSmrg
152c76ae52dSmrg    -o) chowncmd="$chownprog $2"
1538292847cSmrg        shift;;
154c76ae52dSmrg
15525420f97Smrg    -p) cpprog="$cpprog -p";;
15625420f97Smrg
1570d590c07Smrg    -s) stripcmd=$stripprog;;
158c76ae52dSmrg
15925420f97Smrg    -S) backupsuffix="$2"
16025420f97Smrg        shift;;
16125420f97Smrg
1628292847cSmrg    -t)
1638292847cSmrg        is_target_a_directory=always
1648292847cSmrg        dst_arg=$2
1658292847cSmrg        # Protect names problematic for 'test' and other utilities.
1668292847cSmrg        case $dst_arg in
1678292847cSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1688292847cSmrg        esac
1698292847cSmrg        shift;;
170c76ae52dSmrg
1718292847cSmrg    -T) is_target_a_directory=never;;
172c76ae52dSmrg
173c76ae52dSmrg    --version) echo "$0 $scriptversion"; exit $?;;
174c76ae52dSmrg
1758292847cSmrg    --) shift
1768292847cSmrg        break;;
1770d590c07Smrg
1788292847cSmrg    -*) echo "$0: invalid option: $1" >&2
1798292847cSmrg        exit 1;;
1800d590c07Smrg
1810d590c07Smrg    *)  break;;
182c76ae52dSmrg  esac
1830d590c07Smrg  shift
184c76ae52dSmrgdone
185c76ae52dSmrg
1868292847cSmrg# We allow the use of options -d and -T together, by making -d
1878292847cSmrg# take the precedence; this is for compatibility with GNU install.
1888292847cSmrg
1898292847cSmrgif test -n "$dir_arg"; then
1908292847cSmrg  if test -n "$dst_arg"; then
1918292847cSmrg    echo "$0: target directory not allowed when installing a directory." >&2
1928292847cSmrg    exit 1
1938292847cSmrg  fi
1948292847cSmrgfi
1958292847cSmrg
1960d590c07Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1970d590c07Smrg  # When -d is used, all remaining arguments are directories to create.
1980d590c07Smrg  # When -t is used, the destination is already specified.
1990d590c07Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
2000d590c07Smrg  for arg
2010d590c07Smrg  do
2020d590c07Smrg    if test -n "$dst_arg"; then
2030d590c07Smrg      # $@ is not empty: it contains at least $arg.
2040d590c07Smrg      set fnord "$@" "$dst_arg"
2050d590c07Smrg      shift # fnord
2060d590c07Smrg    fi
2070d590c07Smrg    shift # arg
2080d590c07Smrg    dst_arg=$arg
209dff01e5aSmrg    # Protect names problematic for 'test' and other utilities.
2102836776bSmrg    case $dst_arg in
2112836776bSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
2122836776bSmrg    esac
2130d590c07Smrg  done
2140d590c07Smrgfi
2150d590c07Smrg
2160d590c07Smrgif test $# -eq 0; then
217c76ae52dSmrg  if test -z "$dir_arg"; then
218c76ae52dSmrg    echo "$0: no input file specified." >&2
219c76ae52dSmrg    exit 1
220c76ae52dSmrg  fi
221dff01e5aSmrg  # It's OK to call 'install-sh -d' without argument.
222c76ae52dSmrg  # This can happen when creating conditional directories.
223c76ae52dSmrg  exit 0
224c76ae52dSmrgfi
225c76ae52dSmrg
2268292847cSmrgif test -z "$dir_arg"; then
2278292847cSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2288292847cSmrg    if test ! -d "$dst_arg"; then
2298292847cSmrg      echo "$0: $dst_arg: Is not a directory." >&2
2308292847cSmrg      exit 1
2318292847cSmrg    fi
2328292847cSmrg  fi
2338292847cSmrgfi
2348292847cSmrg
2350d590c07Smrgif test -z "$dir_arg"; then
2362836776bSmrg  do_exit='(exit $ret); exit $ret'
2372836776bSmrg  trap "ret=129; $do_exit" 1
2382836776bSmrg  trap "ret=130; $do_exit" 2
2392836776bSmrg  trap "ret=141; $do_exit" 13
2402836776bSmrg  trap "ret=143; $do_exit" 15
2410d590c07Smrg
2420d590c07Smrg  # Set umask so as not to create temps with too-generous modes.
2430d590c07Smrg  # However, 'strip' requires both read and write access to temps.
2440d590c07Smrg  case $mode in
2450d590c07Smrg    # Optimize common cases.
2460d590c07Smrg    *644) cp_umask=133;;
2470d590c07Smrg    *755) cp_umask=22;;
2480d590c07Smrg
2490d590c07Smrg    *[0-7])
2500d590c07Smrg      if test -z "$stripcmd"; then
2518292847cSmrg        u_plus_rw=
2520d590c07Smrg      else
2538292847cSmrg        u_plus_rw='% 200'
2540d590c07Smrg      fi
2550d590c07Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2560d590c07Smrg    *)
2570d590c07Smrg      if test -z "$stripcmd"; then
2588292847cSmrg        u_plus_rw=
2590d590c07Smrg      else
2608292847cSmrg        u_plus_rw=,u+rw
2610d590c07Smrg      fi
2620d590c07Smrg      cp_umask=$mode$u_plus_rw;;
2630d590c07Smrg  esac
2640d590c07Smrgfi
2650d590c07Smrg
266c76ae52dSmrgfor src
267c76ae52dSmrgdo
268dff01e5aSmrg  # Protect names problematic for 'test' and other utilities.
269c76ae52dSmrg  case $src in
2702836776bSmrg    -* | [=\(\)!]) src=./$src;;
271c76ae52dSmrg  esac
272c76ae52dSmrg
273c76ae52dSmrg  if test -n "$dir_arg"; then
274c76ae52dSmrg    dst=$src
2750d590c07Smrg    dstdir=$dst
2760d590c07Smrg    test -d "$dstdir"
2770d590c07Smrg    dstdir_status=$?
27825420f97Smrg    # Don't chown directories that already exist.
27925420f97Smrg    if test $dstdir_status = 0; then
28025420f97Smrg      chowncmd=""
28125420f97Smrg    fi
282c76ae52dSmrg  else
2830d590c07Smrg
284c76ae52dSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285c76ae52dSmrg    # might cause directories to be created, which would be especially bad
286c76ae52dSmrg    # if $src (and thus $dsttmp) contains '*'.
287c76ae52dSmrg    if test ! -f "$src" && test ! -d "$src"; then
288c76ae52dSmrg      echo "$0: $src does not exist." >&2
289c76ae52dSmrg      exit 1
290c76ae52dSmrg    fi
291c76ae52dSmrg
2920d590c07Smrg    if test -z "$dst_arg"; then
293c76ae52dSmrg      echo "$0: no destination specified." >&2
294c76ae52dSmrg      exit 1
295c76ae52dSmrg    fi
2960d590c07Smrg    dst=$dst_arg
297c76ae52dSmrg
29884febdacSmrg    # If destination is a directory, append the input filename.
299c76ae52dSmrg    if test -d "$dst"; then
3008292847cSmrg      if test "$is_target_a_directory" = never; then
3018292847cSmrg        echo "$0: $dst_arg: Is a directory" >&2
3028292847cSmrg        exit 1
303c76ae52dSmrg      fi
3040d590c07Smrg      dstdir=$dst
30584febdacSmrg      dstbase=`basename "$src"`
30684febdacSmrg      case $dst in
30784febdacSmrg	*/) dst=$dst$dstbase;;
30884febdacSmrg	*)  dst=$dst/$dstbase;;
30984febdacSmrg      esac
3100d590c07Smrg      dstdir_status=0
3110d590c07Smrg    else
3128292847cSmrg      dstdir=`dirname "$dst"`
3130d590c07Smrg      test -d "$dstdir"
3140d590c07Smrg      dstdir_status=$?
315c76ae52dSmrg    fi
316c76ae52dSmrg  fi
317c76ae52dSmrg
31884febdacSmrg  case $dstdir in
31984febdacSmrg    */) dstdirslash=$dstdir;;
32084febdacSmrg    *)  dstdirslash=$dstdir/;;
32184febdacSmrg  esac
32284febdacSmrg
3230d590c07Smrg  obsolete_mkdir_used=false
3240d590c07Smrg
3250d590c07Smrg  if test $dstdir_status != 0; then
3260d590c07Smrg    case $posix_mkdir in
3270d590c07Smrg      '')
3288292847cSmrg        # With -d, create the new directory with the user-specified mode.
3298292847cSmrg        # Otherwise, rely on $mkdir_umask.
3308292847cSmrg        if test -n "$dir_arg"; then
3318292847cSmrg          mkdir_mode=-m$mode
3328292847cSmrg        else
3338292847cSmrg          mkdir_mode=
3348292847cSmrg        fi
3358292847cSmrg
3368292847cSmrg        posix_mkdir=false
33725420f97Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33825420f97Smrg	# here however when possible just to lower collision chance.
33925420f97Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34025420f97Smrg
34125420f97Smrg	trap '
34225420f97Smrg	  ret=$?
34325420f97Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34425420f97Smrg	  exit $ret
34525420f97Smrg	' 0
34625420f97Smrg
34725420f97Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
34825420f97Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
34925420f97Smrg	# directory is successfully created first before we actually test
35025420f97Smrg	# 'mkdir -p'.
35125420f97Smrg	if (umask $mkdir_umask &&
35225420f97Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35325420f97Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35425420f97Smrg	then
35525420f97Smrg	  if test -z "$dir_arg" || {
35625420f97Smrg	       # Check for POSIX incompatibilities with -m.
35725420f97Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35825420f97Smrg	       # other-writable bit of parent directory when it shouldn't.
35925420f97Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36025420f97Smrg	       test_tmpdir="$tmpdir/a"
36125420f97Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36225420f97Smrg	       case $ls_ld_tmpdir in
36325420f97Smrg		 d????-?r-*) different_mode=700;;
36425420f97Smrg		 d????-?--*) different_mode=755;;
36525420f97Smrg		 *) false;;
36625420f97Smrg	       esac &&
36725420f97Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36825420f97Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36925420f97Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37025420f97Smrg	       }
37125420f97Smrg	     }
37225420f97Smrg	  then posix_mkdir=:
37325420f97Smrg	  fi
37425420f97Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
37525420f97Smrg	else
37625420f97Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
37725420f97Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37825420f97Smrg	fi
37925420f97Smrg	trap '' 0;;
3800d590c07Smrg    esac
381c76ae52dSmrg
3820d590c07Smrg    if
3830d590c07Smrg      $posix_mkdir && (
3848292847cSmrg        umask $mkdir_umask &&
3858292847cSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3860d590c07Smrg      )
3870d590c07Smrg    then :
3880d590c07Smrg    else
389c76ae52dSmrg
39025420f97Smrg      # mkdir does not conform to POSIX,
3910d590c07Smrg      # or it failed possibly due to a race condition.  Create the
3920d590c07Smrg      # directory the slow way, step by step, checking for races as we go.
393c76ae52dSmrg
3940d590c07Smrg      case $dstdir in
3958292847cSmrg        /*) prefix='/';;
3968292847cSmrg        [-=\(\)!]*) prefix='./';;
3978292847cSmrg        *)  prefix='';;
3980d590c07Smrg      esac
399c76ae52dSmrg
4000d590c07Smrg      oIFS=$IFS
4010d590c07Smrg      IFS=/
4028292847cSmrg      set -f
4030d590c07Smrg      set fnord $dstdir
404c76ae52dSmrg      shift
4058292847cSmrg      set +f
4060d590c07Smrg      IFS=$oIFS
4070d590c07Smrg
4080d590c07Smrg      prefixes=
4090d590c07Smrg
4100d590c07Smrg      for d
4110d590c07Smrg      do
4128292847cSmrg        test X"$d" = X && continue
4138292847cSmrg
4148292847cSmrg        prefix=$prefix$d
4158292847cSmrg        if test -d "$prefix"; then
4168292847cSmrg          prefixes=
4178292847cSmrg        else
4188292847cSmrg          if $posix_mkdir; then
41925420f97Smrg            (umask $mkdir_umask &&
4208292847cSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4218292847cSmrg            # Don't fail if two instances are running concurrently.
4228292847cSmrg            test -d "$prefix" || exit 1
4238292847cSmrg          else
4248292847cSmrg            case $prefix in
4258292847cSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4268292847cSmrg              *) qprefix=$prefix;;
4278292847cSmrg            esac
4288292847cSmrg            prefixes="$prefixes '$qprefix'"
4298292847cSmrg          fi
4308292847cSmrg        fi
4318292847cSmrg        prefix=$prefix/
4320d590c07Smrg      done
4330d590c07Smrg
4340d590c07Smrg      if test -n "$prefixes"; then
4358292847cSmrg        # Don't fail if two instances are running concurrently.
4368292847cSmrg        (umask $mkdir_umask &&
4378292847cSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4388292847cSmrg          test -d "$dstdir" || exit 1
4398292847cSmrg        obsolete_mkdir_used=true
440c76ae52dSmrg      fi
4410d590c07Smrg    fi
442c76ae52dSmrg  fi
443c76ae52dSmrg
444c76ae52dSmrg  if test -n "$dir_arg"; then
4450d590c07Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4460d590c07Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4470d590c07Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4480d590c07Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449c76ae52dSmrg  else
450c76ae52dSmrg
451c76ae52dSmrg    # Make a couple of temp file names in the proper directory.
45284febdacSmrg    dsttmp=${dstdirslash}_inst.$$_
45384febdacSmrg    rmtmp=${dstdirslash}_rm.$$_
454c76ae52dSmrg
455c76ae52dSmrg    # Trap to clean up those temp files at exit.
456c76ae52dSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457c76ae52dSmrg
458c76ae52dSmrg    # Copy the file name to the temp name.
45925420f97Smrg    (umask $cp_umask &&
46025420f97Smrg     { test -z "$stripcmd" || {
46125420f97Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46225420f97Smrg	 # which would cause strip to fail.
46325420f97Smrg	 if test -z "$doit"; then
46425420f97Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46525420f97Smrg	 else
46625420f97Smrg	   $doit touch "$dsttmp"
46725420f97Smrg	 fi
46825420f97Smrg       }
46925420f97Smrg     } &&
47025420f97Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471c76ae52dSmrg
472c76ae52dSmrg    # and set any options; do chmod last to preserve setuid bits.
473c76ae52dSmrg    #
474c76ae52dSmrg    # If any of these fail, we abort the whole thing.  If we want to
475c76ae52dSmrg    # ignore errors from any of these, just make sure not to ignore
476c76ae52dSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477c76ae52dSmrg    #
4780d590c07Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4790d590c07Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4800d590c07Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4810d590c07Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4820d590c07Smrg
4830d590c07Smrg    # If -C, don't bother to copy if it wouldn't change the file.
4840d590c07Smrg    if $copy_on_change &&
4858292847cSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4868292847cSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4878292847cSmrg       set -f &&
4880d590c07Smrg       set X $old && old=:$2:$4:$5:$6 &&
4890d590c07Smrg       set X $new && new=:$2:$4:$5:$6 &&
4908292847cSmrg       set +f &&
4910d590c07Smrg       test "$old" = "$new" &&
4920d590c07Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4930d590c07Smrg    then
4940d590c07Smrg      rm -f "$dsttmp"
4950d590c07Smrg    else
49625420f97Smrg      # If $backupsuffix is set, and the file being installed
49725420f97Smrg      # already exists, attempt a backup.  Don't worry if it fails,
49825420f97Smrg      # e.g., if mv doesn't support -f.
49925420f97Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
50025420f97Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50125420f97Smrg      fi
50225420f97Smrg
5030d590c07Smrg      # Rename the file to the real destination.
5040d590c07Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
5050d590c07Smrg
5060d590c07Smrg      # The rename failed, perhaps because mv can't rename something else
5070d590c07Smrg      # to itself, or perhaps because mv is so ancient that it does not
5080d590c07Smrg      # support -f.
5090d590c07Smrg      {
5108292847cSmrg        # Now remove or move aside any old file at destination location.
5118292847cSmrg        # We try this two ways since rm can't unlink itself on some
5128292847cSmrg        # systems and the destination file might be busy for other
5138292847cSmrg        # reasons.  In this case, the final cleanup might fail but the new
5148292847cSmrg        # file should still install successfully.
5158292847cSmrg        {
5168292847cSmrg          test ! -f "$dst" ||
51725420f97Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
5188292847cSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51925420f97Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
5208292847cSmrg          } ||
5218292847cSmrg          { echo "$0: cannot unlink or rename $dst" >&2
5228292847cSmrg            (exit 1); exit 1
5238292847cSmrg          }
5248292847cSmrg        } &&
5258292847cSmrg
5268292847cSmrg        # Now rename the file to the real destination.
5278292847cSmrg        $doit $mvcmd "$dsttmp" "$dst"
5280d590c07Smrg      }
5290d590c07Smrg    fi || exit 1
5300d590c07Smrg
5310d590c07Smrg    trap '' 0
5320d590c07Smrg  fi
533c76ae52dSmrgdone
534c76ae52dSmrg
535c76ae52dSmrg# Local variables:
53684febdacSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
537c76ae52dSmrg# time-stamp-start: "scriptversion="
538c76ae52dSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53984febdacSmrg# time-stamp-time-zone: "UTC0"
5400d590c07Smrg# time-stamp-end: "; # UTC"
541c76ae52dSmrg# End:
542