1943345d3Smrg#!/bin/sh
2943345d3Smrg# install - install a program, script, or datafile
3943345d3Smrg
415ffece8Smrgscriptversion=2020-11-14.01; # UTC
5943345d3Smrg
6943345d3Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7943345d3Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8943345d3Smrg# following copyright and license.
9943345d3Smrg#
10943345d3Smrg# Copyright (C) 1994 X Consortium
11943345d3Smrg#
12943345d3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13943345d3Smrg# of this software and associated documentation files (the "Software"), to
14943345d3Smrg# deal in the Software without restriction, including without limitation the
15943345d3Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16943345d3Smrg# sell copies of the Software, and to permit persons to whom the Software is
17943345d3Smrg# furnished to do so, subject to the following conditions:
18943345d3Smrg#
19943345d3Smrg# The above copyright notice and this permission notice shall be included in
20943345d3Smrg# all copies or substantial portions of the Software.
21943345d3Smrg#
22943345d3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23943345d3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24943345d3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25943345d3Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26943345d3Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27943345d3Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28943345d3Smrg#
29943345d3Smrg# Except as contained in this notice, the name of the X Consortium shall not
30943345d3Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31943345d3Smrg# ings in this Software without prior written authorization from the X Consor-
32943345d3Smrg# tium.
33943345d3Smrg#
34943345d3Smrg#
35943345d3Smrg# FSF changes to this file are in the public domain.
36943345d3Smrg#
37943345d3Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3815ffece8Smrg# 'make' implicit rules from creating a file called install from it
39943345d3Smrg# when there is no Makefile.
40943345d3Smrg#
41943345d3Smrg# This script is compatible with the BSD install script, but was written
42f67b85aaSmrg# from scratch.
43f67b85aaSmrg
4415ffece8Smrgtab='	'
45f67b85aaSmrgnl='
46f67b85aaSmrg'
4715ffece8SmrgIFS=" $tab$nl"
48943345d3Smrg
4915ffece8Smrg# Set DOITPROG to "echo" to test this script.
50943345d3Smrg
515e695a52Smrgdoit=${DOITPROG-}
5215ffece8Smrgdoit_exec=${doit:-exec}
53943345d3Smrg
54f67b85aaSmrg# Put in absolute file names if you don't have them in your path;
55f67b85aaSmrg# or use environment vars.
56943345d3Smrg
575e695a52Smrgchgrpprog=${CHGRPPROG-chgrp}
585e695a52Smrgchmodprog=${CHMODPROG-chmod}
595e695a52Smrgchownprog=${CHOWNPROG-chown}
605e695a52Smrgcmpprog=${CMPPROG-cmp}
615e695a52Smrgcpprog=${CPPROG-cp}
625e695a52Smrgmkdirprog=${MKDIRPROG-mkdir}
635e695a52Smrgmvprog=${MVPROG-mv}
645e695a52Smrgrmprog=${RMPROG-rm}
655e695a52Smrgstripprog=${STRIPPROG-strip}
665e695a52Smrg
67f67b85aaSmrgposix_mkdir=
68f67b85aaSmrg
69f67b85aaSmrg# Desired mode of installed file.
70f67b85aaSmrgmode=0755
71f67b85aaSmrg
7215ffece8Smrg# Create dirs (including intermediate dirs) using mode 755.
7315ffece8Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
7415ffece8Smrgmkdir_umask=22
7515ffece8Smrg
7615ffece8Smrgbackupsuffix=
775e695a52Smrgchgrpcmd=
78f67b85aaSmrgchmodcmd=$chmodprog
79943345d3Smrgchowncmd=
805e695a52Smrgmvcmd=$mvprog
81943345d3Smrgrmcmd="$rmprog -f"
825e695a52Smrgstripcmd=
835e695a52Smrg
84943345d3Smrgsrc=
85943345d3Smrgdst=
86943345d3Smrgdir_arg=
875e695a52Smrgdst_arg=
885e695a52Smrg
895e695a52Smrgcopy_on_change=false
9015ffece8Smrgis_target_a_directory=possibly
91943345d3Smrg
925e695a52Smrgusage="\
935e695a52SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94943345d3Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95943345d3Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96943345d3Smrg   or: $0 [OPTION]... -d DIRECTORIES...
97943345d3Smrg
98943345d3SmrgIn the 1st form, copy SRCFILE to DSTFILE.
99943345d3SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100943345d3SmrgIn the 4th, create DIRECTORIES.
101943345d3Smrg
102943345d3SmrgOptions:
1035e695a52Smrg     --help     display this help and exit.
1045e695a52Smrg     --version  display version info and exit.
1055e695a52Smrg
1065e695a52Smrg  -c            (ignored)
10715ffece8Smrg  -C            install only if different (preserve data modification time)
1085e695a52Smrg  -d            create directories instead of installing files.
1095e695a52Smrg  -g GROUP      $chgrpprog installed files to GROUP.
1105e695a52Smrg  -m MODE       $chmodprog installed files to MODE.
1115e695a52Smrg  -o USER       $chownprog installed files to USER.
11215ffece8Smrg  -p            pass -p to $cpprog.
1135e695a52Smrg  -s            $stripprog installed files.
11415ffece8Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
1155e695a52Smrg  -t DIRECTORY  install into DIRECTORY.
1165e695a52Smrg  -T            report an error if DSTFILE is a directory.
117943345d3Smrg
118943345d3SmrgEnvironment variables override the default commands:
1195e695a52Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1205e695a52Smrg  RMPROG STRIPPROG
12115ffece8Smrg
12215ffece8SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
12315ffece8Smrgit's up to you to specify -f if you want it.
12415ffece8Smrg
12515ffece8SmrgIf -S is not specified, no backups are attempted.
12615ffece8Smrg
12715ffece8SmrgEmail bug reports to bug-automake@gnu.org.
12815ffece8SmrgAutomake home page: https://www.gnu.org/software/automake/
129943345d3Smrg"
130943345d3Smrg
131f67b85aaSmrgwhile test $# -ne 0; do
132943345d3Smrg  case $1 in
1335e695a52Smrg    -c) ;;
1345e695a52Smrg
1355e695a52Smrg    -C) copy_on_change=true;;
136943345d3Smrg
1375e695a52Smrg    -d) dir_arg=true;;
138943345d3Smrg
139943345d3Smrg    -g) chgrpcmd="$chgrpprog $2"
14015ffece8Smrg        shift;;
141943345d3Smrg
142943345d3Smrg    --help) echo "$usage"; exit $?;;
143943345d3Smrg
144f67b85aaSmrg    -m) mode=$2
14515ffece8Smrg        case $mode in
14615ffece8Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14715ffece8Smrg            echo "$0: invalid mode: $mode" >&2
14815ffece8Smrg            exit 1;;
14915ffece8Smrg        esac
15015ffece8Smrg        shift;;
151943345d3Smrg
152943345d3Smrg    -o) chowncmd="$chownprog $2"
15315ffece8Smrg        shift;;
15415ffece8Smrg
15515ffece8Smrg    -p) cpprog="$cpprog -p";;
156943345d3Smrg
1575e695a52Smrg    -s) stripcmd=$stripprog;;
158943345d3Smrg
15915ffece8Smrg    -S) backupsuffix="$2"
16015ffece8Smrg        shift;;
161943345d3Smrg
16215ffece8Smrg    -t)
16315ffece8Smrg        is_target_a_directory=always
16415ffece8Smrg        dst_arg=$2
16515ffece8Smrg        # Protect names problematic for 'test' and other utilities.
16615ffece8Smrg        case $dst_arg in
16715ffece8Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16815ffece8Smrg        esac
16915ffece8Smrg        shift;;
17015ffece8Smrg
17115ffece8Smrg    -T) is_target_a_directory=never;;
172943345d3Smrg
173943345d3Smrg    --version) echo "$0 $scriptversion"; exit $?;;
174943345d3Smrg
17515ffece8Smrg    --) shift
17615ffece8Smrg        break;;
177f67b85aaSmrg
17815ffece8Smrg    -*) echo "$0: invalid option: $1" >&2
17915ffece8Smrg        exit 1;;
180f67b85aaSmrg
181f67b85aaSmrg    *)  break;;
182943345d3Smrg  esac
1835e695a52Smrg  shift
184943345d3Smrgdone
185943345d3Smrg
18615ffece8Smrg# We allow the use of options -d and -T together, by making -d
18715ffece8Smrg# take the precedence; this is for compatibility with GNU install.
18815ffece8Smrg
18915ffece8Smrgif test -n "$dir_arg"; then
19015ffece8Smrg  if test -n "$dst_arg"; then
19115ffece8Smrg    echo "$0: target directory not allowed when installing a directory." >&2
19215ffece8Smrg    exit 1
19315ffece8Smrg  fi
19415ffece8Smrgfi
19515ffece8Smrg
1965e695a52Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197f67b85aaSmrg  # When -d is used, all remaining arguments are directories to create.
198f67b85aaSmrg  # When -t is used, the destination is already specified.
199f67b85aaSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200f67b85aaSmrg  for arg
201f67b85aaSmrg  do
2025e695a52Smrg    if test -n "$dst_arg"; then
203f67b85aaSmrg      # $@ is not empty: it contains at least $arg.
2045e695a52Smrg      set fnord "$@" "$dst_arg"
205f67b85aaSmrg      shift # fnord
206f67b85aaSmrg    fi
207f67b85aaSmrg    shift # arg
2085e695a52Smrg    dst_arg=$arg
20915ffece8Smrg    # Protect names problematic for 'test' and other utilities.
2103e51e026Smrg    case $dst_arg in
2113e51e026Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
2123e51e026Smrg    esac
213f67b85aaSmrg  done
214f67b85aaSmrgfi
215f67b85aaSmrg
216f67b85aaSmrgif test $# -eq 0; then
217943345d3Smrg  if test -z "$dir_arg"; then
218943345d3Smrg    echo "$0: no input file specified." >&2
219943345d3Smrg    exit 1
220943345d3Smrg  fi
22115ffece8Smrg  # It's OK to call 'install-sh -d' without argument.
222943345d3Smrg  # This can happen when creating conditional directories.
223943345d3Smrg  exit 0
224943345d3Smrgfi
225943345d3Smrg
22615ffece8Smrgif test -z "$dir_arg"; then
22715ffece8Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22815ffece8Smrg    if test ! -d "$dst_arg"; then
22915ffece8Smrg      echo "$0: $dst_arg: Is not a directory." >&2
23015ffece8Smrg      exit 1
23115ffece8Smrg    fi
23215ffece8Smrg  fi
23315ffece8Smrgfi
23415ffece8Smrg
235f67b85aaSmrgif test -z "$dir_arg"; then
2363e51e026Smrg  do_exit='(exit $ret); exit $ret'
2373e51e026Smrg  trap "ret=129; $do_exit" 1
2383e51e026Smrg  trap "ret=130; $do_exit" 2
2393e51e026Smrg  trap "ret=141; $do_exit" 13
2403e51e026Smrg  trap "ret=143; $do_exit" 15
241f67b85aaSmrg
242f67b85aaSmrg  # Set umask so as not to create temps with too-generous modes.
243f67b85aaSmrg  # However, 'strip' requires both read and write access to temps.
244f67b85aaSmrg  case $mode in
245f67b85aaSmrg    # Optimize common cases.
246f67b85aaSmrg    *644) cp_umask=133;;
247f67b85aaSmrg    *755) cp_umask=22;;
248f67b85aaSmrg
249f67b85aaSmrg    *[0-7])
250f67b85aaSmrg      if test -z "$stripcmd"; then
25115ffece8Smrg        u_plus_rw=
252f67b85aaSmrg      else
25315ffece8Smrg        u_plus_rw='% 200'
254f67b85aaSmrg      fi
255f67b85aaSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256f67b85aaSmrg    *)
257f67b85aaSmrg      if test -z "$stripcmd"; then
25815ffece8Smrg        u_plus_rw=
259f67b85aaSmrg      else
26015ffece8Smrg        u_plus_rw=,u+rw
261f67b85aaSmrg      fi
262f67b85aaSmrg      cp_umask=$mode$u_plus_rw;;
263f67b85aaSmrg  esac
264f67b85aaSmrgfi
265f67b85aaSmrg
266943345d3Smrgfor src
267943345d3Smrgdo
26815ffece8Smrg  # Protect names problematic for 'test' and other utilities.
269943345d3Smrg  case $src in
2703e51e026Smrg    -* | [=\(\)!]) src=./$src;;
271943345d3Smrg  esac
272943345d3Smrg
273943345d3Smrg  if test -n "$dir_arg"; then
274943345d3Smrg    dst=$src
275f67b85aaSmrg    dstdir=$dst
276f67b85aaSmrg    test -d "$dstdir"
277f67b85aaSmrg    dstdir_status=$?
27815ffece8Smrg    # Don't chown directories that already exist.
27915ffece8Smrg    if test $dstdir_status = 0; then
28015ffece8Smrg      chowncmd=""
28115ffece8Smrg    fi
282943345d3Smrg  else
283f67b85aaSmrg
284943345d3Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285943345d3Smrg    # might cause directories to be created, which would be especially bad
286943345d3Smrg    # if $src (and thus $dsttmp) contains '*'.
287943345d3Smrg    if test ! -f "$src" && test ! -d "$src"; then
288943345d3Smrg      echo "$0: $src does not exist." >&2
289943345d3Smrg      exit 1
290943345d3Smrg    fi
291943345d3Smrg
2925e695a52Smrg    if test -z "$dst_arg"; then
293943345d3Smrg      echo "$0: no destination specified." >&2
294943345d3Smrg      exit 1
295943345d3Smrg    fi
2965e695a52Smrg    dst=$dst_arg
297943345d3Smrg
29815ffece8Smrg    # If destination is a directory, append the input filename.
299943345d3Smrg    if test -d "$dst"; then
30015ffece8Smrg      if test "$is_target_a_directory" = never; then
30115ffece8Smrg        echo "$0: $dst_arg: Is a directory" >&2
30215ffece8Smrg        exit 1
303943345d3Smrg      fi
304f67b85aaSmrg      dstdir=$dst
30515ffece8Smrg      dstbase=`basename "$src"`
30615ffece8Smrg      case $dst in
30715ffece8Smrg	*/) dst=$dst$dstbase;;
30815ffece8Smrg	*)  dst=$dst/$dstbase;;
30915ffece8Smrg      esac
310f67b85aaSmrg      dstdir_status=0
311f67b85aaSmrg    else
31215ffece8Smrg      dstdir=`dirname "$dst"`
313f67b85aaSmrg      test -d "$dstdir"
314f67b85aaSmrg      dstdir_status=$?
315943345d3Smrg    fi
316943345d3Smrg  fi
317943345d3Smrg
31815ffece8Smrg  case $dstdir in
31915ffece8Smrg    */) dstdirslash=$dstdir;;
32015ffece8Smrg    *)  dstdirslash=$dstdir/;;
32115ffece8Smrg  esac
32215ffece8Smrg
323f67b85aaSmrg  obsolete_mkdir_used=false
324f67b85aaSmrg
325f67b85aaSmrg  if test $dstdir_status != 0; then
326f67b85aaSmrg    case $posix_mkdir in
327f67b85aaSmrg      '')
32815ffece8Smrg        # With -d, create the new directory with the user-specified mode.
32915ffece8Smrg        # Otherwise, rely on $mkdir_umask.
33015ffece8Smrg        if test -n "$dir_arg"; then
33115ffece8Smrg          mkdir_mode=-m$mode
33215ffece8Smrg        else
33315ffece8Smrg          mkdir_mode=
33415ffece8Smrg        fi
33515ffece8Smrg
33615ffece8Smrg        posix_mkdir=false
33715ffece8Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
33815ffece8Smrg	# here however when possible just to lower collision chance.
33915ffece8Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
34015ffece8Smrg
34115ffece8Smrg	trap '
34215ffece8Smrg	  ret=$?
34315ffece8Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
34415ffece8Smrg	  exit $ret
34515ffece8Smrg	' 0
34615ffece8Smrg
34715ffece8Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
34815ffece8Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
34915ffece8Smrg	# directory is successfully created first before we actually test
35015ffece8Smrg	# 'mkdir -p'.
35115ffece8Smrg	if (umask $mkdir_umask &&
35215ffece8Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
35315ffece8Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
35415ffece8Smrg	then
35515ffece8Smrg	  if test -z "$dir_arg" || {
35615ffece8Smrg	       # Check for POSIX incompatibilities with -m.
35715ffece8Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35815ffece8Smrg	       # other-writable bit of parent directory when it shouldn't.
35915ffece8Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
36015ffece8Smrg	       test_tmpdir="$tmpdir/a"
36115ffece8Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
36215ffece8Smrg	       case $ls_ld_tmpdir in
36315ffece8Smrg		 d????-?r-*) different_mode=700;;
36415ffece8Smrg		 d????-?--*) different_mode=755;;
36515ffece8Smrg		 *) false;;
36615ffece8Smrg	       esac &&
36715ffece8Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36815ffece8Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36915ffece8Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
37015ffece8Smrg	       }
37115ffece8Smrg	     }
37215ffece8Smrg	  then posix_mkdir=:
37315ffece8Smrg	  fi
37415ffece8Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375f67b85aaSmrg	else
37615ffece8Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
37715ffece8Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378f67b85aaSmrg	fi
37915ffece8Smrg	trap '' 0;;
380f67b85aaSmrg    esac
381943345d3Smrg
382f67b85aaSmrg    if
383f67b85aaSmrg      $posix_mkdir && (
38415ffece8Smrg        umask $mkdir_umask &&
38515ffece8Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386f67b85aaSmrg      )
387f67b85aaSmrg    then :
388f67b85aaSmrg    else
389943345d3Smrg
39015ffece8Smrg      # mkdir does not conform to POSIX,
391f67b85aaSmrg      # or it failed possibly due to a race condition.  Create the
392f67b85aaSmrg      # directory the slow way, step by step, checking for races as we go.
393f67b85aaSmrg
394f67b85aaSmrg      case $dstdir in
39515ffece8Smrg        /*) prefix='/';;
39615ffece8Smrg        [-=\(\)!]*) prefix='./';;
39715ffece8Smrg        *)  prefix='';;
398f67b85aaSmrg      esac
399f67b85aaSmrg
400f67b85aaSmrg      oIFS=$IFS
401f67b85aaSmrg      IFS=/
40215ffece8Smrg      set -f
403f67b85aaSmrg      set fnord $dstdir
404943345d3Smrg      shift
40515ffece8Smrg      set +f
406f67b85aaSmrg      IFS=$oIFS
407f67b85aaSmrg
408f67b85aaSmrg      prefixes=
409f67b85aaSmrg
410f67b85aaSmrg      for d
411f67b85aaSmrg      do
41215ffece8Smrg        test X"$d" = X && continue
41315ffece8Smrg
41415ffece8Smrg        prefix=$prefix$d
41515ffece8Smrg        if test -d "$prefix"; then
41615ffece8Smrg          prefixes=
41715ffece8Smrg        else
41815ffece8Smrg          if $posix_mkdir; then
41915ffece8Smrg            (umask $mkdir_umask &&
42015ffece8Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42115ffece8Smrg            # Don't fail if two instances are running concurrently.
42215ffece8Smrg            test -d "$prefix" || exit 1
42315ffece8Smrg          else
42415ffece8Smrg            case $prefix in
42515ffece8Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42615ffece8Smrg              *) qprefix=$prefix;;
42715ffece8Smrg            esac
42815ffece8Smrg            prefixes="$prefixes '$qprefix'"
42915ffece8Smrg          fi
43015ffece8Smrg        fi
43115ffece8Smrg        prefix=$prefix/
432f67b85aaSmrg      done
433f67b85aaSmrg
434f67b85aaSmrg      if test -n "$prefixes"; then
43515ffece8Smrg        # Don't fail if two instances are running concurrently.
43615ffece8Smrg        (umask $mkdir_umask &&
43715ffece8Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43815ffece8Smrg          test -d "$dstdir" || exit 1
43915ffece8Smrg        obsolete_mkdir_used=true
440943345d3Smrg      fi
441f67b85aaSmrg    fi
442943345d3Smrg  fi
443943345d3Smrg
444943345d3Smrg  if test -n "$dir_arg"; then
445f67b85aaSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446f67b85aaSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447f67b85aaSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448f67b85aaSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449943345d3Smrg  else
450943345d3Smrg
451943345d3Smrg    # Make a couple of temp file names in the proper directory.
45215ffece8Smrg    dsttmp=${dstdirslash}_inst.$$_
45315ffece8Smrg    rmtmp=${dstdirslash}_rm.$$_
454943345d3Smrg
455943345d3Smrg    # Trap to clean up those temp files at exit.
456943345d3Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457943345d3Smrg
458943345d3Smrg    # Copy the file name to the temp name.
45915ffece8Smrg    (umask $cp_umask &&
46015ffece8Smrg     { test -z "$stripcmd" || {
46115ffece8Smrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46215ffece8Smrg	 # which would cause strip to fail.
46315ffece8Smrg	 if test -z "$doit"; then
46415ffece8Smrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46515ffece8Smrg	 else
46615ffece8Smrg	   $doit touch "$dsttmp"
46715ffece8Smrg	 fi
46815ffece8Smrg       }
46915ffece8Smrg     } &&
47015ffece8Smrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471943345d3Smrg
472943345d3Smrg    # and set any options; do chmod last to preserve setuid bits.
473943345d3Smrg    #
474943345d3Smrg    # If any of these fail, we abort the whole thing.  If we want to
475943345d3Smrg    # ignore errors from any of these, just make sure not to ignore
476943345d3Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477943345d3Smrg    #
4785e695a52Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4795e695a52Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4805e695a52Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4815e695a52Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4825e695a52Smrg
4835e695a52Smrg    # If -C, don't bother to copy if it wouldn't change the file.
4845e695a52Smrg    if $copy_on_change &&
48515ffece8Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48615ffece8Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48715ffece8Smrg       set -f &&
4885e695a52Smrg       set X $old && old=:$2:$4:$5:$6 &&
4895e695a52Smrg       set X $new && new=:$2:$4:$5:$6 &&
49015ffece8Smrg       set +f &&
4915e695a52Smrg       test "$old" = "$new" &&
4925e695a52Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4935e695a52Smrg    then
4945e695a52Smrg      rm -f "$dsttmp"
4955e695a52Smrg    else
49615ffece8Smrg      # If $backupsuffix is set, and the file being installed
49715ffece8Smrg      # already exists, attempt a backup.  Don't worry if it fails,
49815ffece8Smrg      # e.g., if mv doesn't support -f.
49915ffece8Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
50015ffece8Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
50115ffece8Smrg      fi
50215ffece8Smrg
5035e695a52Smrg      # Rename the file to the real destination.
5045e695a52Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
5055e695a52Smrg
5065e695a52Smrg      # The rename failed, perhaps because mv can't rename something else
5075e695a52Smrg      # to itself, or perhaps because mv is so ancient that it does not
5085e695a52Smrg      # support -f.
5095e695a52Smrg      {
51015ffece8Smrg        # Now remove or move aside any old file at destination location.
51115ffece8Smrg        # We try this two ways since rm can't unlink itself on some
51215ffece8Smrg        # systems and the destination file might be busy for other
51315ffece8Smrg        # reasons.  In this case, the final cleanup might fail but the new
51415ffece8Smrg        # file should still install successfully.
51515ffece8Smrg        {
51615ffece8Smrg          test ! -f "$dst" ||
51715ffece8Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
51815ffece8Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
51915ffece8Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52015ffece8Smrg          } ||
52115ffece8Smrg          { echo "$0: cannot unlink or rename $dst" >&2
52215ffece8Smrg            (exit 1); exit 1
52315ffece8Smrg          }
52415ffece8Smrg        } &&
52515ffece8Smrg
52615ffece8Smrg        # Now rename the file to the real destination.
52715ffece8Smrg        $doit $mvcmd "$dsttmp" "$dst"
5285e695a52Smrg      }
5295e695a52Smrg    fi || exit 1
530943345d3Smrg
531f67b85aaSmrg    trap '' 0
532f67b85aaSmrg  fi
533f67b85aaSmrgdone
534943345d3Smrg
535943345d3Smrg# Local variables:
53615ffece8Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
537943345d3Smrg# time-stamp-start: "scriptversion="
538943345d3Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53915ffece8Smrg# time-stamp-time-zone: "UTC0"
5405e695a52Smrg# time-stamp-end: "; # UTC"
541943345d3Smrg# End:
542