install-sh revision 4e8f48c7
1c43cc173Smrg#!/bin/sh
2c43cc173Smrg# install - install a program, script, or datafile
3c43cc173Smrg
44e8f48c7Smrgscriptversion=2020-11-14.01; # UTC
5c43cc173Smrg
6c43cc173Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7c43cc173Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8c43cc173Smrg# following copyright and license.
9c43cc173Smrg#
10c43cc173Smrg# Copyright (C) 1994 X Consortium
11c43cc173Smrg#
12c43cc173Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13c43cc173Smrg# of this software and associated documentation files (the "Software"), to
14c43cc173Smrg# deal in the Software without restriction, including without limitation the
15c43cc173Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16c43cc173Smrg# sell copies of the Software, and to permit persons to whom the Software is
17c43cc173Smrg# furnished to do so, subject to the following conditions:
18c43cc173Smrg#
19c43cc173Smrg# The above copyright notice and this permission notice shall be included in
20c43cc173Smrg# all copies or substantial portions of the Software.
21c43cc173Smrg#
22c43cc173Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c43cc173Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c43cc173Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25c43cc173Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26c43cc173Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27c43cc173Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28c43cc173Smrg#
29c43cc173Smrg# Except as contained in this notice, the name of the X Consortium shall not
30c43cc173Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31c43cc173Smrg# ings in this Software without prior written authorization from the X Consor-
32c43cc173Smrg# tium.
33c43cc173Smrg#
34c43cc173Smrg#
35c43cc173Smrg# FSF changes to this file are in the public domain.
36c43cc173Smrg#
37c43cc173Smrg# Calling this script install-sh is preferred over install.sh, to prevent
38f1ee322dSmrg# 'make' implicit rules from creating a file called install from it
39c43cc173Smrg# when there is no Makefile.
40c43cc173Smrg#
41c43cc173Smrg# This script is compatible with the BSD install script, but was written
42c43cc173Smrg# from scratch.
43c43cc173Smrg
4448e5ce07Smrgtab='	'
45c43cc173Smrgnl='
46c43cc173Smrg'
4748e5ce07SmrgIFS=" $tab$nl"
48c43cc173Smrg
4948e5ce07Smrg# Set DOITPROG to "echo" to test this script.
50c43cc173Smrg
51c27c18e8Smrgdoit=${DOITPROG-}
5248e5ce07Smrgdoit_exec=${doit:-exec}
53c43cc173Smrg
54c43cc173Smrg# Put in absolute file names if you don't have them in your path;
55c43cc173Smrg# or use environment vars.
56c43cc173Smrg
57c27c18e8Smrgchgrpprog=${CHGRPPROG-chgrp}
58c27c18e8Smrgchmodprog=${CHMODPROG-chmod}
59c27c18e8Smrgchownprog=${CHOWNPROG-chown}
60c27c18e8Smrgcmpprog=${CMPPROG-cmp}
61c27c18e8Smrgcpprog=${CPPROG-cp}
62c27c18e8Smrgmkdirprog=${MKDIRPROG-mkdir}
63c27c18e8Smrgmvprog=${MVPROG-mv}
64c27c18e8Smrgrmprog=${RMPROG-rm}
65c27c18e8Smrgstripprog=${STRIPPROG-strip}
66c27c18e8Smrg
67c43cc173Smrgposix_mkdir=
68c43cc173Smrg
69c43cc173Smrg# Desired mode of installed file.
70c43cc173Smrgmode=0755
71c43cc173Smrg
724e8f48c7Smrg# Create dirs (including intermediate dirs) using mode 755.
734e8f48c7Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
744e8f48c7Smrgmkdir_umask=22
754e8f48c7Smrg
764e8f48c7Smrgbackupsuffix=
77c27c18e8Smrgchgrpcmd=
78c43cc173Smrgchmodcmd=$chmodprog
79c43cc173Smrgchowncmd=
80c27c18e8Smrgmvcmd=$mvprog
81c43cc173Smrgrmcmd="$rmprog -f"
82c27c18e8Smrgstripcmd=
83c27c18e8Smrg
84c43cc173Smrgsrc=
85c43cc173Smrgdst=
86c43cc173Smrgdir_arg=
87c27c18e8Smrgdst_arg=
88c27c18e8Smrg
89c27c18e8Smrgcopy_on_change=false
9048e5ce07Smrgis_target_a_directory=possibly
91c43cc173Smrg
92c27c18e8Smrgusage="\
93c27c18e8SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94c43cc173Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95c43cc173Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96c43cc173Smrg   or: $0 [OPTION]... -d DIRECTORIES...
97c43cc173Smrg
98c43cc173SmrgIn the 1st form, copy SRCFILE to DSTFILE.
99c43cc173SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100c43cc173SmrgIn the 4th, create DIRECTORIES.
101c43cc173Smrg
102c43cc173SmrgOptions:
103c27c18e8Smrg     --help     display this help and exit.
104c27c18e8Smrg     --version  display version info and exit.
105c27c18e8Smrg
106c27c18e8Smrg  -c            (ignored)
1074e8f48c7Smrg  -C            install only if different (preserve data modification time)
108c27c18e8Smrg  -d            create directories instead of installing files.
109c27c18e8Smrg  -g GROUP      $chgrpprog installed files to GROUP.
110c27c18e8Smrg  -m MODE       $chmodprog installed files to MODE.
111c27c18e8Smrg  -o USER       $chownprog installed files to USER.
1124e8f48c7Smrg  -p            pass -p to $cpprog.
113c27c18e8Smrg  -s            $stripprog installed files.
1144e8f48c7Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115c27c18e8Smrg  -t DIRECTORY  install into DIRECTORY.
116c27c18e8Smrg  -T            report an error if DSTFILE is a directory.
117c43cc173Smrg
118c43cc173SmrgEnvironment variables override the default commands:
119c27c18e8Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120c27c18e8Smrg  RMPROG STRIPPROG
1214e8f48c7Smrg
1224e8f48c7SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
1234e8f48c7Smrgit's up to you to specify -f if you want it.
1244e8f48c7Smrg
1254e8f48c7SmrgIf -S is not specified, no backups are attempted.
1264e8f48c7Smrg
1274e8f48c7SmrgEmail bug reports to bug-automake@gnu.org.
1284e8f48c7SmrgAutomake home page: https://www.gnu.org/software/automake/
129c43cc173Smrg"
130c43cc173Smrg
131c43cc173Smrgwhile test $# -ne 0; do
132c43cc173Smrg  case $1 in
133c27c18e8Smrg    -c) ;;
134c27c18e8Smrg
135c27c18e8Smrg    -C) copy_on_change=true;;
136c43cc173Smrg
137c27c18e8Smrg    -d) dir_arg=true;;
138c43cc173Smrg
139c43cc173Smrg    -g) chgrpcmd="$chgrpprog $2"
14048e5ce07Smrg        shift;;
141c43cc173Smrg
142c43cc173Smrg    --help) echo "$usage"; exit $?;;
143c43cc173Smrg
144c43cc173Smrg    -m) mode=$2
14548e5ce07Smrg        case $mode in
14648e5ce07Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14748e5ce07Smrg            echo "$0: invalid mode: $mode" >&2
14848e5ce07Smrg            exit 1;;
14948e5ce07Smrg        esac
15048e5ce07Smrg        shift;;
151c43cc173Smrg
152c43cc173Smrg    -o) chowncmd="$chownprog $2"
15348e5ce07Smrg        shift;;
154c43cc173Smrg
1554e8f48c7Smrg    -p) cpprog="$cpprog -p";;
1564e8f48c7Smrg
157c27c18e8Smrg    -s) stripcmd=$stripprog;;
158c43cc173Smrg
1594e8f48c7Smrg    -S) backupsuffix="$2"
1604e8f48c7Smrg        shift;;
1614e8f48c7Smrg
16248e5ce07Smrg    -t)
16348e5ce07Smrg        is_target_a_directory=always
16448e5ce07Smrg        dst_arg=$2
16548e5ce07Smrg        # Protect names problematic for 'test' and other utilities.
16648e5ce07Smrg        case $dst_arg in
16748e5ce07Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16848e5ce07Smrg        esac
16948e5ce07Smrg        shift;;
170c43cc173Smrg
17148e5ce07Smrg    -T) is_target_a_directory=never;;
172c43cc173Smrg
173c43cc173Smrg    --version) echo "$0 $scriptversion"; exit $?;;
174c43cc173Smrg
17548e5ce07Smrg    --) shift
17648e5ce07Smrg        break;;
177c43cc173Smrg
17848e5ce07Smrg    -*) echo "$0: invalid option: $1" >&2
17948e5ce07Smrg        exit 1;;
180c43cc173Smrg
181c43cc173Smrg    *)  break;;
182c43cc173Smrg  esac
183c27c18e8Smrg  shift
184c43cc173Smrgdone
185c43cc173Smrg
18648e5ce07Smrg# We allow the use of options -d and -T together, by making -d
18748e5ce07Smrg# take the precedence; this is for compatibility with GNU install.
18848e5ce07Smrg
18948e5ce07Smrgif test -n "$dir_arg"; then
19048e5ce07Smrg  if test -n "$dst_arg"; then
19148e5ce07Smrg    echo "$0: target directory not allowed when installing a directory." >&2
19248e5ce07Smrg    exit 1
19348e5ce07Smrg  fi
19448e5ce07Smrgfi
19548e5ce07Smrg
196c27c18e8Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197c43cc173Smrg  # When -d is used, all remaining arguments are directories to create.
198c43cc173Smrg  # When -t is used, the destination is already specified.
199c43cc173Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200c43cc173Smrg  for arg
201c43cc173Smrg  do
202c27c18e8Smrg    if test -n "$dst_arg"; then
203c43cc173Smrg      # $@ is not empty: it contains at least $arg.
204c27c18e8Smrg      set fnord "$@" "$dst_arg"
205c43cc173Smrg      shift # fnord
206c43cc173Smrg    fi
207c43cc173Smrg    shift # arg
208c27c18e8Smrg    dst_arg=$arg
209f1ee322dSmrg    # Protect names problematic for 'test' and other utilities.
210f1ee322dSmrg    case $dst_arg in
211f1ee322dSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212f1ee322dSmrg    esac
213c43cc173Smrg  done
214c43cc173Smrgfi
215c43cc173Smrg
216c43cc173Smrgif test $# -eq 0; then
217c43cc173Smrg  if test -z "$dir_arg"; then
218c43cc173Smrg    echo "$0: no input file specified." >&2
219c43cc173Smrg    exit 1
220c43cc173Smrg  fi
221f1ee322dSmrg  # It's OK to call 'install-sh -d' without argument.
222c43cc173Smrg  # This can happen when creating conditional directories.
223c43cc173Smrg  exit 0
224c43cc173Smrgfi
225c43cc173Smrg
22648e5ce07Smrgif test -z "$dir_arg"; then
22748e5ce07Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22848e5ce07Smrg    if test ! -d "$dst_arg"; then
22948e5ce07Smrg      echo "$0: $dst_arg: Is not a directory." >&2
23048e5ce07Smrg      exit 1
23148e5ce07Smrg    fi
23248e5ce07Smrg  fi
23348e5ce07Smrgfi
23448e5ce07Smrg
235c43cc173Smrgif test -z "$dir_arg"; then
236f1ee322dSmrg  do_exit='(exit $ret); exit $ret'
237f1ee322dSmrg  trap "ret=129; $do_exit" 1
238f1ee322dSmrg  trap "ret=130; $do_exit" 2
239f1ee322dSmrg  trap "ret=141; $do_exit" 13
240f1ee322dSmrg  trap "ret=143; $do_exit" 15
241c43cc173Smrg
242c43cc173Smrg  # Set umask so as not to create temps with too-generous modes.
243c43cc173Smrg  # However, 'strip' requires both read and write access to temps.
244c43cc173Smrg  case $mode in
245c43cc173Smrg    # Optimize common cases.
246c43cc173Smrg    *644) cp_umask=133;;
247c43cc173Smrg    *755) cp_umask=22;;
248c43cc173Smrg
249c43cc173Smrg    *[0-7])
250c43cc173Smrg      if test -z "$stripcmd"; then
25148e5ce07Smrg        u_plus_rw=
252c43cc173Smrg      else
25348e5ce07Smrg        u_plus_rw='% 200'
254c43cc173Smrg      fi
255c43cc173Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256c43cc173Smrg    *)
257c43cc173Smrg      if test -z "$stripcmd"; then
25848e5ce07Smrg        u_plus_rw=
259c43cc173Smrg      else
26048e5ce07Smrg        u_plus_rw=,u+rw
261c43cc173Smrg      fi
262c43cc173Smrg      cp_umask=$mode$u_plus_rw;;
263c43cc173Smrg  esac
264c43cc173Smrgfi
265c43cc173Smrg
266c43cc173Smrgfor src
267c43cc173Smrgdo
268f1ee322dSmrg  # Protect names problematic for 'test' and other utilities.
269c43cc173Smrg  case $src in
270f1ee322dSmrg    -* | [=\(\)!]) src=./$src;;
271c43cc173Smrg  esac
272c43cc173Smrg
273c43cc173Smrg  if test -n "$dir_arg"; then
274c43cc173Smrg    dst=$src
275c43cc173Smrg    dstdir=$dst
276c43cc173Smrg    test -d "$dstdir"
277c43cc173Smrg    dstdir_status=$?
2784e8f48c7Smrg    # Don't chown directories that already exist.
2794e8f48c7Smrg    if test $dstdir_status = 0; then
2804e8f48c7Smrg      chowncmd=""
2814e8f48c7Smrg    fi
282c43cc173Smrg  else
283c43cc173Smrg
284c43cc173Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285c43cc173Smrg    # might cause directories to be created, which would be especially bad
286c43cc173Smrg    # if $src (and thus $dsttmp) contains '*'.
287c43cc173Smrg    if test ! -f "$src" && test ! -d "$src"; then
288c43cc173Smrg      echo "$0: $src does not exist." >&2
289c43cc173Smrg      exit 1
290c43cc173Smrg    fi
291c43cc173Smrg
292c27c18e8Smrg    if test -z "$dst_arg"; then
293c43cc173Smrg      echo "$0: no destination specified." >&2
294c43cc173Smrg      exit 1
295c43cc173Smrg    fi
296c27c18e8Smrg    dst=$dst_arg
297c43cc173Smrg
2984940c694Smrg    # If destination is a directory, append the input filename.
299c43cc173Smrg    if test -d "$dst"; then
30048e5ce07Smrg      if test "$is_target_a_directory" = never; then
30148e5ce07Smrg        echo "$0: $dst_arg: Is a directory" >&2
30248e5ce07Smrg        exit 1
303c43cc173Smrg      fi
304c43cc173Smrg      dstdir=$dst
3054940c694Smrg      dstbase=`basename "$src"`
3064940c694Smrg      case $dst in
3074940c694Smrg	*/) dst=$dst$dstbase;;
3084940c694Smrg	*)  dst=$dst/$dstbase;;
3094940c694Smrg      esac
310c43cc173Smrg      dstdir_status=0
311c43cc173Smrg    else
31248e5ce07Smrg      dstdir=`dirname "$dst"`
313c43cc173Smrg      test -d "$dstdir"
314c43cc173Smrg      dstdir_status=$?
315c43cc173Smrg    fi
316c43cc173Smrg  fi
317c43cc173Smrg
3184940c694Smrg  case $dstdir in
3194940c694Smrg    */) dstdirslash=$dstdir;;
3204940c694Smrg    *)  dstdirslash=$dstdir/;;
3214940c694Smrg  esac
3224940c694Smrg
323c43cc173Smrg  obsolete_mkdir_used=false
324c43cc173Smrg
325c43cc173Smrg  if test $dstdir_status != 0; then
326c43cc173Smrg    case $posix_mkdir in
327c43cc173Smrg      '')
32848e5ce07Smrg        # With -d, create the new directory with the user-specified mode.
32948e5ce07Smrg        # Otherwise, rely on $mkdir_umask.
33048e5ce07Smrg        if test -n "$dir_arg"; then
33148e5ce07Smrg          mkdir_mode=-m$mode
33248e5ce07Smrg        else
33348e5ce07Smrg          mkdir_mode=
33448e5ce07Smrg        fi
33548e5ce07Smrg
33648e5ce07Smrg        posix_mkdir=false
3374e8f48c7Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
3384e8f48c7Smrg	# here however when possible just to lower collision chance.
3394e8f48c7Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3404e8f48c7Smrg
3414e8f48c7Smrg	trap '
3424e8f48c7Smrg	  ret=$?
3434e8f48c7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
3444e8f48c7Smrg	  exit $ret
3454e8f48c7Smrg	' 0
3464e8f48c7Smrg
3474e8f48c7Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
3484e8f48c7Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
3494e8f48c7Smrg	# directory is successfully created first before we actually test
3504e8f48c7Smrg	# 'mkdir -p'.
3514e8f48c7Smrg	if (umask $mkdir_umask &&
3524e8f48c7Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
3534e8f48c7Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3544e8f48c7Smrg	then
3554e8f48c7Smrg	  if test -z "$dir_arg" || {
3564e8f48c7Smrg	       # Check for POSIX incompatibilities with -m.
3574e8f48c7Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3584e8f48c7Smrg	       # other-writable bit of parent directory when it shouldn't.
3594e8f48c7Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3604e8f48c7Smrg	       test_tmpdir="$tmpdir/a"
3614e8f48c7Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3624e8f48c7Smrg	       case $ls_ld_tmpdir in
3634e8f48c7Smrg		 d????-?r-*) different_mode=700;;
3644e8f48c7Smrg		 d????-?--*) different_mode=755;;
3654e8f48c7Smrg		 *) false;;
3664e8f48c7Smrg	       esac &&
3674e8f48c7Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3684e8f48c7Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3694e8f48c7Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3704e8f48c7Smrg	       }
3714e8f48c7Smrg	     }
3724e8f48c7Smrg	  then posix_mkdir=:
3734e8f48c7Smrg	  fi
3744e8f48c7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3754e8f48c7Smrg	else
3764e8f48c7Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
3774e8f48c7Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3784e8f48c7Smrg	fi
3794e8f48c7Smrg	trap '' 0;;
380c43cc173Smrg    esac
381c43cc173Smrg
382c43cc173Smrg    if
383c43cc173Smrg      $posix_mkdir && (
38448e5ce07Smrg        umask $mkdir_umask &&
38548e5ce07Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386c43cc173Smrg      )
387c43cc173Smrg    then :
388c43cc173Smrg    else
389c43cc173Smrg
3904e8f48c7Smrg      # mkdir does not conform to POSIX,
391c43cc173Smrg      # or it failed possibly due to a race condition.  Create the
392c43cc173Smrg      # directory the slow way, step by step, checking for races as we go.
393c43cc173Smrg
394c43cc173Smrg      case $dstdir in
39548e5ce07Smrg        /*) prefix='/';;
39648e5ce07Smrg        [-=\(\)!]*) prefix='./';;
39748e5ce07Smrg        *)  prefix='';;
398c43cc173Smrg      esac
399c43cc173Smrg
400c43cc173Smrg      oIFS=$IFS
401c43cc173Smrg      IFS=/
40248e5ce07Smrg      set -f
403c43cc173Smrg      set fnord $dstdir
404c43cc173Smrg      shift
40548e5ce07Smrg      set +f
406c43cc173Smrg      IFS=$oIFS
407c43cc173Smrg
408c43cc173Smrg      prefixes=
409c43cc173Smrg
410c43cc173Smrg      for d
411c43cc173Smrg      do
41248e5ce07Smrg        test X"$d" = X && continue
41348e5ce07Smrg
41448e5ce07Smrg        prefix=$prefix$d
41548e5ce07Smrg        if test -d "$prefix"; then
41648e5ce07Smrg          prefixes=
41748e5ce07Smrg        else
41848e5ce07Smrg          if $posix_mkdir; then
4194e8f48c7Smrg            (umask $mkdir_umask &&
42048e5ce07Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42148e5ce07Smrg            # Don't fail if two instances are running concurrently.
42248e5ce07Smrg            test -d "$prefix" || exit 1
42348e5ce07Smrg          else
42448e5ce07Smrg            case $prefix in
42548e5ce07Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42648e5ce07Smrg              *) qprefix=$prefix;;
42748e5ce07Smrg            esac
42848e5ce07Smrg            prefixes="$prefixes '$qprefix'"
42948e5ce07Smrg          fi
43048e5ce07Smrg        fi
43148e5ce07Smrg        prefix=$prefix/
432c43cc173Smrg      done
433c43cc173Smrg
434c43cc173Smrg      if test -n "$prefixes"; then
43548e5ce07Smrg        # Don't fail if two instances are running concurrently.
43648e5ce07Smrg        (umask $mkdir_umask &&
43748e5ce07Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43848e5ce07Smrg          test -d "$dstdir" || exit 1
43948e5ce07Smrg        obsolete_mkdir_used=true
440c43cc173Smrg      fi
441c43cc173Smrg    fi
442c43cc173Smrg  fi
443c43cc173Smrg
444c43cc173Smrg  if test -n "$dir_arg"; then
445c43cc173Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446c43cc173Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447c43cc173Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448c43cc173Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449c43cc173Smrg  else
450c43cc173Smrg
451c43cc173Smrg    # Make a couple of temp file names in the proper directory.
4524940c694Smrg    dsttmp=${dstdirslash}_inst.$$_
4534940c694Smrg    rmtmp=${dstdirslash}_rm.$$_
454c43cc173Smrg
455c43cc173Smrg    # Trap to clean up those temp files at exit.
456c43cc173Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457c43cc173Smrg
458c43cc173Smrg    # Copy the file name to the temp name.
4594e8f48c7Smrg    (umask $cp_umask &&
4604e8f48c7Smrg     { test -z "$stripcmd" || {
4614e8f48c7Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
4624e8f48c7Smrg	 # which would cause strip to fail.
4634e8f48c7Smrg	 if test -z "$doit"; then
4644e8f48c7Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
4654e8f48c7Smrg	 else
4664e8f48c7Smrg	   $doit touch "$dsttmp"
4674e8f48c7Smrg	 fi
4684e8f48c7Smrg       }
4694e8f48c7Smrg     } &&
4704e8f48c7Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471c43cc173Smrg
472c43cc173Smrg    # and set any options; do chmod last to preserve setuid bits.
473c43cc173Smrg    #
474c43cc173Smrg    # If any of these fail, we abort the whole thing.  If we want to
475c43cc173Smrg    # ignore errors from any of these, just make sure not to ignore
476c43cc173Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477c43cc173Smrg    #
478c27c18e8Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479c27c18e8Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480c27c18e8Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481c27c18e8Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482c27c18e8Smrg
483c27c18e8Smrg    # If -C, don't bother to copy if it wouldn't change the file.
484c27c18e8Smrg    if $copy_on_change &&
48548e5ce07Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48648e5ce07Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48748e5ce07Smrg       set -f &&
488c27c18e8Smrg       set X $old && old=:$2:$4:$5:$6 &&
489c27c18e8Smrg       set X $new && new=:$2:$4:$5:$6 &&
49048e5ce07Smrg       set +f &&
491c27c18e8Smrg       test "$old" = "$new" &&
492c27c18e8Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493c27c18e8Smrg    then
494c27c18e8Smrg      rm -f "$dsttmp"
495c27c18e8Smrg    else
4964e8f48c7Smrg      # If $backupsuffix is set, and the file being installed
4974e8f48c7Smrg      # already exists, attempt a backup.  Don't worry if it fails,
4984e8f48c7Smrg      # e.g., if mv doesn't support -f.
4994e8f48c7Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
5004e8f48c7Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
5014e8f48c7Smrg      fi
5024e8f48c7Smrg
503c27c18e8Smrg      # Rename the file to the real destination.
504c27c18e8Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505c27c18e8Smrg
506c27c18e8Smrg      # The rename failed, perhaps because mv can't rename something else
507c27c18e8Smrg      # to itself, or perhaps because mv is so ancient that it does not
508c27c18e8Smrg      # support -f.
509c27c18e8Smrg      {
51048e5ce07Smrg        # Now remove or move aside any old file at destination location.
51148e5ce07Smrg        # We try this two ways since rm can't unlink itself on some
51248e5ce07Smrg        # systems and the destination file might be busy for other
51348e5ce07Smrg        # reasons.  In this case, the final cleanup might fail but the new
51448e5ce07Smrg        # file should still install successfully.
51548e5ce07Smrg        {
51648e5ce07Smrg          test ! -f "$dst" ||
5174e8f48c7Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
51848e5ce07Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
5194e8f48c7Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52048e5ce07Smrg          } ||
52148e5ce07Smrg          { echo "$0: cannot unlink or rename $dst" >&2
52248e5ce07Smrg            (exit 1); exit 1
52348e5ce07Smrg          }
52448e5ce07Smrg        } &&
52548e5ce07Smrg
52648e5ce07Smrg        # Now rename the file to the real destination.
52748e5ce07Smrg        $doit $mvcmd "$dsttmp" "$dst"
528c27c18e8Smrg      }
529c27c18e8Smrg    fi || exit 1
530c43cc173Smrg
531c43cc173Smrg    trap '' 0
532c43cc173Smrg  fi
533c43cc173Smrgdone
534c43cc173Smrg
535c43cc173Smrg# Local variables:
5364940c694Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537c43cc173Smrg# time-stamp-start: "scriptversion="
538c43cc173Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
5394940c694Smrg# time-stamp-time-zone: "UTC0"
540c27c18e8Smrg# time-stamp-end: "; # UTC"
541c43cc173Smrg# End:
542