install-sh revision 15adf0bf
1dcae5b9eSmrg#!/bin/sh
2dcae5b9eSmrg# install - install a program, script, or datafile
35b28e182Smrg
415adf0bfSmrgscriptversion=2020-11-14.01; # UTC
55b28e182Smrg
6dcae5b9eSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7dcae5b9eSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8dcae5b9eSmrg# following copyright and license.
9dcae5b9eSmrg#
10dcae5b9eSmrg# Copyright (C) 1994 X Consortium
11dcae5b9eSmrg#
12dcae5b9eSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13dcae5b9eSmrg# of this software and associated documentation files (the "Software"), to
14dcae5b9eSmrg# deal in the Software without restriction, including without limitation the
15dcae5b9eSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16dcae5b9eSmrg# sell copies of the Software, and to permit persons to whom the Software is
17dcae5b9eSmrg# furnished to do so, subject to the following conditions:
18dcae5b9eSmrg#
19dcae5b9eSmrg# The above copyright notice and this permission notice shall be included in
20dcae5b9eSmrg# all copies or substantial portions of the Software.
21dcae5b9eSmrg#
22dcae5b9eSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23dcae5b9eSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24dcae5b9eSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25dcae5b9eSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26dcae5b9eSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27dcae5b9eSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28dcae5b9eSmrg#
29dcae5b9eSmrg# Except as contained in this notice, the name of the X Consortium shall not
30dcae5b9eSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31dcae5b9eSmrg# ings in this Software without prior written authorization from the X Consor-
32dcae5b9eSmrg# tium.
33dcae5b9eSmrg#
34dcae5b9eSmrg#
35dcae5b9eSmrg# FSF changes to this file are in the public domain.
36dcae5b9eSmrg#
37dcae5b9eSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3815adf0bfSmrg# 'make' implicit rules from creating a file called install from it
39dcae5b9eSmrg# when there is no Makefile.
40dcae5b9eSmrg#
41dcae5b9eSmrg# This script is compatible with the BSD install script, but was written
425b28e182Smrg# from scratch.
43dcae5b9eSmrg
4415adf0bfSmrgtab='	'
455b28e182Smrgnl='
465b28e182Smrg'
4715adf0bfSmrgIFS=" $tab$nl"
48dcae5b9eSmrg
4915adf0bfSmrg# Set DOITPROG to "echo" to test this script.
50dcae5b9eSmrg
515b28e182Smrgdoit=${DOITPROG-}
5215adf0bfSmrgdoit_exec=${doit:-exec}
53dcae5b9eSmrg
545b28e182Smrg# Put in absolute file names if you don't have them in your path;
555b28e182Smrg# or use environment vars.
565b28e182Smrg
575b28e182Smrgchgrpprog=${CHGRPPROG-chgrp}
585b28e182Smrgchmodprog=${CHMODPROG-chmod}
595b28e182Smrgchownprog=${CHOWNPROG-chown}
605b28e182Smrgcmpprog=${CMPPROG-cmp}
615b28e182Smrgcpprog=${CPPROG-cp}
625b28e182Smrgmkdirprog=${MKDIRPROG-mkdir}
635b28e182Smrgmvprog=${MVPROG-mv}
645b28e182Smrgrmprog=${RMPROG-rm}
655b28e182Smrgstripprog=${STRIPPROG-strip}
665b28e182Smrg
675b28e182Smrgposix_mkdir=
685b28e182Smrg
695b28e182Smrg# Desired mode of installed file.
705b28e182Smrgmode=0755
715b28e182Smrg
7215adf0bfSmrg# Create dirs (including intermediate dirs) using mode 755.
7315adf0bfSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7415adf0bfSmrgmkdir_umask=22
7515adf0bfSmrg
7615adf0bfSmrgbackupsuffix=
775b28e182Smrgchgrpcmd=
785b28e182Smrgchmodcmd=$chmodprog
795b28e182Smrgchowncmd=
805b28e182Smrgmvcmd=$mvprog
815b28e182Smrgrmcmd="$rmprog -f"
825b28e182Smrgstripcmd=
83dcae5b9eSmrg
845b28e182Smrgsrc=
855b28e182Smrgdst=
865b28e182Smrgdir_arg=
875b28e182Smrgdst_arg=
88dcae5b9eSmrg
895b28e182Smrgcopy_on_change=false
9015adf0bfSmrgis_target_a_directory=possibly
91dcae5b9eSmrg
925b28e182Smrgusage="\
935b28e182SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
945b28e182Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
955b28e182Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
965b28e182Smrg   or: $0 [OPTION]... -d DIRECTORIES...
97dcae5b9eSmrg
985b28e182SmrgIn the 1st form, copy SRCFILE to DSTFILE.
995b28e182SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
1005b28e182SmrgIn the 4th, create DIRECTORIES.
101dcae5b9eSmrg
1025b28e182SmrgOptions:
1035b28e182Smrg     --help     display this help and exit.
1045b28e182Smrg     --version  display version info and exit.
105dcae5b9eSmrg
1065b28e182Smrg  -c            (ignored)
10715adf0bfSmrg  -C            install only if different (preserve data modification time)
1085b28e182Smrg  -d            create directories instead of installing files.
1095b28e182Smrg  -g GROUP      $chgrpprog installed files to GROUP.
1105b28e182Smrg  -m MODE       $chmodprog installed files to MODE.
1115b28e182Smrg  -o USER       $chownprog installed files to USER.
11215adf0bfSmrg  -p            pass -p to $cpprog.
1135b28e182Smrg  -s            $stripprog installed files.
11415adf0bfSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
1155b28e182Smrg  -t DIRECTORY  install into DIRECTORY.
1165b28e182Smrg  -T            report an error if DSTFILE is a directory.
117dcae5b9eSmrg
1185b28e182SmrgEnvironment variables override the default commands:
1195b28e182Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1205b28e182Smrg  RMPROG STRIPPROG
12115adf0bfSmrg
12215adf0bfSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12315adf0bfSmrgit's up to you to specify -f if you want it.
12415adf0bfSmrg
12515adf0bfSmrgIf -S is not specified, no backups are attempted.
12615adf0bfSmrg
12715adf0bfSmrgEmail bug reports to bug-automake@gnu.org.
12815adf0bfSmrgAutomake home page: https://www.gnu.org/software/automake/
1295b28e182Smrg"
130dcae5b9eSmrg
1315b28e182Smrgwhile test $# -ne 0; do
1325b28e182Smrg  case $1 in
1335b28e182Smrg    -c) ;;
134dcae5b9eSmrg
1355b28e182Smrg    -C) copy_on_change=true;;
136dcae5b9eSmrg
1375b28e182Smrg    -d) dir_arg=true;;
138dcae5b9eSmrg
1395b28e182Smrg    -g) chgrpcmd="$chgrpprog $2"
14015adf0bfSmrg        shift;;
141dcae5b9eSmrg
1425b28e182Smrg    --help) echo "$usage"; exit $?;;
143dcae5b9eSmrg
1445b28e182Smrg    -m) mode=$2
14515adf0bfSmrg        case $mode in
14615adf0bfSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14715adf0bfSmrg            echo "$0: invalid mode: $mode" >&2
14815adf0bfSmrg            exit 1;;
14915adf0bfSmrg        esac
15015adf0bfSmrg        shift;;
151dcae5b9eSmrg
1525b28e182Smrg    -o) chowncmd="$chownprog $2"
15315adf0bfSmrg        shift;;
15415adf0bfSmrg
15515adf0bfSmrg    -p) cpprog="$cpprog -p";;
156dcae5b9eSmrg
1575b28e182Smrg    -s) stripcmd=$stripprog;;
158dcae5b9eSmrg
15915adf0bfSmrg    -S) backupsuffix="$2"
16015adf0bfSmrg        shift;;
16115adf0bfSmrg
16215adf0bfSmrg    -t)
16315adf0bfSmrg        is_target_a_directory=always
16415adf0bfSmrg        dst_arg=$2
16515adf0bfSmrg        # Protect names problematic for 'test' and other utilities.
16615adf0bfSmrg        case $dst_arg in
16715adf0bfSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16815adf0bfSmrg        esac
16915adf0bfSmrg        shift;;
170dcae5b9eSmrg
17115adf0bfSmrg    -T) is_target_a_directory=never;;
172dcae5b9eSmrg
1735b28e182Smrg    --version) echo "$0 $scriptversion"; exit $?;;
174dcae5b9eSmrg
17515adf0bfSmrg    --) shift
17615adf0bfSmrg        break;;
177dcae5b9eSmrg
17815adf0bfSmrg    -*) echo "$0: invalid option: $1" >&2
17915adf0bfSmrg        exit 1;;
180dcae5b9eSmrg
1815b28e182Smrg    *)  break;;
1825b28e182Smrg  esac
1835b28e182Smrg  shift
1845b28e182Smrgdone
185dcae5b9eSmrg
18615adf0bfSmrg# We allow the use of options -d and -T together, by making -d
18715adf0bfSmrg# take the precedence; this is for compatibility with GNU install.
18815adf0bfSmrg
18915adf0bfSmrgif test -n "$dir_arg"; then
19015adf0bfSmrg  if test -n "$dst_arg"; then
19115adf0bfSmrg    echo "$0: target directory not allowed when installing a directory." >&2
19215adf0bfSmrg    exit 1
19315adf0bfSmrg  fi
19415adf0bfSmrgfi
19515adf0bfSmrg
1965b28e182Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1975b28e182Smrg  # When -d is used, all remaining arguments are directories to create.
1985b28e182Smrg  # When -t is used, the destination is already specified.
1995b28e182Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
2005b28e182Smrg  for arg
2015b28e182Smrg  do
2025b28e182Smrg    if test -n "$dst_arg"; then
2035b28e182Smrg      # $@ is not empty: it contains at least $arg.
2045b28e182Smrg      set fnord "$@" "$dst_arg"
2055b28e182Smrg      shift # fnord
2065b28e182Smrg    fi
2075b28e182Smrg    shift # arg
2085b28e182Smrg    dst_arg=$arg
20915adf0bfSmrg    # Protect names problematic for 'test' and other utilities.
21015adf0bfSmrg    case $dst_arg in
21115adf0bfSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21215adf0bfSmrg    esac
2135b28e182Smrg  done
2145b28e182Smrgfi
215dcae5b9eSmrg
2165b28e182Smrgif test $# -eq 0; then
2175b28e182Smrg  if test -z "$dir_arg"; then
2185b28e182Smrg    echo "$0: no input file specified." >&2
2195b28e182Smrg    exit 1
2205b28e182Smrg  fi
22115adf0bfSmrg  # It's OK to call 'install-sh -d' without argument.
2225b28e182Smrg  # This can happen when creating conditional directories.
2235b28e182Smrg  exit 0
2245b28e182Smrgfi
225dcae5b9eSmrg
2265b28e182Smrgif test -z "$dir_arg"; then
22715adf0bfSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22815adf0bfSmrg    if test ! -d "$dst_arg"; then
22915adf0bfSmrg      echo "$0: $dst_arg: Is not a directory." >&2
23015adf0bfSmrg      exit 1
23115adf0bfSmrg    fi
23215adf0bfSmrg  fi
23315adf0bfSmrgfi
23415adf0bfSmrg
23515adf0bfSmrgif test -z "$dir_arg"; then
23615adf0bfSmrg  do_exit='(exit $ret); exit $ret'
23715adf0bfSmrg  trap "ret=129; $do_exit" 1
23815adf0bfSmrg  trap "ret=130; $do_exit" 2
23915adf0bfSmrg  trap "ret=141; $do_exit" 13
24015adf0bfSmrg  trap "ret=143; $do_exit" 15
2415b28e182Smrg
2425b28e182Smrg  # Set umask so as not to create temps with too-generous modes.
2435b28e182Smrg  # However, 'strip' requires both read and write access to temps.
2445b28e182Smrg  case $mode in
2455b28e182Smrg    # Optimize common cases.
2465b28e182Smrg    *644) cp_umask=133;;
2475b28e182Smrg    *755) cp_umask=22;;
2485b28e182Smrg
2495b28e182Smrg    *[0-7])
2505b28e182Smrg      if test -z "$stripcmd"; then
25115adf0bfSmrg        u_plus_rw=
2525b28e182Smrg      else
25315adf0bfSmrg        u_plus_rw='% 200'
2545b28e182Smrg      fi
2555b28e182Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2565b28e182Smrg    *)
2575b28e182Smrg      if test -z "$stripcmd"; then
25815adf0bfSmrg        u_plus_rw=
2595b28e182Smrg      else
26015adf0bfSmrg        u_plus_rw=,u+rw
2615b28e182Smrg      fi
2625b28e182Smrg      cp_umask=$mode$u_plus_rw;;
2635b28e182Smrg  esac
2645b28e182Smrgfi
265dcae5b9eSmrg
2665b28e182Smrgfor src
2675b28e182Smrgdo
26815adf0bfSmrg  # Protect names problematic for 'test' and other utilities.
2695b28e182Smrg  case $src in
27015adf0bfSmrg    -* | [=\(\)!]) src=./$src;;
2715b28e182Smrg  esac
2725b28e182Smrg
2735b28e182Smrg  if test -n "$dir_arg"; then
2745b28e182Smrg    dst=$src
2755b28e182Smrg    dstdir=$dst
2765b28e182Smrg    test -d "$dstdir"
2775b28e182Smrg    dstdir_status=$?
27815adf0bfSmrg    # Don't chown directories that already exist.
27915adf0bfSmrg    if test $dstdir_status = 0; then
28015adf0bfSmrg      chowncmd=""
28115adf0bfSmrg    fi
2825b28e182Smrg  else
2835b28e182Smrg
2845b28e182Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2855b28e182Smrg    # might cause directories to be created, which would be especially bad
2865b28e182Smrg    # if $src (and thus $dsttmp) contains '*'.
2875b28e182Smrg    if test ! -f "$src" && test ! -d "$src"; then
2885b28e182Smrg      echo "$0: $src does not exist." >&2
2895b28e182Smrg      exit 1
2905b28e182Smrg    fi
2915b28e182Smrg
2925b28e182Smrg    if test -z "$dst_arg"; then
2935b28e182Smrg      echo "$0: no destination specified." >&2
2945b28e182Smrg      exit 1
2955b28e182Smrg    fi
2965b28e182Smrg    dst=$dst_arg
297dcae5b9eSmrg
29815adf0bfSmrg    # If destination is a directory, append the input filename.
2995b28e182Smrg    if test -d "$dst"; then
30015adf0bfSmrg      if test "$is_target_a_directory" = never; then
30115adf0bfSmrg        echo "$0: $dst_arg: Is a directory" >&2
30215adf0bfSmrg        exit 1
3035b28e182Smrg      fi
3045b28e182Smrg      dstdir=$dst
30515adf0bfSmrg      dstbase=`basename "$src"`
30615adf0bfSmrg      case $dst in
30715adf0bfSmrg	*/) dst=$dst$dstbase;;
30815adf0bfSmrg	*)  dst=$dst/$dstbase;;
30915adf0bfSmrg      esac
3105b28e182Smrg      dstdir_status=0
3115b28e182Smrg    else
31215adf0bfSmrg      dstdir=`dirname "$dst"`
3135b28e182Smrg      test -d "$dstdir"
3145b28e182Smrg      dstdir_status=$?
3155b28e182Smrg    fi
3165b28e182Smrg  fi
3175b28e182Smrg
31815adf0bfSmrg  case $dstdir in
31915adf0bfSmrg    */) dstdirslash=$dstdir;;
32015adf0bfSmrg    *)  dstdirslash=$dstdir/;;
32115adf0bfSmrg  esac
32215adf0bfSmrg
3235b28e182Smrg  obsolete_mkdir_used=false
3245b28e182Smrg
3255b28e182Smrg  if test $dstdir_status != 0; then
3265b28e182Smrg    case $posix_mkdir in
3275b28e182Smrg      '')
32815adf0bfSmrg        # With -d, create the new directory with the user-specified mode.
32915adf0bfSmrg        # Otherwise, rely on $mkdir_umask.
33015adf0bfSmrg        if test -n "$dir_arg"; then
33115adf0bfSmrg          mkdir_mode=-m$mode
33215adf0bfSmrg        else
33315adf0bfSmrg          mkdir_mode=
33415adf0bfSmrg        fi
33515adf0bfSmrg
33615adf0bfSmrg        posix_mkdir=false
33715adf0bfSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33815adf0bfSmrg	# here however when possible just to lower collision chance.
33915adf0bfSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34015adf0bfSmrg
34115adf0bfSmrg	trap '
34215adf0bfSmrg	  ret=$?
34315adf0bfSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34415adf0bfSmrg	  exit $ret
34515adf0bfSmrg	' 0
34615adf0bfSmrg
34715adf0bfSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
34815adf0bfSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
34915adf0bfSmrg	# directory is successfully created first before we actually test
35015adf0bfSmrg	# 'mkdir -p'.
35115adf0bfSmrg	if (umask $mkdir_umask &&
35215adf0bfSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35315adf0bfSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35415adf0bfSmrg	then
35515adf0bfSmrg	  if test -z "$dir_arg" || {
35615adf0bfSmrg	       # Check for POSIX incompatibilities with -m.
35715adf0bfSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35815adf0bfSmrg	       # other-writable bit of parent directory when it shouldn't.
35915adf0bfSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36015adf0bfSmrg	       test_tmpdir="$tmpdir/a"
36115adf0bfSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36215adf0bfSmrg	       case $ls_ld_tmpdir in
36315adf0bfSmrg		 d????-?r-*) different_mode=700;;
36415adf0bfSmrg		 d????-?--*) different_mode=755;;
36515adf0bfSmrg		 *) false;;
36615adf0bfSmrg	       esac &&
36715adf0bfSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36815adf0bfSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36915adf0bfSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37015adf0bfSmrg	       }
37115adf0bfSmrg	     }
37215adf0bfSmrg	  then posix_mkdir=:
37315adf0bfSmrg	  fi
37415adf0bfSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375dcae5b9eSmrg	else
37615adf0bfSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
37715adf0bfSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378dcae5b9eSmrg	fi
37915adf0bfSmrg	trap '' 0;;
3805b28e182Smrg    esac
381dcae5b9eSmrg
3825b28e182Smrg    if
3835b28e182Smrg      $posix_mkdir && (
38415adf0bfSmrg        umask $mkdir_umask &&
38515adf0bfSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3865b28e182Smrg      )
3875b28e182Smrg    then :
3885b28e182Smrg    else
3895b28e182Smrg
39015adf0bfSmrg      # mkdir does not conform to POSIX,
3915b28e182Smrg      # or it failed possibly due to a race condition.  Create the
3925b28e182Smrg      # directory the slow way, step by step, checking for races as we go.
3935b28e182Smrg
3945b28e182Smrg      case $dstdir in
39515adf0bfSmrg        /*) prefix='/';;
39615adf0bfSmrg        [-=\(\)!]*) prefix='./';;
39715adf0bfSmrg        *)  prefix='';;
3985b28e182Smrg      esac
3995b28e182Smrg
4005b28e182Smrg      oIFS=$IFS
4015b28e182Smrg      IFS=/
40215adf0bfSmrg      set -f
4035b28e182Smrg      set fnord $dstdir
4045b28e182Smrg      shift
40515adf0bfSmrg      set +f
4065b28e182Smrg      IFS=$oIFS
4075b28e182Smrg
4085b28e182Smrg      prefixes=
4095b28e182Smrg
4105b28e182Smrg      for d
4115b28e182Smrg      do
41215adf0bfSmrg        test X"$d" = X && continue
41315adf0bfSmrg
41415adf0bfSmrg        prefix=$prefix$d
41515adf0bfSmrg        if test -d "$prefix"; then
41615adf0bfSmrg          prefixes=
41715adf0bfSmrg        else
41815adf0bfSmrg          if $posix_mkdir; then
41915adf0bfSmrg            (umask $mkdir_umask &&
42015adf0bfSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42115adf0bfSmrg            # Don't fail if two instances are running concurrently.
42215adf0bfSmrg            test -d "$prefix" || exit 1
42315adf0bfSmrg          else
42415adf0bfSmrg            case $prefix in
42515adf0bfSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42615adf0bfSmrg              *) qprefix=$prefix;;
42715adf0bfSmrg            esac
42815adf0bfSmrg            prefixes="$prefixes '$qprefix'"
42915adf0bfSmrg          fi
43015adf0bfSmrg        fi
43115adf0bfSmrg        prefix=$prefix/
4325b28e182Smrg      done
4335b28e182Smrg
4345b28e182Smrg      if test -n "$prefixes"; then
43515adf0bfSmrg        # Don't fail if two instances are running concurrently.
43615adf0bfSmrg        (umask $mkdir_umask &&
43715adf0bfSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43815adf0bfSmrg          test -d "$dstdir" || exit 1
43915adf0bfSmrg        obsolete_mkdir_used=true
4405b28e182Smrg      fi
4415b28e182Smrg    fi
4425b28e182Smrg  fi
4435b28e182Smrg
4445b28e182Smrg  if test -n "$dir_arg"; then
4455b28e182Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4465b28e182Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4475b28e182Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4485b28e182Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4495b28e182Smrg  else
4505b28e182Smrg
4515b28e182Smrg    # Make a couple of temp file names in the proper directory.
45215adf0bfSmrg    dsttmp=${dstdirslash}_inst.$$_
45315adf0bfSmrg    rmtmp=${dstdirslash}_rm.$$_
4545b28e182Smrg
4555b28e182Smrg    # Trap to clean up those temp files at exit.
4565b28e182Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4575b28e182Smrg
4585b28e182Smrg    # Copy the file name to the temp name.
45915adf0bfSmrg    (umask $cp_umask &&
46015adf0bfSmrg     { test -z "$stripcmd" || {
46115adf0bfSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46215adf0bfSmrg	 # which would cause strip to fail.
46315adf0bfSmrg	 if test -z "$doit"; then
46415adf0bfSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46515adf0bfSmrg	 else
46615adf0bfSmrg	   $doit touch "$dsttmp"
46715adf0bfSmrg	 fi
46815adf0bfSmrg       }
46915adf0bfSmrg     } &&
47015adf0bfSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
4715b28e182Smrg
4725b28e182Smrg    # and set any options; do chmod last to preserve setuid bits.
4735b28e182Smrg    #
4745b28e182Smrg    # If any of these fail, we abort the whole thing.  If we want to
4755b28e182Smrg    # ignore errors from any of these, just make sure not to ignore
4765b28e182Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4775b28e182Smrg    #
4785b28e182Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4795b28e182Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4805b28e182Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4815b28e182Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4825b28e182Smrg
4835b28e182Smrg    # If -C, don't bother to copy if it wouldn't change the file.
4845b28e182Smrg    if $copy_on_change &&
48515adf0bfSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48615adf0bfSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48715adf0bfSmrg       set -f &&
4885b28e182Smrg       set X $old && old=:$2:$4:$5:$6 &&
4895b28e182Smrg       set X $new && new=:$2:$4:$5:$6 &&
49015adf0bfSmrg       set +f &&
4915b28e182Smrg       test "$old" = "$new" &&
4925b28e182Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4935b28e182Smrg    then
4945b28e182Smrg      rm -f "$dsttmp"
4955b28e182Smrg    else
49615adf0bfSmrg      # If $backupsuffix is set, and the file being installed
49715adf0bfSmrg      # already exists, attempt a backup.  Don't worry if it fails,
49815adf0bfSmrg      # e.g., if mv doesn't support -f.
49915adf0bfSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
50015adf0bfSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50115adf0bfSmrg      fi
50215adf0bfSmrg
5035b28e182Smrg      # Rename the file to the real destination.
5045b28e182Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
5055b28e182Smrg
5065b28e182Smrg      # The rename failed, perhaps because mv can't rename something else
5075b28e182Smrg      # to itself, or perhaps because mv is so ancient that it does not
5085b28e182Smrg      # support -f.
5095b28e182Smrg      {
51015adf0bfSmrg        # Now remove or move aside any old file at destination location.
51115adf0bfSmrg        # We try this two ways since rm can't unlink itself on some
51215adf0bfSmrg        # systems and the destination file might be busy for other
51315adf0bfSmrg        # reasons.  In this case, the final cleanup might fail but the new
51415adf0bfSmrg        # file should still install successfully.
51515adf0bfSmrg        {
51615adf0bfSmrg          test ! -f "$dst" ||
51715adf0bfSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
51815adf0bfSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51915adf0bfSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52015adf0bfSmrg          } ||
52115adf0bfSmrg          { echo "$0: cannot unlink or rename $dst" >&2
52215adf0bfSmrg            (exit 1); exit 1
52315adf0bfSmrg          }
52415adf0bfSmrg        } &&
52515adf0bfSmrg
52615adf0bfSmrg        # Now rename the file to the real destination.
52715adf0bfSmrg        $doit $mvcmd "$dsttmp" "$dst"
5285b28e182Smrg      }
5295b28e182Smrg    fi || exit 1
5305b28e182Smrg
5315b28e182Smrg    trap '' 0
5325b28e182Smrg  fi
5335b28e182Smrgdone
534dcae5b9eSmrg
5355b28e182Smrg# Local variables:
53615adf0bfSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
5375b28e182Smrg# time-stamp-start: "scriptversion="
5385b28e182Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53915adf0bfSmrg# time-stamp-time-zone: "UTC0"
5405b28e182Smrg# time-stamp-end: "; # UTC"
5415b28e182Smrg# End:
542