install-sh revision 35d5b7c7
1d6c0b56eSmrg#!/bin/sh
2d6c0b56eSmrg# install - install a program, script, or datafile
3d6c0b56eSmrg
435d5b7c7Smrgscriptversion=2018-03-11.20; # 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
72d6c0b56eSmrgchgrpcmd=
73d6c0b56eSmrgchmodcmd=$chmodprog
74d6c0b56eSmrgchowncmd=
75d6c0b56eSmrgmvcmd=$mvprog
76d6c0b56eSmrgrmcmd="$rmprog -f"
77d6c0b56eSmrgstripcmd=
78d6c0b56eSmrg
79d6c0b56eSmrgsrc=
80d6c0b56eSmrgdst=
81d6c0b56eSmrgdir_arg=
82d6c0b56eSmrgdst_arg=
83d6c0b56eSmrg
84d6c0b56eSmrgcopy_on_change=false
85d6c0b56eSmrgis_target_a_directory=possibly
86d6c0b56eSmrg
87d6c0b56eSmrgusage="\
88d6c0b56eSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89d6c0b56eSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90d6c0b56eSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91d6c0b56eSmrg   or: $0 [OPTION]... -d DIRECTORIES...
92d6c0b56eSmrg
93d6c0b56eSmrgIn the 1st form, copy SRCFILE to DSTFILE.
94d6c0b56eSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95d6c0b56eSmrgIn the 4th, create DIRECTORIES.
96d6c0b56eSmrg
97d6c0b56eSmrgOptions:
98d6c0b56eSmrg     --help     display this help and exit.
99d6c0b56eSmrg     --version  display version info and exit.
100d6c0b56eSmrg
101d6c0b56eSmrg  -c            (ignored)
102d6c0b56eSmrg  -C            install only if different (preserve the last data modification time)
103d6c0b56eSmrg  -d            create directories instead of installing files.
104d6c0b56eSmrg  -g GROUP      $chgrpprog installed files to GROUP.
105d6c0b56eSmrg  -m MODE       $chmodprog installed files to MODE.
106d6c0b56eSmrg  -o USER       $chownprog installed files to USER.
107d6c0b56eSmrg  -s            $stripprog installed files.
108d6c0b56eSmrg  -t DIRECTORY  install into DIRECTORY.
109d6c0b56eSmrg  -T            report an error if DSTFILE is a directory.
110d6c0b56eSmrg
111d6c0b56eSmrgEnvironment variables override the default commands:
112d6c0b56eSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113d6c0b56eSmrg  RMPROG STRIPPROG
114d6c0b56eSmrg"
115d6c0b56eSmrg
116d6c0b56eSmrgwhile test $# -ne 0; do
117d6c0b56eSmrg  case $1 in
118d6c0b56eSmrg    -c) ;;
119d6c0b56eSmrg
120d6c0b56eSmrg    -C) copy_on_change=true;;
121d6c0b56eSmrg
122d6c0b56eSmrg    -d) dir_arg=true;;
123d6c0b56eSmrg
124d6c0b56eSmrg    -g) chgrpcmd="$chgrpprog $2"
125d6c0b56eSmrg        shift;;
126d6c0b56eSmrg
127d6c0b56eSmrg    --help) echo "$usage"; exit $?;;
128d6c0b56eSmrg
129d6c0b56eSmrg    -m) mode=$2
130d6c0b56eSmrg        case $mode in
131d6c0b56eSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132d6c0b56eSmrg            echo "$0: invalid mode: $mode" >&2
133d6c0b56eSmrg            exit 1;;
134d6c0b56eSmrg        esac
135d6c0b56eSmrg        shift;;
136d6c0b56eSmrg
137d6c0b56eSmrg    -o) chowncmd="$chownprog $2"
138d6c0b56eSmrg        shift;;
139d6c0b56eSmrg
140d6c0b56eSmrg    -s) stripcmd=$stripprog;;
141d6c0b56eSmrg
142d6c0b56eSmrg    -t)
143d6c0b56eSmrg        is_target_a_directory=always
144d6c0b56eSmrg        dst_arg=$2
145d6c0b56eSmrg        # Protect names problematic for 'test' and other utilities.
146d6c0b56eSmrg        case $dst_arg in
147d6c0b56eSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148d6c0b56eSmrg        esac
149d6c0b56eSmrg        shift;;
150d6c0b56eSmrg
151d6c0b56eSmrg    -T) is_target_a_directory=never;;
152d6c0b56eSmrg
153d6c0b56eSmrg    --version) echo "$0 $scriptversion"; exit $?;;
154d6c0b56eSmrg
155d6c0b56eSmrg    --) shift
156d6c0b56eSmrg        break;;
157d6c0b56eSmrg
158d6c0b56eSmrg    -*) echo "$0: invalid option: $1" >&2
159d6c0b56eSmrg        exit 1;;
160d6c0b56eSmrg
161d6c0b56eSmrg    *)  break;;
162d6c0b56eSmrg  esac
163d6c0b56eSmrg  shift
164d6c0b56eSmrgdone
165d6c0b56eSmrg
166d6c0b56eSmrg# We allow the use of options -d and -T together, by making -d
167d6c0b56eSmrg# take the precedence; this is for compatibility with GNU install.
168d6c0b56eSmrg
169d6c0b56eSmrgif test -n "$dir_arg"; then
170d6c0b56eSmrg  if test -n "$dst_arg"; then
171d6c0b56eSmrg    echo "$0: target directory not allowed when installing a directory." >&2
172d6c0b56eSmrg    exit 1
173d6c0b56eSmrg  fi
174d6c0b56eSmrgfi
175d6c0b56eSmrg
176d6c0b56eSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177d6c0b56eSmrg  # When -d is used, all remaining arguments are directories to create.
178d6c0b56eSmrg  # When -t is used, the destination is already specified.
179d6c0b56eSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180d6c0b56eSmrg  for arg
181d6c0b56eSmrg  do
182d6c0b56eSmrg    if test -n "$dst_arg"; then
183d6c0b56eSmrg      # $@ is not empty: it contains at least $arg.
184d6c0b56eSmrg      set fnord "$@" "$dst_arg"
185d6c0b56eSmrg      shift # fnord
186d6c0b56eSmrg    fi
187d6c0b56eSmrg    shift # arg
188d6c0b56eSmrg    dst_arg=$arg
189d6c0b56eSmrg    # Protect names problematic for 'test' and other utilities.
190d6c0b56eSmrg    case $dst_arg in
191d6c0b56eSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192d6c0b56eSmrg    esac
193d6c0b56eSmrg  done
194d6c0b56eSmrgfi
195d6c0b56eSmrg
196d6c0b56eSmrgif test $# -eq 0; then
197d6c0b56eSmrg  if test -z "$dir_arg"; then
198d6c0b56eSmrg    echo "$0: no input file specified." >&2
199d6c0b56eSmrg    exit 1
200d6c0b56eSmrg  fi
201d6c0b56eSmrg  # It's OK to call 'install-sh -d' without argument.
202d6c0b56eSmrg  # This can happen when creating conditional directories.
203d6c0b56eSmrg  exit 0
204d6c0b56eSmrgfi
205d6c0b56eSmrg
206d6c0b56eSmrgif test -z "$dir_arg"; then
207d6c0b56eSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208d6c0b56eSmrg    if test ! -d "$dst_arg"; then
209d6c0b56eSmrg      echo "$0: $dst_arg: Is not a directory." >&2
210d6c0b56eSmrg      exit 1
211d6c0b56eSmrg    fi
212d6c0b56eSmrg  fi
213d6c0b56eSmrgfi
214d6c0b56eSmrg
215d6c0b56eSmrgif test -z "$dir_arg"; then
216d6c0b56eSmrg  do_exit='(exit $ret); exit $ret'
217d6c0b56eSmrg  trap "ret=129; $do_exit" 1
218d6c0b56eSmrg  trap "ret=130; $do_exit" 2
219d6c0b56eSmrg  trap "ret=141; $do_exit" 13
220d6c0b56eSmrg  trap "ret=143; $do_exit" 15
221d6c0b56eSmrg
222d6c0b56eSmrg  # Set umask so as not to create temps with too-generous modes.
223d6c0b56eSmrg  # However, 'strip' requires both read and write access to temps.
224d6c0b56eSmrg  case $mode in
225d6c0b56eSmrg    # Optimize common cases.
226d6c0b56eSmrg    *644) cp_umask=133;;
227d6c0b56eSmrg    *755) cp_umask=22;;
228d6c0b56eSmrg
229d6c0b56eSmrg    *[0-7])
230d6c0b56eSmrg      if test -z "$stripcmd"; then
231d6c0b56eSmrg        u_plus_rw=
232d6c0b56eSmrg      else
233d6c0b56eSmrg        u_plus_rw='% 200'
234d6c0b56eSmrg      fi
235d6c0b56eSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236d6c0b56eSmrg    *)
237d6c0b56eSmrg      if test -z "$stripcmd"; then
238d6c0b56eSmrg        u_plus_rw=
239d6c0b56eSmrg      else
240d6c0b56eSmrg        u_plus_rw=,u+rw
241d6c0b56eSmrg      fi
242d6c0b56eSmrg      cp_umask=$mode$u_plus_rw;;
243d6c0b56eSmrg  esac
244d6c0b56eSmrgfi
245d6c0b56eSmrg
246d6c0b56eSmrgfor src
247d6c0b56eSmrgdo
248d6c0b56eSmrg  # Protect names problematic for 'test' and other utilities.
249d6c0b56eSmrg  case $src in
250d6c0b56eSmrg    -* | [=\(\)!]) src=./$src;;
251d6c0b56eSmrg  esac
252d6c0b56eSmrg
253d6c0b56eSmrg  if test -n "$dir_arg"; then
254d6c0b56eSmrg    dst=$src
255d6c0b56eSmrg    dstdir=$dst
256d6c0b56eSmrg    test -d "$dstdir"
257d6c0b56eSmrg    dstdir_status=$?
258d6c0b56eSmrg  else
259d6c0b56eSmrg
260d6c0b56eSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261d6c0b56eSmrg    # might cause directories to be created, which would be especially bad
262d6c0b56eSmrg    # if $src (and thus $dsttmp) contains '*'.
263d6c0b56eSmrg    if test ! -f "$src" && test ! -d "$src"; then
264d6c0b56eSmrg      echo "$0: $src does not exist." >&2
265d6c0b56eSmrg      exit 1
266d6c0b56eSmrg    fi
267d6c0b56eSmrg
268d6c0b56eSmrg    if test -z "$dst_arg"; then
269d6c0b56eSmrg      echo "$0: no destination specified." >&2
270d6c0b56eSmrg      exit 1
271d6c0b56eSmrg    fi
272d6c0b56eSmrg    dst=$dst_arg
273d6c0b56eSmrg
27435d5b7c7Smrg    # If destination is a directory, append the input filename.
275d6c0b56eSmrg    if test -d "$dst"; then
276d6c0b56eSmrg      if test "$is_target_a_directory" = never; then
277d6c0b56eSmrg        echo "$0: $dst_arg: Is a directory" >&2
278d6c0b56eSmrg        exit 1
279d6c0b56eSmrg      fi
280d6c0b56eSmrg      dstdir=$dst
28135d5b7c7Smrg      dstbase=`basename "$src"`
28235d5b7c7Smrg      case $dst in
28335d5b7c7Smrg	*/) dst=$dst$dstbase;;
28435d5b7c7Smrg	*)  dst=$dst/$dstbase;;
28535d5b7c7Smrg      esac
286d6c0b56eSmrg      dstdir_status=0
287d6c0b56eSmrg    else
288d6c0b56eSmrg      dstdir=`dirname "$dst"`
289d6c0b56eSmrg      test -d "$dstdir"
290d6c0b56eSmrg      dstdir_status=$?
291d6c0b56eSmrg    fi
292d6c0b56eSmrg  fi
293d6c0b56eSmrg
29435d5b7c7Smrg  case $dstdir in
29535d5b7c7Smrg    */) dstdirslash=$dstdir;;
29635d5b7c7Smrg    *)  dstdirslash=$dstdir/;;
29735d5b7c7Smrg  esac
29835d5b7c7Smrg
299d6c0b56eSmrg  obsolete_mkdir_used=false
300d6c0b56eSmrg
301d6c0b56eSmrg  if test $dstdir_status != 0; then
302d6c0b56eSmrg    case $posix_mkdir in
303d6c0b56eSmrg      '')
304d6c0b56eSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
305d6c0b56eSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
306d6c0b56eSmrg        umask=`umask`
307d6c0b56eSmrg        case $stripcmd.$umask in
308d6c0b56eSmrg          # Optimize common cases.
309d6c0b56eSmrg          *[2367][2367]) mkdir_umask=$umask;;
310d6c0b56eSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
311d6c0b56eSmrg
312d6c0b56eSmrg          *[0-7])
313d6c0b56eSmrg            mkdir_umask=`expr $umask + 22 \
314d6c0b56eSmrg              - $umask % 100 % 40 + $umask % 20 \
315d6c0b56eSmrg              - $umask % 10 % 4 + $umask % 2
316d6c0b56eSmrg            `;;
317d6c0b56eSmrg          *) mkdir_umask=$umask,go-w;;
318d6c0b56eSmrg        esac
319d6c0b56eSmrg
320d6c0b56eSmrg        # With -d, create the new directory with the user-specified mode.
321d6c0b56eSmrg        # Otherwise, rely on $mkdir_umask.
322d6c0b56eSmrg        if test -n "$dir_arg"; then
323d6c0b56eSmrg          mkdir_mode=-m$mode
324d6c0b56eSmrg        else
325d6c0b56eSmrg          mkdir_mode=
326d6c0b56eSmrg        fi
327d6c0b56eSmrg
328d6c0b56eSmrg        posix_mkdir=false
329d6c0b56eSmrg        case $umask in
330d6c0b56eSmrg          *[123567][0-7][0-7])
331d6c0b56eSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
332d6c0b56eSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
333d6c0b56eSmrg            ;;
334d6c0b56eSmrg          *)
33535d5b7c7Smrg            # Note that $RANDOM variable is not portable (e.g. dash);  Use it
33635d5b7c7Smrg            # here however when possible just to lower collision chance.
337d6c0b56eSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
33835d5b7c7Smrg
339d6c0b56eSmrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
340d6c0b56eSmrg
34135d5b7c7Smrg            # Because "mkdir -p" follows existing symlinks and we likely work
34235d5b7c7Smrg            # directly in world-writeable /tmp, make sure that the '$tmpdir'
34335d5b7c7Smrg            # directory is successfully created first before we actually test
34435d5b7c7Smrg            # 'mkdir -p' feature.
345d6c0b56eSmrg            if (umask $mkdir_umask &&
346d6c0b56eSmrg                $mkdirprog $mkdir_mode "$tmpdir" &&
347d6c0b56eSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
348d6c0b56eSmrg            then
349d6c0b56eSmrg              if test -z "$dir_arg" || {
350d6c0b56eSmrg                   # Check for POSIX incompatibilities with -m.
351d6c0b56eSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
352d6c0b56eSmrg                   # other-writable bit of parent directory when it shouldn't.
353d6c0b56eSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
354d6c0b56eSmrg                   test_tmpdir="$tmpdir/a"
355d6c0b56eSmrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
356d6c0b56eSmrg                   case $ls_ld_tmpdir in
357d6c0b56eSmrg                     d????-?r-*) different_mode=700;;
358d6c0b56eSmrg                     d????-?--*) different_mode=755;;
359d6c0b56eSmrg                     *) false;;
360d6c0b56eSmrg                   esac &&
361d6c0b56eSmrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
362d6c0b56eSmrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
363d6c0b56eSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
364d6c0b56eSmrg                   }
365d6c0b56eSmrg                 }
366d6c0b56eSmrg              then posix_mkdir=:
367d6c0b56eSmrg              fi
368d6c0b56eSmrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
369d6c0b56eSmrg            else
370d6c0b56eSmrg              # Remove any dirs left behind by ancient mkdir implementations.
371d6c0b56eSmrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
372d6c0b56eSmrg            fi
373d6c0b56eSmrg            trap '' 0;;
374d6c0b56eSmrg        esac;;
375d6c0b56eSmrg    esac
376d6c0b56eSmrg
377d6c0b56eSmrg    if
378d6c0b56eSmrg      $posix_mkdir && (
379d6c0b56eSmrg        umask $mkdir_umask &&
380d6c0b56eSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
381d6c0b56eSmrg      )
382d6c0b56eSmrg    then :
383d6c0b56eSmrg    else
384d6c0b56eSmrg
385d6c0b56eSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
386d6c0b56eSmrg      # or it failed possibly due to a race condition.  Create the
387d6c0b56eSmrg      # directory the slow way, step by step, checking for races as we go.
388d6c0b56eSmrg
389d6c0b56eSmrg      case $dstdir in
390d6c0b56eSmrg        /*) prefix='/';;
391d6c0b56eSmrg        [-=\(\)!]*) prefix='./';;
392d6c0b56eSmrg        *)  prefix='';;
393d6c0b56eSmrg      esac
394d6c0b56eSmrg
395d6c0b56eSmrg      oIFS=$IFS
396d6c0b56eSmrg      IFS=/
397d6c0b56eSmrg      set -f
398d6c0b56eSmrg      set fnord $dstdir
399d6c0b56eSmrg      shift
400d6c0b56eSmrg      set +f
401d6c0b56eSmrg      IFS=$oIFS
402d6c0b56eSmrg
403d6c0b56eSmrg      prefixes=
404d6c0b56eSmrg
405d6c0b56eSmrg      for d
406d6c0b56eSmrg      do
407d6c0b56eSmrg        test X"$d" = X && continue
408d6c0b56eSmrg
409d6c0b56eSmrg        prefix=$prefix$d
410d6c0b56eSmrg        if test -d "$prefix"; then
411d6c0b56eSmrg          prefixes=
412d6c0b56eSmrg        else
413d6c0b56eSmrg          if $posix_mkdir; then
414d6c0b56eSmrg            (umask=$mkdir_umask &&
415d6c0b56eSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
416d6c0b56eSmrg            # Don't fail if two instances are running concurrently.
417d6c0b56eSmrg            test -d "$prefix" || exit 1
418d6c0b56eSmrg          else
419d6c0b56eSmrg            case $prefix in
420d6c0b56eSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
421d6c0b56eSmrg              *) qprefix=$prefix;;
422d6c0b56eSmrg            esac
423d6c0b56eSmrg            prefixes="$prefixes '$qprefix'"
424d6c0b56eSmrg          fi
425d6c0b56eSmrg        fi
426d6c0b56eSmrg        prefix=$prefix/
427d6c0b56eSmrg      done
428d6c0b56eSmrg
429d6c0b56eSmrg      if test -n "$prefixes"; then
430d6c0b56eSmrg        # Don't fail if two instances are running concurrently.
431d6c0b56eSmrg        (umask $mkdir_umask &&
432d6c0b56eSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
433d6c0b56eSmrg          test -d "$dstdir" || exit 1
434d6c0b56eSmrg        obsolete_mkdir_used=true
435d6c0b56eSmrg      fi
436d6c0b56eSmrg    fi
437d6c0b56eSmrg  fi
438d6c0b56eSmrg
439d6c0b56eSmrg  if test -n "$dir_arg"; then
440d6c0b56eSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
441d6c0b56eSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
442d6c0b56eSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
443d6c0b56eSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
444d6c0b56eSmrg  else
445d6c0b56eSmrg
446d6c0b56eSmrg    # Make a couple of temp file names in the proper directory.
44735d5b7c7Smrg    dsttmp=${dstdirslash}_inst.$$_
44835d5b7c7Smrg    rmtmp=${dstdirslash}_rm.$$_
449d6c0b56eSmrg
450d6c0b56eSmrg    # Trap to clean up those temp files at exit.
451d6c0b56eSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
452d6c0b56eSmrg
453d6c0b56eSmrg    # Copy the file name to the temp name.
454d6c0b56eSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
455d6c0b56eSmrg
456d6c0b56eSmrg    # and set any options; do chmod last to preserve setuid bits.
457d6c0b56eSmrg    #
458d6c0b56eSmrg    # If any of these fail, we abort the whole thing.  If we want to
459d6c0b56eSmrg    # ignore errors from any of these, just make sure not to ignore
460d6c0b56eSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
461d6c0b56eSmrg    #
462d6c0b56eSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
463d6c0b56eSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
464d6c0b56eSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
465d6c0b56eSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
466d6c0b56eSmrg
467d6c0b56eSmrg    # If -C, don't bother to copy if it wouldn't change the file.
468d6c0b56eSmrg    if $copy_on_change &&
469d6c0b56eSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
470d6c0b56eSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
471d6c0b56eSmrg       set -f &&
472d6c0b56eSmrg       set X $old && old=:$2:$4:$5:$6 &&
473d6c0b56eSmrg       set X $new && new=:$2:$4:$5:$6 &&
474d6c0b56eSmrg       set +f &&
475d6c0b56eSmrg       test "$old" = "$new" &&
476d6c0b56eSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
477d6c0b56eSmrg    then
478d6c0b56eSmrg      rm -f "$dsttmp"
479d6c0b56eSmrg    else
480d6c0b56eSmrg      # Rename the file to the real destination.
481d6c0b56eSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
482d6c0b56eSmrg
483d6c0b56eSmrg      # The rename failed, perhaps because mv can't rename something else
484d6c0b56eSmrg      # to itself, or perhaps because mv is so ancient that it does not
485d6c0b56eSmrg      # support -f.
486d6c0b56eSmrg      {
487d6c0b56eSmrg        # Now remove or move aside any old file at destination location.
488d6c0b56eSmrg        # We try this two ways since rm can't unlink itself on some
489d6c0b56eSmrg        # systems and the destination file might be busy for other
490d6c0b56eSmrg        # reasons.  In this case, the final cleanup might fail but the new
491d6c0b56eSmrg        # file should still install successfully.
492d6c0b56eSmrg        {
493d6c0b56eSmrg          test ! -f "$dst" ||
494d6c0b56eSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
495d6c0b56eSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
496d6c0b56eSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
497d6c0b56eSmrg          } ||
498d6c0b56eSmrg          { echo "$0: cannot unlink or rename $dst" >&2
499d6c0b56eSmrg            (exit 1); exit 1
500d6c0b56eSmrg          }
501d6c0b56eSmrg        } &&
502d6c0b56eSmrg
503d6c0b56eSmrg        # Now rename the file to the real destination.
504d6c0b56eSmrg        $doit $mvcmd "$dsttmp" "$dst"
505d6c0b56eSmrg      }
506d6c0b56eSmrg    fi || exit 1
507d6c0b56eSmrg
508d6c0b56eSmrg    trap '' 0
509d6c0b56eSmrg  fi
510d6c0b56eSmrgdone
511d6c0b56eSmrg
512d6c0b56eSmrg# Local variables:
51335d5b7c7Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
514d6c0b56eSmrg# time-stamp-start: "scriptversion="
515d6c0b56eSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
51635d5b7c7Smrg# time-stamp-time-zone: "UTC0"
517d6c0b56eSmrg# time-stamp-end: "; # UTC"
518d6c0b56eSmrg# End:
519