install-sh revision 05cf1079
104007ebaSmrg#!/bin/sh
204007ebaSmrg# install - install a program, script, or datafile
304007ebaSmrg
405cf1079Smrgscriptversion=2018-03-11.20; # UTC
504007ebaSmrg
604007ebaSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
704007ebaSmrg# later released in X11R6 (xc/config/util/install.sh) with the
804007ebaSmrg# following copyright and license.
904007ebaSmrg#
1004007ebaSmrg# Copyright (C) 1994 X Consortium
1104007ebaSmrg#
1204007ebaSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1304007ebaSmrg# of this software and associated documentation files (the "Software"), to
1404007ebaSmrg# deal in the Software without restriction, including without limitation the
1504007ebaSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1604007ebaSmrg# sell copies of the Software, and to permit persons to whom the Software is
1704007ebaSmrg# furnished to do so, subject to the following conditions:
1804007ebaSmrg#
1904007ebaSmrg# The above copyright notice and this permission notice shall be included in
2004007ebaSmrg# all copies or substantial portions of the Software.
2104007ebaSmrg#
2204007ebaSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2304007ebaSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2404007ebaSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2504007ebaSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2604007ebaSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2704007ebaSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2804007ebaSmrg#
2904007ebaSmrg# Except as contained in this notice, the name of the X Consortium shall not
3004007ebaSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3104007ebaSmrg# ings in this Software without prior written authorization from the X Consor-
3204007ebaSmrg# tium.
3304007ebaSmrg#
3404007ebaSmrg#
3504007ebaSmrg# FSF changes to this file are in the public domain.
3604007ebaSmrg#
3704007ebaSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3804007ebaSmrg# 'make' implicit rules from creating a file called install from it
3904007ebaSmrg# when there is no Makefile.
4004007ebaSmrg#
4104007ebaSmrg# This script is compatible with the BSD install script, but was written
4204007ebaSmrg# from scratch.
4304007ebaSmrg
4405cf1079Smrgtab='	'
4504007ebaSmrgnl='
4604007ebaSmrg'
4705cf1079SmrgIFS=" $tab$nl"
4804007ebaSmrg
4905cf1079Smrg# Set DOITPROG to "echo" to test this script.
5004007ebaSmrg
5104007ebaSmrgdoit=${DOITPROG-}
5205cf1079Smrgdoit_exec=${doit:-exec}
5304007ebaSmrg
5404007ebaSmrg# Put in absolute file names if you don't have them in your path;
5504007ebaSmrg# or use environment vars.
5604007ebaSmrg
5704007ebaSmrgchgrpprog=${CHGRPPROG-chgrp}
5804007ebaSmrgchmodprog=${CHMODPROG-chmod}
5904007ebaSmrgchownprog=${CHOWNPROG-chown}
6004007ebaSmrgcmpprog=${CMPPROG-cmp}
6104007ebaSmrgcpprog=${CPPROG-cp}
6204007ebaSmrgmkdirprog=${MKDIRPROG-mkdir}
6304007ebaSmrgmvprog=${MVPROG-mv}
6404007ebaSmrgrmprog=${RMPROG-rm}
6504007ebaSmrgstripprog=${STRIPPROG-strip}
6604007ebaSmrg
6704007ebaSmrgposix_mkdir=
6804007ebaSmrg
6904007ebaSmrg# Desired mode of installed file.
7004007ebaSmrgmode=0755
7104007ebaSmrg
7204007ebaSmrgchgrpcmd=
7304007ebaSmrgchmodcmd=$chmodprog
7404007ebaSmrgchowncmd=
7504007ebaSmrgmvcmd=$mvprog
7604007ebaSmrgrmcmd="$rmprog -f"
7704007ebaSmrgstripcmd=
7804007ebaSmrg
7904007ebaSmrgsrc=
8004007ebaSmrgdst=
8104007ebaSmrgdir_arg=
8204007ebaSmrgdst_arg=
8304007ebaSmrg
8404007ebaSmrgcopy_on_change=false
8505cf1079Smrgis_target_a_directory=possibly
8604007ebaSmrg
8704007ebaSmrgusage="\
8804007ebaSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8904007ebaSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9004007ebaSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9104007ebaSmrg   or: $0 [OPTION]... -d DIRECTORIES...
9204007ebaSmrg
9304007ebaSmrgIn the 1st form, copy SRCFILE to DSTFILE.
9404007ebaSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
9504007ebaSmrgIn the 4th, create DIRECTORIES.
9604007ebaSmrg
9704007ebaSmrgOptions:
9804007ebaSmrg     --help     display this help and exit.
9904007ebaSmrg     --version  display version info and exit.
10004007ebaSmrg
10104007ebaSmrg  -c            (ignored)
10204007ebaSmrg  -C            install only if different (preserve the last data modification time)
10304007ebaSmrg  -d            create directories instead of installing files.
10404007ebaSmrg  -g GROUP      $chgrpprog installed files to GROUP.
10504007ebaSmrg  -m MODE       $chmodprog installed files to MODE.
10604007ebaSmrg  -o USER       $chownprog installed files to USER.
10704007ebaSmrg  -s            $stripprog installed files.
10804007ebaSmrg  -t DIRECTORY  install into DIRECTORY.
10904007ebaSmrg  -T            report an error if DSTFILE is a directory.
11004007ebaSmrg
11104007ebaSmrgEnvironment variables override the default commands:
11204007ebaSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
11304007ebaSmrg  RMPROG STRIPPROG
11404007ebaSmrg"
11504007ebaSmrg
11604007ebaSmrgwhile test $# -ne 0; do
11704007ebaSmrg  case $1 in
11804007ebaSmrg    -c) ;;
11904007ebaSmrg
12004007ebaSmrg    -C) copy_on_change=true;;
12104007ebaSmrg
12204007ebaSmrg    -d) dir_arg=true;;
12304007ebaSmrg
12404007ebaSmrg    -g) chgrpcmd="$chgrpprog $2"
12505cf1079Smrg        shift;;
12604007ebaSmrg
12704007ebaSmrg    --help) echo "$usage"; exit $?;;
12804007ebaSmrg
12904007ebaSmrg    -m) mode=$2
13005cf1079Smrg        case $mode in
13105cf1079Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
13205cf1079Smrg            echo "$0: invalid mode: $mode" >&2
13305cf1079Smrg            exit 1;;
13405cf1079Smrg        esac
13505cf1079Smrg        shift;;
13604007ebaSmrg
13704007ebaSmrg    -o) chowncmd="$chownprog $2"
13805cf1079Smrg        shift;;
13904007ebaSmrg
14004007ebaSmrg    -s) stripcmd=$stripprog;;
14104007ebaSmrg
14205cf1079Smrg    -t)
14305cf1079Smrg        is_target_a_directory=always
14405cf1079Smrg        dst_arg=$2
14505cf1079Smrg        # Protect names problematic for 'test' and other utilities.
14605cf1079Smrg        case $dst_arg in
14705cf1079Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14805cf1079Smrg        esac
14905cf1079Smrg        shift;;
15004007ebaSmrg
15105cf1079Smrg    -T) is_target_a_directory=never;;
15204007ebaSmrg
15304007ebaSmrg    --version) echo "$0 $scriptversion"; exit $?;;
15404007ebaSmrg
15505cf1079Smrg    --) shift
15605cf1079Smrg        break;;
15704007ebaSmrg
15805cf1079Smrg    -*) echo "$0: invalid option: $1" >&2
15905cf1079Smrg        exit 1;;
16004007ebaSmrg
16104007ebaSmrg    *)  break;;
16204007ebaSmrg  esac
16304007ebaSmrg  shift
16404007ebaSmrgdone
16504007ebaSmrg
16605cf1079Smrg# We allow the use of options -d and -T together, by making -d
16705cf1079Smrg# take the precedence; this is for compatibility with GNU install.
16805cf1079Smrg
16905cf1079Smrgif test -n "$dir_arg"; then
17005cf1079Smrg  if test -n "$dst_arg"; then
17105cf1079Smrg    echo "$0: target directory not allowed when installing a directory." >&2
17205cf1079Smrg    exit 1
17305cf1079Smrg  fi
17405cf1079Smrgfi
17505cf1079Smrg
17604007ebaSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
17704007ebaSmrg  # When -d is used, all remaining arguments are directories to create.
17804007ebaSmrg  # When -t is used, the destination is already specified.
17904007ebaSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
18004007ebaSmrg  for arg
18104007ebaSmrg  do
18204007ebaSmrg    if test -n "$dst_arg"; then
18304007ebaSmrg      # $@ is not empty: it contains at least $arg.
18404007ebaSmrg      set fnord "$@" "$dst_arg"
18504007ebaSmrg      shift # fnord
18604007ebaSmrg    fi
18704007ebaSmrg    shift # arg
18804007ebaSmrg    dst_arg=$arg
18904007ebaSmrg    # Protect names problematic for 'test' and other utilities.
19004007ebaSmrg    case $dst_arg in
19104007ebaSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19204007ebaSmrg    esac
19304007ebaSmrg  done
19404007ebaSmrgfi
19504007ebaSmrg
19604007ebaSmrgif test $# -eq 0; then
19704007ebaSmrg  if test -z "$dir_arg"; then
19804007ebaSmrg    echo "$0: no input file specified." >&2
19904007ebaSmrg    exit 1
20004007ebaSmrg  fi
20104007ebaSmrg  # It's OK to call 'install-sh -d' without argument.
20204007ebaSmrg  # This can happen when creating conditional directories.
20304007ebaSmrg  exit 0
20404007ebaSmrgfi
20504007ebaSmrg
20605cf1079Smrgif test -z "$dir_arg"; then
20705cf1079Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20805cf1079Smrg    if test ! -d "$dst_arg"; then
20905cf1079Smrg      echo "$0: $dst_arg: Is not a directory." >&2
21005cf1079Smrg      exit 1
21105cf1079Smrg    fi
21205cf1079Smrg  fi
21305cf1079Smrgfi
21405cf1079Smrg
21504007ebaSmrgif test -z "$dir_arg"; then
21604007ebaSmrg  do_exit='(exit $ret); exit $ret'
21704007ebaSmrg  trap "ret=129; $do_exit" 1
21804007ebaSmrg  trap "ret=130; $do_exit" 2
21904007ebaSmrg  trap "ret=141; $do_exit" 13
22004007ebaSmrg  trap "ret=143; $do_exit" 15
22104007ebaSmrg
22204007ebaSmrg  # Set umask so as not to create temps with too-generous modes.
22304007ebaSmrg  # However, 'strip' requires both read and write access to temps.
22404007ebaSmrg  case $mode in
22504007ebaSmrg    # Optimize common cases.
22604007ebaSmrg    *644) cp_umask=133;;
22704007ebaSmrg    *755) cp_umask=22;;
22804007ebaSmrg
22904007ebaSmrg    *[0-7])
23004007ebaSmrg      if test -z "$stripcmd"; then
23105cf1079Smrg        u_plus_rw=
23204007ebaSmrg      else
23305cf1079Smrg        u_plus_rw='% 200'
23404007ebaSmrg      fi
23504007ebaSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
23604007ebaSmrg    *)
23704007ebaSmrg      if test -z "$stripcmd"; then
23805cf1079Smrg        u_plus_rw=
23904007ebaSmrg      else
24005cf1079Smrg        u_plus_rw=,u+rw
24104007ebaSmrg      fi
24204007ebaSmrg      cp_umask=$mode$u_plus_rw;;
24304007ebaSmrg  esac
24404007ebaSmrgfi
24504007ebaSmrg
24604007ebaSmrgfor src
24704007ebaSmrgdo
24804007ebaSmrg  # Protect names problematic for 'test' and other utilities.
24904007ebaSmrg  case $src in
25004007ebaSmrg    -* | [=\(\)!]) src=./$src;;
25104007ebaSmrg  esac
25204007ebaSmrg
25304007ebaSmrg  if test -n "$dir_arg"; then
25404007ebaSmrg    dst=$src
25504007ebaSmrg    dstdir=$dst
25604007ebaSmrg    test -d "$dstdir"
25704007ebaSmrg    dstdir_status=$?
25804007ebaSmrg  else
25904007ebaSmrg
26004007ebaSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26104007ebaSmrg    # might cause directories to be created, which would be especially bad
26204007ebaSmrg    # if $src (and thus $dsttmp) contains '*'.
26304007ebaSmrg    if test ! -f "$src" && test ! -d "$src"; then
26404007ebaSmrg      echo "$0: $src does not exist." >&2
26504007ebaSmrg      exit 1
26604007ebaSmrg    fi
26704007ebaSmrg
26804007ebaSmrg    if test -z "$dst_arg"; then
26904007ebaSmrg      echo "$0: no destination specified." >&2
27004007ebaSmrg      exit 1
27104007ebaSmrg    fi
27204007ebaSmrg    dst=$dst_arg
27304007ebaSmrg
27405cf1079Smrg    # If destination is a directory, append the input filename.
27504007ebaSmrg    if test -d "$dst"; then
27605cf1079Smrg      if test "$is_target_a_directory" = never; then
27705cf1079Smrg        echo "$0: $dst_arg: Is a directory" >&2
27805cf1079Smrg        exit 1
27904007ebaSmrg      fi
28004007ebaSmrg      dstdir=$dst
28105cf1079Smrg      dstbase=`basename "$src"`
28205cf1079Smrg      case $dst in
28305cf1079Smrg	*/) dst=$dst$dstbase;;
28405cf1079Smrg	*)  dst=$dst/$dstbase;;
28505cf1079Smrg      esac
28604007ebaSmrg      dstdir_status=0
28704007ebaSmrg    else
28805cf1079Smrg      dstdir=`dirname "$dst"`
28904007ebaSmrg      test -d "$dstdir"
29004007ebaSmrg      dstdir_status=$?
29104007ebaSmrg    fi
29204007ebaSmrg  fi
29304007ebaSmrg
29405cf1079Smrg  case $dstdir in
29505cf1079Smrg    */) dstdirslash=$dstdir;;
29605cf1079Smrg    *)  dstdirslash=$dstdir/;;
29705cf1079Smrg  esac
29805cf1079Smrg
29904007ebaSmrg  obsolete_mkdir_used=false
30004007ebaSmrg
30104007ebaSmrg  if test $dstdir_status != 0; then
30204007ebaSmrg    case $posix_mkdir in
30304007ebaSmrg      '')
30405cf1079Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
30505cf1079Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
30605cf1079Smrg        umask=`umask`
30705cf1079Smrg        case $stripcmd.$umask in
30805cf1079Smrg          # Optimize common cases.
30905cf1079Smrg          *[2367][2367]) mkdir_umask=$umask;;
31005cf1079Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
31105cf1079Smrg
31205cf1079Smrg          *[0-7])
31305cf1079Smrg            mkdir_umask=`expr $umask + 22 \
31405cf1079Smrg              - $umask % 100 % 40 + $umask % 20 \
31505cf1079Smrg              - $umask % 10 % 4 + $umask % 2
31605cf1079Smrg            `;;
31705cf1079Smrg          *) mkdir_umask=$umask,go-w;;
31805cf1079Smrg        esac
31905cf1079Smrg
32005cf1079Smrg        # With -d, create the new directory with the user-specified mode.
32105cf1079Smrg        # Otherwise, rely on $mkdir_umask.
32205cf1079Smrg        if test -n "$dir_arg"; then
32305cf1079Smrg          mkdir_mode=-m$mode
32405cf1079Smrg        else
32505cf1079Smrg          mkdir_mode=
32605cf1079Smrg        fi
32705cf1079Smrg
32805cf1079Smrg        posix_mkdir=false
32905cf1079Smrg        case $umask in
33005cf1079Smrg          *[123567][0-7][0-7])
33105cf1079Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
33205cf1079Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
33305cf1079Smrg            ;;
33405cf1079Smrg          *)
33505cf1079Smrg            # Note that $RANDOM variable is not portable (e.g. dash);  Use it
33605cf1079Smrg            # here however when possible just to lower collision chance.
33705cf1079Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
33805cf1079Smrg
33905cf1079Smrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
34005cf1079Smrg
34105cf1079Smrg            # Because "mkdir -p" follows existing symlinks and we likely work
34205cf1079Smrg            # directly in world-writeable /tmp, make sure that the '$tmpdir'
34305cf1079Smrg            # directory is successfully created first before we actually test
34405cf1079Smrg            # 'mkdir -p' feature.
34505cf1079Smrg            if (umask $mkdir_umask &&
34605cf1079Smrg                $mkdirprog $mkdir_mode "$tmpdir" &&
34705cf1079Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
34805cf1079Smrg            then
34905cf1079Smrg              if test -z "$dir_arg" || {
35005cf1079Smrg                   # Check for POSIX incompatibilities with -m.
35105cf1079Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35205cf1079Smrg                   # other-writable bit of parent directory when it shouldn't.
35305cf1079Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
35405cf1079Smrg                   test_tmpdir="$tmpdir/a"
35505cf1079Smrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
35605cf1079Smrg                   case $ls_ld_tmpdir in
35705cf1079Smrg                     d????-?r-*) different_mode=700;;
35805cf1079Smrg                     d????-?--*) different_mode=755;;
35905cf1079Smrg                     *) false;;
36005cf1079Smrg                   esac &&
36105cf1079Smrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36205cf1079Smrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36305cf1079Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
36405cf1079Smrg                   }
36505cf1079Smrg                 }
36605cf1079Smrg              then posix_mkdir=:
36705cf1079Smrg              fi
36805cf1079Smrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
36905cf1079Smrg            else
37005cf1079Smrg              # Remove any dirs left behind by ancient mkdir implementations.
37105cf1079Smrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37205cf1079Smrg            fi
37305cf1079Smrg            trap '' 0;;
37405cf1079Smrg        esac;;
37504007ebaSmrg    esac
37604007ebaSmrg
37704007ebaSmrg    if
37804007ebaSmrg      $posix_mkdir && (
37905cf1079Smrg        umask $mkdir_umask &&
38005cf1079Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
38104007ebaSmrg      )
38204007ebaSmrg    then :
38304007ebaSmrg    else
38404007ebaSmrg
38504007ebaSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
38604007ebaSmrg      # or it failed possibly due to a race condition.  Create the
38704007ebaSmrg      # directory the slow way, step by step, checking for races as we go.
38804007ebaSmrg
38904007ebaSmrg      case $dstdir in
39005cf1079Smrg        /*) prefix='/';;
39105cf1079Smrg        [-=\(\)!]*) prefix='./';;
39205cf1079Smrg        *)  prefix='';;
39304007ebaSmrg      esac
39404007ebaSmrg
39504007ebaSmrg      oIFS=$IFS
39604007ebaSmrg      IFS=/
39705cf1079Smrg      set -f
39804007ebaSmrg      set fnord $dstdir
39904007ebaSmrg      shift
40005cf1079Smrg      set +f
40104007ebaSmrg      IFS=$oIFS
40204007ebaSmrg
40304007ebaSmrg      prefixes=
40404007ebaSmrg
40504007ebaSmrg      for d
40604007ebaSmrg      do
40705cf1079Smrg        test X"$d" = X && continue
40805cf1079Smrg
40905cf1079Smrg        prefix=$prefix$d
41005cf1079Smrg        if test -d "$prefix"; then
41105cf1079Smrg          prefixes=
41205cf1079Smrg        else
41305cf1079Smrg          if $posix_mkdir; then
41405cf1079Smrg            (umask=$mkdir_umask &&
41505cf1079Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
41605cf1079Smrg            # Don't fail if two instances are running concurrently.
41705cf1079Smrg            test -d "$prefix" || exit 1
41805cf1079Smrg          else
41905cf1079Smrg            case $prefix in
42005cf1079Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42105cf1079Smrg              *) qprefix=$prefix;;
42205cf1079Smrg            esac
42305cf1079Smrg            prefixes="$prefixes '$qprefix'"
42405cf1079Smrg          fi
42505cf1079Smrg        fi
42605cf1079Smrg        prefix=$prefix/
42704007ebaSmrg      done
42804007ebaSmrg
42904007ebaSmrg      if test -n "$prefixes"; then
43005cf1079Smrg        # Don't fail if two instances are running concurrently.
43105cf1079Smrg        (umask $mkdir_umask &&
43205cf1079Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43305cf1079Smrg          test -d "$dstdir" || exit 1
43405cf1079Smrg        obsolete_mkdir_used=true
43504007ebaSmrg      fi
43604007ebaSmrg    fi
43704007ebaSmrg  fi
43804007ebaSmrg
43904007ebaSmrg  if test -n "$dir_arg"; then
44004007ebaSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
44104007ebaSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
44204007ebaSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
44304007ebaSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
44404007ebaSmrg  else
44504007ebaSmrg
44604007ebaSmrg    # Make a couple of temp file names in the proper directory.
44705cf1079Smrg    dsttmp=${dstdirslash}_inst.$$_
44805cf1079Smrg    rmtmp=${dstdirslash}_rm.$$_
44904007ebaSmrg
45004007ebaSmrg    # Trap to clean up those temp files at exit.
45104007ebaSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
45204007ebaSmrg
45304007ebaSmrg    # Copy the file name to the temp name.
45404007ebaSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
45504007ebaSmrg
45604007ebaSmrg    # and set any options; do chmod last to preserve setuid bits.
45704007ebaSmrg    #
45804007ebaSmrg    # If any of these fail, we abort the whole thing.  If we want to
45904007ebaSmrg    # ignore errors from any of these, just make sure not to ignore
46004007ebaSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
46104007ebaSmrg    #
46204007ebaSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
46304007ebaSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
46404007ebaSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
46504007ebaSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
46604007ebaSmrg
46704007ebaSmrg    # If -C, don't bother to copy if it wouldn't change the file.
46804007ebaSmrg    if $copy_on_change &&
46905cf1079Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
47005cf1079Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
47105cf1079Smrg       set -f &&
47204007ebaSmrg       set X $old && old=:$2:$4:$5:$6 &&
47304007ebaSmrg       set X $new && new=:$2:$4:$5:$6 &&
47405cf1079Smrg       set +f &&
47504007ebaSmrg       test "$old" = "$new" &&
47604007ebaSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
47704007ebaSmrg    then
47804007ebaSmrg      rm -f "$dsttmp"
47904007ebaSmrg    else
48004007ebaSmrg      # Rename the file to the real destination.
48104007ebaSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
48204007ebaSmrg
48304007ebaSmrg      # The rename failed, perhaps because mv can't rename something else
48404007ebaSmrg      # to itself, or perhaps because mv is so ancient that it does not
48504007ebaSmrg      # support -f.
48604007ebaSmrg      {
48705cf1079Smrg        # Now remove or move aside any old file at destination location.
48805cf1079Smrg        # We try this two ways since rm can't unlink itself on some
48905cf1079Smrg        # systems and the destination file might be busy for other
49005cf1079Smrg        # reasons.  In this case, the final cleanup might fail but the new
49105cf1079Smrg        # file should still install successfully.
49205cf1079Smrg        {
49305cf1079Smrg          test ! -f "$dst" ||
49405cf1079Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
49505cf1079Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
49605cf1079Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
49705cf1079Smrg          } ||
49805cf1079Smrg          { echo "$0: cannot unlink or rename $dst" >&2
49905cf1079Smrg            (exit 1); exit 1
50005cf1079Smrg          }
50105cf1079Smrg        } &&
50205cf1079Smrg
50305cf1079Smrg        # Now rename the file to the real destination.
50405cf1079Smrg        $doit $mvcmd "$dsttmp" "$dst"
50504007ebaSmrg      }
50604007ebaSmrg    fi || exit 1
50704007ebaSmrg
50804007ebaSmrg    trap '' 0
50904007ebaSmrg  fi
51004007ebaSmrgdone
51104007ebaSmrg
51204007ebaSmrg# Local variables:
51305cf1079Smrg# eval: (add-hook 'before-save-hook 'time-stamp)
51404007ebaSmrg# time-stamp-start: "scriptversion="
51504007ebaSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
51605cf1079Smrg# time-stamp-time-zone: "UTC0"
51704007ebaSmrg# time-stamp-end: "; # UTC"
51804007ebaSmrg# End:
519