install-sh revision f9c28e31
1fc89c0fbSmrg#!/bin/sh
2fc89c0fbSmrg# install - install a program, script, or datafile
3fc89c0fbSmrg
4f9c28e31Smrgscriptversion=2018-03-11.20; # UTC
5fc89c0fbSmrg
6fc89c0fbSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7fc89c0fbSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8fc89c0fbSmrg# following copyright and license.
9fc89c0fbSmrg#
10fc89c0fbSmrg# Copyright (C) 1994 X Consortium
11fc89c0fbSmrg#
12fc89c0fbSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13fc89c0fbSmrg# of this software and associated documentation files (the "Software"), to
14fc89c0fbSmrg# deal in the Software without restriction, including without limitation the
15fc89c0fbSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16fc89c0fbSmrg# sell copies of the Software, and to permit persons to whom the Software is
17fc89c0fbSmrg# furnished to do so, subject to the following conditions:
18fc89c0fbSmrg#
19fc89c0fbSmrg# The above copyright notice and this permission notice shall be included in
20fc89c0fbSmrg# all copies or substantial portions of the Software.
21fc89c0fbSmrg#
22fc89c0fbSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23fc89c0fbSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24fc89c0fbSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25fc89c0fbSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26fc89c0fbSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27fc89c0fbSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28fc89c0fbSmrg#
29fc89c0fbSmrg# Except as contained in this notice, the name of the X Consortium shall not
30fc89c0fbSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31fc89c0fbSmrg# ings in this Software without prior written authorization from the X Consor-
32fc89c0fbSmrg# tium.
33fc89c0fbSmrg#
34fc89c0fbSmrg#
35fc89c0fbSmrg# FSF changes to this file are in the public domain.
36fc89c0fbSmrg#
37fc89c0fbSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38576bbdfcSmrg# 'make' implicit rules from creating a file called install from it
39fc89c0fbSmrg# when there is no Makefile.
40fc89c0fbSmrg#
41fc89c0fbSmrg# This script is compatible with the BSD install script, but was written
42fc89c0fbSmrg# from scratch.
43fc89c0fbSmrg
4481676fe2Smrgtab='	'
45fc89c0fbSmrgnl='
46fc89c0fbSmrg'
4781676fe2SmrgIFS=" $tab$nl"
48fc89c0fbSmrg
4981676fe2Smrg# Set DOITPROG to "echo" to test this script.
50fc89c0fbSmrg
5191ec45ceSmrgdoit=${DOITPROG-}
5281676fe2Smrgdoit_exec=${doit:-exec}
53fc89c0fbSmrg
54fc89c0fbSmrg# Put in absolute file names if you don't have them in your path;
55fc89c0fbSmrg# or use environment vars.
56fc89c0fbSmrg
5791ec45ceSmrgchgrpprog=${CHGRPPROG-chgrp}
5891ec45ceSmrgchmodprog=${CHMODPROG-chmod}
5991ec45ceSmrgchownprog=${CHOWNPROG-chown}
6091ec45ceSmrgcmpprog=${CMPPROG-cmp}
6191ec45ceSmrgcpprog=${CPPROG-cp}
6291ec45ceSmrgmkdirprog=${MKDIRPROG-mkdir}
6391ec45ceSmrgmvprog=${MVPROG-mv}
6491ec45ceSmrgrmprog=${RMPROG-rm}
6591ec45ceSmrgstripprog=${STRIPPROG-strip}
6691ec45ceSmrg
67fc89c0fbSmrgposix_mkdir=
68fc89c0fbSmrg
69fc89c0fbSmrg# Desired mode of installed file.
70fc89c0fbSmrgmode=0755
71fc89c0fbSmrg
7291ec45ceSmrgchgrpcmd=
73fc89c0fbSmrgchmodcmd=$chmodprog
74fc89c0fbSmrgchowncmd=
7591ec45ceSmrgmvcmd=$mvprog
76fc89c0fbSmrgrmcmd="$rmprog -f"
7791ec45ceSmrgstripcmd=
7891ec45ceSmrg
79fc89c0fbSmrgsrc=
80fc89c0fbSmrgdst=
81fc89c0fbSmrgdir_arg=
8291ec45ceSmrgdst_arg=
8391ec45ceSmrg
8491ec45ceSmrgcopy_on_change=false
8581676fe2Smrgis_target_a_directory=possibly
86fc89c0fbSmrg
8791ec45ceSmrgusage="\
8891ec45ceSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89fc89c0fbSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90fc89c0fbSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91fc89c0fbSmrg   or: $0 [OPTION]... -d DIRECTORIES...
92fc89c0fbSmrg
93fc89c0fbSmrgIn the 1st form, copy SRCFILE to DSTFILE.
94fc89c0fbSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95fc89c0fbSmrgIn the 4th, create DIRECTORIES.
96fc89c0fbSmrg
97fc89c0fbSmrgOptions:
9891ec45ceSmrg     --help     display this help and exit.
9991ec45ceSmrg     --version  display version info and exit.
10091ec45ceSmrg
10191ec45ceSmrg  -c            (ignored)
10291ec45ceSmrg  -C            install only if different (preserve the last data modification time)
10391ec45ceSmrg  -d            create directories instead of installing files.
10491ec45ceSmrg  -g GROUP      $chgrpprog installed files to GROUP.
10591ec45ceSmrg  -m MODE       $chmodprog installed files to MODE.
10691ec45ceSmrg  -o USER       $chownprog installed files to USER.
10791ec45ceSmrg  -s            $stripprog installed files.
10891ec45ceSmrg  -t DIRECTORY  install into DIRECTORY.
10991ec45ceSmrg  -T            report an error if DSTFILE is a directory.
110fc89c0fbSmrg
111fc89c0fbSmrgEnvironment variables override the default commands:
11291ec45ceSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
11391ec45ceSmrg  RMPROG STRIPPROG
114fc89c0fbSmrg"
115fc89c0fbSmrg
116fc89c0fbSmrgwhile test $# -ne 0; do
117fc89c0fbSmrg  case $1 in
11891ec45ceSmrg    -c) ;;
11991ec45ceSmrg
12091ec45ceSmrg    -C) copy_on_change=true;;
121fc89c0fbSmrg
12291ec45ceSmrg    -d) dir_arg=true;;
123fc89c0fbSmrg
124fc89c0fbSmrg    -g) chgrpcmd="$chgrpprog $2"
12581676fe2Smrg        shift;;
126fc89c0fbSmrg
127fc89c0fbSmrg    --help) echo "$usage"; exit $?;;
128fc89c0fbSmrg
129fc89c0fbSmrg    -m) mode=$2
13081676fe2Smrg        case $mode in
13181676fe2Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
13281676fe2Smrg            echo "$0: invalid mode: $mode" >&2
13381676fe2Smrg            exit 1;;
13481676fe2Smrg        esac
13581676fe2Smrg        shift;;
136fc89c0fbSmrg
137fc89c0fbSmrg    -o) chowncmd="$chownprog $2"
13881676fe2Smrg        shift;;
139fc89c0fbSmrg
14091ec45ceSmrg    -s) stripcmd=$stripprog;;
141fc89c0fbSmrg
14281676fe2Smrg    -t)
14381676fe2Smrg        is_target_a_directory=always
14481676fe2Smrg        dst_arg=$2
14581676fe2Smrg        # Protect names problematic for 'test' and other utilities.
14681676fe2Smrg        case $dst_arg in
14781676fe2Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14881676fe2Smrg        esac
14981676fe2Smrg        shift;;
150fc89c0fbSmrg
15181676fe2Smrg    -T) is_target_a_directory=never;;
152fc89c0fbSmrg
153fc89c0fbSmrg    --version) echo "$0 $scriptversion"; exit $?;;
154fc89c0fbSmrg
15581676fe2Smrg    --) shift
15681676fe2Smrg        break;;
157fc89c0fbSmrg
15881676fe2Smrg    -*) echo "$0: invalid option: $1" >&2
15981676fe2Smrg        exit 1;;
160fc89c0fbSmrg
161fc89c0fbSmrg    *)  break;;
162fc89c0fbSmrg  esac
16391ec45ceSmrg  shift
164fc89c0fbSmrgdone
165fc89c0fbSmrg
16681676fe2Smrg# We allow the use of options -d and -T together, by making -d
16781676fe2Smrg# take the precedence; this is for compatibility with GNU install.
16881676fe2Smrg
16981676fe2Smrgif test -n "$dir_arg"; then
17081676fe2Smrg  if test -n "$dst_arg"; then
17181676fe2Smrg    echo "$0: target directory not allowed when installing a directory." >&2
17281676fe2Smrg    exit 1
17381676fe2Smrg  fi
17481676fe2Smrgfi
17581676fe2Smrg
17691ec45ceSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177fc89c0fbSmrg  # When -d is used, all remaining arguments are directories to create.
178fc89c0fbSmrg  # When -t is used, the destination is already specified.
179fc89c0fbSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180fc89c0fbSmrg  for arg
181fc89c0fbSmrg  do
18291ec45ceSmrg    if test -n "$dst_arg"; then
183fc89c0fbSmrg      # $@ is not empty: it contains at least $arg.
18491ec45ceSmrg      set fnord "$@" "$dst_arg"
185fc89c0fbSmrg      shift # fnord
186fc89c0fbSmrg    fi
187fc89c0fbSmrg    shift # arg
18891ec45ceSmrg    dst_arg=$arg
189576bbdfcSmrg    # Protect names problematic for 'test' and other utilities.
190576bbdfcSmrg    case $dst_arg in
191576bbdfcSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192576bbdfcSmrg    esac
193fc89c0fbSmrg  done
194fc89c0fbSmrgfi
195fc89c0fbSmrg
196fc89c0fbSmrgif test $# -eq 0; then
197fc89c0fbSmrg  if test -z "$dir_arg"; then
198fc89c0fbSmrg    echo "$0: no input file specified." >&2
199fc89c0fbSmrg    exit 1
200fc89c0fbSmrg  fi
201576bbdfcSmrg  # It's OK to call 'install-sh -d' without argument.
202fc89c0fbSmrg  # This can happen when creating conditional directories.
203fc89c0fbSmrg  exit 0
204fc89c0fbSmrgfi
205fc89c0fbSmrg
20681676fe2Smrgif test -z "$dir_arg"; then
20781676fe2Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20881676fe2Smrg    if test ! -d "$dst_arg"; then
20981676fe2Smrg      echo "$0: $dst_arg: Is not a directory." >&2
21081676fe2Smrg      exit 1
21181676fe2Smrg    fi
21281676fe2Smrg  fi
21381676fe2Smrgfi
21481676fe2Smrg
215fc89c0fbSmrgif test -z "$dir_arg"; then
216576bbdfcSmrg  do_exit='(exit $ret); exit $ret'
217576bbdfcSmrg  trap "ret=129; $do_exit" 1
218576bbdfcSmrg  trap "ret=130; $do_exit" 2
219576bbdfcSmrg  trap "ret=141; $do_exit" 13
220576bbdfcSmrg  trap "ret=143; $do_exit" 15
221fc89c0fbSmrg
222fc89c0fbSmrg  # Set umask so as not to create temps with too-generous modes.
223fc89c0fbSmrg  # However, 'strip' requires both read and write access to temps.
224fc89c0fbSmrg  case $mode in
225fc89c0fbSmrg    # Optimize common cases.
226fc89c0fbSmrg    *644) cp_umask=133;;
227fc89c0fbSmrg    *755) cp_umask=22;;
228fc89c0fbSmrg
229fc89c0fbSmrg    *[0-7])
230fc89c0fbSmrg      if test -z "$stripcmd"; then
23181676fe2Smrg        u_plus_rw=
232fc89c0fbSmrg      else
23381676fe2Smrg        u_plus_rw='% 200'
234fc89c0fbSmrg      fi
235fc89c0fbSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236fc89c0fbSmrg    *)
237fc89c0fbSmrg      if test -z "$stripcmd"; then
23881676fe2Smrg        u_plus_rw=
239fc89c0fbSmrg      else
24081676fe2Smrg        u_plus_rw=,u+rw
241fc89c0fbSmrg      fi
242fc89c0fbSmrg      cp_umask=$mode$u_plus_rw;;
243fc89c0fbSmrg  esac
244fc89c0fbSmrgfi
245fc89c0fbSmrg
246fc89c0fbSmrgfor src
247fc89c0fbSmrgdo
248576bbdfcSmrg  # Protect names problematic for 'test' and other utilities.
249fc89c0fbSmrg  case $src in
250576bbdfcSmrg    -* | [=\(\)!]) src=./$src;;
251fc89c0fbSmrg  esac
252fc89c0fbSmrg
253fc89c0fbSmrg  if test -n "$dir_arg"; then
254fc89c0fbSmrg    dst=$src
255fc89c0fbSmrg    dstdir=$dst
256fc89c0fbSmrg    test -d "$dstdir"
257fc89c0fbSmrg    dstdir_status=$?
258fc89c0fbSmrg  else
259fc89c0fbSmrg
260fc89c0fbSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261fc89c0fbSmrg    # might cause directories to be created, which would be especially bad
262fc89c0fbSmrg    # if $src (and thus $dsttmp) contains '*'.
263fc89c0fbSmrg    if test ! -f "$src" && test ! -d "$src"; then
264fc89c0fbSmrg      echo "$0: $src does not exist." >&2
265fc89c0fbSmrg      exit 1
266fc89c0fbSmrg    fi
267fc89c0fbSmrg
26891ec45ceSmrg    if test -z "$dst_arg"; then
269fc89c0fbSmrg      echo "$0: no destination specified." >&2
270fc89c0fbSmrg      exit 1
271fc89c0fbSmrg    fi
27291ec45ceSmrg    dst=$dst_arg
273fc89c0fbSmrg
274f9c28e31Smrg    # If destination is a directory, append the input filename.
275fc89c0fbSmrg    if test -d "$dst"; then
27681676fe2Smrg      if test "$is_target_a_directory" = never; then
27781676fe2Smrg        echo "$0: $dst_arg: Is a directory" >&2
27881676fe2Smrg        exit 1
279fc89c0fbSmrg      fi
280fc89c0fbSmrg      dstdir=$dst
281f9c28e31Smrg      dstbase=`basename "$src"`
282f9c28e31Smrg      case $dst in
283f9c28e31Smrg	*/) dst=$dst$dstbase;;
284f9c28e31Smrg	*)  dst=$dst/$dstbase;;
285f9c28e31Smrg      esac
286fc89c0fbSmrg      dstdir_status=0
287fc89c0fbSmrg    else
28881676fe2Smrg      dstdir=`dirname "$dst"`
289fc89c0fbSmrg      test -d "$dstdir"
290fc89c0fbSmrg      dstdir_status=$?
291fc89c0fbSmrg    fi
292fc89c0fbSmrg  fi
293fc89c0fbSmrg
294f9c28e31Smrg  case $dstdir in
295f9c28e31Smrg    */) dstdirslash=$dstdir;;
296f9c28e31Smrg    *)  dstdirslash=$dstdir/;;
297f9c28e31Smrg  esac
298f9c28e31Smrg
299fc89c0fbSmrg  obsolete_mkdir_used=false
300fc89c0fbSmrg
301fc89c0fbSmrg  if test $dstdir_status != 0; then
302fc89c0fbSmrg    case $posix_mkdir in
303fc89c0fbSmrg      '')
30481676fe2Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
30581676fe2Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
30681676fe2Smrg        umask=`umask`
30781676fe2Smrg        case $stripcmd.$umask in
30881676fe2Smrg          # Optimize common cases.
30981676fe2Smrg          *[2367][2367]) mkdir_umask=$umask;;
31081676fe2Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
31181676fe2Smrg
31281676fe2Smrg          *[0-7])
31381676fe2Smrg            mkdir_umask=`expr $umask + 22 \
31481676fe2Smrg              - $umask % 100 % 40 + $umask % 20 \
31581676fe2Smrg              - $umask % 10 % 4 + $umask % 2
31681676fe2Smrg            `;;
31781676fe2Smrg          *) mkdir_umask=$umask,go-w;;
31881676fe2Smrg        esac
31981676fe2Smrg
32081676fe2Smrg        # With -d, create the new directory with the user-specified mode.
32181676fe2Smrg        # Otherwise, rely on $mkdir_umask.
32281676fe2Smrg        if test -n "$dir_arg"; then
32381676fe2Smrg          mkdir_mode=-m$mode
32481676fe2Smrg        else
32581676fe2Smrg          mkdir_mode=
32681676fe2Smrg        fi
32781676fe2Smrg
32881676fe2Smrg        posix_mkdir=false
32981676fe2Smrg        case $umask in
33081676fe2Smrg          *[123567][0-7][0-7])
33181676fe2Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
33281676fe2Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
33381676fe2Smrg            ;;
33481676fe2Smrg          *)
335f9c28e31Smrg            # Note that $RANDOM variable is not portable (e.g. dash);  Use it
336f9c28e31Smrg            # here however when possible just to lower collision chance.
33781676fe2Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
33881676fe2Smrg
339f9c28e31Smrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
340f9c28e31Smrg
341f9c28e31Smrg            # Because "mkdir -p" follows existing symlinks and we likely work
342f9c28e31Smrg            # directly in world-writeable /tmp, make sure that the '$tmpdir'
343f9c28e31Smrg            # directory is successfully created first before we actually test
344f9c28e31Smrg            # 'mkdir -p' feature.
34581676fe2Smrg            if (umask $mkdir_umask &&
346f9c28e31Smrg                $mkdirprog $mkdir_mode "$tmpdir" &&
347f9c28e31Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
34881676fe2Smrg            then
34981676fe2Smrg              if test -z "$dir_arg" || {
35081676fe2Smrg                   # Check for POSIX incompatibilities with -m.
35181676fe2Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35281676fe2Smrg                   # other-writable bit of parent directory when it shouldn't.
35381676fe2Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
354f9c28e31Smrg                   test_tmpdir="$tmpdir/a"
355f9c28e31Smrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
35681676fe2Smrg                   case $ls_ld_tmpdir in
35781676fe2Smrg                     d????-?r-*) different_mode=700;;
35881676fe2Smrg                     d????-?--*) different_mode=755;;
35981676fe2Smrg                     *) false;;
36081676fe2Smrg                   esac &&
361f9c28e31Smrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
362f9c28e31Smrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36381676fe2Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
36481676fe2Smrg                   }
36581676fe2Smrg                 }
36681676fe2Smrg              then posix_mkdir=:
36781676fe2Smrg              fi
368f9c28e31Smrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
36981676fe2Smrg            else
37081676fe2Smrg              # Remove any dirs left behind by ancient mkdir implementations.
371f9c28e31Smrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37281676fe2Smrg            fi
37381676fe2Smrg            trap '' 0;;
37481676fe2Smrg        esac;;
375fc89c0fbSmrg    esac
376fc89c0fbSmrg
377fc89c0fbSmrg    if
378fc89c0fbSmrg      $posix_mkdir && (
37981676fe2Smrg        umask $mkdir_umask &&
38081676fe2Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
381fc89c0fbSmrg      )
382fc89c0fbSmrg    then :
383fc89c0fbSmrg    else
384fc89c0fbSmrg
385fc89c0fbSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
386fc89c0fbSmrg      # or it failed possibly due to a race condition.  Create the
387fc89c0fbSmrg      # directory the slow way, step by step, checking for races as we go.
388fc89c0fbSmrg
389fc89c0fbSmrg      case $dstdir in
39081676fe2Smrg        /*) prefix='/';;
39181676fe2Smrg        [-=\(\)!]*) prefix='./';;
39281676fe2Smrg        *)  prefix='';;
393fc89c0fbSmrg      esac
394fc89c0fbSmrg
395fc89c0fbSmrg      oIFS=$IFS
396fc89c0fbSmrg      IFS=/
39781676fe2Smrg      set -f
398fc89c0fbSmrg      set fnord $dstdir
399fc89c0fbSmrg      shift
40081676fe2Smrg      set +f
401fc89c0fbSmrg      IFS=$oIFS
402fc89c0fbSmrg
403fc89c0fbSmrg      prefixes=
404fc89c0fbSmrg
405fc89c0fbSmrg      for d
406fc89c0fbSmrg      do
40781676fe2Smrg        test X"$d" = X && continue
40881676fe2Smrg
40981676fe2Smrg        prefix=$prefix$d
41081676fe2Smrg        if test -d "$prefix"; then
41181676fe2Smrg          prefixes=
41281676fe2Smrg        else
41381676fe2Smrg          if $posix_mkdir; then
41481676fe2Smrg            (umask=$mkdir_umask &&
41581676fe2Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
41681676fe2Smrg            # Don't fail if two instances are running concurrently.
41781676fe2Smrg            test -d "$prefix" || exit 1
41881676fe2Smrg          else
41981676fe2Smrg            case $prefix in
42081676fe2Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42181676fe2Smrg              *) qprefix=$prefix;;
42281676fe2Smrg            esac
42381676fe2Smrg            prefixes="$prefixes '$qprefix'"
42481676fe2Smrg          fi
42581676fe2Smrg        fi
42681676fe2Smrg        prefix=$prefix/
427fc89c0fbSmrg      done
428fc89c0fbSmrg
429fc89c0fbSmrg      if test -n "$prefixes"; then
43081676fe2Smrg        # Don't fail if two instances are running concurrently.
43181676fe2Smrg        (umask $mkdir_umask &&
43281676fe2Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43381676fe2Smrg          test -d "$dstdir" || exit 1
43481676fe2Smrg        obsolete_mkdir_used=true
435fc89c0fbSmrg      fi
436fc89c0fbSmrg    fi
437fc89c0fbSmrg  fi
438fc89c0fbSmrg
439fc89c0fbSmrg  if test -n "$dir_arg"; then
440fc89c0fbSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
441fc89c0fbSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
442fc89c0fbSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
443fc89c0fbSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
444fc89c0fbSmrg  else
445fc89c0fbSmrg
446fc89c0fbSmrg    # Make a couple of temp file names in the proper directory.
447f9c28e31Smrg    dsttmp=${dstdirslash}_inst.$$_
448f9c28e31Smrg    rmtmp=${dstdirslash}_rm.$$_
449fc89c0fbSmrg
450fc89c0fbSmrg    # Trap to clean up those temp files at exit.
451fc89c0fbSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
452fc89c0fbSmrg
453fc89c0fbSmrg    # Copy the file name to the temp name.
454f9c28e31Smrg    (umask $cp_umask &&
455f9c28e31Smrg     { test -z "$stripcmd" || {
456f9c28e31Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
457f9c28e31Smrg	 # which would cause strip to fail.
458f9c28e31Smrg	 if test -z "$doit"; then
459f9c28e31Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
460f9c28e31Smrg	 else
461f9c28e31Smrg	   $doit touch "$dsttmp"
462f9c28e31Smrg	 fi
463f9c28e31Smrg       }
464f9c28e31Smrg     } &&
465f9c28e31Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
466fc89c0fbSmrg
467fc89c0fbSmrg    # and set any options; do chmod last to preserve setuid bits.
468fc89c0fbSmrg    #
469fc89c0fbSmrg    # If any of these fail, we abort the whole thing.  If we want to
470fc89c0fbSmrg    # ignore errors from any of these, just make sure not to ignore
471fc89c0fbSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
472fc89c0fbSmrg    #
47391ec45ceSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
47491ec45ceSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
47591ec45ceSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
47691ec45ceSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
47791ec45ceSmrg
47891ec45ceSmrg    # If -C, don't bother to copy if it wouldn't change the file.
47991ec45ceSmrg    if $copy_on_change &&
48081676fe2Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48181676fe2Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48281676fe2Smrg       set -f &&
48391ec45ceSmrg       set X $old && old=:$2:$4:$5:$6 &&
48491ec45ceSmrg       set X $new && new=:$2:$4:$5:$6 &&
48581676fe2Smrg       set +f &&
48691ec45ceSmrg       test "$old" = "$new" &&
48791ec45ceSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
48891ec45ceSmrg    then
48991ec45ceSmrg      rm -f "$dsttmp"
49091ec45ceSmrg    else
49191ec45ceSmrg      # Rename the file to the real destination.
49291ec45ceSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
49391ec45ceSmrg
49491ec45ceSmrg      # The rename failed, perhaps because mv can't rename something else
49591ec45ceSmrg      # to itself, or perhaps because mv is so ancient that it does not
49691ec45ceSmrg      # support -f.
49791ec45ceSmrg      {
49881676fe2Smrg        # Now remove or move aside any old file at destination location.
49981676fe2Smrg        # We try this two ways since rm can't unlink itself on some
50081676fe2Smrg        # systems and the destination file might be busy for other
50181676fe2Smrg        # reasons.  In this case, the final cleanup might fail but the new
50281676fe2Smrg        # file should still install successfully.
50381676fe2Smrg        {
50481676fe2Smrg          test ! -f "$dst" ||
50581676fe2Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
50681676fe2Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
50781676fe2Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
50881676fe2Smrg          } ||
50981676fe2Smrg          { echo "$0: cannot unlink or rename $dst" >&2
51081676fe2Smrg            (exit 1); exit 1
51181676fe2Smrg          }
51281676fe2Smrg        } &&
51381676fe2Smrg
51481676fe2Smrg        # Now rename the file to the real destination.
51581676fe2Smrg        $doit $mvcmd "$dsttmp" "$dst"
51691ec45ceSmrg      }
51791ec45ceSmrg    fi || exit 1
518fc89c0fbSmrg
519fc89c0fbSmrg    trap '' 0
520fc89c0fbSmrg  fi
521fc89c0fbSmrgdone
522fc89c0fbSmrg
523fc89c0fbSmrg# Local variables:
524f9c28e31Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
525fc89c0fbSmrg# time-stamp-start: "scriptversion="
526fc89c0fbSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
527f9c28e31Smrg# time-stamp-time-zone: "UTC0"
52891ec45ceSmrg# time-stamp-end: "; # UTC"
529fc89c0fbSmrg# End:
530