1d6c0b56eSmrg#!/bin/sh
2d6c0b56eSmrg# install - install a program, script, or datafile
3d6c0b56eSmrg
4e49c54bcSmrgscriptversion=2020-11-14.01; # UTC
5d6c0b56eSmrg
6d6c0b56eSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7d6c0b56eSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8d6c0b56eSmrg# following copyright and license.
9d6c0b56eSmrg#
10d6c0b56eSmrg# Copyright (C) 1994 X Consortium
11d6c0b56eSmrg#
12d6c0b56eSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13d6c0b56eSmrg# of this software and associated documentation files (the "Software"), to
14d6c0b56eSmrg# deal in the Software without restriction, including without limitation the
15d6c0b56eSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16d6c0b56eSmrg# sell copies of the Software, and to permit persons to whom the Software is
17d6c0b56eSmrg# furnished to do so, subject to the following conditions:
18d6c0b56eSmrg#
19d6c0b56eSmrg# The above copyright notice and this permission notice shall be included in
20d6c0b56eSmrg# all copies or substantial portions of the Software.
21d6c0b56eSmrg#
22d6c0b56eSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23d6c0b56eSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24d6c0b56eSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25d6c0b56eSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26d6c0b56eSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27d6c0b56eSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28d6c0b56eSmrg#
29d6c0b56eSmrg# Except as contained in this notice, the name of the X Consortium shall not
30d6c0b56eSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31d6c0b56eSmrg# ings in this Software without prior written authorization from the X Consor-
32d6c0b56eSmrg# tium.
33d6c0b56eSmrg#
34d6c0b56eSmrg#
35d6c0b56eSmrg# FSF changes to this file are in the public domain.
36d6c0b56eSmrg#
37d6c0b56eSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38d6c0b56eSmrg# 'make' implicit rules from creating a file called install from it
39d6c0b56eSmrg# when there is no Makefile.
40d6c0b56eSmrg#
41d6c0b56eSmrg# This script is compatible with the BSD install script, but was written
42d6c0b56eSmrg# from scratch.
43d6c0b56eSmrg
44d6c0b56eSmrgtab='	'
45d6c0b56eSmrgnl='
46d6c0b56eSmrg'
47d6c0b56eSmrgIFS=" $tab$nl"
48d6c0b56eSmrg
49d6c0b56eSmrg# Set DOITPROG to "echo" to test this script.
50d6c0b56eSmrg
51d6c0b56eSmrgdoit=${DOITPROG-}
52d6c0b56eSmrgdoit_exec=${doit:-exec}
53d6c0b56eSmrg
54d6c0b56eSmrg# Put in absolute file names if you don't have them in your path;
55d6c0b56eSmrg# or use environment vars.
56d6c0b56eSmrg
57d6c0b56eSmrgchgrpprog=${CHGRPPROG-chgrp}
58d6c0b56eSmrgchmodprog=${CHMODPROG-chmod}
59d6c0b56eSmrgchownprog=${CHOWNPROG-chown}
60d6c0b56eSmrgcmpprog=${CMPPROG-cmp}
61d6c0b56eSmrgcpprog=${CPPROG-cp}
62d6c0b56eSmrgmkdirprog=${MKDIRPROG-mkdir}
63d6c0b56eSmrgmvprog=${MVPROG-mv}
64d6c0b56eSmrgrmprog=${RMPROG-rm}
65d6c0b56eSmrgstripprog=${STRIPPROG-strip}
66d6c0b56eSmrg
67d6c0b56eSmrgposix_mkdir=
68d6c0b56eSmrg
69d6c0b56eSmrg# Desired mode of installed file.
70d6c0b56eSmrgmode=0755
71d6c0b56eSmrg
72e49c54bcSmrg# Create dirs (including intermediate dirs) using mode 755.
73e49c54bcSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
74e49c54bcSmrgmkdir_umask=22
75e49c54bcSmrg
76e49c54bcSmrgbackupsuffix=
77d6c0b56eSmrgchgrpcmd=
78d6c0b56eSmrgchmodcmd=$chmodprog
79d6c0b56eSmrgchowncmd=
80d6c0b56eSmrgmvcmd=$mvprog
81d6c0b56eSmrgrmcmd="$rmprog -f"
82d6c0b56eSmrgstripcmd=
83d6c0b56eSmrg
84d6c0b56eSmrgsrc=
85d6c0b56eSmrgdst=
86d6c0b56eSmrgdir_arg=
87d6c0b56eSmrgdst_arg=
88d6c0b56eSmrg
89d6c0b56eSmrgcopy_on_change=false
90d6c0b56eSmrgis_target_a_directory=possibly
91d6c0b56eSmrg
92d6c0b56eSmrgusage="\
93d6c0b56eSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94d6c0b56eSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95d6c0b56eSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96d6c0b56eSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97d6c0b56eSmrg
98d6c0b56eSmrgIn the 1st form, copy SRCFILE to DSTFILE.
99d6c0b56eSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100d6c0b56eSmrgIn the 4th, create DIRECTORIES.
101d6c0b56eSmrg
102d6c0b56eSmrgOptions:
103d6c0b56eSmrg     --help     display this help and exit.
104d6c0b56eSmrg     --version  display version info and exit.
105d6c0b56eSmrg
106d6c0b56eSmrg  -c            (ignored)
107e49c54bcSmrg  -C            install only if different (preserve data modification time)
108d6c0b56eSmrg  -d            create directories instead of installing files.
109d6c0b56eSmrg  -g GROUP      $chgrpprog installed files to GROUP.
110d6c0b56eSmrg  -m MODE       $chmodprog installed files to MODE.
111d6c0b56eSmrg  -o USER       $chownprog installed files to USER.
112e49c54bcSmrg  -p            pass -p to $cpprog.
113d6c0b56eSmrg  -s            $stripprog installed files.
114e49c54bcSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115d6c0b56eSmrg  -t DIRECTORY  install into DIRECTORY.
116d6c0b56eSmrg  -T            report an error if DSTFILE is a directory.
117d6c0b56eSmrg
118d6c0b56eSmrgEnvironment variables override the default commands:
119d6c0b56eSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120d6c0b56eSmrg  RMPROG STRIPPROG
121e49c54bcSmrg
122e49c54bcSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
123e49c54bcSmrgit's up to you to specify -f if you want it.
124e49c54bcSmrg
125e49c54bcSmrgIf -S is not specified, no backups are attempted.
126e49c54bcSmrg
127e49c54bcSmrgEmail bug reports to bug-automake@gnu.org.
128e49c54bcSmrgAutomake home page: https://www.gnu.org/software/automake/
129d6c0b56eSmrg"
130d6c0b56eSmrg
131d6c0b56eSmrgwhile test $# -ne 0; do
132d6c0b56eSmrg  case $1 in
133d6c0b56eSmrg    -c) ;;
134d6c0b56eSmrg
135d6c0b56eSmrg    -C) copy_on_change=true;;
136d6c0b56eSmrg
137d6c0b56eSmrg    -d) dir_arg=true;;
138d6c0b56eSmrg
139d6c0b56eSmrg    -g) chgrpcmd="$chgrpprog $2"
140d6c0b56eSmrg        shift;;
141d6c0b56eSmrg
142d6c0b56eSmrg    --help) echo "$usage"; exit $?;;
143d6c0b56eSmrg
144d6c0b56eSmrg    -m) mode=$2
145d6c0b56eSmrg        case $mode in
146d6c0b56eSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147d6c0b56eSmrg            echo "$0: invalid mode: $mode" >&2
148d6c0b56eSmrg            exit 1;;
149d6c0b56eSmrg        esac
150d6c0b56eSmrg        shift;;
151d6c0b56eSmrg
152d6c0b56eSmrg    -o) chowncmd="$chownprog $2"
153d6c0b56eSmrg        shift;;
154d6c0b56eSmrg
155e49c54bcSmrg    -p) cpprog="$cpprog -p";;
156e49c54bcSmrg
157d6c0b56eSmrg    -s) stripcmd=$stripprog;;
158d6c0b56eSmrg
159e49c54bcSmrg    -S) backupsuffix="$2"
160e49c54bcSmrg        shift;;
161e49c54bcSmrg
162d6c0b56eSmrg    -t)
163d6c0b56eSmrg        is_target_a_directory=always
164d6c0b56eSmrg        dst_arg=$2
165d6c0b56eSmrg        # Protect names problematic for 'test' and other utilities.
166d6c0b56eSmrg        case $dst_arg in
167d6c0b56eSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
168d6c0b56eSmrg        esac
169d6c0b56eSmrg        shift;;
170d6c0b56eSmrg
171d6c0b56eSmrg    -T) is_target_a_directory=never;;
172d6c0b56eSmrg
173d6c0b56eSmrg    --version) echo "$0 $scriptversion"; exit $?;;
174d6c0b56eSmrg
175d6c0b56eSmrg    --) shift
176d6c0b56eSmrg        break;;
177d6c0b56eSmrg
178d6c0b56eSmrg    -*) echo "$0: invalid option: $1" >&2
179d6c0b56eSmrg        exit 1;;
180d6c0b56eSmrg
181d6c0b56eSmrg    *)  break;;
182d6c0b56eSmrg  esac
183d6c0b56eSmrg  shift
184d6c0b56eSmrgdone
185d6c0b56eSmrg
186d6c0b56eSmrg# We allow the use of options -d and -T together, by making -d
187d6c0b56eSmrg# take the precedence; this is for compatibility with GNU install.
188d6c0b56eSmrg
189d6c0b56eSmrgif test -n "$dir_arg"; then
190d6c0b56eSmrg  if test -n "$dst_arg"; then
191d6c0b56eSmrg    echo "$0: target directory not allowed when installing a directory." >&2
192d6c0b56eSmrg    exit 1
193d6c0b56eSmrg  fi
194d6c0b56eSmrgfi
195d6c0b56eSmrg
196d6c0b56eSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197d6c0b56eSmrg  # When -d is used, all remaining arguments are directories to create.
198d6c0b56eSmrg  # When -t is used, the destination is already specified.
199d6c0b56eSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200d6c0b56eSmrg  for arg
201d6c0b56eSmrg  do
202d6c0b56eSmrg    if test -n "$dst_arg"; then
203d6c0b56eSmrg      # $@ is not empty: it contains at least $arg.
204d6c0b56eSmrg      set fnord "$@" "$dst_arg"
205d6c0b56eSmrg      shift # fnord
206d6c0b56eSmrg    fi
207d6c0b56eSmrg    shift # arg
208d6c0b56eSmrg    dst_arg=$arg
209d6c0b56eSmrg    # Protect names problematic for 'test' and other utilities.
210d6c0b56eSmrg    case $dst_arg in
211d6c0b56eSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212d6c0b56eSmrg    esac
213d6c0b56eSmrg  done
214d6c0b56eSmrgfi
215d6c0b56eSmrg
216d6c0b56eSmrgif test $# -eq 0; then
217d6c0b56eSmrg  if test -z "$dir_arg"; then
218d6c0b56eSmrg    echo "$0: no input file specified." >&2
219d6c0b56eSmrg    exit 1
220d6c0b56eSmrg  fi
221d6c0b56eSmrg  # It's OK to call 'install-sh -d' without argument.
222d6c0b56eSmrg  # This can happen when creating conditional directories.
223d6c0b56eSmrg  exit 0
224d6c0b56eSmrgfi
225d6c0b56eSmrg
226d6c0b56eSmrgif test -z "$dir_arg"; then
227d6c0b56eSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
228d6c0b56eSmrg    if test ! -d "$dst_arg"; then
229d6c0b56eSmrg      echo "$0: $dst_arg: Is not a directory." >&2
230d6c0b56eSmrg      exit 1
231d6c0b56eSmrg    fi
232d6c0b56eSmrg  fi
233d6c0b56eSmrgfi
234d6c0b56eSmrg
235d6c0b56eSmrgif test -z "$dir_arg"; then
236d6c0b56eSmrg  do_exit='(exit $ret); exit $ret'
237d6c0b56eSmrg  trap "ret=129; $do_exit" 1
238d6c0b56eSmrg  trap "ret=130; $do_exit" 2
239d6c0b56eSmrg  trap "ret=141; $do_exit" 13
240d6c0b56eSmrg  trap "ret=143; $do_exit" 15
241d6c0b56eSmrg
242d6c0b56eSmrg  # Set umask so as not to create temps with too-generous modes.
243d6c0b56eSmrg  # However, 'strip' requires both read and write access to temps.
244d6c0b56eSmrg  case $mode in
245d6c0b56eSmrg    # Optimize common cases.
246d6c0b56eSmrg    *644) cp_umask=133;;
247d6c0b56eSmrg    *755) cp_umask=22;;
248d6c0b56eSmrg
249d6c0b56eSmrg    *[0-7])
250d6c0b56eSmrg      if test -z "$stripcmd"; then
251d6c0b56eSmrg        u_plus_rw=
252d6c0b56eSmrg      else
253d6c0b56eSmrg        u_plus_rw='% 200'
254d6c0b56eSmrg      fi
255d6c0b56eSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256d6c0b56eSmrg    *)
257d6c0b56eSmrg      if test -z "$stripcmd"; then
258d6c0b56eSmrg        u_plus_rw=
259d6c0b56eSmrg      else
260d6c0b56eSmrg        u_plus_rw=,u+rw
261d6c0b56eSmrg      fi
262d6c0b56eSmrg      cp_umask=$mode$u_plus_rw;;
263d6c0b56eSmrg  esac
264d6c0b56eSmrgfi
265d6c0b56eSmrg
266d6c0b56eSmrgfor src
267d6c0b56eSmrgdo
268d6c0b56eSmrg  # Protect names problematic for 'test' and other utilities.
269d6c0b56eSmrg  case $src in
270d6c0b56eSmrg    -* | [=\(\)!]) src=./$src;;
271d6c0b56eSmrg  esac
272d6c0b56eSmrg
273d6c0b56eSmrg  if test -n "$dir_arg"; then
274d6c0b56eSmrg    dst=$src
275d6c0b56eSmrg    dstdir=$dst
276d6c0b56eSmrg    test -d "$dstdir"
277d6c0b56eSmrg    dstdir_status=$?
278e49c54bcSmrg    # Don't chown directories that already exist.
279e49c54bcSmrg    if test $dstdir_status = 0; then
280e49c54bcSmrg      chowncmd=""
281e49c54bcSmrg    fi
282d6c0b56eSmrg  else
283d6c0b56eSmrg
284d6c0b56eSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285d6c0b56eSmrg    # might cause directories to be created, which would be especially bad
286d6c0b56eSmrg    # if $src (and thus $dsttmp) contains '*'.
287d6c0b56eSmrg    if test ! -f "$src" && test ! -d "$src"; then
288d6c0b56eSmrg      echo "$0: $src does not exist." >&2
289d6c0b56eSmrg      exit 1
290d6c0b56eSmrg    fi
291d6c0b56eSmrg
292d6c0b56eSmrg    if test -z "$dst_arg"; then
293d6c0b56eSmrg      echo "$0: no destination specified." >&2
294d6c0b56eSmrg      exit 1
295d6c0b56eSmrg    fi
296d6c0b56eSmrg    dst=$dst_arg
297d6c0b56eSmrg
29835d5b7c7Smrg    # If destination is a directory, append the input filename.
299d6c0b56eSmrg    if test -d "$dst"; then
300d6c0b56eSmrg      if test "$is_target_a_directory" = never; then
301d6c0b56eSmrg        echo "$0: $dst_arg: Is a directory" >&2
302d6c0b56eSmrg        exit 1
303d6c0b56eSmrg      fi
304d6c0b56eSmrg      dstdir=$dst
30535d5b7c7Smrg      dstbase=`basename "$src"`
30635d5b7c7Smrg      case $dst in
30735d5b7c7Smrg	*/) dst=$dst$dstbase;;
30835d5b7c7Smrg	*)  dst=$dst/$dstbase;;
30935d5b7c7Smrg      esac
310d6c0b56eSmrg      dstdir_status=0
311d6c0b56eSmrg    else
312d6c0b56eSmrg      dstdir=`dirname "$dst"`
313d6c0b56eSmrg      test -d "$dstdir"
314d6c0b56eSmrg      dstdir_status=$?
315d6c0b56eSmrg    fi
316d6c0b56eSmrg  fi
317d6c0b56eSmrg
31835d5b7c7Smrg  case $dstdir in
31935d5b7c7Smrg    */) dstdirslash=$dstdir;;
32035d5b7c7Smrg    *)  dstdirslash=$dstdir/;;
32135d5b7c7Smrg  esac
32235d5b7c7Smrg
323d6c0b56eSmrg  obsolete_mkdir_used=false
324d6c0b56eSmrg
325d6c0b56eSmrg  if test $dstdir_status != 0; then
326d6c0b56eSmrg    case $posix_mkdir in
327d6c0b56eSmrg      '')
328d6c0b56eSmrg        # With -d, create the new directory with the user-specified mode.
329d6c0b56eSmrg        # Otherwise, rely on $mkdir_umask.
330d6c0b56eSmrg        if test -n "$dir_arg"; then
331d6c0b56eSmrg          mkdir_mode=-m$mode
332d6c0b56eSmrg        else
333d6c0b56eSmrg          mkdir_mode=
334d6c0b56eSmrg        fi
335d6c0b56eSmrg
336d6c0b56eSmrg        posix_mkdir=false
337e49c54bcSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
338e49c54bcSmrg	# here however when possible just to lower collision chance.
339e49c54bcSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340e49c54bcSmrg
341e49c54bcSmrg	trap '
342e49c54bcSmrg	  ret=$?
343e49c54bcSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344e49c54bcSmrg	  exit $ret
345e49c54bcSmrg	' 0
346e49c54bcSmrg
347e49c54bcSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
348e49c54bcSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
349e49c54bcSmrg	# directory is successfully created first before we actually test
350e49c54bcSmrg	# 'mkdir -p'.
351e49c54bcSmrg	if (umask $mkdir_umask &&
352e49c54bcSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
353e49c54bcSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354e49c54bcSmrg	then
355e49c54bcSmrg	  if test -z "$dir_arg" || {
356e49c54bcSmrg	       # Check for POSIX incompatibilities with -m.
357e49c54bcSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358e49c54bcSmrg	       # other-writable bit of parent directory when it shouldn't.
359e49c54bcSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360e49c54bcSmrg	       test_tmpdir="$tmpdir/a"
361e49c54bcSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362e49c54bcSmrg	       case $ls_ld_tmpdir in
363e49c54bcSmrg		 d????-?r-*) different_mode=700;;
364e49c54bcSmrg		 d????-?--*) different_mode=755;;
365e49c54bcSmrg		 *) false;;
366e49c54bcSmrg	       esac &&
367e49c54bcSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368e49c54bcSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369e49c54bcSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370e49c54bcSmrg	       }
371e49c54bcSmrg	     }
372e49c54bcSmrg	  then posix_mkdir=:
373e49c54bcSmrg	  fi
374e49c54bcSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375e49c54bcSmrg	else
376e49c54bcSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
377e49c54bcSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378e49c54bcSmrg	fi
379e49c54bcSmrg	trap '' 0;;
380d6c0b56eSmrg    esac
381d6c0b56eSmrg
382d6c0b56eSmrg    if
383d6c0b56eSmrg      $posix_mkdir && (
384d6c0b56eSmrg        umask $mkdir_umask &&
385d6c0b56eSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386d6c0b56eSmrg      )
387d6c0b56eSmrg    then :
388d6c0b56eSmrg    else
389d6c0b56eSmrg
390e49c54bcSmrg      # mkdir does not conform to POSIX,
391d6c0b56eSmrg      # or it failed possibly due to a race condition.  Create the
392d6c0b56eSmrg      # directory the slow way, step by step, checking for races as we go.
393d6c0b56eSmrg
394d6c0b56eSmrg      case $dstdir in
395d6c0b56eSmrg        /*) prefix='/';;
396d6c0b56eSmrg        [-=\(\)!]*) prefix='./';;
397d6c0b56eSmrg        *)  prefix='';;
398d6c0b56eSmrg      esac
399d6c0b56eSmrg
400d6c0b56eSmrg      oIFS=$IFS
401d6c0b56eSmrg      IFS=/
402d6c0b56eSmrg      set -f
403d6c0b56eSmrg      set fnord $dstdir
404d6c0b56eSmrg      shift
405d6c0b56eSmrg      set +f
406d6c0b56eSmrg      IFS=$oIFS
407d6c0b56eSmrg
408d6c0b56eSmrg      prefixes=
409d6c0b56eSmrg
410d6c0b56eSmrg      for d
411d6c0b56eSmrg      do
412d6c0b56eSmrg        test X"$d" = X && continue
413d6c0b56eSmrg
414d6c0b56eSmrg        prefix=$prefix$d
415d6c0b56eSmrg        if test -d "$prefix"; then
416d6c0b56eSmrg          prefixes=
417d6c0b56eSmrg        else
418d6c0b56eSmrg          if $posix_mkdir; then
419e49c54bcSmrg            (umask $mkdir_umask &&
420d6c0b56eSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421d6c0b56eSmrg            # Don't fail if two instances are running concurrently.
422d6c0b56eSmrg            test -d "$prefix" || exit 1
423d6c0b56eSmrg          else
424d6c0b56eSmrg            case $prefix in
425d6c0b56eSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426d6c0b56eSmrg              *) qprefix=$prefix;;
427d6c0b56eSmrg            esac
428d6c0b56eSmrg            prefixes="$prefixes '$qprefix'"
429d6c0b56eSmrg          fi
430d6c0b56eSmrg        fi
431d6c0b56eSmrg        prefix=$prefix/
432d6c0b56eSmrg      done
433d6c0b56eSmrg
434d6c0b56eSmrg      if test -n "$prefixes"; then
435d6c0b56eSmrg        # Don't fail if two instances are running concurrently.
436d6c0b56eSmrg        (umask $mkdir_umask &&
437d6c0b56eSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
438d6c0b56eSmrg          test -d "$dstdir" || exit 1
439d6c0b56eSmrg        obsolete_mkdir_used=true
440d6c0b56eSmrg      fi
441d6c0b56eSmrg    fi
442d6c0b56eSmrg  fi
443d6c0b56eSmrg
444d6c0b56eSmrg  if test -n "$dir_arg"; then
445d6c0b56eSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446d6c0b56eSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447d6c0b56eSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448d6c0b56eSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449d6c0b56eSmrg  else
450d6c0b56eSmrg
451d6c0b56eSmrg    # Make a couple of temp file names in the proper directory.
45235d5b7c7Smrg    dsttmp=${dstdirslash}_inst.$$_
45335d5b7c7Smrg    rmtmp=${dstdirslash}_rm.$$_
454d6c0b56eSmrg
455d6c0b56eSmrg    # Trap to clean up those temp files at exit.
456d6c0b56eSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457d6c0b56eSmrg
458d6c0b56eSmrg    # Copy the file name to the temp name.
45946845023Smrg    (umask $cp_umask &&
46046845023Smrg     { test -z "$stripcmd" || {
46146845023Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46246845023Smrg	 # which would cause strip to fail.
46346845023Smrg	 if test -z "$doit"; then
46446845023Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46546845023Smrg	 else
46646845023Smrg	   $doit touch "$dsttmp"
46746845023Smrg	 fi
46846845023Smrg       }
46946845023Smrg     } &&
47046845023Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471d6c0b56eSmrg
472d6c0b56eSmrg    # and set any options; do chmod last to preserve setuid bits.
473d6c0b56eSmrg    #
474d6c0b56eSmrg    # If any of these fail, we abort the whole thing.  If we want to
475d6c0b56eSmrg    # ignore errors from any of these, just make sure not to ignore
476d6c0b56eSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477d6c0b56eSmrg    #
478d6c0b56eSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479d6c0b56eSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480d6c0b56eSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481d6c0b56eSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482d6c0b56eSmrg
483d6c0b56eSmrg    # If -C, don't bother to copy if it wouldn't change the file.
484d6c0b56eSmrg    if $copy_on_change &&
485d6c0b56eSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
486d6c0b56eSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
487d6c0b56eSmrg       set -f &&
488d6c0b56eSmrg       set X $old && old=:$2:$4:$5:$6 &&
489d6c0b56eSmrg       set X $new && new=:$2:$4:$5:$6 &&
490d6c0b56eSmrg       set +f &&
491d6c0b56eSmrg       test "$old" = "$new" &&
492d6c0b56eSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493d6c0b56eSmrg    then
494d6c0b56eSmrg      rm -f "$dsttmp"
495d6c0b56eSmrg    else
496e49c54bcSmrg      # If $backupsuffix is set, and the file being installed
497e49c54bcSmrg      # already exists, attempt a backup.  Don't worry if it fails,
498e49c54bcSmrg      # e.g., if mv doesn't support -f.
499e49c54bcSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
500e49c54bcSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501e49c54bcSmrg      fi
502e49c54bcSmrg
503d6c0b56eSmrg      # Rename the file to the real destination.
504d6c0b56eSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505d6c0b56eSmrg
506d6c0b56eSmrg      # The rename failed, perhaps because mv can't rename something else
507d6c0b56eSmrg      # to itself, or perhaps because mv is so ancient that it does not
508d6c0b56eSmrg      # support -f.
509d6c0b56eSmrg      {
510d6c0b56eSmrg        # Now remove or move aside any old file at destination location.
511d6c0b56eSmrg        # We try this two ways since rm can't unlink itself on some
512d6c0b56eSmrg        # systems and the destination file might be busy for other
513d6c0b56eSmrg        # reasons.  In this case, the final cleanup might fail but the new
514d6c0b56eSmrg        # file should still install successfully.
515d6c0b56eSmrg        {
516d6c0b56eSmrg          test ! -f "$dst" ||
517e49c54bcSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
518d6c0b56eSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519e49c54bcSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520d6c0b56eSmrg          } ||
521d6c0b56eSmrg          { echo "$0: cannot unlink or rename $dst" >&2
522d6c0b56eSmrg            (exit 1); exit 1
523d6c0b56eSmrg          }
524d6c0b56eSmrg        } &&
525d6c0b56eSmrg
526d6c0b56eSmrg        # Now rename the file to the real destination.
527d6c0b56eSmrg        $doit $mvcmd "$dsttmp" "$dst"
528d6c0b56eSmrg      }
529d6c0b56eSmrg    fi || exit 1
530d6c0b56eSmrg
531d6c0b56eSmrg    trap '' 0
532d6c0b56eSmrg  fi
533d6c0b56eSmrgdone
534d6c0b56eSmrg
535d6c0b56eSmrg# Local variables:
53635d5b7c7Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537d6c0b56eSmrg# time-stamp-start: "scriptversion="
538d6c0b56eSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53935d5b7c7Smrg# time-stamp-time-zone: "UTC0"
540d6c0b56eSmrg# time-stamp-end: "; # UTC"
541d6c0b56eSmrg# End:
542