install-sh revision a67f45c3
176910425Smrg#!/bin/sh
276910425Smrg# install - install a program, script, or datafile
376910425Smrg
4a67f45c3Smrgscriptversion=2020-11-14.01; # UTC
576910425Smrg
676910425Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
776910425Smrg# later released in X11R6 (xc/config/util/install.sh) with the
876910425Smrg# following copyright and license.
976910425Smrg#
1076910425Smrg# Copyright (C) 1994 X Consortium
1176910425Smrg#
1276910425Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1376910425Smrg# of this software and associated documentation files (the "Software"), to
1476910425Smrg# deal in the Software without restriction, including without limitation the
1576910425Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1676910425Smrg# sell copies of the Software, and to permit persons to whom the Software is
1776910425Smrg# furnished to do so, subject to the following conditions:
1876910425Smrg#
1976910425Smrg# The above copyright notice and this permission notice shall be included in
2076910425Smrg# all copies or substantial portions of the Software.
2176910425Smrg#
2276910425Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2376910425Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2476910425Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2576910425Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2676910425Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2776910425Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2876910425Smrg#
2976910425Smrg# Except as contained in this notice, the name of the X Consortium shall not
3076910425Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3176910425Smrg# ings in this Software without prior written authorization from the X Consor-
3276910425Smrg# tium.
3376910425Smrg#
3476910425Smrg#
3576910425Smrg# FSF changes to this file are in the public domain.
3676910425Smrg#
3776910425Smrg# Calling this script install-sh is preferred over install.sh, to prevent
389ff100acSmrg# 'make' implicit rules from creating a file called install from it
3976910425Smrg# when there is no Makefile.
4076910425Smrg#
4176910425Smrg# This script is compatible with the BSD install script, but was written
42db17cd6dSmrg# from scratch.
43db17cd6dSmrg
449ff100acSmrgtab='	'
45db17cd6dSmrgnl='
46db17cd6dSmrg'
479ff100acSmrgIFS=" $tab$nl"
4876910425Smrg
499ff100acSmrg# Set DOITPROG to "echo" to test this script.
5076910425Smrg
51db17cd6dSmrgdoit=${DOITPROG-}
529ff100acSmrgdoit_exec=${doit:-exec}
5376910425Smrg
54db17cd6dSmrg# Put in absolute file names if you don't have them in your path;
55db17cd6dSmrg# or use environment vars.
56db17cd6dSmrg
57db17cd6dSmrgchgrpprog=${CHGRPPROG-chgrp}
58db17cd6dSmrgchmodprog=${CHMODPROG-chmod}
59db17cd6dSmrgchownprog=${CHOWNPROG-chown}
60db17cd6dSmrgcmpprog=${CMPPROG-cmp}
61db17cd6dSmrgcpprog=${CPPROG-cp}
62db17cd6dSmrgmkdirprog=${MKDIRPROG-mkdir}
63db17cd6dSmrgmvprog=${MVPROG-mv}
64db17cd6dSmrgrmprog=${RMPROG-rm}
65db17cd6dSmrgstripprog=${STRIPPROG-strip}
66db17cd6dSmrg
67db17cd6dSmrgposix_mkdir=
68db17cd6dSmrg
69db17cd6dSmrg# Desired mode of installed file.
70db17cd6dSmrgmode=0755
7176910425Smrg
72a67f45c3Smrg# Create dirs (including intermediate dirs) using mode 755.
73a67f45c3Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
74a67f45c3Smrgmkdir_umask=22
75a67f45c3Smrg
76a67f45c3Smrgbackupsuffix=
7776910425Smrgchgrpcmd=
78db17cd6dSmrgchmodcmd=$chmodprog
79db17cd6dSmrgchowncmd=
80db17cd6dSmrgmvcmd=$mvprog
8176910425Smrgrmcmd="$rmprog -f"
82db17cd6dSmrgstripcmd=
83db17cd6dSmrg
8476910425Smrgsrc=
8576910425Smrgdst=
8676910425Smrgdir_arg=
87db17cd6dSmrgdst_arg=
88db17cd6dSmrg
89db17cd6dSmrgcopy_on_change=false
909ff100acSmrgis_target_a_directory=possibly
9176910425Smrg
92db17cd6dSmrgusage="\
93db17cd6dSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
9476910425Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9576910425Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9676910425Smrg   or: $0 [OPTION]... -d DIRECTORIES...
9776910425Smrg
9876910425SmrgIn the 1st form, copy SRCFILE to DSTFILE.
9976910425SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
10076910425SmrgIn the 4th, create DIRECTORIES.
10176910425Smrg
10276910425SmrgOptions:
103db17cd6dSmrg     --help     display this help and exit.
104db17cd6dSmrg     --version  display version info and exit.
105db17cd6dSmrg
106db17cd6dSmrg  -c            (ignored)
107a67f45c3Smrg  -C            install only if different (preserve data modification time)
108db17cd6dSmrg  -d            create directories instead of installing files.
109db17cd6dSmrg  -g GROUP      $chgrpprog installed files to GROUP.
110db17cd6dSmrg  -m MODE       $chmodprog installed files to MODE.
111db17cd6dSmrg  -o USER       $chownprog installed files to USER.
112a67f45c3Smrg  -p            pass -p to $cpprog.
113db17cd6dSmrg  -s            $stripprog installed files.
114a67f45c3Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115db17cd6dSmrg  -t DIRECTORY  install into DIRECTORY.
116db17cd6dSmrg  -T            report an error if DSTFILE is a directory.
11776910425Smrg
11876910425SmrgEnvironment variables override the default commands:
119db17cd6dSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120db17cd6dSmrg  RMPROG STRIPPROG
121a67f45c3Smrg
122a67f45c3SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
123a67f45c3Smrgit's up to you to specify -f if you want it.
124a67f45c3Smrg
125a67f45c3SmrgIf -S is not specified, no backups are attempted.
126a67f45c3Smrg
127a67f45c3SmrgEmail bug reports to bug-automake@gnu.org.
128a67f45c3SmrgAutomake home page: https://www.gnu.org/software/automake/
12976910425Smrg"
13076910425Smrg
131db17cd6dSmrgwhile test $# -ne 0; do
13276910425Smrg  case $1 in
133db17cd6dSmrg    -c) ;;
134db17cd6dSmrg
135db17cd6dSmrg    -C) copy_on_change=true;;
13676910425Smrg
137db17cd6dSmrg    -d) dir_arg=true;;
13876910425Smrg
13976910425Smrg    -g) chgrpcmd="$chgrpprog $2"
1409ff100acSmrg        shift;;
14176910425Smrg
14276910425Smrg    --help) echo "$usage"; exit $?;;
14376910425Smrg
144db17cd6dSmrg    -m) mode=$2
1459ff100acSmrg        case $mode in
1469ff100acSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1479ff100acSmrg            echo "$0: invalid mode: $mode" >&2
1489ff100acSmrg            exit 1;;
1499ff100acSmrg        esac
1509ff100acSmrg        shift;;
15176910425Smrg
15276910425Smrg    -o) chowncmd="$chownprog $2"
1539ff100acSmrg        shift;;
15476910425Smrg
155a67f45c3Smrg    -p) cpprog="$cpprog -p";;
156a67f45c3Smrg
157db17cd6dSmrg    -s) stripcmd=$stripprog;;
15876910425Smrg
159a67f45c3Smrg    -S) backupsuffix="$2"
160a67f45c3Smrg        shift;;
161a67f45c3Smrg
1629ff100acSmrg    -t)
1639ff100acSmrg        is_target_a_directory=always
1649ff100acSmrg        dst_arg=$2
1659ff100acSmrg        # Protect names problematic for 'test' and other utilities.
1669ff100acSmrg        case $dst_arg in
1679ff100acSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1689ff100acSmrg        esac
1699ff100acSmrg        shift;;
17076910425Smrg
1719ff100acSmrg    -T) is_target_a_directory=never;;
17276910425Smrg
17376910425Smrg    --version) echo "$0 $scriptversion"; exit $?;;
17476910425Smrg
1759ff100acSmrg    --) shift
1769ff100acSmrg        break;;
177db17cd6dSmrg
1789ff100acSmrg    -*) echo "$0: invalid option: $1" >&2
1799ff100acSmrg        exit 1;;
180db17cd6dSmrg
181db17cd6dSmrg    *)  break;;
18276910425Smrg  esac
183db17cd6dSmrg  shift
18476910425Smrgdone
18576910425Smrg
1869ff100acSmrg# We allow the use of options -d and -T together, by making -d
1879ff100acSmrg# take the precedence; this is for compatibility with GNU install.
1889ff100acSmrg
1899ff100acSmrgif test -n "$dir_arg"; then
1909ff100acSmrg  if test -n "$dst_arg"; then
1919ff100acSmrg    echo "$0: target directory not allowed when installing a directory." >&2
1929ff100acSmrg    exit 1
1939ff100acSmrg  fi
1949ff100acSmrgfi
1959ff100acSmrg
196db17cd6dSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197db17cd6dSmrg  # When -d is used, all remaining arguments are directories to create.
198db17cd6dSmrg  # When -t is used, the destination is already specified.
199db17cd6dSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200db17cd6dSmrg  for arg
201db17cd6dSmrg  do
202db17cd6dSmrg    if test -n "$dst_arg"; then
203db17cd6dSmrg      # $@ is not empty: it contains at least $arg.
204db17cd6dSmrg      set fnord "$@" "$dst_arg"
205db17cd6dSmrg      shift # fnord
206db17cd6dSmrg    fi
207db17cd6dSmrg    shift # arg
208db17cd6dSmrg    dst_arg=$arg
2099ff100acSmrg    # Protect names problematic for 'test' and other utilities.
2109ff100acSmrg    case $dst_arg in
2119ff100acSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
2129ff100acSmrg    esac
213db17cd6dSmrg  done
214db17cd6dSmrgfi
215db17cd6dSmrg
216db17cd6dSmrgif test $# -eq 0; then
21776910425Smrg  if test -z "$dir_arg"; then
21876910425Smrg    echo "$0: no input file specified." >&2
21976910425Smrg    exit 1
22076910425Smrg  fi
2219ff100acSmrg  # It's OK to call 'install-sh -d' without argument.
22276910425Smrg  # This can happen when creating conditional directories.
22376910425Smrg  exit 0
22476910425Smrgfi
22576910425Smrg
226db17cd6dSmrgif test -z "$dir_arg"; then
2279ff100acSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2289ff100acSmrg    if test ! -d "$dst_arg"; then
2299ff100acSmrg      echo "$0: $dst_arg: Is not a directory." >&2
2309ff100acSmrg      exit 1
2319ff100acSmrg    fi
2329ff100acSmrg  fi
2339ff100acSmrgfi
2349ff100acSmrg
2359ff100acSmrgif test -z "$dir_arg"; then
2369ff100acSmrg  do_exit='(exit $ret); exit $ret'
2379ff100acSmrg  trap "ret=129; $do_exit" 1
2389ff100acSmrg  trap "ret=130; $do_exit" 2
2399ff100acSmrg  trap "ret=141; $do_exit" 13
2409ff100acSmrg  trap "ret=143; $do_exit" 15
241db17cd6dSmrg
242db17cd6dSmrg  # Set umask so as not to create temps with too-generous modes.
243db17cd6dSmrg  # However, 'strip' requires both read and write access to temps.
244db17cd6dSmrg  case $mode in
245db17cd6dSmrg    # Optimize common cases.
246db17cd6dSmrg    *644) cp_umask=133;;
247db17cd6dSmrg    *755) cp_umask=22;;
248db17cd6dSmrg
249db17cd6dSmrg    *[0-7])
250db17cd6dSmrg      if test -z "$stripcmd"; then
2519ff100acSmrg        u_plus_rw=
252db17cd6dSmrg      else
2539ff100acSmrg        u_plus_rw='% 200'
254db17cd6dSmrg      fi
255db17cd6dSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256db17cd6dSmrg    *)
257db17cd6dSmrg      if test -z "$stripcmd"; then
2589ff100acSmrg        u_plus_rw=
259db17cd6dSmrg      else
2609ff100acSmrg        u_plus_rw=,u+rw
261db17cd6dSmrg      fi
262db17cd6dSmrg      cp_umask=$mode$u_plus_rw;;
263db17cd6dSmrg  esac
264db17cd6dSmrgfi
265db17cd6dSmrg
26676910425Smrgfor src
26776910425Smrgdo
2689ff100acSmrg  # Protect names problematic for 'test' and other utilities.
26976910425Smrg  case $src in
2709ff100acSmrg    -* | [=\(\)!]) src=./$src;;
27176910425Smrg  esac
27276910425Smrg
27376910425Smrg  if test -n "$dir_arg"; then
27476910425Smrg    dst=$src
275db17cd6dSmrg    dstdir=$dst
276db17cd6dSmrg    test -d "$dstdir"
277db17cd6dSmrg    dstdir_status=$?
278a67f45c3Smrg    # Don't chown directories that already exist.
279a67f45c3Smrg    if test $dstdir_status = 0; then
280a67f45c3Smrg      chowncmd=""
281a67f45c3Smrg    fi
28276910425Smrg  else
283db17cd6dSmrg
28476910425Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
28576910425Smrg    # might cause directories to be created, which would be especially bad
28676910425Smrg    # if $src (and thus $dsttmp) contains '*'.
28776910425Smrg    if test ! -f "$src" && test ! -d "$src"; then
28876910425Smrg      echo "$0: $src does not exist." >&2
28976910425Smrg      exit 1
29076910425Smrg    fi
29176910425Smrg
292db17cd6dSmrg    if test -z "$dst_arg"; then
29376910425Smrg      echo "$0: no destination specified." >&2
29476910425Smrg      exit 1
29576910425Smrg    fi
296db17cd6dSmrg    dst=$dst_arg
29776910425Smrg
298a67f45c3Smrg    # If destination is a directory, append the input filename.
29976910425Smrg    if test -d "$dst"; then
3009ff100acSmrg      if test "$is_target_a_directory" = never; then
3019ff100acSmrg        echo "$0: $dst_arg: Is a directory" >&2
3029ff100acSmrg        exit 1
30376910425Smrg      fi
304db17cd6dSmrg      dstdir=$dst
305a67f45c3Smrg      dstbase=`basename "$src"`
306a67f45c3Smrg      case $dst in
307a67f45c3Smrg	*/) dst=$dst$dstbase;;
308a67f45c3Smrg	*)  dst=$dst/$dstbase;;
309a67f45c3Smrg      esac
310db17cd6dSmrg      dstdir_status=0
311db17cd6dSmrg    else
3129ff100acSmrg      dstdir=`dirname "$dst"`
313db17cd6dSmrg      test -d "$dstdir"
314db17cd6dSmrg      dstdir_status=$?
31576910425Smrg    fi
31676910425Smrg  fi
31776910425Smrg
318a67f45c3Smrg  case $dstdir in
319a67f45c3Smrg    */) dstdirslash=$dstdir;;
320a67f45c3Smrg    *)  dstdirslash=$dstdir/;;
321a67f45c3Smrg  esac
322a67f45c3Smrg
323db17cd6dSmrg  obsolete_mkdir_used=false
324db17cd6dSmrg
325db17cd6dSmrg  if test $dstdir_status != 0; then
326db17cd6dSmrg    case $posix_mkdir in
327db17cd6dSmrg      '')
3289ff100acSmrg        # With -d, create the new directory with the user-specified mode.
3299ff100acSmrg        # Otherwise, rely on $mkdir_umask.
3309ff100acSmrg        if test -n "$dir_arg"; then
3319ff100acSmrg          mkdir_mode=-m$mode
3329ff100acSmrg        else
3339ff100acSmrg          mkdir_mode=
3349ff100acSmrg        fi
3359ff100acSmrg
3369ff100acSmrg        posix_mkdir=false
337a67f45c3Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
338a67f45c3Smrg	# here however when possible just to lower collision chance.
339a67f45c3Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340a67f45c3Smrg
341a67f45c3Smrg	trap '
342a67f45c3Smrg	  ret=$?
343a67f45c3Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344a67f45c3Smrg	  exit $ret
345a67f45c3Smrg	' 0
346a67f45c3Smrg
347a67f45c3Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
348a67f45c3Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
349a67f45c3Smrg	# directory is successfully created first before we actually test
350a67f45c3Smrg	# 'mkdir -p'.
351a67f45c3Smrg	if (umask $mkdir_umask &&
352a67f45c3Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
353a67f45c3Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354a67f45c3Smrg	then
355a67f45c3Smrg	  if test -z "$dir_arg" || {
356a67f45c3Smrg	       # Check for POSIX incompatibilities with -m.
357a67f45c3Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358a67f45c3Smrg	       # other-writable bit of parent directory when it shouldn't.
359a67f45c3Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360a67f45c3Smrg	       test_tmpdir="$tmpdir/a"
361a67f45c3Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362a67f45c3Smrg	       case $ls_ld_tmpdir in
363a67f45c3Smrg		 d????-?r-*) different_mode=700;;
364a67f45c3Smrg		 d????-?--*) different_mode=755;;
365a67f45c3Smrg		 *) false;;
366a67f45c3Smrg	       esac &&
367a67f45c3Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368a67f45c3Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369a67f45c3Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370a67f45c3Smrg	       }
371a67f45c3Smrg	     }
372a67f45c3Smrg	  then posix_mkdir=:
373a67f45c3Smrg	  fi
374a67f45c3Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375a67f45c3Smrg	else
376a67f45c3Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
377a67f45c3Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378a67f45c3Smrg	fi
379a67f45c3Smrg	trap '' 0;;
380db17cd6dSmrg    esac
38176910425Smrg
382db17cd6dSmrg    if
383db17cd6dSmrg      $posix_mkdir && (
3849ff100acSmrg        umask $mkdir_umask &&
3859ff100acSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386db17cd6dSmrg      )
387db17cd6dSmrg    then :
388db17cd6dSmrg    else
38976910425Smrg
390a67f45c3Smrg      # mkdir does not conform to POSIX,
391db17cd6dSmrg      # or it failed possibly due to a race condition.  Create the
392db17cd6dSmrg      # directory the slow way, step by step, checking for races as we go.
39376910425Smrg
394db17cd6dSmrg      case $dstdir in
3959ff100acSmrg        /*) prefix='/';;
3969ff100acSmrg        [-=\(\)!]*) prefix='./';;
3979ff100acSmrg        *)  prefix='';;
398db17cd6dSmrg      esac
39976910425Smrg
400db17cd6dSmrg      oIFS=$IFS
401db17cd6dSmrg      IFS=/
4029ff100acSmrg      set -f
403db17cd6dSmrg      set fnord $dstdir
40476910425Smrg      shift
4059ff100acSmrg      set +f
406db17cd6dSmrg      IFS=$oIFS
407db17cd6dSmrg
408db17cd6dSmrg      prefixes=
409db17cd6dSmrg
410db17cd6dSmrg      for d
411db17cd6dSmrg      do
4129ff100acSmrg        test X"$d" = X && continue
4139ff100acSmrg
4149ff100acSmrg        prefix=$prefix$d
4159ff100acSmrg        if test -d "$prefix"; then
4169ff100acSmrg          prefixes=
4179ff100acSmrg        else
4189ff100acSmrg          if $posix_mkdir; then
419a67f45c3Smrg            (umask $mkdir_umask &&
4209ff100acSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4219ff100acSmrg            # Don't fail if two instances are running concurrently.
4229ff100acSmrg            test -d "$prefix" || exit 1
4239ff100acSmrg          else
4249ff100acSmrg            case $prefix in
4259ff100acSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4269ff100acSmrg              *) qprefix=$prefix;;
4279ff100acSmrg            esac
4289ff100acSmrg            prefixes="$prefixes '$qprefix'"
4299ff100acSmrg          fi
4309ff100acSmrg        fi
4319ff100acSmrg        prefix=$prefix/
432db17cd6dSmrg      done
433db17cd6dSmrg
434db17cd6dSmrg      if test -n "$prefixes"; then
4359ff100acSmrg        # Don't fail if two instances are running concurrently.
4369ff100acSmrg        (umask $mkdir_umask &&
4379ff100acSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4389ff100acSmrg          test -d "$dstdir" || exit 1
4399ff100acSmrg        obsolete_mkdir_used=true
44076910425Smrg      fi
441db17cd6dSmrg    fi
44276910425Smrg  fi
44376910425Smrg
44476910425Smrg  if test -n "$dir_arg"; then
445db17cd6dSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446db17cd6dSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447db17cd6dSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448db17cd6dSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
44976910425Smrg  else
45076910425Smrg
45176910425Smrg    # Make a couple of temp file names in the proper directory.
452a67f45c3Smrg    dsttmp=${dstdirslash}_inst.$$_
453a67f45c3Smrg    rmtmp=${dstdirslash}_rm.$$_
45476910425Smrg
45576910425Smrg    # Trap to clean up those temp files at exit.
45676910425Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
45776910425Smrg
45876910425Smrg    # Copy the file name to the temp name.
459a67f45c3Smrg    (umask $cp_umask &&
460a67f45c3Smrg     { test -z "$stripcmd" || {
461a67f45c3Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
462a67f45c3Smrg	 # which would cause strip to fail.
463a67f45c3Smrg	 if test -z "$doit"; then
464a67f45c3Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
465a67f45c3Smrg	 else
466a67f45c3Smrg	   $doit touch "$dsttmp"
467a67f45c3Smrg	 fi
468a67f45c3Smrg       }
469a67f45c3Smrg     } &&
470a67f45c3Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
47176910425Smrg
47276910425Smrg    # and set any options; do chmod last to preserve setuid bits.
47376910425Smrg    #
47476910425Smrg    # If any of these fail, we abort the whole thing.  If we want to
47576910425Smrg    # ignore errors from any of these, just make sure not to ignore
47676910425Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
47776910425Smrg    #
478db17cd6dSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479db17cd6dSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480db17cd6dSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481db17cd6dSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482db17cd6dSmrg
483db17cd6dSmrg    # If -C, don't bother to copy if it wouldn't change the file.
484db17cd6dSmrg    if $copy_on_change &&
4859ff100acSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4869ff100acSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4879ff100acSmrg       set -f &&
488db17cd6dSmrg       set X $old && old=:$2:$4:$5:$6 &&
489db17cd6dSmrg       set X $new && new=:$2:$4:$5:$6 &&
4909ff100acSmrg       set +f &&
491db17cd6dSmrg       test "$old" = "$new" &&
492db17cd6dSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493db17cd6dSmrg    then
494db17cd6dSmrg      rm -f "$dsttmp"
495db17cd6dSmrg    else
496a67f45c3Smrg      # If $backupsuffix is set, and the file being installed
497a67f45c3Smrg      # already exists, attempt a backup.  Don't worry if it fails,
498a67f45c3Smrg      # e.g., if mv doesn't support -f.
499a67f45c3Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
500a67f45c3Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501a67f45c3Smrg      fi
502a67f45c3Smrg
503db17cd6dSmrg      # Rename the file to the real destination.
504db17cd6dSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505db17cd6dSmrg
506db17cd6dSmrg      # The rename failed, perhaps because mv can't rename something else
507db17cd6dSmrg      # to itself, or perhaps because mv is so ancient that it does not
508db17cd6dSmrg      # support -f.
509db17cd6dSmrg      {
5109ff100acSmrg        # Now remove or move aside any old file at destination location.
5119ff100acSmrg        # We try this two ways since rm can't unlink itself on some
5129ff100acSmrg        # systems and the destination file might be busy for other
5139ff100acSmrg        # reasons.  In this case, the final cleanup might fail but the new
5149ff100acSmrg        # file should still install successfully.
5159ff100acSmrg        {
5169ff100acSmrg          test ! -f "$dst" ||
517a67f45c3Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
5189ff100acSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519a67f45c3Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
5209ff100acSmrg          } ||
5219ff100acSmrg          { echo "$0: cannot unlink or rename $dst" >&2
5229ff100acSmrg            (exit 1); exit 1
5239ff100acSmrg          }
5249ff100acSmrg        } &&
5259ff100acSmrg
5269ff100acSmrg        # Now rename the file to the real destination.
5279ff100acSmrg        $doit $mvcmd "$dsttmp" "$dst"
528db17cd6dSmrg      }
529db17cd6dSmrg    fi || exit 1
530db17cd6dSmrg
531db17cd6dSmrg    trap '' 0
532db17cd6dSmrg  fi
53376910425Smrgdone
53476910425Smrg
53576910425Smrg# Local variables:
536a67f45c3Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
53776910425Smrg# time-stamp-start: "scriptversion="
53876910425Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
539a67f45c3Smrg# time-stamp-time-zone: "UTC0"
540db17cd6dSmrg# time-stamp-end: "; # UTC"
54176910425Smrg# End:
542