10fa2845dSmrg#!/bin/sh
20fa2845dSmrg# install - install a program, script, or datafile
30fa2845dSmrg
4a0d387c7Smrgscriptversion=2020-11-14.01; # UTC
50fa2845dSmrg
60fa2845dSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
70fa2845dSmrg# later released in X11R6 (xc/config/util/install.sh) with the
80fa2845dSmrg# following copyright and license.
90fa2845dSmrg#
100fa2845dSmrg# Copyright (C) 1994 X Consortium
110fa2845dSmrg#
120fa2845dSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
130fa2845dSmrg# of this software and associated documentation files (the "Software"), to
140fa2845dSmrg# deal in the Software without restriction, including without limitation the
150fa2845dSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
160fa2845dSmrg# sell copies of the Software, and to permit persons to whom the Software is
170fa2845dSmrg# furnished to do so, subject to the following conditions:
180fa2845dSmrg#
190fa2845dSmrg# The above copyright notice and this permission notice shall be included in
200fa2845dSmrg# all copies or substantial portions of the Software.
210fa2845dSmrg#
220fa2845dSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
230fa2845dSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
240fa2845dSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
250fa2845dSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
260fa2845dSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
270fa2845dSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
280fa2845dSmrg#
290fa2845dSmrg# Except as contained in this notice, the name of the X Consortium shall not
300fa2845dSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
310fa2845dSmrg# ings in this Software without prior written authorization from the X Consor-
320fa2845dSmrg# tium.
330fa2845dSmrg#
340fa2845dSmrg#
350fa2845dSmrg# FSF changes to this file are in the public domain.
360fa2845dSmrg#
370fa2845dSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38f66be5ecSmrg# 'make' implicit rules from creating a file called install from it
390fa2845dSmrg# when there is no Makefile.
400fa2845dSmrg#
410fa2845dSmrg# This script is compatible with the BSD install script, but was written
420fa2845dSmrg# from scratch.
430fa2845dSmrg
44f66be5ecSmrgtab='	'
450fa2845dSmrgnl='
460fa2845dSmrg'
47f66be5ecSmrgIFS=" $tab$nl"
480fa2845dSmrg
49f66be5ecSmrg# Set DOITPROG to "echo" to test this script.
500fa2845dSmrg
517888fd0eSmrgdoit=${DOITPROG-}
52f66be5ecSmrgdoit_exec=${doit:-exec}
530fa2845dSmrg
540fa2845dSmrg# Put in absolute file names if you don't have them in your path;
550fa2845dSmrg# or use environment vars.
560fa2845dSmrg
577888fd0eSmrgchgrpprog=${CHGRPPROG-chgrp}
587888fd0eSmrgchmodprog=${CHMODPROG-chmod}
597888fd0eSmrgchownprog=${CHOWNPROG-chown}
607888fd0eSmrgcmpprog=${CMPPROG-cmp}
617888fd0eSmrgcpprog=${CPPROG-cp}
627888fd0eSmrgmkdirprog=${MKDIRPROG-mkdir}
637888fd0eSmrgmvprog=${MVPROG-mv}
647888fd0eSmrgrmprog=${RMPROG-rm}
657888fd0eSmrgstripprog=${STRIPPROG-strip}
667888fd0eSmrg
670fa2845dSmrgposix_mkdir=
680fa2845dSmrg
690fa2845dSmrg# Desired mode of installed file.
700fa2845dSmrgmode=0755
710fa2845dSmrg
72a0d387c7Smrg# Create dirs (including intermediate dirs) using mode 755.
73a0d387c7Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
74a0d387c7Smrgmkdir_umask=22
75a0d387c7Smrg
76a0d387c7Smrgbackupsuffix=
777888fd0eSmrgchgrpcmd=
780fa2845dSmrgchmodcmd=$chmodprog
790fa2845dSmrgchowncmd=
807888fd0eSmrgmvcmd=$mvprog
810fa2845dSmrgrmcmd="$rmprog -f"
827888fd0eSmrgstripcmd=
837888fd0eSmrg
840fa2845dSmrgsrc=
850fa2845dSmrgdst=
860fa2845dSmrgdir_arg=
877888fd0eSmrgdst_arg=
887888fd0eSmrg
897888fd0eSmrgcopy_on_change=false
90f66be5ecSmrgis_target_a_directory=possibly
910fa2845dSmrg
927888fd0eSmrgusage="\
937888fd0eSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
940fa2845dSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
950fa2845dSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
960fa2845dSmrg   or: $0 [OPTION]... -d DIRECTORIES...
970fa2845dSmrg
980fa2845dSmrgIn the 1st form, copy SRCFILE to DSTFILE.
990fa2845dSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
1000fa2845dSmrgIn the 4th, create DIRECTORIES.
1010fa2845dSmrg
1020fa2845dSmrgOptions:
1037888fd0eSmrg     --help     display this help and exit.
1047888fd0eSmrg     --version  display version info and exit.
1057888fd0eSmrg
1067888fd0eSmrg  -c            (ignored)
107a0d387c7Smrg  -C            install only if different (preserve data modification time)
1087888fd0eSmrg  -d            create directories instead of installing files.
1097888fd0eSmrg  -g GROUP      $chgrpprog installed files to GROUP.
1107888fd0eSmrg  -m MODE       $chmodprog installed files to MODE.
1117888fd0eSmrg  -o USER       $chownprog installed files to USER.
112a0d387c7Smrg  -p            pass -p to $cpprog.
1137888fd0eSmrg  -s            $stripprog installed files.
114a0d387c7Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
1157888fd0eSmrg  -t DIRECTORY  install into DIRECTORY.
1167888fd0eSmrg  -T            report an error if DSTFILE is a directory.
1170fa2845dSmrg
1180fa2845dSmrgEnvironment variables override the default commands:
1197888fd0eSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1207888fd0eSmrg  RMPROG STRIPPROG
121a0d387c7Smrg
122a0d387c7SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
123a0d387c7Smrgit's up to you to specify -f if you want it.
124a0d387c7Smrg
125a0d387c7SmrgIf -S is not specified, no backups are attempted.
126a0d387c7Smrg
127a0d387c7SmrgEmail bug reports to bug-automake@gnu.org.
128a0d387c7SmrgAutomake home page: https://www.gnu.org/software/automake/
1290fa2845dSmrg"
1300fa2845dSmrg
1310fa2845dSmrgwhile test $# -ne 0; do
1320fa2845dSmrg  case $1 in
1337888fd0eSmrg    -c) ;;
1347888fd0eSmrg
1357888fd0eSmrg    -C) copy_on_change=true;;
1360fa2845dSmrg
1377888fd0eSmrg    -d) dir_arg=true;;
1380fa2845dSmrg
1390fa2845dSmrg    -g) chgrpcmd="$chgrpprog $2"
140f66be5ecSmrg        shift;;
1410fa2845dSmrg
1420fa2845dSmrg    --help) echo "$usage"; exit $?;;
1430fa2845dSmrg
1440fa2845dSmrg    -m) mode=$2
145f66be5ecSmrg        case $mode in
146f66be5ecSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147f66be5ecSmrg            echo "$0: invalid mode: $mode" >&2
148f66be5ecSmrg            exit 1;;
149f66be5ecSmrg        esac
150f66be5ecSmrg        shift;;
1510fa2845dSmrg
1520fa2845dSmrg    -o) chowncmd="$chownprog $2"
153f66be5ecSmrg        shift;;
1540fa2845dSmrg
155a0d387c7Smrg    -p) cpprog="$cpprog -p";;
156a0d387c7Smrg
1577888fd0eSmrg    -s) stripcmd=$stripprog;;
1580fa2845dSmrg
159a0d387c7Smrg    -S) backupsuffix="$2"
160a0d387c7Smrg        shift;;
161a0d387c7Smrg
162f66be5ecSmrg    -t)
163f66be5ecSmrg        is_target_a_directory=always
164f66be5ecSmrg        dst_arg=$2
165f66be5ecSmrg        # Protect names problematic for 'test' and other utilities.
166f66be5ecSmrg        case $dst_arg in
167f66be5ecSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
168f66be5ecSmrg        esac
169f66be5ecSmrg        shift;;
1700fa2845dSmrg
171f66be5ecSmrg    -T) is_target_a_directory=never;;
1720fa2845dSmrg
1730fa2845dSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1740fa2845dSmrg
175f66be5ecSmrg    --) shift
176f66be5ecSmrg        break;;
1770fa2845dSmrg
178f66be5ecSmrg    -*) echo "$0: invalid option: $1" >&2
179f66be5ecSmrg        exit 1;;
1800fa2845dSmrg
1810fa2845dSmrg    *)  break;;
1820fa2845dSmrg  esac
1837888fd0eSmrg  shift
1840fa2845dSmrgdone
1850fa2845dSmrg
186f66be5ecSmrg# We allow the use of options -d and -T together, by making -d
187f66be5ecSmrg# take the precedence; this is for compatibility with GNU install.
188f66be5ecSmrg
189f66be5ecSmrgif test -n "$dir_arg"; then
190f66be5ecSmrg  if test -n "$dst_arg"; then
191f66be5ecSmrg    echo "$0: target directory not allowed when installing a directory." >&2
192f66be5ecSmrg    exit 1
193f66be5ecSmrg  fi
194f66be5ecSmrgfi
195f66be5ecSmrg
1967888fd0eSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1970fa2845dSmrg  # When -d is used, all remaining arguments are directories to create.
1980fa2845dSmrg  # When -t is used, the destination is already specified.
1990fa2845dSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
2000fa2845dSmrg  for arg
2010fa2845dSmrg  do
2027888fd0eSmrg    if test -n "$dst_arg"; then
2030fa2845dSmrg      # $@ is not empty: it contains at least $arg.
2047888fd0eSmrg      set fnord "$@" "$dst_arg"
2050fa2845dSmrg      shift # fnord
2060fa2845dSmrg    fi
2070fa2845dSmrg    shift # arg
2087888fd0eSmrg    dst_arg=$arg
209f66be5ecSmrg    # Protect names problematic for 'test' and other utilities.
210f66be5ecSmrg    case $dst_arg in
211f66be5ecSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212f66be5ecSmrg    esac
2130fa2845dSmrg  done
2140fa2845dSmrgfi
2150fa2845dSmrg
2160fa2845dSmrgif test $# -eq 0; then
2170fa2845dSmrg  if test -z "$dir_arg"; then
2180fa2845dSmrg    echo "$0: no input file specified." >&2
2190fa2845dSmrg    exit 1
2200fa2845dSmrg  fi
221f66be5ecSmrg  # It's OK to call 'install-sh -d' without argument.
2220fa2845dSmrg  # This can happen when creating conditional directories.
2230fa2845dSmrg  exit 0
2240fa2845dSmrgfi
2250fa2845dSmrg
2260fa2845dSmrgif test -z "$dir_arg"; then
227f66be5ecSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
228f66be5ecSmrg    if test ! -d "$dst_arg"; then
229f66be5ecSmrg      echo "$0: $dst_arg: Is not a directory." >&2
230f66be5ecSmrg      exit 1
231f66be5ecSmrg    fi
232f66be5ecSmrg  fi
233f66be5ecSmrgfi
234f66be5ecSmrg
235f66be5ecSmrgif test -z "$dir_arg"; then
236f66be5ecSmrg  do_exit='(exit $ret); exit $ret'
237f66be5ecSmrg  trap "ret=129; $do_exit" 1
238f66be5ecSmrg  trap "ret=130; $do_exit" 2
239f66be5ecSmrg  trap "ret=141; $do_exit" 13
240f66be5ecSmrg  trap "ret=143; $do_exit" 15
2410fa2845dSmrg
2420fa2845dSmrg  # Set umask so as not to create temps with too-generous modes.
2430fa2845dSmrg  # However, 'strip' requires both read and write access to temps.
2440fa2845dSmrg  case $mode in
2450fa2845dSmrg    # Optimize common cases.
2460fa2845dSmrg    *644) cp_umask=133;;
2470fa2845dSmrg    *755) cp_umask=22;;
2480fa2845dSmrg
2490fa2845dSmrg    *[0-7])
2500fa2845dSmrg      if test -z "$stripcmd"; then
251f66be5ecSmrg        u_plus_rw=
2520fa2845dSmrg      else
253f66be5ecSmrg        u_plus_rw='% 200'
2540fa2845dSmrg      fi
2550fa2845dSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2560fa2845dSmrg    *)
2570fa2845dSmrg      if test -z "$stripcmd"; then
258f66be5ecSmrg        u_plus_rw=
2590fa2845dSmrg      else
260f66be5ecSmrg        u_plus_rw=,u+rw
2610fa2845dSmrg      fi
2620fa2845dSmrg      cp_umask=$mode$u_plus_rw;;
2630fa2845dSmrg  esac
2640fa2845dSmrgfi
2650fa2845dSmrg
2660fa2845dSmrgfor src
2670fa2845dSmrgdo
268f66be5ecSmrg  # Protect names problematic for 'test' and other utilities.
2690fa2845dSmrg  case $src in
270f66be5ecSmrg    -* | [=\(\)!]) src=./$src;;
2710fa2845dSmrg  esac
2720fa2845dSmrg
2730fa2845dSmrg  if test -n "$dir_arg"; then
2740fa2845dSmrg    dst=$src
2750fa2845dSmrg    dstdir=$dst
2760fa2845dSmrg    test -d "$dstdir"
2770fa2845dSmrg    dstdir_status=$?
278a0d387c7Smrg    # Don't chown directories that already exist.
279a0d387c7Smrg    if test $dstdir_status = 0; then
280a0d387c7Smrg      chowncmd=""
281a0d387c7Smrg    fi
2820fa2845dSmrg  else
2830fa2845dSmrg
2840fa2845dSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2850fa2845dSmrg    # might cause directories to be created, which would be especially bad
2860fa2845dSmrg    # if $src (and thus $dsttmp) contains '*'.
2870fa2845dSmrg    if test ! -f "$src" && test ! -d "$src"; then
2880fa2845dSmrg      echo "$0: $src does not exist." >&2
2890fa2845dSmrg      exit 1
2900fa2845dSmrg    fi
2910fa2845dSmrg
2927888fd0eSmrg    if test -z "$dst_arg"; then
2930fa2845dSmrg      echo "$0: no destination specified." >&2
2940fa2845dSmrg      exit 1
2950fa2845dSmrg    fi
2967888fd0eSmrg    dst=$dst_arg
2970fa2845dSmrg
298a0d387c7Smrg    # If destination is a directory, append the input filename.
2990fa2845dSmrg    if test -d "$dst"; then
300f66be5ecSmrg      if test "$is_target_a_directory" = never; then
301f66be5ecSmrg        echo "$0: $dst_arg: Is a directory" >&2
302f66be5ecSmrg        exit 1
3030fa2845dSmrg      fi
3040fa2845dSmrg      dstdir=$dst
305a0d387c7Smrg      dstbase=`basename "$src"`
306a0d387c7Smrg      case $dst in
307a0d387c7Smrg	*/) dst=$dst$dstbase;;
308a0d387c7Smrg	*)  dst=$dst/$dstbase;;
309a0d387c7Smrg      esac
3100fa2845dSmrg      dstdir_status=0
3110fa2845dSmrg    else
312f66be5ecSmrg      dstdir=`dirname "$dst"`
3130fa2845dSmrg      test -d "$dstdir"
3140fa2845dSmrg      dstdir_status=$?
3150fa2845dSmrg    fi
3160fa2845dSmrg  fi
3170fa2845dSmrg
318a0d387c7Smrg  case $dstdir in
319a0d387c7Smrg    */) dstdirslash=$dstdir;;
320a0d387c7Smrg    *)  dstdirslash=$dstdir/;;
321a0d387c7Smrg  esac
322a0d387c7Smrg
3230fa2845dSmrg  obsolete_mkdir_used=false
3240fa2845dSmrg
3250fa2845dSmrg  if test $dstdir_status != 0; then
3260fa2845dSmrg    case $posix_mkdir in
3270fa2845dSmrg      '')
328f66be5ecSmrg        # With -d, create the new directory with the user-specified mode.
329f66be5ecSmrg        # Otherwise, rely on $mkdir_umask.
330f66be5ecSmrg        if test -n "$dir_arg"; then
331f66be5ecSmrg          mkdir_mode=-m$mode
332f66be5ecSmrg        else
333f66be5ecSmrg          mkdir_mode=
334f66be5ecSmrg        fi
335f66be5ecSmrg
336f66be5ecSmrg        posix_mkdir=false
337a0d387c7Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
338a0d387c7Smrg	# here however when possible just to lower collision chance.
339a0d387c7Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340a0d387c7Smrg
341a0d387c7Smrg	trap '
342a0d387c7Smrg	  ret=$?
343a0d387c7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344a0d387c7Smrg	  exit $ret
345a0d387c7Smrg	' 0
346a0d387c7Smrg
347a0d387c7Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
348a0d387c7Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
349a0d387c7Smrg	# directory is successfully created first before we actually test
350a0d387c7Smrg	# 'mkdir -p'.
351a0d387c7Smrg	if (umask $mkdir_umask &&
352a0d387c7Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
353a0d387c7Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354a0d387c7Smrg	then
355a0d387c7Smrg	  if test -z "$dir_arg" || {
356a0d387c7Smrg	       # Check for POSIX incompatibilities with -m.
357a0d387c7Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358a0d387c7Smrg	       # other-writable bit of parent directory when it shouldn't.
359a0d387c7Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360a0d387c7Smrg	       test_tmpdir="$tmpdir/a"
361a0d387c7Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362a0d387c7Smrg	       case $ls_ld_tmpdir in
363a0d387c7Smrg		 d????-?r-*) different_mode=700;;
364a0d387c7Smrg		 d????-?--*) different_mode=755;;
365a0d387c7Smrg		 *) false;;
366a0d387c7Smrg	       esac &&
367a0d387c7Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368a0d387c7Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369a0d387c7Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370a0d387c7Smrg	       }
371a0d387c7Smrg	     }
372a0d387c7Smrg	  then posix_mkdir=:
373a0d387c7Smrg	  fi
374a0d387c7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375a0d387c7Smrg	else
376a0d387c7Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
377a0d387c7Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378a0d387c7Smrg	fi
379a0d387c7Smrg	trap '' 0;;
3800fa2845dSmrg    esac
3810fa2845dSmrg
3820fa2845dSmrg    if
3830fa2845dSmrg      $posix_mkdir && (
384f66be5ecSmrg        umask $mkdir_umask &&
385f66be5ecSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3860fa2845dSmrg      )
3870fa2845dSmrg    then :
3880fa2845dSmrg    else
3890fa2845dSmrg
390a0d387c7Smrg      # mkdir does not conform to POSIX,
3910fa2845dSmrg      # or it failed possibly due to a race condition.  Create the
3920fa2845dSmrg      # directory the slow way, step by step, checking for races as we go.
3930fa2845dSmrg
3940fa2845dSmrg      case $dstdir in
395f66be5ecSmrg        /*) prefix='/';;
396f66be5ecSmrg        [-=\(\)!]*) prefix='./';;
397f66be5ecSmrg        *)  prefix='';;
3980fa2845dSmrg      esac
3990fa2845dSmrg
4000fa2845dSmrg      oIFS=$IFS
4010fa2845dSmrg      IFS=/
402f66be5ecSmrg      set -f
4030fa2845dSmrg      set fnord $dstdir
4040fa2845dSmrg      shift
405f66be5ecSmrg      set +f
4060fa2845dSmrg      IFS=$oIFS
4070fa2845dSmrg
4080fa2845dSmrg      prefixes=
4090fa2845dSmrg
4100fa2845dSmrg      for d
4110fa2845dSmrg      do
412f66be5ecSmrg        test X"$d" = X && continue
413f66be5ecSmrg
414f66be5ecSmrg        prefix=$prefix$d
415f66be5ecSmrg        if test -d "$prefix"; then
416f66be5ecSmrg          prefixes=
417f66be5ecSmrg        else
418f66be5ecSmrg          if $posix_mkdir; then
419a0d387c7Smrg            (umask $mkdir_umask &&
420f66be5ecSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421f66be5ecSmrg            # Don't fail if two instances are running concurrently.
422f66be5ecSmrg            test -d "$prefix" || exit 1
423f66be5ecSmrg          else
424f66be5ecSmrg            case $prefix in
425f66be5ecSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426f66be5ecSmrg              *) qprefix=$prefix;;
427f66be5ecSmrg            esac
428f66be5ecSmrg            prefixes="$prefixes '$qprefix'"
429f66be5ecSmrg          fi
430f66be5ecSmrg        fi
431f66be5ecSmrg        prefix=$prefix/
4320fa2845dSmrg      done
4330fa2845dSmrg
4340fa2845dSmrg      if test -n "$prefixes"; then
435f66be5ecSmrg        # Don't fail if two instances are running concurrently.
436f66be5ecSmrg        (umask $mkdir_umask &&
437f66be5ecSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
438f66be5ecSmrg          test -d "$dstdir" || exit 1
439f66be5ecSmrg        obsolete_mkdir_used=true
4400fa2845dSmrg      fi
4410fa2845dSmrg    fi
4420fa2845dSmrg  fi
4430fa2845dSmrg
4440fa2845dSmrg  if test -n "$dir_arg"; then
4450fa2845dSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4460fa2845dSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4470fa2845dSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4480fa2845dSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4490fa2845dSmrg  else
4500fa2845dSmrg
4510fa2845dSmrg    # Make a couple of temp file names in the proper directory.
452a0d387c7Smrg    dsttmp=${dstdirslash}_inst.$$_
453a0d387c7Smrg    rmtmp=${dstdirslash}_rm.$$_
4540fa2845dSmrg
4550fa2845dSmrg    # Trap to clean up those temp files at exit.
4560fa2845dSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4570fa2845dSmrg
4580fa2845dSmrg    # Copy the file name to the temp name.
459a0d387c7Smrg    (umask $cp_umask &&
460a0d387c7Smrg     { test -z "$stripcmd" || {
461a0d387c7Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
462a0d387c7Smrg	 # which would cause strip to fail.
463a0d387c7Smrg	 if test -z "$doit"; then
464a0d387c7Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
465a0d387c7Smrg	 else
466a0d387c7Smrg	   $doit touch "$dsttmp"
467a0d387c7Smrg	 fi
468a0d387c7Smrg       }
469a0d387c7Smrg     } &&
470a0d387c7Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
4710fa2845dSmrg
4720fa2845dSmrg    # and set any options; do chmod last to preserve setuid bits.
4730fa2845dSmrg    #
4740fa2845dSmrg    # If any of these fail, we abort the whole thing.  If we want to
4750fa2845dSmrg    # ignore errors from any of these, just make sure not to ignore
4760fa2845dSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4770fa2845dSmrg    #
4787888fd0eSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4797888fd0eSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4807888fd0eSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4817888fd0eSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4827888fd0eSmrg
4837888fd0eSmrg    # If -C, don't bother to copy if it wouldn't change the file.
4847888fd0eSmrg    if $copy_on_change &&
485f66be5ecSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
486f66be5ecSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
487f66be5ecSmrg       set -f &&
4887888fd0eSmrg       set X $old && old=:$2:$4:$5:$6 &&
4897888fd0eSmrg       set X $new && new=:$2:$4:$5:$6 &&
490f66be5ecSmrg       set +f &&
4917888fd0eSmrg       test "$old" = "$new" &&
4927888fd0eSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4937888fd0eSmrg    then
4947888fd0eSmrg      rm -f "$dsttmp"
4957888fd0eSmrg    else
496a0d387c7Smrg      # If $backupsuffix is set, and the file being installed
497a0d387c7Smrg      # already exists, attempt a backup.  Don't worry if it fails,
498a0d387c7Smrg      # e.g., if mv doesn't support -f.
499a0d387c7Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
500a0d387c7Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501a0d387c7Smrg      fi
502a0d387c7Smrg
5037888fd0eSmrg      # Rename the file to the real destination.
5047888fd0eSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
5057888fd0eSmrg
5067888fd0eSmrg      # The rename failed, perhaps because mv can't rename something else
5077888fd0eSmrg      # to itself, or perhaps because mv is so ancient that it does not
5087888fd0eSmrg      # support -f.
5097888fd0eSmrg      {
510f66be5ecSmrg        # Now remove or move aside any old file at destination location.
511f66be5ecSmrg        # We try this two ways since rm can't unlink itself on some
512f66be5ecSmrg        # systems and the destination file might be busy for other
513f66be5ecSmrg        # reasons.  In this case, the final cleanup might fail but the new
514f66be5ecSmrg        # file should still install successfully.
515f66be5ecSmrg        {
516f66be5ecSmrg          test ! -f "$dst" ||
517a0d387c7Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
518f66be5ecSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519a0d387c7Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520f66be5ecSmrg          } ||
521f66be5ecSmrg          { echo "$0: cannot unlink or rename $dst" >&2
522f66be5ecSmrg            (exit 1); exit 1
523f66be5ecSmrg          }
524f66be5ecSmrg        } &&
525f66be5ecSmrg
526f66be5ecSmrg        # Now rename the file to the real destination.
527f66be5ecSmrg        $doit $mvcmd "$dsttmp" "$dst"
5287888fd0eSmrg      }
5297888fd0eSmrg    fi || exit 1
5300fa2845dSmrg
5310fa2845dSmrg    trap '' 0
5320fa2845dSmrg  fi
5330fa2845dSmrgdone
5340fa2845dSmrg
5350fa2845dSmrg# Local variables:
536a0d387c7Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
5370fa2845dSmrg# time-stamp-start: "scriptversion="
5380fa2845dSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
539a0d387c7Smrg# time-stamp-time-zone: "UTC0"
5407888fd0eSmrg# time-stamp-end: "; # UTC"
5410fa2845dSmrg# End:
542