11cc8c64fSmrg#!/bin/sh
21cc8c64fSmrg# install - install a program, script, or datafile
3b9bb67cbSmrg
418eba588Smrgscriptversion=2020-11-14.01; # UTC
5b9bb67cbSmrg
61cc8c64fSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
71cc8c64fSmrg# later released in X11R6 (xc/config/util/install.sh) with the
81cc8c64fSmrg# following copyright and license.
91cc8c64fSmrg#
101cc8c64fSmrg# Copyright (C) 1994 X Consortium
111cc8c64fSmrg#
121cc8c64fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
131cc8c64fSmrg# of this software and associated documentation files (the "Software"), to
141cc8c64fSmrg# deal in the Software without restriction, including without limitation the
151cc8c64fSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
161cc8c64fSmrg# sell copies of the Software, and to permit persons to whom the Software is
171cc8c64fSmrg# furnished to do so, subject to the following conditions:
181cc8c64fSmrg#
191cc8c64fSmrg# The above copyright notice and this permission notice shall be included in
201cc8c64fSmrg# all copies or substantial portions of the Software.
211cc8c64fSmrg#
221cc8c64fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
231cc8c64fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
241cc8c64fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
251cc8c64fSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
261cc8c64fSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
271cc8c64fSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
281cc8c64fSmrg#
291cc8c64fSmrg# Except as contained in this notice, the name of the X Consortium shall not
301cc8c64fSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
311cc8c64fSmrg# ings in this Software without prior written authorization from the X Consor-
321cc8c64fSmrg# tium.
331cc8c64fSmrg#
341cc8c64fSmrg#
351cc8c64fSmrg# FSF changes to this file are in the public domain.
361cc8c64fSmrg#
371cc8c64fSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3818eba588Smrg# 'make' implicit rules from creating a file called install from it
391cc8c64fSmrg# when there is no Makefile.
401cc8c64fSmrg#
411cc8c64fSmrg# This script is compatible with the BSD install script, but was written
42b9bb67cbSmrg# from scratch.
431cc8c64fSmrg
4418eba588Smrgtab='	'
45b9bb67cbSmrgnl='
46b9bb67cbSmrg'
4718eba588SmrgIFS=" $tab$nl"
481cc8c64fSmrg
4918eba588Smrg# Set DOITPROG to "echo" to test this script.
501cc8c64fSmrg
51b9bb67cbSmrgdoit=${DOITPROG-}
5218eba588Smrgdoit_exec=${doit:-exec}
531cc8c64fSmrg
54b9bb67cbSmrg# Put in absolute file names if you don't have them in your path;
55b9bb67cbSmrg# or use environment vars.
56b9bb67cbSmrg
57b9bb67cbSmrgchgrpprog=${CHGRPPROG-chgrp}
58b9bb67cbSmrgchmodprog=${CHMODPROG-chmod}
59b9bb67cbSmrgchownprog=${CHOWNPROG-chown}
60b9bb67cbSmrgcmpprog=${CMPPROG-cmp}
61b9bb67cbSmrgcpprog=${CPPROG-cp}
62b9bb67cbSmrgmkdirprog=${MKDIRPROG-mkdir}
63b9bb67cbSmrgmvprog=${MVPROG-mv}
64b9bb67cbSmrgrmprog=${RMPROG-rm}
65b9bb67cbSmrgstripprog=${STRIPPROG-strip}
66b9bb67cbSmrg
67b9bb67cbSmrgposix_mkdir=
68b9bb67cbSmrg
69b9bb67cbSmrg# Desired mode of installed file.
70b9bb67cbSmrgmode=0755
71b9bb67cbSmrg
7218eba588Smrg# Create dirs (including intermediate dirs) using mode 755.
7318eba588Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7418eba588Smrgmkdir_umask=22
7518eba588Smrg
7618eba588Smrgbackupsuffix=
77b9bb67cbSmrgchgrpcmd=
78b9bb67cbSmrgchmodcmd=$chmodprog
79b9bb67cbSmrgchowncmd=
80b9bb67cbSmrgmvcmd=$mvprog
81b9bb67cbSmrgrmcmd="$rmprog -f"
82b9bb67cbSmrgstripcmd=
831cc8c64fSmrg
84b9bb67cbSmrgsrc=
85b9bb67cbSmrgdst=
86b9bb67cbSmrgdir_arg=
87b9bb67cbSmrgdst_arg=
881cc8c64fSmrg
89b9bb67cbSmrgcopy_on_change=false
9018eba588Smrgis_target_a_directory=possibly
911cc8c64fSmrg
92b9bb67cbSmrgusage="\
93b9bb67cbSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94b9bb67cbSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95b9bb67cbSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96b9bb67cbSmrg   or: $0 [OPTION]... -d DIRECTORIES...
971cc8c64fSmrg
98b9bb67cbSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99b9bb67cbSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100b9bb67cbSmrgIn the 4th, create DIRECTORIES.
1011cc8c64fSmrg
102b9bb67cbSmrgOptions:
103b9bb67cbSmrg     --help     display this help and exit.
104b9bb67cbSmrg     --version  display version info and exit.
1051cc8c64fSmrg
106b9bb67cbSmrg  -c            (ignored)
10718eba588Smrg  -C            install only if different (preserve data modification time)
108b9bb67cbSmrg  -d            create directories instead of installing files.
109b9bb67cbSmrg  -g GROUP      $chgrpprog installed files to GROUP.
110b9bb67cbSmrg  -m MODE       $chmodprog installed files to MODE.
111b9bb67cbSmrg  -o USER       $chownprog installed files to USER.
11218eba588Smrg  -p            pass -p to $cpprog.
113b9bb67cbSmrg  -s            $stripprog installed files.
11418eba588Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115b9bb67cbSmrg  -t DIRECTORY  install into DIRECTORY.
116b9bb67cbSmrg  -T            report an error if DSTFILE is a directory.
1171cc8c64fSmrg
118b9bb67cbSmrgEnvironment variables override the default commands:
119b9bb67cbSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120b9bb67cbSmrg  RMPROG STRIPPROG
12118eba588Smrg
12218eba588SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12318eba588Smrgit's up to you to specify -f if you want it.
12418eba588Smrg
12518eba588SmrgIf -S is not specified, no backups are attempted.
12618eba588Smrg
12718eba588SmrgEmail bug reports to bug-automake@gnu.org.
12818eba588SmrgAutomake home page: https://www.gnu.org/software/automake/
129b9bb67cbSmrg"
1301cc8c64fSmrg
131b9bb67cbSmrgwhile test $# -ne 0; do
132b9bb67cbSmrg  case $1 in
133b9bb67cbSmrg    -c) ;;
1341cc8c64fSmrg
135b9bb67cbSmrg    -C) copy_on_change=true;;
1361cc8c64fSmrg
137b9bb67cbSmrg    -d) dir_arg=true;;
1381cc8c64fSmrg
139b9bb67cbSmrg    -g) chgrpcmd="$chgrpprog $2"
14018eba588Smrg        shift;;
1411cc8c64fSmrg
142b9bb67cbSmrg    --help) echo "$usage"; exit $?;;
1431cc8c64fSmrg
144b9bb67cbSmrg    -m) mode=$2
14518eba588Smrg        case $mode in
14618eba588Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14718eba588Smrg            echo "$0: invalid mode: $mode" >&2
14818eba588Smrg            exit 1;;
14918eba588Smrg        esac
15018eba588Smrg        shift;;
1511cc8c64fSmrg
152b9bb67cbSmrg    -o) chowncmd="$chownprog $2"
15318eba588Smrg        shift;;
15418eba588Smrg
15518eba588Smrg    -p) cpprog="$cpprog -p";;
1561cc8c64fSmrg
157b9bb67cbSmrg    -s) stripcmd=$stripprog;;
1581cc8c64fSmrg
15918eba588Smrg    -S) backupsuffix="$2"
16018eba588Smrg        shift;;
16118eba588Smrg
16218eba588Smrg    -t)
16318eba588Smrg        is_target_a_directory=always
16418eba588Smrg        dst_arg=$2
16518eba588Smrg        # Protect names problematic for 'test' and other utilities.
16618eba588Smrg        case $dst_arg in
16718eba588Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16818eba588Smrg        esac
16918eba588Smrg        shift;;
1701cc8c64fSmrg
17118eba588Smrg    -T) is_target_a_directory=never;;
1721cc8c64fSmrg
173b9bb67cbSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1741cc8c64fSmrg
17518eba588Smrg    --) shift
17618eba588Smrg        break;;
1771cc8c64fSmrg
17818eba588Smrg    -*) echo "$0: invalid option: $1" >&2
17918eba588Smrg        exit 1;;
1801cc8c64fSmrg
181b9bb67cbSmrg    *)  break;;
182b9bb67cbSmrg  esac
183b9bb67cbSmrg  shift
184b9bb67cbSmrgdone
1851cc8c64fSmrg
18618eba588Smrg# We allow the use of options -d and -T together, by making -d
18718eba588Smrg# take the precedence; this is for compatibility with GNU install.
18818eba588Smrg
18918eba588Smrgif test -n "$dir_arg"; then
19018eba588Smrg  if test -n "$dst_arg"; then
19118eba588Smrg    echo "$0: target directory not allowed when installing a directory." >&2
19218eba588Smrg    exit 1
19318eba588Smrg  fi
19418eba588Smrgfi
19518eba588Smrg
196b9bb67cbSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197b9bb67cbSmrg  # When -d is used, all remaining arguments are directories to create.
198b9bb67cbSmrg  # When -t is used, the destination is already specified.
199b9bb67cbSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200b9bb67cbSmrg  for arg
201b9bb67cbSmrg  do
202b9bb67cbSmrg    if test -n "$dst_arg"; then
203b9bb67cbSmrg      # $@ is not empty: it contains at least $arg.
204b9bb67cbSmrg      set fnord "$@" "$dst_arg"
205b9bb67cbSmrg      shift # fnord
206b9bb67cbSmrg    fi
207b9bb67cbSmrg    shift # arg
208b9bb67cbSmrg    dst_arg=$arg
20918eba588Smrg    # Protect names problematic for 'test' and other utilities.
21018eba588Smrg    case $dst_arg in
21118eba588Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21218eba588Smrg    esac
213b9bb67cbSmrg  done
214b9bb67cbSmrgfi
2151cc8c64fSmrg
216b9bb67cbSmrgif test $# -eq 0; then
217b9bb67cbSmrg  if test -z "$dir_arg"; then
218b9bb67cbSmrg    echo "$0: no input file specified." >&2
219b9bb67cbSmrg    exit 1
220b9bb67cbSmrg  fi
22118eba588Smrg  # It's OK to call 'install-sh -d' without argument.
222b9bb67cbSmrg  # This can happen when creating conditional directories.
223b9bb67cbSmrg  exit 0
224b9bb67cbSmrgfi
2251cc8c64fSmrg
226b9bb67cbSmrgif test -z "$dir_arg"; then
22718eba588Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22818eba588Smrg    if test ! -d "$dst_arg"; then
22918eba588Smrg      echo "$0: $dst_arg: Is not a directory." >&2
23018eba588Smrg      exit 1
23118eba588Smrg    fi
23218eba588Smrg  fi
23318eba588Smrgfi
23418eba588Smrg
23518eba588Smrgif test -z "$dir_arg"; then
23618eba588Smrg  do_exit='(exit $ret); exit $ret'
23718eba588Smrg  trap "ret=129; $do_exit" 1
23818eba588Smrg  trap "ret=130; $do_exit" 2
23918eba588Smrg  trap "ret=141; $do_exit" 13
24018eba588Smrg  trap "ret=143; $do_exit" 15
241b9bb67cbSmrg
242b9bb67cbSmrg  # Set umask so as not to create temps with too-generous modes.
243b9bb67cbSmrg  # However, 'strip' requires both read and write access to temps.
244b9bb67cbSmrg  case $mode in
245b9bb67cbSmrg    # Optimize common cases.
246b9bb67cbSmrg    *644) cp_umask=133;;
247b9bb67cbSmrg    *755) cp_umask=22;;
248b9bb67cbSmrg
249b9bb67cbSmrg    *[0-7])
250b9bb67cbSmrg      if test -z "$stripcmd"; then
25118eba588Smrg        u_plus_rw=
252b9bb67cbSmrg      else
25318eba588Smrg        u_plus_rw='% 200'
254b9bb67cbSmrg      fi
255b9bb67cbSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256b9bb67cbSmrg    *)
257b9bb67cbSmrg      if test -z "$stripcmd"; then
25818eba588Smrg        u_plus_rw=
259b9bb67cbSmrg      else
26018eba588Smrg        u_plus_rw=,u+rw
261b9bb67cbSmrg      fi
262b9bb67cbSmrg      cp_umask=$mode$u_plus_rw;;
263b9bb67cbSmrg  esac
264b9bb67cbSmrgfi
2651cc8c64fSmrg
266b9bb67cbSmrgfor src
267b9bb67cbSmrgdo
26818eba588Smrg  # Protect names problematic for 'test' and other utilities.
269b9bb67cbSmrg  case $src in
27018eba588Smrg    -* | [=\(\)!]) src=./$src;;
271b9bb67cbSmrg  esac
272b9bb67cbSmrg
273b9bb67cbSmrg  if test -n "$dir_arg"; then
274b9bb67cbSmrg    dst=$src
275b9bb67cbSmrg    dstdir=$dst
276b9bb67cbSmrg    test -d "$dstdir"
277b9bb67cbSmrg    dstdir_status=$?
27818eba588Smrg    # Don't chown directories that already exist.
27918eba588Smrg    if test $dstdir_status = 0; then
28018eba588Smrg      chowncmd=""
28118eba588Smrg    fi
282b9bb67cbSmrg  else
283b9bb67cbSmrg
284b9bb67cbSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285b9bb67cbSmrg    # might cause directories to be created, which would be especially bad
286b9bb67cbSmrg    # if $src (and thus $dsttmp) contains '*'.
287b9bb67cbSmrg    if test ! -f "$src" && test ! -d "$src"; then
288b9bb67cbSmrg      echo "$0: $src does not exist." >&2
289b9bb67cbSmrg      exit 1
290b9bb67cbSmrg    fi
291b9bb67cbSmrg
292b9bb67cbSmrg    if test -z "$dst_arg"; then
293b9bb67cbSmrg      echo "$0: no destination specified." >&2
294b9bb67cbSmrg      exit 1
295b9bb67cbSmrg    fi
296b9bb67cbSmrg    dst=$dst_arg
2971cc8c64fSmrg
29818eba588Smrg    # If destination is a directory, append the input filename.
299b9bb67cbSmrg    if test -d "$dst"; then
30018eba588Smrg      if test "$is_target_a_directory" = never; then
30118eba588Smrg        echo "$0: $dst_arg: Is a directory" >&2
30218eba588Smrg        exit 1
303b9bb67cbSmrg      fi
304b9bb67cbSmrg      dstdir=$dst
30518eba588Smrg      dstbase=`basename "$src"`
30618eba588Smrg      case $dst in
30718eba588Smrg	*/) dst=$dst$dstbase;;
30818eba588Smrg	*)  dst=$dst/$dstbase;;
30918eba588Smrg      esac
310b9bb67cbSmrg      dstdir_status=0
311b9bb67cbSmrg    else
31218eba588Smrg      dstdir=`dirname "$dst"`
313b9bb67cbSmrg      test -d "$dstdir"
314b9bb67cbSmrg      dstdir_status=$?
315b9bb67cbSmrg    fi
316b9bb67cbSmrg  fi
317b9bb67cbSmrg
31818eba588Smrg  case $dstdir in
31918eba588Smrg    */) dstdirslash=$dstdir;;
32018eba588Smrg    *)  dstdirslash=$dstdir/;;
32118eba588Smrg  esac
32218eba588Smrg
323b9bb67cbSmrg  obsolete_mkdir_used=false
324b9bb67cbSmrg
325b9bb67cbSmrg  if test $dstdir_status != 0; then
326b9bb67cbSmrg    case $posix_mkdir in
327b9bb67cbSmrg      '')
32818eba588Smrg        # With -d, create the new directory with the user-specified mode.
32918eba588Smrg        # Otherwise, rely on $mkdir_umask.
33018eba588Smrg        if test -n "$dir_arg"; then
33118eba588Smrg          mkdir_mode=-m$mode
33218eba588Smrg        else
33318eba588Smrg          mkdir_mode=
33418eba588Smrg        fi
33518eba588Smrg
33618eba588Smrg        posix_mkdir=false
33718eba588Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33818eba588Smrg	# here however when possible just to lower collision chance.
33918eba588Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34018eba588Smrg
34118eba588Smrg	trap '
34218eba588Smrg	  ret=$?
34318eba588Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34418eba588Smrg	  exit $ret
34518eba588Smrg	' 0
34618eba588Smrg
34718eba588Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
34818eba588Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
34918eba588Smrg	# directory is successfully created first before we actually test
35018eba588Smrg	# 'mkdir -p'.
35118eba588Smrg	if (umask $mkdir_umask &&
35218eba588Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35318eba588Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35418eba588Smrg	then
35518eba588Smrg	  if test -z "$dir_arg" || {
35618eba588Smrg	       # Check for POSIX incompatibilities with -m.
35718eba588Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35818eba588Smrg	       # other-writable bit of parent directory when it shouldn't.
35918eba588Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36018eba588Smrg	       test_tmpdir="$tmpdir/a"
36118eba588Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36218eba588Smrg	       case $ls_ld_tmpdir in
36318eba588Smrg		 d????-?r-*) different_mode=700;;
36418eba588Smrg		 d????-?--*) different_mode=755;;
36518eba588Smrg		 *) false;;
36618eba588Smrg	       esac &&
36718eba588Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36818eba588Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36918eba588Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37018eba588Smrg	       }
37118eba588Smrg	     }
37218eba588Smrg	  then posix_mkdir=:
37318eba588Smrg	  fi
37418eba588Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3751cc8c64fSmrg	else
37618eba588Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
37718eba588Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3781cc8c64fSmrg	fi
37918eba588Smrg	trap '' 0;;
380b9bb67cbSmrg    esac
3811cc8c64fSmrg
382b9bb67cbSmrg    if
383b9bb67cbSmrg      $posix_mkdir && (
38418eba588Smrg        umask $mkdir_umask &&
38518eba588Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386b9bb67cbSmrg      )
387b9bb67cbSmrg    then :
388b9bb67cbSmrg    else
389b9bb67cbSmrg
39018eba588Smrg      # mkdir does not conform to POSIX,
391b9bb67cbSmrg      # or it failed possibly due to a race condition.  Create the
392b9bb67cbSmrg      # directory the slow way, step by step, checking for races as we go.
393b9bb67cbSmrg
394b9bb67cbSmrg      case $dstdir in
39518eba588Smrg        /*) prefix='/';;
39618eba588Smrg        [-=\(\)!]*) prefix='./';;
39718eba588Smrg        *)  prefix='';;
398b9bb67cbSmrg      esac
399b9bb67cbSmrg
400b9bb67cbSmrg      oIFS=$IFS
401b9bb67cbSmrg      IFS=/
40218eba588Smrg      set -f
403b9bb67cbSmrg      set fnord $dstdir
404b9bb67cbSmrg      shift
40518eba588Smrg      set +f
406b9bb67cbSmrg      IFS=$oIFS
407b9bb67cbSmrg
408b9bb67cbSmrg      prefixes=
409b9bb67cbSmrg
410b9bb67cbSmrg      for d
411b9bb67cbSmrg      do
41218eba588Smrg        test X"$d" = X && continue
41318eba588Smrg
41418eba588Smrg        prefix=$prefix$d
41518eba588Smrg        if test -d "$prefix"; then
41618eba588Smrg          prefixes=
41718eba588Smrg        else
41818eba588Smrg          if $posix_mkdir; then
41918eba588Smrg            (umask $mkdir_umask &&
42018eba588Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42118eba588Smrg            # Don't fail if two instances are running concurrently.
42218eba588Smrg            test -d "$prefix" || exit 1
42318eba588Smrg          else
42418eba588Smrg            case $prefix in
42518eba588Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42618eba588Smrg              *) qprefix=$prefix;;
42718eba588Smrg            esac
42818eba588Smrg            prefixes="$prefixes '$qprefix'"
42918eba588Smrg          fi
43018eba588Smrg        fi
43118eba588Smrg        prefix=$prefix/
432b9bb67cbSmrg      done
433b9bb67cbSmrg
434b9bb67cbSmrg      if test -n "$prefixes"; then
43518eba588Smrg        # Don't fail if two instances are running concurrently.
43618eba588Smrg        (umask $mkdir_umask &&
43718eba588Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43818eba588Smrg          test -d "$dstdir" || exit 1
43918eba588Smrg        obsolete_mkdir_used=true
440b9bb67cbSmrg      fi
441b9bb67cbSmrg    fi
442b9bb67cbSmrg  fi
443b9bb67cbSmrg
444b9bb67cbSmrg  if test -n "$dir_arg"; then
445b9bb67cbSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446b9bb67cbSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447b9bb67cbSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448b9bb67cbSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449b9bb67cbSmrg  else
450b9bb67cbSmrg
451b9bb67cbSmrg    # Make a couple of temp file names in the proper directory.
45218eba588Smrg    dsttmp=${dstdirslash}_inst.$$_
45318eba588Smrg    rmtmp=${dstdirslash}_rm.$$_
454b9bb67cbSmrg
455b9bb67cbSmrg    # Trap to clean up those temp files at exit.
456b9bb67cbSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457b9bb67cbSmrg
458b9bb67cbSmrg    # Copy the file name to the temp name.
45918eba588Smrg    (umask $cp_umask &&
46018eba588Smrg     { test -z "$stripcmd" || {
46118eba588Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46218eba588Smrg	 # which would cause strip to fail.
46318eba588Smrg	 if test -z "$doit"; then
46418eba588Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46518eba588Smrg	 else
46618eba588Smrg	   $doit touch "$dsttmp"
46718eba588Smrg	 fi
46818eba588Smrg       }
46918eba588Smrg     } &&
47018eba588Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471b9bb67cbSmrg
472b9bb67cbSmrg    # and set any options; do chmod last to preserve setuid bits.
473b9bb67cbSmrg    #
474b9bb67cbSmrg    # If any of these fail, we abort the whole thing.  If we want to
475b9bb67cbSmrg    # ignore errors from any of these, just make sure not to ignore
476b9bb67cbSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477b9bb67cbSmrg    #
478b9bb67cbSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479b9bb67cbSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480b9bb67cbSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481b9bb67cbSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482b9bb67cbSmrg
483b9bb67cbSmrg    # If -C, don't bother to copy if it wouldn't change the file.
484b9bb67cbSmrg    if $copy_on_change &&
48518eba588Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48618eba588Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48718eba588Smrg       set -f &&
488b9bb67cbSmrg       set X $old && old=:$2:$4:$5:$6 &&
489b9bb67cbSmrg       set X $new && new=:$2:$4:$5:$6 &&
49018eba588Smrg       set +f &&
491b9bb67cbSmrg       test "$old" = "$new" &&
492b9bb67cbSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493b9bb67cbSmrg    then
494b9bb67cbSmrg      rm -f "$dsttmp"
495b9bb67cbSmrg    else
49618eba588Smrg      # If $backupsuffix is set, and the file being installed
49718eba588Smrg      # already exists, attempt a backup.  Don't worry if it fails,
49818eba588Smrg      # e.g., if mv doesn't support -f.
49918eba588Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
50018eba588Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50118eba588Smrg      fi
50218eba588Smrg
503b9bb67cbSmrg      # Rename the file to the real destination.
504b9bb67cbSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505b9bb67cbSmrg
506b9bb67cbSmrg      # The rename failed, perhaps because mv can't rename something else
507b9bb67cbSmrg      # to itself, or perhaps because mv is so ancient that it does not
508b9bb67cbSmrg      # support -f.
509b9bb67cbSmrg      {
51018eba588Smrg        # Now remove or move aside any old file at destination location.
51118eba588Smrg        # We try this two ways since rm can't unlink itself on some
51218eba588Smrg        # systems and the destination file might be busy for other
51318eba588Smrg        # reasons.  In this case, the final cleanup might fail but the new
51418eba588Smrg        # file should still install successfully.
51518eba588Smrg        {
51618eba588Smrg          test ! -f "$dst" ||
51718eba588Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
51818eba588Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51918eba588Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52018eba588Smrg          } ||
52118eba588Smrg          { echo "$0: cannot unlink or rename $dst" >&2
52218eba588Smrg            (exit 1); exit 1
52318eba588Smrg          }
52418eba588Smrg        } &&
52518eba588Smrg
52618eba588Smrg        # Now rename the file to the real destination.
52718eba588Smrg        $doit $mvcmd "$dsttmp" "$dst"
528b9bb67cbSmrg      }
529b9bb67cbSmrg    fi || exit 1
530b9bb67cbSmrg
531b9bb67cbSmrg    trap '' 0
532b9bb67cbSmrg  fi
533b9bb67cbSmrgdone
5341cc8c64fSmrg
535b9bb67cbSmrg# Local variables:
53618eba588Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537b9bb67cbSmrg# time-stamp-start: "scriptversion="
538b9bb67cbSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53918eba588Smrg# time-stamp-time-zone: "UTC0"
540b9bb67cbSmrg# time-stamp-end: "; # UTC"
541b9bb67cbSmrg# End:
542