install-sh revision 0f595aed
1c95b42baSmrg#!/bin/sh
2c95b42baSmrg# install - install a program, script, or datafile
3c95b42baSmrg
40f595aedSmrgscriptversion=2020-11-14.01; # UTC
5c95b42baSmrg
6c95b42baSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7c95b42baSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8c95b42baSmrg# following copyright and license.
9c95b42baSmrg#
10c95b42baSmrg# Copyright (C) 1994 X Consortium
11c95b42baSmrg#
12c95b42baSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13c95b42baSmrg# of this software and associated documentation files (the "Software"), to
14c95b42baSmrg# deal in the Software without restriction, including without limitation the
15c95b42baSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16c95b42baSmrg# sell copies of the Software, and to permit persons to whom the Software is
17c95b42baSmrg# furnished to do so, subject to the following conditions:
18c95b42baSmrg#
19c95b42baSmrg# The above copyright notice and this permission notice shall be included in
20c95b42baSmrg# all copies or substantial portions of the Software.
21c95b42baSmrg#
22c95b42baSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c95b42baSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c95b42baSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25c95b42baSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26c95b42baSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27c95b42baSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28c95b42baSmrg#
29c95b42baSmrg# Except as contained in this notice, the name of the X Consortium shall not
30c95b42baSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31c95b42baSmrg# ings in this Software without prior written authorization from the X Consor-
32c95b42baSmrg# tium.
33c95b42baSmrg#
34c95b42baSmrg#
35c95b42baSmrg# FSF changes to this file are in the public domain.
36c95b42baSmrg#
37c95b42baSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38b8f63ae3Smrg# 'make' implicit rules from creating a file called install from it
39c95b42baSmrg# when there is no Makefile.
40c95b42baSmrg#
41c95b42baSmrg# This script is compatible with the BSD install script, but was written
42f40e0d56Smrg# from scratch.
43f40e0d56Smrg
44b8f63ae3Smrgtab='	'
45f40e0d56Smrgnl='
46f40e0d56Smrg'
47b8f63ae3SmrgIFS=" $tab$nl"
48c95b42baSmrg
49b8f63ae3Smrg# Set DOITPROG to "echo" to test this script.
50c95b42baSmrg
51f40e0d56Smrgdoit=${DOITPROG-}
52b8f63ae3Smrgdoit_exec=${doit:-exec}
53c95b42baSmrg
54f40e0d56Smrg# Put in absolute file names if you don't have them in your path;
55f40e0d56Smrg# or use environment vars.
56f40e0d56Smrg
57f40e0d56Smrgchgrpprog=${CHGRPPROG-chgrp}
58f40e0d56Smrgchmodprog=${CHMODPROG-chmod}
59f40e0d56Smrgchownprog=${CHOWNPROG-chown}
60f40e0d56Smrgcmpprog=${CMPPROG-cmp}
61f40e0d56Smrgcpprog=${CPPROG-cp}
62f40e0d56Smrgmkdirprog=${MKDIRPROG-mkdir}
63f40e0d56Smrgmvprog=${MVPROG-mv}
64f40e0d56Smrgrmprog=${RMPROG-rm}
65f40e0d56Smrgstripprog=${STRIPPROG-strip}
66f40e0d56Smrg
67f40e0d56Smrgposix_mkdir=
68f40e0d56Smrg
69f40e0d56Smrg# Desired mode of installed file.
70f40e0d56Smrgmode=0755
71c95b42baSmrg
720f595aedSmrg# Create dirs (including intermediate dirs) using mode 755.
730f595aedSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
740f595aedSmrgmkdir_umask=22
750f595aedSmrg
760f595aedSmrgbackupsuffix=
77c95b42baSmrgchgrpcmd=
78f40e0d56Smrgchmodcmd=$chmodprog
79f40e0d56Smrgchowncmd=
80f40e0d56Smrgmvcmd=$mvprog
81c95b42baSmrgrmcmd="$rmprog -f"
82f40e0d56Smrgstripcmd=
83f40e0d56Smrg
84c95b42baSmrgsrc=
85c95b42baSmrgdst=
86c95b42baSmrgdir_arg=
87f40e0d56Smrgdst_arg=
88f40e0d56Smrg
89f40e0d56Smrgcopy_on_change=false
90b8f63ae3Smrgis_target_a_directory=possibly
91c95b42baSmrg
92f40e0d56Smrgusage="\
93f40e0d56SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94c95b42baSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95c95b42baSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96c95b42baSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97c95b42baSmrg
98c95b42baSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99c95b42baSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100c95b42baSmrgIn the 4th, create DIRECTORIES.
101c95b42baSmrg
102c95b42baSmrgOptions:
103f40e0d56Smrg     --help     display this help and exit.
104f40e0d56Smrg     --version  display version info and exit.
105f40e0d56Smrg
106f40e0d56Smrg  -c            (ignored)
1070f595aedSmrg  -C            install only if different (preserve data modification time)
108f40e0d56Smrg  -d            create directories instead of installing files.
109f40e0d56Smrg  -g GROUP      $chgrpprog installed files to GROUP.
110f40e0d56Smrg  -m MODE       $chmodprog installed files to MODE.
111f40e0d56Smrg  -o USER       $chownprog installed files to USER.
1120f595aedSmrg  -p            pass -p to $cpprog.
113f40e0d56Smrg  -s            $stripprog installed files.
1140f595aedSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115f40e0d56Smrg  -t DIRECTORY  install into DIRECTORY.
116f40e0d56Smrg  -T            report an error if DSTFILE is a directory.
117c95b42baSmrg
118c95b42baSmrgEnvironment variables override the default commands:
119f40e0d56Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120f40e0d56Smrg  RMPROG STRIPPROG
1210f595aedSmrg
1220f595aedSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
1230f595aedSmrgit's up to you to specify -f if you want it.
1240f595aedSmrg
1250f595aedSmrgIf -S is not specified, no backups are attempted.
1260f595aedSmrg
1270f595aedSmrgEmail bug reports to bug-automake@gnu.org.
1280f595aedSmrgAutomake home page: https://www.gnu.org/software/automake/
129c95b42baSmrg"
130c95b42baSmrg
131f40e0d56Smrgwhile test $# -ne 0; do
132c95b42baSmrg  case $1 in
133f40e0d56Smrg    -c) ;;
134f40e0d56Smrg
135f40e0d56Smrg    -C) copy_on_change=true;;
136c95b42baSmrg
137f40e0d56Smrg    -d) dir_arg=true;;
138c95b42baSmrg
139c95b42baSmrg    -g) chgrpcmd="$chgrpprog $2"
140b8f63ae3Smrg        shift;;
141c95b42baSmrg
142c95b42baSmrg    --help) echo "$usage"; exit $?;;
143c95b42baSmrg
144f40e0d56Smrg    -m) mode=$2
145b8f63ae3Smrg        case $mode in
146b8f63ae3Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147b8f63ae3Smrg            echo "$0: invalid mode: $mode" >&2
148b8f63ae3Smrg            exit 1;;
149b8f63ae3Smrg        esac
150b8f63ae3Smrg        shift;;
151c95b42baSmrg
152c95b42baSmrg    -o) chowncmd="$chownprog $2"
153b8f63ae3Smrg        shift;;
154c95b42baSmrg
1550f595aedSmrg    -p) cpprog="$cpprog -p";;
1560f595aedSmrg
157f40e0d56Smrg    -s) stripcmd=$stripprog;;
158c95b42baSmrg
1590f595aedSmrg    -S) backupsuffix="$2"
1600f595aedSmrg        shift;;
1610f595aedSmrg
162b8f63ae3Smrg    -t)
163b8f63ae3Smrg        is_target_a_directory=always
164b8f63ae3Smrg        dst_arg=$2
165b8f63ae3Smrg        # Protect names problematic for 'test' and other utilities.
166b8f63ae3Smrg        case $dst_arg in
167b8f63ae3Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
168b8f63ae3Smrg        esac
169b8f63ae3Smrg        shift;;
170c95b42baSmrg
171b8f63ae3Smrg    -T) is_target_a_directory=never;;
172c95b42baSmrg
173c95b42baSmrg    --version) echo "$0 $scriptversion"; exit $?;;
174c95b42baSmrg
175b8f63ae3Smrg    --) shift
176b8f63ae3Smrg        break;;
177f40e0d56Smrg
178b8f63ae3Smrg    -*) echo "$0: invalid option: $1" >&2
179b8f63ae3Smrg        exit 1;;
180f40e0d56Smrg
181f40e0d56Smrg    *)  break;;
182c95b42baSmrg  esac
183f40e0d56Smrg  shift
184c95b42baSmrgdone
185c95b42baSmrg
186b8f63ae3Smrg# We allow the use of options -d and -T together, by making -d
187b8f63ae3Smrg# take the precedence; this is for compatibility with GNU install.
188b8f63ae3Smrg
189b8f63ae3Smrgif test -n "$dir_arg"; then
190b8f63ae3Smrg  if test -n "$dst_arg"; then
191b8f63ae3Smrg    echo "$0: target directory not allowed when installing a directory." >&2
192b8f63ae3Smrg    exit 1
193b8f63ae3Smrg  fi
194b8f63ae3Smrgfi
195b8f63ae3Smrg
196f40e0d56Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197f40e0d56Smrg  # When -d is used, all remaining arguments are directories to create.
198f40e0d56Smrg  # When -t is used, the destination is already specified.
199f40e0d56Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200f40e0d56Smrg  for arg
201f40e0d56Smrg  do
202f40e0d56Smrg    if test -n "$dst_arg"; then
203f40e0d56Smrg      # $@ is not empty: it contains at least $arg.
204f40e0d56Smrg      set fnord "$@" "$dst_arg"
205f40e0d56Smrg      shift # fnord
206f40e0d56Smrg    fi
207f40e0d56Smrg    shift # arg
208f40e0d56Smrg    dst_arg=$arg
209b8f63ae3Smrg    # Protect names problematic for 'test' and other utilities.
21062aeb71dSmrg    case $dst_arg in
21162aeb71dSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21262aeb71dSmrg    esac
213f40e0d56Smrg  done
214f40e0d56Smrgfi
215f40e0d56Smrg
216f40e0d56Smrgif test $# -eq 0; then
217c95b42baSmrg  if test -z "$dir_arg"; then
218c95b42baSmrg    echo "$0: no input file specified." >&2
219c95b42baSmrg    exit 1
220c95b42baSmrg  fi
221b8f63ae3Smrg  # It's OK to call 'install-sh -d' without argument.
222c95b42baSmrg  # This can happen when creating conditional directories.
223c95b42baSmrg  exit 0
224c95b42baSmrgfi
225c95b42baSmrg
226b8f63ae3Smrgif test -z "$dir_arg"; then
227b8f63ae3Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
228b8f63ae3Smrg    if test ! -d "$dst_arg"; then
229b8f63ae3Smrg      echo "$0: $dst_arg: Is not a directory." >&2
230b8f63ae3Smrg      exit 1
231b8f63ae3Smrg    fi
232b8f63ae3Smrg  fi
233b8f63ae3Smrgfi
234b8f63ae3Smrg
235f40e0d56Smrgif test -z "$dir_arg"; then
23662aeb71dSmrg  do_exit='(exit $ret); exit $ret'
23762aeb71dSmrg  trap "ret=129; $do_exit" 1
23862aeb71dSmrg  trap "ret=130; $do_exit" 2
23962aeb71dSmrg  trap "ret=141; $do_exit" 13
24062aeb71dSmrg  trap "ret=143; $do_exit" 15
241f40e0d56Smrg
242f40e0d56Smrg  # Set umask so as not to create temps with too-generous modes.
243f40e0d56Smrg  # However, 'strip' requires both read and write access to temps.
244f40e0d56Smrg  case $mode in
245f40e0d56Smrg    # Optimize common cases.
246f40e0d56Smrg    *644) cp_umask=133;;
247f40e0d56Smrg    *755) cp_umask=22;;
248f40e0d56Smrg
249f40e0d56Smrg    *[0-7])
250f40e0d56Smrg      if test -z "$stripcmd"; then
251b8f63ae3Smrg        u_plus_rw=
252f40e0d56Smrg      else
253b8f63ae3Smrg        u_plus_rw='% 200'
254f40e0d56Smrg      fi
255f40e0d56Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256f40e0d56Smrg    *)
257f40e0d56Smrg      if test -z "$stripcmd"; then
258b8f63ae3Smrg        u_plus_rw=
259f40e0d56Smrg      else
260b8f63ae3Smrg        u_plus_rw=,u+rw
261f40e0d56Smrg      fi
262f40e0d56Smrg      cp_umask=$mode$u_plus_rw;;
263f40e0d56Smrg  esac
264f40e0d56Smrgfi
265f40e0d56Smrg
266c95b42baSmrgfor src
267c95b42baSmrgdo
268b8f63ae3Smrg  # Protect names problematic for 'test' and other utilities.
269c95b42baSmrg  case $src in
27062aeb71dSmrg    -* | [=\(\)!]) src=./$src;;
271c95b42baSmrg  esac
272c95b42baSmrg
273c95b42baSmrg  if test -n "$dir_arg"; then
274c95b42baSmrg    dst=$src
275f40e0d56Smrg    dstdir=$dst
276f40e0d56Smrg    test -d "$dstdir"
277f40e0d56Smrg    dstdir_status=$?
2780f595aedSmrg    # Don't chown directories that already exist.
2790f595aedSmrg    if test $dstdir_status = 0; then
2800f595aedSmrg      chowncmd=""
2810f595aedSmrg    fi
282c95b42baSmrg  else
283f40e0d56Smrg
284c95b42baSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285c95b42baSmrg    # might cause directories to be created, which would be especially bad
286c95b42baSmrg    # if $src (and thus $dsttmp) contains '*'.
287c95b42baSmrg    if test ! -f "$src" && test ! -d "$src"; then
288c95b42baSmrg      echo "$0: $src does not exist." >&2
289c95b42baSmrg      exit 1
290c95b42baSmrg    fi
291c95b42baSmrg
292f40e0d56Smrg    if test -z "$dst_arg"; then
293c95b42baSmrg      echo "$0: no destination specified." >&2
294c95b42baSmrg      exit 1
295c95b42baSmrg    fi
296f40e0d56Smrg    dst=$dst_arg
297c95b42baSmrg
2980f595aedSmrg    # If destination is a directory, append the input filename.
299c95b42baSmrg    if test -d "$dst"; then
300b8f63ae3Smrg      if test "$is_target_a_directory" = never; then
301b8f63ae3Smrg        echo "$0: $dst_arg: Is a directory" >&2
302b8f63ae3Smrg        exit 1
303c95b42baSmrg      fi
304f40e0d56Smrg      dstdir=$dst
3050f595aedSmrg      dstbase=`basename "$src"`
3060f595aedSmrg      case $dst in
3070f595aedSmrg	*/) dst=$dst$dstbase;;
3080f595aedSmrg	*)  dst=$dst/$dstbase;;
3090f595aedSmrg      esac
310f40e0d56Smrg      dstdir_status=0
311f40e0d56Smrg    else
312b8f63ae3Smrg      dstdir=`dirname "$dst"`
313f40e0d56Smrg      test -d "$dstdir"
314f40e0d56Smrg      dstdir_status=$?
315c95b42baSmrg    fi
316c95b42baSmrg  fi
317c95b42baSmrg
3180f595aedSmrg  case $dstdir in
3190f595aedSmrg    */) dstdirslash=$dstdir;;
3200f595aedSmrg    *)  dstdirslash=$dstdir/;;
3210f595aedSmrg  esac
3220f595aedSmrg
323f40e0d56Smrg  obsolete_mkdir_used=false
324f40e0d56Smrg
325f40e0d56Smrg  if test $dstdir_status != 0; then
326f40e0d56Smrg    case $posix_mkdir in
327f40e0d56Smrg      '')
328b8f63ae3Smrg        # With -d, create the new directory with the user-specified mode.
329b8f63ae3Smrg        # Otherwise, rely on $mkdir_umask.
330b8f63ae3Smrg        if test -n "$dir_arg"; then
331b8f63ae3Smrg          mkdir_mode=-m$mode
332b8f63ae3Smrg        else
333b8f63ae3Smrg          mkdir_mode=
334b8f63ae3Smrg        fi
335b8f63ae3Smrg
336b8f63ae3Smrg        posix_mkdir=false
3370f595aedSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
3380f595aedSmrg	# here however when possible just to lower collision chance.
3390f595aedSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3400f595aedSmrg
3410f595aedSmrg	trap '
3420f595aedSmrg	  ret=$?
3430f595aedSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
3440f595aedSmrg	  exit $ret
3450f595aedSmrg	' 0
3460f595aedSmrg
3470f595aedSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
3480f595aedSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
3490f595aedSmrg	# directory is successfully created first before we actually test
3500f595aedSmrg	# 'mkdir -p'.
3510f595aedSmrg	if (umask $mkdir_umask &&
3520f595aedSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
3530f595aedSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3540f595aedSmrg	then
3550f595aedSmrg	  if test -z "$dir_arg" || {
3560f595aedSmrg	       # Check for POSIX incompatibilities with -m.
3570f595aedSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3580f595aedSmrg	       # other-writable bit of parent directory when it shouldn't.
3590f595aedSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3600f595aedSmrg	       test_tmpdir="$tmpdir/a"
3610f595aedSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3620f595aedSmrg	       case $ls_ld_tmpdir in
3630f595aedSmrg		 d????-?r-*) different_mode=700;;
3640f595aedSmrg		 d????-?--*) different_mode=755;;
3650f595aedSmrg		 *) false;;
3660f595aedSmrg	       esac &&
3670f595aedSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3680f595aedSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3690f595aedSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3700f595aedSmrg	       }
3710f595aedSmrg	     }
3720f595aedSmrg	  then posix_mkdir=:
3730f595aedSmrg	  fi
3740f595aedSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3750f595aedSmrg	else
3760f595aedSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
3770f595aedSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3780f595aedSmrg	fi
3790f595aedSmrg	trap '' 0;;
380f40e0d56Smrg    esac
381c95b42baSmrg
382f40e0d56Smrg    if
383f40e0d56Smrg      $posix_mkdir && (
384b8f63ae3Smrg        umask $mkdir_umask &&
385b8f63ae3Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386f40e0d56Smrg      )
387f40e0d56Smrg    then :
388f40e0d56Smrg    else
389c95b42baSmrg
3900f595aedSmrg      # mkdir does not conform to POSIX,
391f40e0d56Smrg      # or it failed possibly due to a race condition.  Create the
392f40e0d56Smrg      # directory the slow way, step by step, checking for races as we go.
393c95b42baSmrg
394f40e0d56Smrg      case $dstdir in
395b8f63ae3Smrg        /*) prefix='/';;
396b8f63ae3Smrg        [-=\(\)!]*) prefix='./';;
397b8f63ae3Smrg        *)  prefix='';;
398f40e0d56Smrg      esac
399c95b42baSmrg
400f40e0d56Smrg      oIFS=$IFS
401f40e0d56Smrg      IFS=/
402b8f63ae3Smrg      set -f
403f40e0d56Smrg      set fnord $dstdir
404c95b42baSmrg      shift
405b8f63ae3Smrg      set +f
406f40e0d56Smrg      IFS=$oIFS
407f40e0d56Smrg
408f40e0d56Smrg      prefixes=
409f40e0d56Smrg
410f40e0d56Smrg      for d
411f40e0d56Smrg      do
412b8f63ae3Smrg        test X"$d" = X && continue
413b8f63ae3Smrg
414b8f63ae3Smrg        prefix=$prefix$d
415b8f63ae3Smrg        if test -d "$prefix"; then
416b8f63ae3Smrg          prefixes=
417b8f63ae3Smrg        else
418b8f63ae3Smrg          if $posix_mkdir; then
4190f595aedSmrg            (umask $mkdir_umask &&
420b8f63ae3Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421b8f63ae3Smrg            # Don't fail if two instances are running concurrently.
422b8f63ae3Smrg            test -d "$prefix" || exit 1
423b8f63ae3Smrg          else
424b8f63ae3Smrg            case $prefix in
425b8f63ae3Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426b8f63ae3Smrg              *) qprefix=$prefix;;
427b8f63ae3Smrg            esac
428b8f63ae3Smrg            prefixes="$prefixes '$qprefix'"
429b8f63ae3Smrg          fi
430b8f63ae3Smrg        fi
431b8f63ae3Smrg        prefix=$prefix/
432f40e0d56Smrg      done
433f40e0d56Smrg
434f40e0d56Smrg      if test -n "$prefixes"; then
435b8f63ae3Smrg        # Don't fail if two instances are running concurrently.
436b8f63ae3Smrg        (umask $mkdir_umask &&
437b8f63ae3Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
438b8f63ae3Smrg          test -d "$dstdir" || exit 1
439b8f63ae3Smrg        obsolete_mkdir_used=true
440c95b42baSmrg      fi
441f40e0d56Smrg    fi
442c95b42baSmrg  fi
443c95b42baSmrg
444c95b42baSmrg  if test -n "$dir_arg"; then
445f40e0d56Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446f40e0d56Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447f40e0d56Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448f40e0d56Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449c95b42baSmrg  else
450c95b42baSmrg
451c95b42baSmrg    # Make a couple of temp file names in the proper directory.
4520f595aedSmrg    dsttmp=${dstdirslash}_inst.$$_
4530f595aedSmrg    rmtmp=${dstdirslash}_rm.$$_
454c95b42baSmrg
455c95b42baSmrg    # Trap to clean up those temp files at exit.
456c95b42baSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457c95b42baSmrg
458c95b42baSmrg    # Copy the file name to the temp name.
4590f595aedSmrg    (umask $cp_umask &&
4600f595aedSmrg     { test -z "$stripcmd" || {
4610f595aedSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
4620f595aedSmrg	 # which would cause strip to fail.
4630f595aedSmrg	 if test -z "$doit"; then
4640f595aedSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
4650f595aedSmrg	 else
4660f595aedSmrg	   $doit touch "$dsttmp"
4670f595aedSmrg	 fi
4680f595aedSmrg       }
4690f595aedSmrg     } &&
4700f595aedSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471c95b42baSmrg
472c95b42baSmrg    # and set any options; do chmod last to preserve setuid bits.
473c95b42baSmrg    #
474c95b42baSmrg    # If any of these fail, we abort the whole thing.  If we want to
475c95b42baSmrg    # ignore errors from any of these, just make sure not to ignore
476c95b42baSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477c95b42baSmrg    #
478f40e0d56Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479f40e0d56Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480f40e0d56Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481f40e0d56Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482f40e0d56Smrg
483f40e0d56Smrg    # If -C, don't bother to copy if it wouldn't change the file.
484f40e0d56Smrg    if $copy_on_change &&
485b8f63ae3Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
486b8f63ae3Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
487b8f63ae3Smrg       set -f &&
488f40e0d56Smrg       set X $old && old=:$2:$4:$5:$6 &&
489f40e0d56Smrg       set X $new && new=:$2:$4:$5:$6 &&
490b8f63ae3Smrg       set +f &&
491f40e0d56Smrg       test "$old" = "$new" &&
492f40e0d56Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493f40e0d56Smrg    then
494f40e0d56Smrg      rm -f "$dsttmp"
495f40e0d56Smrg    else
4960f595aedSmrg      # If $backupsuffix is set, and the file being installed
4970f595aedSmrg      # already exists, attempt a backup.  Don't worry if it fails,
4980f595aedSmrg      # e.g., if mv doesn't support -f.
4990f595aedSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
5000f595aedSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
5010f595aedSmrg      fi
5020f595aedSmrg
503f40e0d56Smrg      # Rename the file to the real destination.
504f40e0d56Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505f40e0d56Smrg
506f40e0d56Smrg      # The rename failed, perhaps because mv can't rename something else
507f40e0d56Smrg      # to itself, or perhaps because mv is so ancient that it does not
508f40e0d56Smrg      # support -f.
509f40e0d56Smrg      {
510b8f63ae3Smrg        # Now remove or move aside any old file at destination location.
511b8f63ae3Smrg        # We try this two ways since rm can't unlink itself on some
512b8f63ae3Smrg        # systems and the destination file might be busy for other
513b8f63ae3Smrg        # reasons.  In this case, the final cleanup might fail but the new
514b8f63ae3Smrg        # file should still install successfully.
515b8f63ae3Smrg        {
516b8f63ae3Smrg          test ! -f "$dst" ||
5170f595aedSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
518b8f63ae3Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
5190f595aedSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520b8f63ae3Smrg          } ||
521b8f63ae3Smrg          { echo "$0: cannot unlink or rename $dst" >&2
522b8f63ae3Smrg            (exit 1); exit 1
523b8f63ae3Smrg          }
524b8f63ae3Smrg        } &&
525b8f63ae3Smrg
526b8f63ae3Smrg        # Now rename the file to the real destination.
527b8f63ae3Smrg        $doit $mvcmd "$dsttmp" "$dst"
528f40e0d56Smrg      }
529f40e0d56Smrg    fi || exit 1
530f40e0d56Smrg
531f40e0d56Smrg    trap '' 0
532f40e0d56Smrg  fi
533c95b42baSmrgdone
534c95b42baSmrg
535c95b42baSmrg# Local variables:
5360f595aedSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
537c95b42baSmrg# time-stamp-start: "scriptversion="
538c95b42baSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
5390f595aedSmrg# time-stamp-time-zone: "UTC0"
540f40e0d56Smrg# time-stamp-end: "; # UTC"
541c95b42baSmrg# End:
542