install-sh revision e5db2183
1bb2e14f3Smrg#!/bin/sh
2bb2e14f3Smrg# install - install a program, script, or datafile
3bb2e14f3Smrg
4e5db2183Smrgscriptversion=2020-11-14.01; # UTC
5bb2e14f3Smrg
6bb2e14f3Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7bb2e14f3Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8bb2e14f3Smrg# following copyright and license.
9bb2e14f3Smrg#
10bb2e14f3Smrg# Copyright (C) 1994 X Consortium
11bb2e14f3Smrg#
12bb2e14f3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13bb2e14f3Smrg# of this software and associated documentation files (the "Software"), to
14bb2e14f3Smrg# deal in the Software without restriction, including without limitation the
15bb2e14f3Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16bb2e14f3Smrg# sell copies of the Software, and to permit persons to whom the Software is
17bb2e14f3Smrg# furnished to do so, subject to the following conditions:
18bb2e14f3Smrg#
19bb2e14f3Smrg# The above copyright notice and this permission notice shall be included in
20bb2e14f3Smrg# all copies or substantial portions of the Software.
21bb2e14f3Smrg#
22bb2e14f3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23bb2e14f3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24bb2e14f3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25bb2e14f3Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26bb2e14f3Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27bb2e14f3Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28bb2e14f3Smrg#
29bb2e14f3Smrg# Except as contained in this notice, the name of the X Consortium shall not
30bb2e14f3Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31bb2e14f3Smrg# ings in this Software without prior written authorization from the X Consor-
32bb2e14f3Smrg# tium.
33bb2e14f3Smrg#
34bb2e14f3Smrg#
35bb2e14f3Smrg# FSF changes to this file are in the public domain.
36bb2e14f3Smrg#
37bb2e14f3Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3839f9c979Smrg# 'make' implicit rules from creating a file called install from it
39bb2e14f3Smrg# when there is no Makefile.
40bb2e14f3Smrg#
41bb2e14f3Smrg# This script is compatible with the BSD install script, but was written
42a5399cb1Smrg# from scratch.
43a5399cb1Smrg
448a954913Smrgtab='	'
45a5399cb1Smrgnl='
46a5399cb1Smrg'
478a954913SmrgIFS=" $tab$nl"
48bb2e14f3Smrg
498a954913Smrg# Set DOITPROG to "echo" to test this script.
50bb2e14f3Smrg
51a5399cb1Smrgdoit=${DOITPROG-}
528a954913Smrgdoit_exec=${doit:-exec}
53bb2e14f3Smrg
54a5399cb1Smrg# Put in absolute file names if you don't have them in your path;
55a5399cb1Smrg# or use environment vars.
56a5399cb1Smrg
57a5399cb1Smrgchgrpprog=${CHGRPPROG-chgrp}
58a5399cb1Smrgchmodprog=${CHMODPROG-chmod}
59a5399cb1Smrgchownprog=${CHOWNPROG-chown}
60a5399cb1Smrgcmpprog=${CMPPROG-cmp}
61a5399cb1Smrgcpprog=${CPPROG-cp}
62a5399cb1Smrgmkdirprog=${MKDIRPROG-mkdir}
63a5399cb1Smrgmvprog=${MVPROG-mv}
64a5399cb1Smrgrmprog=${RMPROG-rm}
65a5399cb1Smrgstripprog=${STRIPPROG-strip}
66a5399cb1Smrg
67a5399cb1Smrgposix_mkdir=
68a5399cb1Smrg
69a5399cb1Smrg# Desired mode of installed file.
70a5399cb1Smrgmode=0755
71bb2e14f3Smrg
72e5db2183Smrg# Create dirs (including intermediate dirs) using mode 755.
73e5db2183Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
74e5db2183Smrgmkdir_umask=22
75e5db2183Smrg
76e5db2183Smrgbackupsuffix=
77bb2e14f3Smrgchgrpcmd=
78a5399cb1Smrgchmodcmd=$chmodprog
79a5399cb1Smrgchowncmd=
80a5399cb1Smrgmvcmd=$mvprog
81bb2e14f3Smrgrmcmd="$rmprog -f"
82a5399cb1Smrgstripcmd=
83a5399cb1Smrg
84bb2e14f3Smrgsrc=
85bb2e14f3Smrgdst=
86bb2e14f3Smrgdir_arg=
87a5399cb1Smrgdst_arg=
88a5399cb1Smrg
89a5399cb1Smrgcopy_on_change=false
908a954913Smrgis_target_a_directory=possibly
91bb2e14f3Smrg
92a5399cb1Smrgusage="\
93a5399cb1SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94bb2e14f3Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95bb2e14f3Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96bb2e14f3Smrg   or: $0 [OPTION]... -d DIRECTORIES...
97bb2e14f3Smrg
98bb2e14f3SmrgIn the 1st form, copy SRCFILE to DSTFILE.
99bb2e14f3SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100bb2e14f3SmrgIn the 4th, create DIRECTORIES.
101bb2e14f3Smrg
102bb2e14f3SmrgOptions:
103a5399cb1Smrg     --help     display this help and exit.
104a5399cb1Smrg     --version  display version info and exit.
105a5399cb1Smrg
106a5399cb1Smrg  -c            (ignored)
107e5db2183Smrg  -C            install only if different (preserve data modification time)
108a5399cb1Smrg  -d            create directories instead of installing files.
109a5399cb1Smrg  -g GROUP      $chgrpprog installed files to GROUP.
110a5399cb1Smrg  -m MODE       $chmodprog installed files to MODE.
111a5399cb1Smrg  -o USER       $chownprog installed files to USER.
112e5db2183Smrg  -p            pass -p to $cpprog.
113a5399cb1Smrg  -s            $stripprog installed files.
114e5db2183Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115a5399cb1Smrg  -t DIRECTORY  install into DIRECTORY.
116a5399cb1Smrg  -T            report an error if DSTFILE is a directory.
117bb2e14f3Smrg
118bb2e14f3SmrgEnvironment variables override the default commands:
119a5399cb1Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120a5399cb1Smrg  RMPROG STRIPPROG
121e5db2183Smrg
122e5db2183SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
123e5db2183Smrgit's up to you to specify -f if you want it.
124e5db2183Smrg
125e5db2183SmrgIf -S is not specified, no backups are attempted.
126e5db2183Smrg
127e5db2183SmrgEmail bug reports to bug-automake@gnu.org.
128e5db2183SmrgAutomake home page: https://www.gnu.org/software/automake/
129bb2e14f3Smrg"
130bb2e14f3Smrg
131a5399cb1Smrgwhile test $# -ne 0; do
132bb2e14f3Smrg  case $1 in
133a5399cb1Smrg    -c) ;;
134a5399cb1Smrg
135a5399cb1Smrg    -C) copy_on_change=true;;
136bb2e14f3Smrg
137a5399cb1Smrg    -d) dir_arg=true;;
138bb2e14f3Smrg
139bb2e14f3Smrg    -g) chgrpcmd="$chgrpprog $2"
1408a954913Smrg        shift;;
141bb2e14f3Smrg
142bb2e14f3Smrg    --help) echo "$usage"; exit $?;;
143bb2e14f3Smrg
144a5399cb1Smrg    -m) mode=$2
1458a954913Smrg        case $mode in
1468a954913Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1478a954913Smrg            echo "$0: invalid mode: $mode" >&2
1488a954913Smrg            exit 1;;
1498a954913Smrg        esac
1508a954913Smrg        shift;;
151bb2e14f3Smrg
152bb2e14f3Smrg    -o) chowncmd="$chownprog $2"
1538a954913Smrg        shift;;
154bb2e14f3Smrg
155e5db2183Smrg    -p) cpprog="$cpprog -p";;
156e5db2183Smrg
157a5399cb1Smrg    -s) stripcmd=$stripprog;;
158bb2e14f3Smrg
159e5db2183Smrg    -S) backupsuffix="$2"
160e5db2183Smrg        shift;;
161e5db2183Smrg
1628a954913Smrg    -t)
1638a954913Smrg        is_target_a_directory=always
1648a954913Smrg        dst_arg=$2
1658a954913Smrg        # Protect names problematic for 'test' and other utilities.
1668a954913Smrg        case $dst_arg in
1678a954913Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1688a954913Smrg        esac
1698a954913Smrg        shift;;
170bb2e14f3Smrg
1718a954913Smrg    -T) is_target_a_directory=never;;
172bb2e14f3Smrg
173bb2e14f3Smrg    --version) echo "$0 $scriptversion"; exit $?;;
174bb2e14f3Smrg
1758a954913Smrg    --) shift
1768a954913Smrg        break;;
177a5399cb1Smrg
1788a954913Smrg    -*) echo "$0: invalid option: $1" >&2
1798a954913Smrg        exit 1;;
180a5399cb1Smrg
181a5399cb1Smrg    *)  break;;
182bb2e14f3Smrg  esac
183a5399cb1Smrg  shift
184bb2e14f3Smrgdone
185bb2e14f3Smrg
1868a954913Smrg# We allow the use of options -d and -T together, by making -d
1878a954913Smrg# take the precedence; this is for compatibility with GNU install.
1888a954913Smrg
1898a954913Smrgif test -n "$dir_arg"; then
1908a954913Smrg  if test -n "$dst_arg"; then
1918a954913Smrg    echo "$0: target directory not allowed when installing a directory." >&2
1928a954913Smrg    exit 1
1938a954913Smrg  fi
1948a954913Smrgfi
1958a954913Smrg
196a5399cb1Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197a5399cb1Smrg  # When -d is used, all remaining arguments are directories to create.
198a5399cb1Smrg  # When -t is used, the destination is already specified.
199a5399cb1Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200a5399cb1Smrg  for arg
201a5399cb1Smrg  do
202a5399cb1Smrg    if test -n "$dst_arg"; then
203a5399cb1Smrg      # $@ is not empty: it contains at least $arg.
204a5399cb1Smrg      set fnord "$@" "$dst_arg"
205a5399cb1Smrg      shift # fnord
206a5399cb1Smrg    fi
207a5399cb1Smrg    shift # arg
208a5399cb1Smrg    dst_arg=$arg
20939f9c979Smrg    # Protect names problematic for 'test' and other utilities.
21039f9c979Smrg    case $dst_arg in
21139f9c979Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21239f9c979Smrg    esac
213a5399cb1Smrg  done
214a5399cb1Smrgfi
215a5399cb1Smrg
216a5399cb1Smrgif test $# -eq 0; then
217bb2e14f3Smrg  if test -z "$dir_arg"; then
218bb2e14f3Smrg    echo "$0: no input file specified." >&2
219bb2e14f3Smrg    exit 1
220bb2e14f3Smrg  fi
22139f9c979Smrg  # It's OK to call 'install-sh -d' without argument.
222bb2e14f3Smrg  # This can happen when creating conditional directories.
223bb2e14f3Smrg  exit 0
224bb2e14f3Smrgfi
225bb2e14f3Smrg
2268a954913Smrgif test -z "$dir_arg"; then
2278a954913Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2288a954913Smrg    if test ! -d "$dst_arg"; then
2298a954913Smrg      echo "$0: $dst_arg: Is not a directory." >&2
2308a954913Smrg      exit 1
2318a954913Smrg    fi
2328a954913Smrg  fi
2338a954913Smrgfi
2348a954913Smrg
235a5399cb1Smrgif test -z "$dir_arg"; then
23639f9c979Smrg  do_exit='(exit $ret); exit $ret'
23739f9c979Smrg  trap "ret=129; $do_exit" 1
23839f9c979Smrg  trap "ret=130; $do_exit" 2
23939f9c979Smrg  trap "ret=141; $do_exit" 13
24039f9c979Smrg  trap "ret=143; $do_exit" 15
241a5399cb1Smrg
242a5399cb1Smrg  # Set umask so as not to create temps with too-generous modes.
243a5399cb1Smrg  # However, 'strip' requires both read and write access to temps.
244a5399cb1Smrg  case $mode in
245a5399cb1Smrg    # Optimize common cases.
246a5399cb1Smrg    *644) cp_umask=133;;
247a5399cb1Smrg    *755) cp_umask=22;;
248a5399cb1Smrg
249a5399cb1Smrg    *[0-7])
250a5399cb1Smrg      if test -z "$stripcmd"; then
2518a954913Smrg        u_plus_rw=
252a5399cb1Smrg      else
2538a954913Smrg        u_plus_rw='% 200'
254a5399cb1Smrg      fi
255a5399cb1Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256a5399cb1Smrg    *)
257a5399cb1Smrg      if test -z "$stripcmd"; then
2588a954913Smrg        u_plus_rw=
259a5399cb1Smrg      else
2608a954913Smrg        u_plus_rw=,u+rw
261a5399cb1Smrg      fi
262a5399cb1Smrg      cp_umask=$mode$u_plus_rw;;
263a5399cb1Smrg  esac
264a5399cb1Smrgfi
265a5399cb1Smrg
266bb2e14f3Smrgfor src
267bb2e14f3Smrgdo
26839f9c979Smrg  # Protect names problematic for 'test' and other utilities.
269bb2e14f3Smrg  case $src in
27039f9c979Smrg    -* | [=\(\)!]) src=./$src;;
271bb2e14f3Smrg  esac
272bb2e14f3Smrg
273bb2e14f3Smrg  if test -n "$dir_arg"; then
274bb2e14f3Smrg    dst=$src
275a5399cb1Smrg    dstdir=$dst
276a5399cb1Smrg    test -d "$dstdir"
277a5399cb1Smrg    dstdir_status=$?
278e5db2183Smrg    # Don't chown directories that already exist.
279e5db2183Smrg    if test $dstdir_status = 0; then
280e5db2183Smrg      chowncmd=""
281e5db2183Smrg    fi
282bb2e14f3Smrg  else
283a5399cb1Smrg
284bb2e14f3Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285bb2e14f3Smrg    # might cause directories to be created, which would be especially bad
286bb2e14f3Smrg    # if $src (and thus $dsttmp) contains '*'.
287bb2e14f3Smrg    if test ! -f "$src" && test ! -d "$src"; then
288bb2e14f3Smrg      echo "$0: $src does not exist." >&2
289bb2e14f3Smrg      exit 1
290bb2e14f3Smrg    fi
291bb2e14f3Smrg
292a5399cb1Smrg    if test -z "$dst_arg"; then
293bb2e14f3Smrg      echo "$0: no destination specified." >&2
294bb2e14f3Smrg      exit 1
295bb2e14f3Smrg    fi
296a5399cb1Smrg    dst=$dst_arg
297bb2e14f3Smrg
298e5db2183Smrg    # If destination is a directory, append the input filename.
299bb2e14f3Smrg    if test -d "$dst"; then
3008a954913Smrg      if test "$is_target_a_directory" = never; then
3018a954913Smrg        echo "$0: $dst_arg: Is a directory" >&2
3028a954913Smrg        exit 1
303bb2e14f3Smrg      fi
304a5399cb1Smrg      dstdir=$dst
305e5db2183Smrg      dstbase=`basename "$src"`
306e5db2183Smrg      case $dst in
307e5db2183Smrg	*/) dst=$dst$dstbase;;
308e5db2183Smrg	*)  dst=$dst/$dstbase;;
309e5db2183Smrg      esac
310a5399cb1Smrg      dstdir_status=0
311a5399cb1Smrg    else
3128a954913Smrg      dstdir=`dirname "$dst"`
313a5399cb1Smrg      test -d "$dstdir"
314a5399cb1Smrg      dstdir_status=$?
315bb2e14f3Smrg    fi
316bb2e14f3Smrg  fi
317bb2e14f3Smrg
318e5db2183Smrg  case $dstdir in
319e5db2183Smrg    */) dstdirslash=$dstdir;;
320e5db2183Smrg    *)  dstdirslash=$dstdir/;;
321e5db2183Smrg  esac
322e5db2183Smrg
323a5399cb1Smrg  obsolete_mkdir_used=false
324a5399cb1Smrg
325a5399cb1Smrg  if test $dstdir_status != 0; then
326a5399cb1Smrg    case $posix_mkdir in
327a5399cb1Smrg      '')
3288a954913Smrg        # With -d, create the new directory with the user-specified mode.
3298a954913Smrg        # Otherwise, rely on $mkdir_umask.
3308a954913Smrg        if test -n "$dir_arg"; then
3318a954913Smrg          mkdir_mode=-m$mode
3328a954913Smrg        else
3338a954913Smrg          mkdir_mode=
3348a954913Smrg        fi
3358a954913Smrg
3368a954913Smrg        posix_mkdir=false
337e5db2183Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
338e5db2183Smrg	# here however when possible just to lower collision chance.
339e5db2183Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340e5db2183Smrg
341e5db2183Smrg	trap '
342e5db2183Smrg	  ret=$?
343e5db2183Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344e5db2183Smrg	  exit $ret
345e5db2183Smrg	' 0
346e5db2183Smrg
347e5db2183Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
348e5db2183Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
349e5db2183Smrg	# directory is successfully created first before we actually test
350e5db2183Smrg	# 'mkdir -p'.
351e5db2183Smrg	if (umask $mkdir_umask &&
352e5db2183Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
353e5db2183Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354e5db2183Smrg	then
355e5db2183Smrg	  if test -z "$dir_arg" || {
356e5db2183Smrg	       # Check for POSIX incompatibilities with -m.
357e5db2183Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358e5db2183Smrg	       # other-writable bit of parent directory when it shouldn't.
359e5db2183Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360e5db2183Smrg	       test_tmpdir="$tmpdir/a"
361e5db2183Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362e5db2183Smrg	       case $ls_ld_tmpdir in
363e5db2183Smrg		 d????-?r-*) different_mode=700;;
364e5db2183Smrg		 d????-?--*) different_mode=755;;
365e5db2183Smrg		 *) false;;
366e5db2183Smrg	       esac &&
367e5db2183Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368e5db2183Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369e5db2183Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370e5db2183Smrg	       }
371e5db2183Smrg	     }
372e5db2183Smrg	  then posix_mkdir=:
373e5db2183Smrg	  fi
374e5db2183Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375e5db2183Smrg	else
376e5db2183Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
377e5db2183Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378e5db2183Smrg	fi
379e5db2183Smrg	trap '' 0;;
380a5399cb1Smrg    esac
381bb2e14f3Smrg
382a5399cb1Smrg    if
383a5399cb1Smrg      $posix_mkdir && (
3848a954913Smrg        umask $mkdir_umask &&
3858a954913Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386a5399cb1Smrg      )
387a5399cb1Smrg    then :
388a5399cb1Smrg    else
389bb2e14f3Smrg
390e5db2183Smrg      # mkdir does not conform to POSIX,
391a5399cb1Smrg      # or it failed possibly due to a race condition.  Create the
392a5399cb1Smrg      # directory the slow way, step by step, checking for races as we go.
393bb2e14f3Smrg
394a5399cb1Smrg      case $dstdir in
3958a954913Smrg        /*) prefix='/';;
3968a954913Smrg        [-=\(\)!]*) prefix='./';;
3978a954913Smrg        *)  prefix='';;
398a5399cb1Smrg      esac
399bb2e14f3Smrg
400a5399cb1Smrg      oIFS=$IFS
401a5399cb1Smrg      IFS=/
4028a954913Smrg      set -f
403a5399cb1Smrg      set fnord $dstdir
404bb2e14f3Smrg      shift
4058a954913Smrg      set +f
406a5399cb1Smrg      IFS=$oIFS
407a5399cb1Smrg
408a5399cb1Smrg      prefixes=
409a5399cb1Smrg
410a5399cb1Smrg      for d
411a5399cb1Smrg      do
4128a954913Smrg        test X"$d" = X && continue
4138a954913Smrg
4148a954913Smrg        prefix=$prefix$d
4158a954913Smrg        if test -d "$prefix"; then
4168a954913Smrg          prefixes=
4178a954913Smrg        else
4188a954913Smrg          if $posix_mkdir; then
419e5db2183Smrg            (umask $mkdir_umask &&
4208a954913Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4218a954913Smrg            # Don't fail if two instances are running concurrently.
4228a954913Smrg            test -d "$prefix" || exit 1
4238a954913Smrg          else
4248a954913Smrg            case $prefix in
4258a954913Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4268a954913Smrg              *) qprefix=$prefix;;
4278a954913Smrg            esac
4288a954913Smrg            prefixes="$prefixes '$qprefix'"
4298a954913Smrg          fi
4308a954913Smrg        fi
4318a954913Smrg        prefix=$prefix/
432a5399cb1Smrg      done
433a5399cb1Smrg
434a5399cb1Smrg      if test -n "$prefixes"; then
4358a954913Smrg        # Don't fail if two instances are running concurrently.
4368a954913Smrg        (umask $mkdir_umask &&
4378a954913Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4388a954913Smrg          test -d "$dstdir" || exit 1
4398a954913Smrg        obsolete_mkdir_used=true
440bb2e14f3Smrg      fi
441a5399cb1Smrg    fi
442bb2e14f3Smrg  fi
443bb2e14f3Smrg
444bb2e14f3Smrg  if test -n "$dir_arg"; then
445a5399cb1Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446a5399cb1Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447a5399cb1Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448a5399cb1Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449bb2e14f3Smrg  else
450bb2e14f3Smrg
451bb2e14f3Smrg    # Make a couple of temp file names in the proper directory.
452e5db2183Smrg    dsttmp=${dstdirslash}_inst.$$_
453e5db2183Smrg    rmtmp=${dstdirslash}_rm.$$_
454bb2e14f3Smrg
455bb2e14f3Smrg    # Trap to clean up those temp files at exit.
456bb2e14f3Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457bb2e14f3Smrg
458bb2e14f3Smrg    # Copy the file name to the temp name.
459e5db2183Smrg    (umask $cp_umask &&
460e5db2183Smrg     { test -z "$stripcmd" || {
461e5db2183Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
462e5db2183Smrg	 # which would cause strip to fail.
463e5db2183Smrg	 if test -z "$doit"; then
464e5db2183Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
465e5db2183Smrg	 else
466e5db2183Smrg	   $doit touch "$dsttmp"
467e5db2183Smrg	 fi
468e5db2183Smrg       }
469e5db2183Smrg     } &&
470e5db2183Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471bb2e14f3Smrg
472bb2e14f3Smrg    # and set any options; do chmod last to preserve setuid bits.
473bb2e14f3Smrg    #
474bb2e14f3Smrg    # If any of these fail, we abort the whole thing.  If we want to
475bb2e14f3Smrg    # ignore errors from any of these, just make sure not to ignore
476bb2e14f3Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477bb2e14f3Smrg    #
478a5399cb1Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479a5399cb1Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480a5399cb1Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481a5399cb1Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482a5399cb1Smrg
483a5399cb1Smrg    # If -C, don't bother to copy if it wouldn't change the file.
484a5399cb1Smrg    if $copy_on_change &&
4858a954913Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4868a954913Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4878a954913Smrg       set -f &&
488a5399cb1Smrg       set X $old && old=:$2:$4:$5:$6 &&
489a5399cb1Smrg       set X $new && new=:$2:$4:$5:$6 &&
4908a954913Smrg       set +f &&
491a5399cb1Smrg       test "$old" = "$new" &&
492a5399cb1Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493a5399cb1Smrg    then
494a5399cb1Smrg      rm -f "$dsttmp"
495a5399cb1Smrg    else
496e5db2183Smrg      # If $backupsuffix is set, and the file being installed
497e5db2183Smrg      # already exists, attempt a backup.  Don't worry if it fails,
498e5db2183Smrg      # e.g., if mv doesn't support -f.
499e5db2183Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
500e5db2183Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501e5db2183Smrg      fi
502e5db2183Smrg
503a5399cb1Smrg      # Rename the file to the real destination.
504a5399cb1Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505a5399cb1Smrg
506a5399cb1Smrg      # The rename failed, perhaps because mv can't rename something else
507a5399cb1Smrg      # to itself, or perhaps because mv is so ancient that it does not
508a5399cb1Smrg      # support -f.
509a5399cb1Smrg      {
5108a954913Smrg        # Now remove or move aside any old file at destination location.
5118a954913Smrg        # We try this two ways since rm can't unlink itself on some
5128a954913Smrg        # systems and the destination file might be busy for other
5138a954913Smrg        # reasons.  In this case, the final cleanup might fail but the new
5148a954913Smrg        # file should still install successfully.
5158a954913Smrg        {
5168a954913Smrg          test ! -f "$dst" ||
517e5db2183Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
5188a954913Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519e5db2183Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
5208a954913Smrg          } ||
5218a954913Smrg          { echo "$0: cannot unlink or rename $dst" >&2
5228a954913Smrg            (exit 1); exit 1
5238a954913Smrg          }
5248a954913Smrg        } &&
5258a954913Smrg
5268a954913Smrg        # Now rename the file to the real destination.
5278a954913Smrg        $doit $mvcmd "$dsttmp" "$dst"
528a5399cb1Smrg      }
529a5399cb1Smrg    fi || exit 1
530a5399cb1Smrg
531a5399cb1Smrg    trap '' 0
532a5399cb1Smrg  fi
533bb2e14f3Smrgdone
534bb2e14f3Smrg
535bb2e14f3Smrg# Local variables:
536e5db2183Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537bb2e14f3Smrg# time-stamp-start: "scriptversion="
538bb2e14f3Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
539e5db2183Smrg# time-stamp-time-zone: "UTC0"
540a5399cb1Smrg# time-stamp-end: "; # UTC"
541bb2e14f3Smrg# End:
542