1c19de146Smrg#!/bin/sh
2c19de146Smrg# install - install a program, script, or datafile
39ef7378bSmrg
43b83913fSmrgscriptversion=2020-11-14.01; # UTC
59ef7378bSmrg
6c19de146Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7c19de146Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8c19de146Smrg# following copyright and license.
9c19de146Smrg#
10c19de146Smrg# Copyright (C) 1994 X Consortium
11c19de146Smrg#
12c19de146Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13c19de146Smrg# of this software and associated documentation files (the "Software"), to
14c19de146Smrg# deal in the Software without restriction, including without limitation the
15c19de146Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16c19de146Smrg# sell copies of the Software, and to permit persons to whom the Software is
17c19de146Smrg# furnished to do so, subject to the following conditions:
18c19de146Smrg#
19c19de146Smrg# The above copyright notice and this permission notice shall be included in
20c19de146Smrg# all copies or substantial portions of the Software.
21c19de146Smrg#
22c19de146Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c19de146Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c19de146Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25c19de146Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26c19de146Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27c19de146Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28c19de146Smrg#
29c19de146Smrg# Except as contained in this notice, the name of the X Consortium shall not
30c19de146Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31c19de146Smrg# ings in this Software without prior written authorization from the X Consor-
32c19de146Smrg# tium.
33c19de146Smrg#
34c19de146Smrg#
35c19de146Smrg# FSF changes to this file are in the public domain.
36c19de146Smrg#
37c19de146Smrg# Calling this script install-sh is preferred over install.sh, to prevent
38a39bb051Smrg# 'make' implicit rules from creating a file called install from it
39c19de146Smrg# when there is no Makefile.
40c19de146Smrg#
41c19de146Smrg# This script is compatible with the BSD install script, but was written
429ef7378bSmrg# from scratch.
43c19de146Smrg
44a39bb051Smrgtab='	'
459ef7378bSmrgnl='
469ef7378bSmrg'
47a39bb051SmrgIFS=" $tab$nl"
48c19de146Smrg
49a39bb051Smrg# Set DOITPROG to "echo" to test this script.
50c19de146Smrg
519ef7378bSmrgdoit=${DOITPROG-}
52a39bb051Smrgdoit_exec=${doit:-exec}
53c19de146Smrg
549ef7378bSmrg# Put in absolute file names if you don't have them in your path;
559ef7378bSmrg# or use environment vars.
569ef7378bSmrg
579ef7378bSmrgchgrpprog=${CHGRPPROG-chgrp}
589ef7378bSmrgchmodprog=${CHMODPROG-chmod}
599ef7378bSmrgchownprog=${CHOWNPROG-chown}
609ef7378bSmrgcmpprog=${CMPPROG-cmp}
619ef7378bSmrgcpprog=${CPPROG-cp}
629ef7378bSmrgmkdirprog=${MKDIRPROG-mkdir}
639ef7378bSmrgmvprog=${MVPROG-mv}
649ef7378bSmrgrmprog=${RMPROG-rm}
659ef7378bSmrgstripprog=${STRIPPROG-strip}
669ef7378bSmrg
679ef7378bSmrgposix_mkdir=
689ef7378bSmrg
699ef7378bSmrg# Desired mode of installed file.
709ef7378bSmrgmode=0755
719ef7378bSmrg
723b83913fSmrg# Create dirs (including intermediate dirs) using mode 755.
733b83913fSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
743b83913fSmrgmkdir_umask=22
753b83913fSmrg
763b83913fSmrgbackupsuffix=
779ef7378bSmrgchgrpcmd=
789ef7378bSmrgchmodcmd=$chmodprog
799ef7378bSmrgchowncmd=
809ef7378bSmrgmvcmd=$mvprog
819ef7378bSmrgrmcmd="$rmprog -f"
829ef7378bSmrgstripcmd=
83c19de146Smrg
849ef7378bSmrgsrc=
859ef7378bSmrgdst=
869ef7378bSmrgdir_arg=
879ef7378bSmrgdst_arg=
88c19de146Smrg
899ef7378bSmrgcopy_on_change=false
90a39bb051Smrgis_target_a_directory=possibly
91c19de146Smrg
929ef7378bSmrgusage="\
939ef7378bSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
949ef7378bSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
959ef7378bSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
969ef7378bSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97c19de146Smrg
989ef7378bSmrgIn the 1st form, copy SRCFILE to DSTFILE.
999ef7378bSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
1009ef7378bSmrgIn the 4th, create DIRECTORIES.
101c19de146Smrg
1029ef7378bSmrgOptions:
1039ef7378bSmrg     --help     display this help and exit.
1049ef7378bSmrg     --version  display version info and exit.
105c19de146Smrg
1069ef7378bSmrg  -c            (ignored)
1073b83913fSmrg  -C            install only if different (preserve data modification time)
1089ef7378bSmrg  -d            create directories instead of installing files.
1099ef7378bSmrg  -g GROUP      $chgrpprog installed files to GROUP.
1109ef7378bSmrg  -m MODE       $chmodprog installed files to MODE.
1119ef7378bSmrg  -o USER       $chownprog installed files to USER.
1123b83913fSmrg  -p            pass -p to $cpprog.
1139ef7378bSmrg  -s            $stripprog installed files.
1143b83913fSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
1159ef7378bSmrg  -t DIRECTORY  install into DIRECTORY.
1169ef7378bSmrg  -T            report an error if DSTFILE is a directory.
117c19de146Smrg
1189ef7378bSmrgEnvironment variables override the default commands:
1199ef7378bSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1209ef7378bSmrg  RMPROG STRIPPROG
1213b83913fSmrg
1223b83913fSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
1233b83913fSmrgit's up to you to specify -f if you want it.
1243b83913fSmrg
1253b83913fSmrgIf -S is not specified, no backups are attempted.
1263b83913fSmrg
1273b83913fSmrgEmail bug reports to bug-automake@gnu.org.
1283b83913fSmrgAutomake home page: https://www.gnu.org/software/automake/
1299ef7378bSmrg"
130c19de146Smrg
1319ef7378bSmrgwhile test $# -ne 0; do
1329ef7378bSmrg  case $1 in
1339ef7378bSmrg    -c) ;;
134c19de146Smrg
1359ef7378bSmrg    -C) copy_on_change=true;;
136c19de146Smrg
1379ef7378bSmrg    -d) dir_arg=true;;
138c19de146Smrg
1399ef7378bSmrg    -g) chgrpcmd="$chgrpprog $2"
140a39bb051Smrg        shift;;
141c19de146Smrg
1429ef7378bSmrg    --help) echo "$usage"; exit $?;;
143c19de146Smrg
1449ef7378bSmrg    -m) mode=$2
145a39bb051Smrg        case $mode in
146a39bb051Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147a39bb051Smrg            echo "$0: invalid mode: $mode" >&2
148a39bb051Smrg            exit 1;;
149a39bb051Smrg        esac
150a39bb051Smrg        shift;;
151c19de146Smrg
1529ef7378bSmrg    -o) chowncmd="$chownprog $2"
153a39bb051Smrg        shift;;
154c19de146Smrg
1553b83913fSmrg    -p) cpprog="$cpprog -p";;
1563b83913fSmrg
1579ef7378bSmrg    -s) stripcmd=$stripprog;;
158c19de146Smrg
1593b83913fSmrg    -S) backupsuffix="$2"
1603b83913fSmrg        shift;;
1613b83913fSmrg
162a39bb051Smrg    -t)
163a39bb051Smrg        is_target_a_directory=always
164a39bb051Smrg        dst_arg=$2
165a39bb051Smrg        # Protect names problematic for 'test' and other utilities.
166a39bb051Smrg        case $dst_arg in
167a39bb051Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
168a39bb051Smrg        esac
169a39bb051Smrg        shift;;
170c19de146Smrg
171a39bb051Smrg    -T) is_target_a_directory=never;;
172c19de146Smrg
1739ef7378bSmrg    --version) echo "$0 $scriptversion"; exit $?;;
174c19de146Smrg
175a39bb051Smrg    --) shift
176a39bb051Smrg        break;;
177c19de146Smrg
178a39bb051Smrg    -*) echo "$0: invalid option: $1" >&2
179a39bb051Smrg        exit 1;;
180c19de146Smrg
1819ef7378bSmrg    *)  break;;
1829ef7378bSmrg  esac
1839ef7378bSmrg  shift
1849ef7378bSmrgdone
185c19de146Smrg
186a39bb051Smrg# We allow the use of options -d and -T together, by making -d
187a39bb051Smrg# take the precedence; this is for compatibility with GNU install.
188a39bb051Smrg
189a39bb051Smrgif test -n "$dir_arg"; then
190a39bb051Smrg  if test -n "$dst_arg"; then
191a39bb051Smrg    echo "$0: target directory not allowed when installing a directory." >&2
192a39bb051Smrg    exit 1
193a39bb051Smrg  fi
194a39bb051Smrgfi
195a39bb051Smrg
1969ef7378bSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1979ef7378bSmrg  # When -d is used, all remaining arguments are directories to create.
1989ef7378bSmrg  # When -t is used, the destination is already specified.
1999ef7378bSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
2009ef7378bSmrg  for arg
2019ef7378bSmrg  do
2029ef7378bSmrg    if test -n "$dst_arg"; then
2039ef7378bSmrg      # $@ is not empty: it contains at least $arg.
2049ef7378bSmrg      set fnord "$@" "$dst_arg"
2059ef7378bSmrg      shift # fnord
2069ef7378bSmrg    fi
2079ef7378bSmrg    shift # arg
2089ef7378bSmrg    dst_arg=$arg
209a39bb051Smrg    # Protect names problematic for 'test' and other utilities.
210a39bb051Smrg    case $dst_arg in
211a39bb051Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212a39bb051Smrg    esac
2139ef7378bSmrg  done
2149ef7378bSmrgfi
215c19de146Smrg
2169ef7378bSmrgif test $# -eq 0; then
2179ef7378bSmrg  if test -z "$dir_arg"; then
2189ef7378bSmrg    echo "$0: no input file specified." >&2
2199ef7378bSmrg    exit 1
2209ef7378bSmrg  fi
221a39bb051Smrg  # It's OK to call 'install-sh -d' without argument.
2229ef7378bSmrg  # This can happen when creating conditional directories.
2239ef7378bSmrg  exit 0
2249ef7378bSmrgfi
225c19de146Smrg
2269ef7378bSmrgif test -z "$dir_arg"; then
227a39bb051Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
228a39bb051Smrg    if test ! -d "$dst_arg"; then
229a39bb051Smrg      echo "$0: $dst_arg: Is not a directory." >&2
230a39bb051Smrg      exit 1
231a39bb051Smrg    fi
232a39bb051Smrg  fi
233a39bb051Smrgfi
234a39bb051Smrg
235a39bb051Smrgif test -z "$dir_arg"; then
236a39bb051Smrg  do_exit='(exit $ret); exit $ret'
237a39bb051Smrg  trap "ret=129; $do_exit" 1
238a39bb051Smrg  trap "ret=130; $do_exit" 2
239a39bb051Smrg  trap "ret=141; $do_exit" 13
240a39bb051Smrg  trap "ret=143; $do_exit" 15
2419ef7378bSmrg
2429ef7378bSmrg  # Set umask so as not to create temps with too-generous modes.
2439ef7378bSmrg  # However, 'strip' requires both read and write access to temps.
2449ef7378bSmrg  case $mode in
2459ef7378bSmrg    # Optimize common cases.
2469ef7378bSmrg    *644) cp_umask=133;;
2479ef7378bSmrg    *755) cp_umask=22;;
2489ef7378bSmrg
2499ef7378bSmrg    *[0-7])
2509ef7378bSmrg      if test -z "$stripcmd"; then
251a39bb051Smrg        u_plus_rw=
2529ef7378bSmrg      else
253a39bb051Smrg        u_plus_rw='% 200'
2549ef7378bSmrg      fi
2559ef7378bSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2569ef7378bSmrg    *)
2579ef7378bSmrg      if test -z "$stripcmd"; then
258a39bb051Smrg        u_plus_rw=
2599ef7378bSmrg      else
260a39bb051Smrg        u_plus_rw=,u+rw
2619ef7378bSmrg      fi
2629ef7378bSmrg      cp_umask=$mode$u_plus_rw;;
2639ef7378bSmrg  esac
2649ef7378bSmrgfi
265c19de146Smrg
2669ef7378bSmrgfor src
2679ef7378bSmrgdo
268a39bb051Smrg  # Protect names problematic for 'test' and other utilities.
2699ef7378bSmrg  case $src in
270a39bb051Smrg    -* | [=\(\)!]) src=./$src;;
2719ef7378bSmrg  esac
2729ef7378bSmrg
2739ef7378bSmrg  if test -n "$dir_arg"; then
2749ef7378bSmrg    dst=$src
2759ef7378bSmrg    dstdir=$dst
2769ef7378bSmrg    test -d "$dstdir"
2779ef7378bSmrg    dstdir_status=$?
2783b83913fSmrg    # Don't chown directories that already exist.
2793b83913fSmrg    if test $dstdir_status = 0; then
2803b83913fSmrg      chowncmd=""
2813b83913fSmrg    fi
2829ef7378bSmrg  else
2839ef7378bSmrg
2849ef7378bSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2859ef7378bSmrg    # might cause directories to be created, which would be especially bad
2869ef7378bSmrg    # if $src (and thus $dsttmp) contains '*'.
2879ef7378bSmrg    if test ! -f "$src" && test ! -d "$src"; then
2889ef7378bSmrg      echo "$0: $src does not exist." >&2
2899ef7378bSmrg      exit 1
2909ef7378bSmrg    fi
2919ef7378bSmrg
2929ef7378bSmrg    if test -z "$dst_arg"; then
2939ef7378bSmrg      echo "$0: no destination specified." >&2
2949ef7378bSmrg      exit 1
2959ef7378bSmrg    fi
2969ef7378bSmrg    dst=$dst_arg
297c19de146Smrg
2983b83913fSmrg    # If destination is a directory, append the input filename.
2999ef7378bSmrg    if test -d "$dst"; then
300a39bb051Smrg      if test "$is_target_a_directory" = never; then
301a39bb051Smrg        echo "$0: $dst_arg: Is a directory" >&2
302a39bb051Smrg        exit 1
3039ef7378bSmrg      fi
3049ef7378bSmrg      dstdir=$dst
3053b83913fSmrg      dstbase=`basename "$src"`
3063b83913fSmrg      case $dst in
3073b83913fSmrg	*/) dst=$dst$dstbase;;
3083b83913fSmrg	*)  dst=$dst/$dstbase;;
3093b83913fSmrg      esac
3109ef7378bSmrg      dstdir_status=0
3119ef7378bSmrg    else
312a39bb051Smrg      dstdir=`dirname "$dst"`
3139ef7378bSmrg      test -d "$dstdir"
3149ef7378bSmrg      dstdir_status=$?
3159ef7378bSmrg    fi
3169ef7378bSmrg  fi
3179ef7378bSmrg
3183b83913fSmrg  case $dstdir in
3193b83913fSmrg    */) dstdirslash=$dstdir;;
3203b83913fSmrg    *)  dstdirslash=$dstdir/;;
3213b83913fSmrg  esac
3223b83913fSmrg
3239ef7378bSmrg  obsolete_mkdir_used=false
3249ef7378bSmrg
3259ef7378bSmrg  if test $dstdir_status != 0; then
3269ef7378bSmrg    case $posix_mkdir in
3279ef7378bSmrg      '')
328a39bb051Smrg        # With -d, create the new directory with the user-specified mode.
329a39bb051Smrg        # Otherwise, rely on $mkdir_umask.
330a39bb051Smrg        if test -n "$dir_arg"; then
331a39bb051Smrg          mkdir_mode=-m$mode
332a39bb051Smrg        else
333a39bb051Smrg          mkdir_mode=
334a39bb051Smrg        fi
335a39bb051Smrg
336a39bb051Smrg        posix_mkdir=false
3373b83913fSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
3383b83913fSmrg	# here however when possible just to lower collision chance.
3393b83913fSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3403b83913fSmrg
3413b83913fSmrg	trap '
3423b83913fSmrg	  ret=$?
3433b83913fSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
3443b83913fSmrg	  exit $ret
3453b83913fSmrg	' 0
3463b83913fSmrg
3473b83913fSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
3483b83913fSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
3493b83913fSmrg	# directory is successfully created first before we actually test
3503b83913fSmrg	# 'mkdir -p'.
3513b83913fSmrg	if (umask $mkdir_umask &&
3523b83913fSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
3533b83913fSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3543b83913fSmrg	then
3553b83913fSmrg	  if test -z "$dir_arg" || {
3563b83913fSmrg	       # Check for POSIX incompatibilities with -m.
3573b83913fSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3583b83913fSmrg	       # other-writable bit of parent directory when it shouldn't.
3593b83913fSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3603b83913fSmrg	       test_tmpdir="$tmpdir/a"
3613b83913fSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3623b83913fSmrg	       case $ls_ld_tmpdir in
3633b83913fSmrg		 d????-?r-*) different_mode=700;;
3643b83913fSmrg		 d????-?--*) different_mode=755;;
3653b83913fSmrg		 *) false;;
3663b83913fSmrg	       esac &&
3673b83913fSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3683b83913fSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3693b83913fSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3703b83913fSmrg	       }
3713b83913fSmrg	     }
3723b83913fSmrg	  then posix_mkdir=:
3733b83913fSmrg	  fi
3743b83913fSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3753b83913fSmrg	else
3763b83913fSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
3773b83913fSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3783b83913fSmrg	fi
3793b83913fSmrg	trap '' 0;;
3809ef7378bSmrg    esac
381c19de146Smrg
3829ef7378bSmrg    if
3839ef7378bSmrg      $posix_mkdir && (
384a39bb051Smrg        umask $mkdir_umask &&
385a39bb051Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3869ef7378bSmrg      )
3879ef7378bSmrg    then :
3889ef7378bSmrg    else
3899ef7378bSmrg
3903b83913fSmrg      # mkdir does not conform to POSIX,
3919ef7378bSmrg      # or it failed possibly due to a race condition.  Create the
3929ef7378bSmrg      # directory the slow way, step by step, checking for races as we go.
3939ef7378bSmrg
3949ef7378bSmrg      case $dstdir in
395a39bb051Smrg        /*) prefix='/';;
396a39bb051Smrg        [-=\(\)!]*) prefix='./';;
397a39bb051Smrg        *)  prefix='';;
3989ef7378bSmrg      esac
3999ef7378bSmrg
4009ef7378bSmrg      oIFS=$IFS
4019ef7378bSmrg      IFS=/
402a39bb051Smrg      set -f
4039ef7378bSmrg      set fnord $dstdir
4049ef7378bSmrg      shift
405a39bb051Smrg      set +f
4069ef7378bSmrg      IFS=$oIFS
4079ef7378bSmrg
4089ef7378bSmrg      prefixes=
4099ef7378bSmrg
4109ef7378bSmrg      for d
4119ef7378bSmrg      do
412a39bb051Smrg        test X"$d" = X && continue
413a39bb051Smrg
414a39bb051Smrg        prefix=$prefix$d
415a39bb051Smrg        if test -d "$prefix"; then
416a39bb051Smrg          prefixes=
417a39bb051Smrg        else
418a39bb051Smrg          if $posix_mkdir; then
4193b83913fSmrg            (umask $mkdir_umask &&
420a39bb051Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421a39bb051Smrg            # Don't fail if two instances are running concurrently.
422a39bb051Smrg            test -d "$prefix" || exit 1
423a39bb051Smrg          else
424a39bb051Smrg            case $prefix in
425a39bb051Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426a39bb051Smrg              *) qprefix=$prefix;;
427a39bb051Smrg            esac
428a39bb051Smrg            prefixes="$prefixes '$qprefix'"
429a39bb051Smrg          fi
430a39bb051Smrg        fi
431a39bb051Smrg        prefix=$prefix/
4329ef7378bSmrg      done
4339ef7378bSmrg
4349ef7378bSmrg      if test -n "$prefixes"; then
435a39bb051Smrg        # Don't fail if two instances are running concurrently.
436a39bb051Smrg        (umask $mkdir_umask &&
437a39bb051Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
438a39bb051Smrg          test -d "$dstdir" || exit 1
439a39bb051Smrg        obsolete_mkdir_used=true
4409ef7378bSmrg      fi
4419ef7378bSmrg    fi
4429ef7378bSmrg  fi
4439ef7378bSmrg
4449ef7378bSmrg  if test -n "$dir_arg"; then
4459ef7378bSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4469ef7378bSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4479ef7378bSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4489ef7378bSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4499ef7378bSmrg  else
4509ef7378bSmrg
4519ef7378bSmrg    # Make a couple of temp file names in the proper directory.
4523b83913fSmrg    dsttmp=${dstdirslash}_inst.$$_
4533b83913fSmrg    rmtmp=${dstdirslash}_rm.$$_
4549ef7378bSmrg
4559ef7378bSmrg    # Trap to clean up those temp files at exit.
4569ef7378bSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4579ef7378bSmrg
4589ef7378bSmrg    # Copy the file name to the temp name.
4593b83913fSmrg    (umask $cp_umask &&
4603b83913fSmrg     { test -z "$stripcmd" || {
4613b83913fSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
4623b83913fSmrg	 # which would cause strip to fail.
4633b83913fSmrg	 if test -z "$doit"; then
4643b83913fSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
4653b83913fSmrg	 else
4663b83913fSmrg	   $doit touch "$dsttmp"
4673b83913fSmrg	 fi
4683b83913fSmrg       }
4693b83913fSmrg     } &&
4703b83913fSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
4719ef7378bSmrg
4729ef7378bSmrg    # and set any options; do chmod last to preserve setuid bits.
4739ef7378bSmrg    #
4749ef7378bSmrg    # If any of these fail, we abort the whole thing.  If we want to
4759ef7378bSmrg    # ignore errors from any of these, just make sure not to ignore
4769ef7378bSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4779ef7378bSmrg    #
4789ef7378bSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4799ef7378bSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4809ef7378bSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4819ef7378bSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4829ef7378bSmrg
4839ef7378bSmrg    # If -C, don't bother to copy if it wouldn't change the file.
4849ef7378bSmrg    if $copy_on_change &&
485a39bb051Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
486a39bb051Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
487a39bb051Smrg       set -f &&
4889ef7378bSmrg       set X $old && old=:$2:$4:$5:$6 &&
4899ef7378bSmrg       set X $new && new=:$2:$4:$5:$6 &&
490a39bb051Smrg       set +f &&
4919ef7378bSmrg       test "$old" = "$new" &&
4929ef7378bSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4939ef7378bSmrg    then
4949ef7378bSmrg      rm -f "$dsttmp"
4959ef7378bSmrg    else
4963b83913fSmrg      # If $backupsuffix is set, and the file being installed
4973b83913fSmrg      # already exists, attempt a backup.  Don't worry if it fails,
4983b83913fSmrg      # e.g., if mv doesn't support -f.
4993b83913fSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
5003b83913fSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
5013b83913fSmrg      fi
5023b83913fSmrg
5039ef7378bSmrg      # Rename the file to the real destination.
5049ef7378bSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
5059ef7378bSmrg
5069ef7378bSmrg      # The rename failed, perhaps because mv can't rename something else
5079ef7378bSmrg      # to itself, or perhaps because mv is so ancient that it does not
5089ef7378bSmrg      # support -f.
5099ef7378bSmrg      {
510a39bb051Smrg        # Now remove or move aside any old file at destination location.
511a39bb051Smrg        # We try this two ways since rm can't unlink itself on some
512a39bb051Smrg        # systems and the destination file might be busy for other
513a39bb051Smrg        # reasons.  In this case, the final cleanup might fail but the new
514a39bb051Smrg        # file should still install successfully.
515a39bb051Smrg        {
516a39bb051Smrg          test ! -f "$dst" ||
5173b83913fSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
518a39bb051Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
5193b83913fSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520a39bb051Smrg          } ||
521a39bb051Smrg          { echo "$0: cannot unlink or rename $dst" >&2
522a39bb051Smrg            (exit 1); exit 1
523a39bb051Smrg          }
524a39bb051Smrg        } &&
525a39bb051Smrg
526a39bb051Smrg        # Now rename the file to the real destination.
527a39bb051Smrg        $doit $mvcmd "$dsttmp" "$dst"
5289ef7378bSmrg      }
5299ef7378bSmrg    fi || exit 1
5309ef7378bSmrg
5319ef7378bSmrg    trap '' 0
5329ef7378bSmrg  fi
5339ef7378bSmrgdone
534c19de146Smrg
5359ef7378bSmrg# Local variables:
5363b83913fSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
5379ef7378bSmrg# time-stamp-start: "scriptversion="
5389ef7378bSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
5393b83913fSmrg# time-stamp-time-zone: "UTC0"
5409ef7378bSmrg# time-stamp-end: "; # UTC"
5419ef7378bSmrg# End:
542