install-sh revision 5a81ca49
132b578d3Smrg#!/bin/sh
232b578d3Smrg# install - install a program, script, or datafile
332b578d3Smrg
45a81ca49Smrgscriptversion=2013-12-25.23; # UTC
532b578d3Smrg
632b578d3Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
732b578d3Smrg# later released in X11R6 (xc/config/util/install.sh) with the
832b578d3Smrg# following copyright and license.
932b578d3Smrg#
1032b578d3Smrg# Copyright (C) 1994 X Consortium
1132b578d3Smrg#
1232b578d3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1332b578d3Smrg# of this software and associated documentation files (the "Software"), to
1432b578d3Smrg# deal in the Software without restriction, including without limitation the
1532b578d3Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1632b578d3Smrg# sell copies of the Software, and to permit persons to whom the Software is
1732b578d3Smrg# furnished to do so, subject to the following conditions:
1832b578d3Smrg#
1932b578d3Smrg# The above copyright notice and this permission notice shall be included in
2032b578d3Smrg# all copies or substantial portions of the Software.
2132b578d3Smrg#
2232b578d3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2332b578d3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2432b578d3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2532b578d3Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2632b578d3Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2732b578d3Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2832b578d3Smrg#
2932b578d3Smrg# Except as contained in this notice, the name of the X Consortium shall not
3032b578d3Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3132b578d3Smrg# ings in this Software without prior written authorization from the X Consor-
3232b578d3Smrg# tium.
3332b578d3Smrg#
3432b578d3Smrg#
3532b578d3Smrg# FSF changes to this file are in the public domain.
3632b578d3Smrg#
3732b578d3Smrg# Calling this script install-sh is preferred over install.sh, to prevent
385a81ca49Smrg# 'make' implicit rules from creating a file called install from it
3932b578d3Smrg# when there is no Makefile.
4032b578d3Smrg#
4132b578d3Smrg# This script is compatible with the BSD install script, but was written
4232b578d3Smrg# from scratch.
4332b578d3Smrg
445a81ca49Smrgtab='	'
4532b578d3Smrgnl='
4632b578d3Smrg'
475a81ca49SmrgIFS=" $tab$nl"
4832b578d3Smrg
495a81ca49Smrg# Set DOITPROG to "echo" to test this script.
5032b578d3Smrg
512a51b5beSmrgdoit=${DOITPROG-}
525a81ca49Smrgdoit_exec=${doit:-exec}
5332b578d3Smrg
5432b578d3Smrg# Put in absolute file names if you don't have them in your path;
5532b578d3Smrg# or use environment vars.
5632b578d3Smrg
572a51b5beSmrgchgrpprog=${CHGRPPROG-chgrp}
582a51b5beSmrgchmodprog=${CHMODPROG-chmod}
592a51b5beSmrgchownprog=${CHOWNPROG-chown}
602a51b5beSmrgcmpprog=${CMPPROG-cmp}
612a51b5beSmrgcpprog=${CPPROG-cp}
622a51b5beSmrgmkdirprog=${MKDIRPROG-mkdir}
632a51b5beSmrgmvprog=${MVPROG-mv}
642a51b5beSmrgrmprog=${RMPROG-rm}
652a51b5beSmrgstripprog=${STRIPPROG-strip}
662a51b5beSmrg
6732b578d3Smrgposix_mkdir=
6832b578d3Smrg
6932b578d3Smrg# Desired mode of installed file.
7032b578d3Smrgmode=0755
7132b578d3Smrg
722a51b5beSmrgchgrpcmd=
7332b578d3Smrgchmodcmd=$chmodprog
7432b578d3Smrgchowncmd=
752a51b5beSmrgmvcmd=$mvprog
76d31dbc53Smrgrmcmd="$rmprog -f"
772a51b5beSmrgstripcmd=
782a51b5beSmrg
7932b578d3Smrgsrc=
8032b578d3Smrgdst=
8132b578d3Smrgdir_arg=
822a51b5beSmrgdst_arg=
832a51b5beSmrg
842a51b5beSmrgcopy_on_change=false
855a81ca49Smrgis_target_a_directory=possibly
8632b578d3Smrg
872a51b5beSmrgusage="\
882a51b5beSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8932b578d3Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9032b578d3Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9132b578d3Smrg   or: $0 [OPTION]... -d DIRECTORIES...
9232b578d3Smrg
9332b578d3SmrgIn the 1st form, copy SRCFILE to DSTFILE.
9432b578d3SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
9532b578d3SmrgIn the 4th, create DIRECTORIES.
9632b578d3Smrg
9732b578d3SmrgOptions:
982a51b5beSmrg     --help     display this help and exit.
992a51b5beSmrg     --version  display version info and exit.
1002a51b5beSmrg
1012a51b5beSmrg  -c            (ignored)
1022a51b5beSmrg  -C            install only if different (preserve the last data modification time)
1032a51b5beSmrg  -d            create directories instead of installing files.
1042a51b5beSmrg  -g GROUP      $chgrpprog installed files to GROUP.
1052a51b5beSmrg  -m MODE       $chmodprog installed files to MODE.
1062a51b5beSmrg  -o USER       $chownprog installed files to USER.
1072a51b5beSmrg  -s            $stripprog installed files.
1082a51b5beSmrg  -t DIRECTORY  install into DIRECTORY.
1092a51b5beSmrg  -T            report an error if DSTFILE is a directory.
11032b578d3Smrg
11132b578d3SmrgEnvironment variables override the default commands:
1122a51b5beSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1132a51b5beSmrg  RMPROG STRIPPROG
11432b578d3Smrg"
11532b578d3Smrg
11632b578d3Smrgwhile test $# -ne 0; do
11732b578d3Smrg  case $1 in
1182a51b5beSmrg    -c) ;;
1192a51b5beSmrg
1202a51b5beSmrg    -C) copy_on_change=true;;
12132b578d3Smrg
1222a51b5beSmrg    -d) dir_arg=true;;
12332b578d3Smrg
12432b578d3Smrg    -g) chgrpcmd="$chgrpprog $2"
1255a81ca49Smrg        shift;;
12632b578d3Smrg
12732b578d3Smrg    --help) echo "$usage"; exit $?;;
12832b578d3Smrg
12932b578d3Smrg    -m) mode=$2
1305a81ca49Smrg        case $mode in
1315a81ca49Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1325a81ca49Smrg            echo "$0: invalid mode: $mode" >&2
1335a81ca49Smrg            exit 1;;
1345a81ca49Smrg        esac
1355a81ca49Smrg        shift;;
13632b578d3Smrg
13732b578d3Smrg    -o) chowncmd="$chownprog $2"
1385a81ca49Smrg        shift;;
13932b578d3Smrg
1402a51b5beSmrg    -s) stripcmd=$stripprog;;
14132b578d3Smrg
1425a81ca49Smrg    -t)
1435a81ca49Smrg        is_target_a_directory=always
1445a81ca49Smrg        dst_arg=$2
1455a81ca49Smrg        # Protect names problematic for 'test' and other utilities.
1465a81ca49Smrg        case $dst_arg in
1475a81ca49Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1485a81ca49Smrg        esac
1495a81ca49Smrg        shift;;
15032b578d3Smrg
1515a81ca49Smrg    -T) is_target_a_directory=never;;
15232b578d3Smrg
15332b578d3Smrg    --version) echo "$0 $scriptversion"; exit $?;;
15432b578d3Smrg
1555a81ca49Smrg    --) shift
1565a81ca49Smrg        break;;
15732b578d3Smrg
1585a81ca49Smrg    -*) echo "$0: invalid option: $1" >&2
1595a81ca49Smrg        exit 1;;
16032b578d3Smrg
16132b578d3Smrg    *)  break;;
16232b578d3Smrg  esac
1632a51b5beSmrg  shift
16432b578d3Smrgdone
16532b578d3Smrg
1665a81ca49Smrg# We allow the use of options -d and -T together, by making -d
1675a81ca49Smrg# take the precedence; this is for compatibility with GNU install.
1685a81ca49Smrg
1695a81ca49Smrgif test -n "$dir_arg"; then
1705a81ca49Smrg  if test -n "$dst_arg"; then
1715a81ca49Smrg    echo "$0: target directory not allowed when installing a directory." >&2
1725a81ca49Smrg    exit 1
1735a81ca49Smrg  fi
1745a81ca49Smrgfi
1755a81ca49Smrg
1762a51b5beSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
17732b578d3Smrg  # When -d is used, all remaining arguments are directories to create.
17832b578d3Smrg  # When -t is used, the destination is already specified.
17932b578d3Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
18032b578d3Smrg  for arg
18132b578d3Smrg  do
1822a51b5beSmrg    if test -n "$dst_arg"; then
18332b578d3Smrg      # $@ is not empty: it contains at least $arg.
1842a51b5beSmrg      set fnord "$@" "$dst_arg"
18532b578d3Smrg      shift # fnord
18632b578d3Smrg    fi
18732b578d3Smrg    shift # arg
1882a51b5beSmrg    dst_arg=$arg
1895a81ca49Smrg    # Protect names problematic for 'test' and other utilities.
190e35d4d8eSmrg    case $dst_arg in
191e35d4d8eSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192e35d4d8eSmrg    esac
19332b578d3Smrg  done
19432b578d3Smrgfi
19532b578d3Smrg
19632b578d3Smrgif test $# -eq 0; then
19732b578d3Smrg  if test -z "$dir_arg"; then
19832b578d3Smrg    echo "$0: no input file specified." >&2
19932b578d3Smrg    exit 1
20032b578d3Smrg  fi
2015a81ca49Smrg  # It's OK to call 'install-sh -d' without argument.
20232b578d3Smrg  # This can happen when creating conditional directories.
20332b578d3Smrg  exit 0
20432b578d3Smrgfi
20532b578d3Smrg
2065a81ca49Smrgif test -z "$dir_arg"; then
2075a81ca49Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2085a81ca49Smrg    if test ! -d "$dst_arg"; then
2095a81ca49Smrg      echo "$0: $dst_arg: Is not a directory." >&2
2105a81ca49Smrg      exit 1
2115a81ca49Smrg    fi
2125a81ca49Smrg  fi
2135a81ca49Smrgfi
2145a81ca49Smrg
21532b578d3Smrgif test -z "$dir_arg"; then
216e35d4d8eSmrg  do_exit='(exit $ret); exit $ret'
217e35d4d8eSmrg  trap "ret=129; $do_exit" 1
218e35d4d8eSmrg  trap "ret=130; $do_exit" 2
219e35d4d8eSmrg  trap "ret=141; $do_exit" 13
220e35d4d8eSmrg  trap "ret=143; $do_exit" 15
22132b578d3Smrg
22232b578d3Smrg  # Set umask so as not to create temps with too-generous modes.
22332b578d3Smrg  # However, 'strip' requires both read and write access to temps.
22432b578d3Smrg  case $mode in
22532b578d3Smrg    # Optimize common cases.
22632b578d3Smrg    *644) cp_umask=133;;
22732b578d3Smrg    *755) cp_umask=22;;
22832b578d3Smrg
22932b578d3Smrg    *[0-7])
23032b578d3Smrg      if test -z "$stripcmd"; then
2315a81ca49Smrg        u_plus_rw=
23232b578d3Smrg      else
2335a81ca49Smrg        u_plus_rw='% 200'
23432b578d3Smrg      fi
23532b578d3Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
23632b578d3Smrg    *)
23732b578d3Smrg      if test -z "$stripcmd"; then
2385a81ca49Smrg        u_plus_rw=
23932b578d3Smrg      else
2405a81ca49Smrg        u_plus_rw=,u+rw
24132b578d3Smrg      fi
24232b578d3Smrg      cp_umask=$mode$u_plus_rw;;
24332b578d3Smrg  esac
24432b578d3Smrgfi
24532b578d3Smrg
24632b578d3Smrgfor src
24732b578d3Smrgdo
2485a81ca49Smrg  # Protect names problematic for 'test' and other utilities.
24932b578d3Smrg  case $src in
250e35d4d8eSmrg    -* | [=\(\)!]) src=./$src;;
25132b578d3Smrg  esac
25232b578d3Smrg
25332b578d3Smrg  if test -n "$dir_arg"; then
25432b578d3Smrg    dst=$src
25532b578d3Smrg    dstdir=$dst
25632b578d3Smrg    test -d "$dstdir"
25732b578d3Smrg    dstdir_status=$?
25832b578d3Smrg  else
25932b578d3Smrg
26032b578d3Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26132b578d3Smrg    # might cause directories to be created, which would be especially bad
26232b578d3Smrg    # if $src (and thus $dsttmp) contains '*'.
26332b578d3Smrg    if test ! -f "$src" && test ! -d "$src"; then
26432b578d3Smrg      echo "$0: $src does not exist." >&2
26532b578d3Smrg      exit 1
26632b578d3Smrg    fi
26732b578d3Smrg
2682a51b5beSmrg    if test -z "$dst_arg"; then
26932b578d3Smrg      echo "$0: no destination specified." >&2
27032b578d3Smrg      exit 1
27132b578d3Smrg    fi
2722a51b5beSmrg    dst=$dst_arg
27332b578d3Smrg
27432b578d3Smrg    # If destination is a directory, append the input filename; won't work
27532b578d3Smrg    # if double slashes aren't ignored.
27632b578d3Smrg    if test -d "$dst"; then
2775a81ca49Smrg      if test "$is_target_a_directory" = never; then
2785a81ca49Smrg        echo "$0: $dst_arg: Is a directory" >&2
2795a81ca49Smrg        exit 1
28032b578d3Smrg      fi
28132b578d3Smrg      dstdir=$dst
28232b578d3Smrg      dst=$dstdir/`basename "$src"`
28332b578d3Smrg      dstdir_status=0
28432b578d3Smrg    else
2855a81ca49Smrg      dstdir=`dirname "$dst"`
28632b578d3Smrg      test -d "$dstdir"
28732b578d3Smrg      dstdir_status=$?
28832b578d3Smrg    fi
28932b578d3Smrg  fi
29032b578d3Smrg
29132b578d3Smrg  obsolete_mkdir_used=false
29232b578d3Smrg
29332b578d3Smrg  if test $dstdir_status != 0; then
29432b578d3Smrg    case $posix_mkdir in
29532b578d3Smrg      '')
2965a81ca49Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
2975a81ca49Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
2985a81ca49Smrg        umask=`umask`
2995a81ca49Smrg        case $stripcmd.$umask in
3005a81ca49Smrg          # Optimize common cases.
3015a81ca49Smrg          *[2367][2367]) mkdir_umask=$umask;;
3025a81ca49Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3035a81ca49Smrg
3045a81ca49Smrg          *[0-7])
3055a81ca49Smrg            mkdir_umask=`expr $umask + 22 \
3065a81ca49Smrg              - $umask % 100 % 40 + $umask % 20 \
3075a81ca49Smrg              - $umask % 10 % 4 + $umask % 2
3085a81ca49Smrg            `;;
3095a81ca49Smrg          *) mkdir_umask=$umask,go-w;;
3105a81ca49Smrg        esac
3115a81ca49Smrg
3125a81ca49Smrg        # With -d, create the new directory with the user-specified mode.
3135a81ca49Smrg        # Otherwise, rely on $mkdir_umask.
3145a81ca49Smrg        if test -n "$dir_arg"; then
3155a81ca49Smrg          mkdir_mode=-m$mode
3165a81ca49Smrg        else
3175a81ca49Smrg          mkdir_mode=
3185a81ca49Smrg        fi
3195a81ca49Smrg
3205a81ca49Smrg        posix_mkdir=false
3215a81ca49Smrg        case $umask in
3225a81ca49Smrg          *[123567][0-7][0-7])
3235a81ca49Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
3245a81ca49Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
3255a81ca49Smrg            ;;
3265a81ca49Smrg          *)
3275a81ca49Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3285a81ca49Smrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
3295a81ca49Smrg
3305a81ca49Smrg            if (umask $mkdir_umask &&
3315a81ca49Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
3325a81ca49Smrg            then
3335a81ca49Smrg              if test -z "$dir_arg" || {
3345a81ca49Smrg                   # Check for POSIX incompatibilities with -m.
3355a81ca49Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3365a81ca49Smrg                   # other-writable bit of parent directory when it shouldn't.
3375a81ca49Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3385a81ca49Smrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
3395a81ca49Smrg                   case $ls_ld_tmpdir in
3405a81ca49Smrg                     d????-?r-*) different_mode=700;;
3415a81ca49Smrg                     d????-?--*) different_mode=755;;
3425a81ca49Smrg                     *) false;;
3435a81ca49Smrg                   esac &&
3445a81ca49Smrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
3455a81ca49Smrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
3465a81ca49Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3475a81ca49Smrg                   }
3485a81ca49Smrg                 }
3495a81ca49Smrg              then posix_mkdir=:
3505a81ca49Smrg              fi
3515a81ca49Smrg              rmdir "$tmpdir/d" "$tmpdir"
3525a81ca49Smrg            else
3535a81ca49Smrg              # Remove any dirs left behind by ancient mkdir implementations.
3545a81ca49Smrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
3555a81ca49Smrg            fi
3565a81ca49Smrg            trap '' 0;;
3575a81ca49Smrg        esac;;
35832b578d3Smrg    esac
35932b578d3Smrg
36032b578d3Smrg    if
36132b578d3Smrg      $posix_mkdir && (
3625a81ca49Smrg        umask $mkdir_umask &&
3635a81ca49Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
36432b578d3Smrg      )
36532b578d3Smrg    then :
36632b578d3Smrg    else
36732b578d3Smrg
36832b578d3Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
36932b578d3Smrg      # or it failed possibly due to a race condition.  Create the
37032b578d3Smrg      # directory the slow way, step by step, checking for races as we go.
37132b578d3Smrg
37232b578d3Smrg      case $dstdir in
3735a81ca49Smrg        /*) prefix='/';;
3745a81ca49Smrg        [-=\(\)!]*) prefix='./';;
3755a81ca49Smrg        *)  prefix='';;
37632b578d3Smrg      esac
37732b578d3Smrg
37832b578d3Smrg      oIFS=$IFS
37932b578d3Smrg      IFS=/
3805a81ca49Smrg      set -f
38132b578d3Smrg      set fnord $dstdir
38232b578d3Smrg      shift
3835a81ca49Smrg      set +f
38432b578d3Smrg      IFS=$oIFS
38532b578d3Smrg
38632b578d3Smrg      prefixes=
38732b578d3Smrg
38832b578d3Smrg      for d
38932b578d3Smrg      do
3905a81ca49Smrg        test X"$d" = X && continue
3915a81ca49Smrg
3925a81ca49Smrg        prefix=$prefix$d
3935a81ca49Smrg        if test -d "$prefix"; then
3945a81ca49Smrg          prefixes=
3955a81ca49Smrg        else
3965a81ca49Smrg          if $posix_mkdir; then
3975a81ca49Smrg            (umask=$mkdir_umask &&
3985a81ca49Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
3995a81ca49Smrg            # Don't fail if two instances are running concurrently.
4005a81ca49Smrg            test -d "$prefix" || exit 1
4015a81ca49Smrg          else
4025a81ca49Smrg            case $prefix in
4035a81ca49Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4045a81ca49Smrg              *) qprefix=$prefix;;
4055a81ca49Smrg            esac
4065a81ca49Smrg            prefixes="$prefixes '$qprefix'"
4075a81ca49Smrg          fi
4085a81ca49Smrg        fi
4095a81ca49Smrg        prefix=$prefix/
41032b578d3Smrg      done
41132b578d3Smrg
41232b578d3Smrg      if test -n "$prefixes"; then
4135a81ca49Smrg        # Don't fail if two instances are running concurrently.
4145a81ca49Smrg        (umask $mkdir_umask &&
4155a81ca49Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4165a81ca49Smrg          test -d "$dstdir" || exit 1
4175a81ca49Smrg        obsolete_mkdir_used=true
41832b578d3Smrg      fi
41932b578d3Smrg    fi
42032b578d3Smrg  fi
42132b578d3Smrg
42232b578d3Smrg  if test -n "$dir_arg"; then
42332b578d3Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
42432b578d3Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
42532b578d3Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
42632b578d3Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
42732b578d3Smrg  else
42832b578d3Smrg
42932b578d3Smrg    # Make a couple of temp file names in the proper directory.
43032b578d3Smrg    dsttmp=$dstdir/_inst.$$_
43132b578d3Smrg    rmtmp=$dstdir/_rm.$$_
43232b578d3Smrg
43332b578d3Smrg    # Trap to clean up those temp files at exit.
43432b578d3Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
43532b578d3Smrg
43632b578d3Smrg    # Copy the file name to the temp name.
43732b578d3Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
43832b578d3Smrg
43932b578d3Smrg    # and set any options; do chmod last to preserve setuid bits.
44032b578d3Smrg    #
44132b578d3Smrg    # If any of these fail, we abort the whole thing.  If we want to
44232b578d3Smrg    # ignore errors from any of these, just make sure not to ignore
44332b578d3Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
44432b578d3Smrg    #
4452a51b5beSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4462a51b5beSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4472a51b5beSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4482a51b5beSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4492a51b5beSmrg
4502a51b5beSmrg    # If -C, don't bother to copy if it wouldn't change the file.
4512a51b5beSmrg    if $copy_on_change &&
4525a81ca49Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4535a81ca49Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4545a81ca49Smrg       set -f &&
4552a51b5beSmrg       set X $old && old=:$2:$4:$5:$6 &&
4562a51b5beSmrg       set X $new && new=:$2:$4:$5:$6 &&
4575a81ca49Smrg       set +f &&
4582a51b5beSmrg       test "$old" = "$new" &&
4592a51b5beSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4602a51b5beSmrg    then
4612a51b5beSmrg      rm -f "$dsttmp"
4622a51b5beSmrg    else
4632a51b5beSmrg      # Rename the file to the real destination.
4642a51b5beSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4652a51b5beSmrg
4662a51b5beSmrg      # The rename failed, perhaps because mv can't rename something else
4672a51b5beSmrg      # to itself, or perhaps because mv is so ancient that it does not
4682a51b5beSmrg      # support -f.
4692a51b5beSmrg      {
4705a81ca49Smrg        # Now remove or move aside any old file at destination location.
4715a81ca49Smrg        # We try this two ways since rm can't unlink itself on some
4725a81ca49Smrg        # systems and the destination file might be busy for other
4735a81ca49Smrg        # reasons.  In this case, the final cleanup might fail but the new
4745a81ca49Smrg        # file should still install successfully.
4755a81ca49Smrg        {
4765a81ca49Smrg          test ! -f "$dst" ||
4775a81ca49Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
4785a81ca49Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
4795a81ca49Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
4805a81ca49Smrg          } ||
4815a81ca49Smrg          { echo "$0: cannot unlink or rename $dst" >&2
4825a81ca49Smrg            (exit 1); exit 1
4835a81ca49Smrg          }
4845a81ca49Smrg        } &&
4855a81ca49Smrg
4865a81ca49Smrg        # Now rename the file to the real destination.
4875a81ca49Smrg        $doit $mvcmd "$dsttmp" "$dst"
4882a51b5beSmrg      }
4892a51b5beSmrg    fi || exit 1
49032b578d3Smrg
49132b578d3Smrg    trap '' 0
49232b578d3Smrg  fi
49332b578d3Smrgdone
49432b578d3Smrg
49532b578d3Smrg# Local variables:
49632b578d3Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
49732b578d3Smrg# time-stamp-start: "scriptversion="
49832b578d3Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
4992a51b5beSmrg# time-stamp-time-zone: "UTC"
5002a51b5beSmrg# time-stamp-end: "; # UTC"
50132b578d3Smrg# End:
502