132001f49Smrg#!/bin/sh
232001f49Smrg# install - install a program, script, or datafile
332001f49Smrg
47ec3b29aSmrgscriptversion=2014-09-12.12; # UTC
532001f49Smrg
632001f49Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
732001f49Smrg# later released in X11R6 (xc/config/util/install.sh) with the
832001f49Smrg# following copyright and license.
932001f49Smrg#
1032001f49Smrg# Copyright (C) 1994 X Consortium
1132001f49Smrg#
1232001f49Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1332001f49Smrg# of this software and associated documentation files (the "Software"), to
1432001f49Smrg# deal in the Software without restriction, including without limitation the
1532001f49Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1632001f49Smrg# sell copies of the Software, and to permit persons to whom the Software is
1732001f49Smrg# furnished to do so, subject to the following conditions:
1832001f49Smrg#
1932001f49Smrg# The above copyright notice and this permission notice shall be included in
2032001f49Smrg# all copies or substantial portions of the Software.
2132001f49Smrg#
2232001f49Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2332001f49Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2432001f49Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2532001f49Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2632001f49Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2732001f49Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2832001f49Smrg#
2932001f49Smrg# Except as contained in this notice, the name of the X Consortium shall not
3032001f49Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
3132001f49Smrg# ings in this Software without prior written authorization from the X Consor-
3232001f49Smrg# tium.
3332001f49Smrg#
3432001f49Smrg#
3532001f49Smrg# FSF changes to this file are in the public domain.
3632001f49Smrg#
3732001f49Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3832001f49Smrg# 'make' implicit rules from creating a file called install from it
3932001f49Smrg# when there is no Makefile.
4032001f49Smrg#
4132001f49Smrg# This script is compatible with the BSD install script, but was written
4232001f49Smrg# from scratch.
4332001f49Smrg
447ec3b29aSmrgtab='	'
4532001f49Smrgnl='
4632001f49Smrg'
477ec3b29aSmrgIFS=" $tab$nl"
4832001f49Smrg
497ec3b29aSmrg# Set DOITPROG to "echo" to test this script.
5032001f49Smrg
5132001f49Smrgdoit=${DOITPROG-}
527ec3b29aSmrgdoit_exec=${doit:-exec}
5332001f49Smrg
5432001f49Smrg# Put in absolute file names if you don't have them in your path;
5532001f49Smrg# or use environment vars.
5632001f49Smrg
5732001f49Smrgchgrpprog=${CHGRPPROG-chgrp}
5832001f49Smrgchmodprog=${CHMODPROG-chmod}
5932001f49Smrgchownprog=${CHOWNPROG-chown}
6032001f49Smrgcmpprog=${CMPPROG-cmp}
6132001f49Smrgcpprog=${CPPROG-cp}
6232001f49Smrgmkdirprog=${MKDIRPROG-mkdir}
6332001f49Smrgmvprog=${MVPROG-mv}
6432001f49Smrgrmprog=${RMPROG-rm}
6532001f49Smrgstripprog=${STRIPPROG-strip}
6632001f49Smrg
6732001f49Smrgposix_mkdir=
6832001f49Smrg
6932001f49Smrg# Desired mode of installed file.
7032001f49Smrgmode=0755
7132001f49Smrg
7232001f49Smrgchgrpcmd=
7332001f49Smrgchmodcmd=$chmodprog
7432001f49Smrgchowncmd=
7532001f49Smrgmvcmd=$mvprog
7632001f49Smrgrmcmd="$rmprog -f"
7732001f49Smrgstripcmd=
7832001f49Smrg
7932001f49Smrgsrc=
8032001f49Smrgdst=
8132001f49Smrgdir_arg=
8232001f49Smrgdst_arg=
8332001f49Smrg
8432001f49Smrgcopy_on_change=false
857ec3b29aSmrgis_target_a_directory=possibly
8632001f49Smrg
8732001f49Smrgusage="\
8832001f49SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8932001f49Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9032001f49Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9132001f49Smrg   or: $0 [OPTION]... -d DIRECTORIES...
9232001f49Smrg
9332001f49SmrgIn the 1st form, copy SRCFILE to DSTFILE.
9432001f49SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
9532001f49SmrgIn the 4th, create DIRECTORIES.
9632001f49Smrg
9732001f49SmrgOptions:
9832001f49Smrg     --help     display this help and exit.
9932001f49Smrg     --version  display version info and exit.
10032001f49Smrg
10132001f49Smrg  -c            (ignored)
10232001f49Smrg  -C            install only if different (preserve the last data modification time)
10332001f49Smrg  -d            create directories instead of installing files.
10432001f49Smrg  -g GROUP      $chgrpprog installed files to GROUP.
10532001f49Smrg  -m MODE       $chmodprog installed files to MODE.
10632001f49Smrg  -o USER       $chownprog installed files to USER.
10732001f49Smrg  -s            $stripprog installed files.
10832001f49Smrg  -t DIRECTORY  install into DIRECTORY.
10932001f49Smrg  -T            report an error if DSTFILE is a directory.
11032001f49Smrg
11132001f49SmrgEnvironment variables override the default commands:
11232001f49Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
11332001f49Smrg  RMPROG STRIPPROG
11432001f49Smrg"
11532001f49Smrg
11632001f49Smrgwhile test $# -ne 0; do
11732001f49Smrg  case $1 in
11832001f49Smrg    -c) ;;
11932001f49Smrg
12032001f49Smrg    -C) copy_on_change=true;;
12132001f49Smrg
12232001f49Smrg    -d) dir_arg=true;;
12332001f49Smrg
12432001f49Smrg    -g) chgrpcmd="$chgrpprog $2"
1257ec3b29aSmrg        shift;;
12632001f49Smrg
12732001f49Smrg    --help) echo "$usage"; exit $?;;
12832001f49Smrg
12932001f49Smrg    -m) mode=$2
1307ec3b29aSmrg        case $mode in
1317ec3b29aSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1327ec3b29aSmrg            echo "$0: invalid mode: $mode" >&2
1337ec3b29aSmrg            exit 1;;
1347ec3b29aSmrg        esac
1357ec3b29aSmrg        shift;;
13632001f49Smrg
13732001f49Smrg    -o) chowncmd="$chownprog $2"
1387ec3b29aSmrg        shift;;
13932001f49Smrg
14032001f49Smrg    -s) stripcmd=$stripprog;;
14132001f49Smrg
1427ec3b29aSmrg    -t)
1437ec3b29aSmrg        is_target_a_directory=always
1447ec3b29aSmrg        dst_arg=$2
1457ec3b29aSmrg        # Protect names problematic for 'test' and other utilities.
1467ec3b29aSmrg        case $dst_arg in
1477ec3b29aSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1487ec3b29aSmrg        esac
1497ec3b29aSmrg        shift;;
15032001f49Smrg
1517ec3b29aSmrg    -T) is_target_a_directory=never;;
15232001f49Smrg
15332001f49Smrg    --version) echo "$0 $scriptversion"; exit $?;;
15432001f49Smrg
1557ec3b29aSmrg    --) shift
1567ec3b29aSmrg        break;;
15732001f49Smrg
1587ec3b29aSmrg    -*) echo "$0: invalid option: $1" >&2
1597ec3b29aSmrg        exit 1;;
16032001f49Smrg
16132001f49Smrg    *)  break;;
16232001f49Smrg  esac
16332001f49Smrg  shift
16432001f49Smrgdone
16532001f49Smrg
1667ec3b29aSmrg# We allow the use of options -d and -T together, by making -d
1677ec3b29aSmrg# take the precedence; this is for compatibility with GNU install.
1687ec3b29aSmrg
1697ec3b29aSmrgif test -n "$dir_arg"; then
1707ec3b29aSmrg  if test -n "$dst_arg"; then
1717ec3b29aSmrg    echo "$0: target directory not allowed when installing a directory." >&2
1727ec3b29aSmrg    exit 1
1737ec3b29aSmrg  fi
1747ec3b29aSmrgfi
1757ec3b29aSmrg
17632001f49Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
17732001f49Smrg  # When -d is used, all remaining arguments are directories to create.
17832001f49Smrg  # When -t is used, the destination is already specified.
17932001f49Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
18032001f49Smrg  for arg
18132001f49Smrg  do
18232001f49Smrg    if test -n "$dst_arg"; then
18332001f49Smrg      # $@ is not empty: it contains at least $arg.
18432001f49Smrg      set fnord "$@" "$dst_arg"
18532001f49Smrg      shift # fnord
18632001f49Smrg    fi
18732001f49Smrg    shift # arg
18832001f49Smrg    dst_arg=$arg
18932001f49Smrg    # Protect names problematic for 'test' and other utilities.
19032001f49Smrg    case $dst_arg in
19132001f49Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19232001f49Smrg    esac
19332001f49Smrg  done
19432001f49Smrgfi
19532001f49Smrg
19632001f49Smrgif test $# -eq 0; then
19732001f49Smrg  if test -z "$dir_arg"; then
19832001f49Smrg    echo "$0: no input file specified." >&2
19932001f49Smrg    exit 1
20032001f49Smrg  fi
20132001f49Smrg  # It's OK to call 'install-sh -d' without argument.
20232001f49Smrg  # This can happen when creating conditional directories.
20332001f49Smrg  exit 0
20432001f49Smrgfi
20532001f49Smrg
2067ec3b29aSmrgif test -z "$dir_arg"; then
2077ec3b29aSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2087ec3b29aSmrg    if test ! -d "$dst_arg"; then
2097ec3b29aSmrg      echo "$0: $dst_arg: Is not a directory." >&2
2107ec3b29aSmrg      exit 1
2117ec3b29aSmrg    fi
2127ec3b29aSmrg  fi
2137ec3b29aSmrgfi
2147ec3b29aSmrg
21532001f49Smrgif test -z "$dir_arg"; then
21632001f49Smrg  do_exit='(exit $ret); exit $ret'
21732001f49Smrg  trap "ret=129; $do_exit" 1
21832001f49Smrg  trap "ret=130; $do_exit" 2
21932001f49Smrg  trap "ret=141; $do_exit" 13
22032001f49Smrg  trap "ret=143; $do_exit" 15
22132001f49Smrg
22232001f49Smrg  # Set umask so as not to create temps with too-generous modes.
22332001f49Smrg  # However, 'strip' requires both read and write access to temps.
22432001f49Smrg  case $mode in
22532001f49Smrg    # Optimize common cases.
22632001f49Smrg    *644) cp_umask=133;;
22732001f49Smrg    *755) cp_umask=22;;
22832001f49Smrg
22932001f49Smrg    *[0-7])
23032001f49Smrg      if test -z "$stripcmd"; then
2317ec3b29aSmrg        u_plus_rw=
23232001f49Smrg      else
2337ec3b29aSmrg        u_plus_rw='% 200'
23432001f49Smrg      fi
23532001f49Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
23632001f49Smrg    *)
23732001f49Smrg      if test -z "$stripcmd"; then
2387ec3b29aSmrg        u_plus_rw=
23932001f49Smrg      else
2407ec3b29aSmrg        u_plus_rw=,u+rw
24132001f49Smrg      fi
24232001f49Smrg      cp_umask=$mode$u_plus_rw;;
24332001f49Smrg  esac
24432001f49Smrgfi
24532001f49Smrg
24632001f49Smrgfor src
24732001f49Smrgdo
24832001f49Smrg  # Protect names problematic for 'test' and other utilities.
24932001f49Smrg  case $src in
25032001f49Smrg    -* | [=\(\)!]) src=./$src;;
25132001f49Smrg  esac
25232001f49Smrg
25332001f49Smrg  if test -n "$dir_arg"; then
25432001f49Smrg    dst=$src
25532001f49Smrg    dstdir=$dst
25632001f49Smrg    test -d "$dstdir"
25732001f49Smrg    dstdir_status=$?
25832001f49Smrg  else
25932001f49Smrg
26032001f49Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26132001f49Smrg    # might cause directories to be created, which would be especially bad
26232001f49Smrg    # if $src (and thus $dsttmp) contains '*'.
26332001f49Smrg    if test ! -f "$src" && test ! -d "$src"; then
26432001f49Smrg      echo "$0: $src does not exist." >&2
26532001f49Smrg      exit 1
26632001f49Smrg    fi
26732001f49Smrg
26832001f49Smrg    if test -z "$dst_arg"; then
26932001f49Smrg      echo "$0: no destination specified." >&2
27032001f49Smrg      exit 1
27132001f49Smrg    fi
27232001f49Smrg    dst=$dst_arg
27332001f49Smrg
27432001f49Smrg    # If destination is a directory, append the input filename; won't work
27532001f49Smrg    # if double slashes aren't ignored.
27632001f49Smrg    if test -d "$dst"; then
2777ec3b29aSmrg      if test "$is_target_a_directory" = never; then
2787ec3b29aSmrg        echo "$0: $dst_arg: Is a directory" >&2
2797ec3b29aSmrg        exit 1
28032001f49Smrg      fi
28132001f49Smrg      dstdir=$dst
28232001f49Smrg      dst=$dstdir/`basename "$src"`
28332001f49Smrg      dstdir_status=0
28432001f49Smrg    else
2857ec3b29aSmrg      dstdir=`dirname "$dst"`
28632001f49Smrg      test -d "$dstdir"
28732001f49Smrg      dstdir_status=$?
28832001f49Smrg    fi
28932001f49Smrg  fi
29032001f49Smrg
29132001f49Smrg  obsolete_mkdir_used=false
29232001f49Smrg
29332001f49Smrg  if test $dstdir_status != 0; then
29432001f49Smrg    case $posix_mkdir in
29532001f49Smrg      '')
2967ec3b29aSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
2977ec3b29aSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
2987ec3b29aSmrg        umask=`umask`
2997ec3b29aSmrg        case $stripcmd.$umask in
3007ec3b29aSmrg          # Optimize common cases.
3017ec3b29aSmrg          *[2367][2367]) mkdir_umask=$umask;;
3027ec3b29aSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3037ec3b29aSmrg
3047ec3b29aSmrg          *[0-7])
3057ec3b29aSmrg            mkdir_umask=`expr $umask + 22 \
3067ec3b29aSmrg              - $umask % 100 % 40 + $umask % 20 \
3077ec3b29aSmrg              - $umask % 10 % 4 + $umask % 2
3087ec3b29aSmrg            `;;
3097ec3b29aSmrg          *) mkdir_umask=$umask,go-w;;
3107ec3b29aSmrg        esac
3117ec3b29aSmrg
3127ec3b29aSmrg        # With -d, create the new directory with the user-specified mode.
3137ec3b29aSmrg        # Otherwise, rely on $mkdir_umask.
3147ec3b29aSmrg        if test -n "$dir_arg"; then
3157ec3b29aSmrg          mkdir_mode=-m$mode
3167ec3b29aSmrg        else
3177ec3b29aSmrg          mkdir_mode=
3187ec3b29aSmrg        fi
3197ec3b29aSmrg
3207ec3b29aSmrg        posix_mkdir=false
3217ec3b29aSmrg        case $umask in
3227ec3b29aSmrg          *[123567][0-7][0-7])
3237ec3b29aSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
3247ec3b29aSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
3257ec3b29aSmrg            ;;
3267ec3b29aSmrg          *)
3277ec3b29aSmrg            # $RANDOM is not portable (e.g. dash);  use it when possible to
3287ec3b29aSmrg            # lower collision chance
3297ec3b29aSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3307ec3b29aSmrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
3317ec3b29aSmrg
3327ec3b29aSmrg            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
3337ec3b29aSmrg            # create the $tmpdir first (and fail if unsuccessful) to make sure
3347ec3b29aSmrg            # that nobody tries to guess the $tmpdir name.
3357ec3b29aSmrg            if (umask $mkdir_umask &&
3367ec3b29aSmrg                $mkdirprog $mkdir_mode "$tmpdir" &&
3377ec3b29aSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3387ec3b29aSmrg            then
3397ec3b29aSmrg              if test -z "$dir_arg" || {
3407ec3b29aSmrg                   # Check for POSIX incompatibilities with -m.
3417ec3b29aSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3427ec3b29aSmrg                   # other-writable bit of parent directory when it shouldn't.
3437ec3b29aSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3447ec3b29aSmrg                   test_tmpdir="$tmpdir/a"
3457ec3b29aSmrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3467ec3b29aSmrg                   case $ls_ld_tmpdir in
3477ec3b29aSmrg                     d????-?r-*) different_mode=700;;
3487ec3b29aSmrg                     d????-?--*) different_mode=755;;
3497ec3b29aSmrg                     *) false;;
3507ec3b29aSmrg                   esac &&
3517ec3b29aSmrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3527ec3b29aSmrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3537ec3b29aSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3547ec3b29aSmrg                   }
3557ec3b29aSmrg                 }
3567ec3b29aSmrg              then posix_mkdir=:
3577ec3b29aSmrg              fi
3587ec3b29aSmrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3597ec3b29aSmrg            else
3607ec3b29aSmrg              # Remove any dirs left behind by ancient mkdir implementations.
3617ec3b29aSmrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3627ec3b29aSmrg            fi
3637ec3b29aSmrg            trap '' 0;;
3647ec3b29aSmrg        esac;;
36532001f49Smrg    esac
36632001f49Smrg
36732001f49Smrg    if
36832001f49Smrg      $posix_mkdir && (
3697ec3b29aSmrg        umask $mkdir_umask &&
3707ec3b29aSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
37132001f49Smrg      )
37232001f49Smrg    then :
37332001f49Smrg    else
37432001f49Smrg
37532001f49Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
37632001f49Smrg      # or it failed possibly due to a race condition.  Create the
37732001f49Smrg      # directory the slow way, step by step, checking for races as we go.
37832001f49Smrg
37932001f49Smrg      case $dstdir in
3807ec3b29aSmrg        /*) prefix='/';;
3817ec3b29aSmrg        [-=\(\)!]*) prefix='./';;
3827ec3b29aSmrg        *)  prefix='';;
38332001f49Smrg      esac
38432001f49Smrg
38532001f49Smrg      oIFS=$IFS
38632001f49Smrg      IFS=/
3877ec3b29aSmrg      set -f
38832001f49Smrg      set fnord $dstdir
38932001f49Smrg      shift
3907ec3b29aSmrg      set +f
39132001f49Smrg      IFS=$oIFS
39232001f49Smrg
39332001f49Smrg      prefixes=
39432001f49Smrg
39532001f49Smrg      for d
39632001f49Smrg      do
3977ec3b29aSmrg        test X"$d" = X && continue
3987ec3b29aSmrg
3997ec3b29aSmrg        prefix=$prefix$d
4007ec3b29aSmrg        if test -d "$prefix"; then
4017ec3b29aSmrg          prefixes=
4027ec3b29aSmrg        else
4037ec3b29aSmrg          if $posix_mkdir; then
4047ec3b29aSmrg            (umask=$mkdir_umask &&
4057ec3b29aSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4067ec3b29aSmrg            # Don't fail if two instances are running concurrently.
4077ec3b29aSmrg            test -d "$prefix" || exit 1
4087ec3b29aSmrg          else
4097ec3b29aSmrg            case $prefix in
4107ec3b29aSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4117ec3b29aSmrg              *) qprefix=$prefix;;
4127ec3b29aSmrg            esac
4137ec3b29aSmrg            prefixes="$prefixes '$qprefix'"
4147ec3b29aSmrg          fi
4157ec3b29aSmrg        fi
4167ec3b29aSmrg        prefix=$prefix/
41732001f49Smrg      done
41832001f49Smrg
41932001f49Smrg      if test -n "$prefixes"; then
4207ec3b29aSmrg        # Don't fail if two instances are running concurrently.
4217ec3b29aSmrg        (umask $mkdir_umask &&
4227ec3b29aSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4237ec3b29aSmrg          test -d "$dstdir" || exit 1
4247ec3b29aSmrg        obsolete_mkdir_used=true
42532001f49Smrg      fi
42632001f49Smrg    fi
42732001f49Smrg  fi
42832001f49Smrg
42932001f49Smrg  if test -n "$dir_arg"; then
43032001f49Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
43132001f49Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
43232001f49Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
43332001f49Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
43432001f49Smrg  else
43532001f49Smrg
43632001f49Smrg    # Make a couple of temp file names in the proper directory.
43732001f49Smrg    dsttmp=$dstdir/_inst.$$_
43832001f49Smrg    rmtmp=$dstdir/_rm.$$_
43932001f49Smrg
44032001f49Smrg    # Trap to clean up those temp files at exit.
44132001f49Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
44232001f49Smrg
44332001f49Smrg    # Copy the file name to the temp name.
44432001f49Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
44532001f49Smrg
44632001f49Smrg    # and set any options; do chmod last to preserve setuid bits.
44732001f49Smrg    #
44832001f49Smrg    # If any of these fail, we abort the whole thing.  If we want to
44932001f49Smrg    # ignore errors from any of these, just make sure not to ignore
45032001f49Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
45132001f49Smrg    #
45232001f49Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
45332001f49Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
45432001f49Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
45532001f49Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
45632001f49Smrg
45732001f49Smrg    # If -C, don't bother to copy if it wouldn't change the file.
45832001f49Smrg    if $copy_on_change &&
4597ec3b29aSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4607ec3b29aSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4617ec3b29aSmrg       set -f &&
46232001f49Smrg       set X $old && old=:$2:$4:$5:$6 &&
46332001f49Smrg       set X $new && new=:$2:$4:$5:$6 &&
4647ec3b29aSmrg       set +f &&
46532001f49Smrg       test "$old" = "$new" &&
46632001f49Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
46732001f49Smrg    then
46832001f49Smrg      rm -f "$dsttmp"
46932001f49Smrg    else
47032001f49Smrg      # Rename the file to the real destination.
47132001f49Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
47232001f49Smrg
47332001f49Smrg      # The rename failed, perhaps because mv can't rename something else
47432001f49Smrg      # to itself, or perhaps because mv is so ancient that it does not
47532001f49Smrg      # support -f.
47632001f49Smrg      {
4777ec3b29aSmrg        # Now remove or move aside any old file at destination location.
4787ec3b29aSmrg        # We try this two ways since rm can't unlink itself on some
4797ec3b29aSmrg        # systems and the destination file might be busy for other
4807ec3b29aSmrg        # reasons.  In this case, the final cleanup might fail but the new
4817ec3b29aSmrg        # file should still install successfully.
4827ec3b29aSmrg        {
4837ec3b29aSmrg          test ! -f "$dst" ||
4847ec3b29aSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
4857ec3b29aSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
4867ec3b29aSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
4877ec3b29aSmrg          } ||
4887ec3b29aSmrg          { echo "$0: cannot unlink or rename $dst" >&2
4897ec3b29aSmrg            (exit 1); exit 1
4907ec3b29aSmrg          }
4917ec3b29aSmrg        } &&
4927ec3b29aSmrg
4937ec3b29aSmrg        # Now rename the file to the real destination.
4947ec3b29aSmrg        $doit $mvcmd "$dsttmp" "$dst"
49532001f49Smrg      }
49632001f49Smrg    fi || exit 1
49732001f49Smrg
49832001f49Smrg    trap '' 0
49932001f49Smrg  fi
50032001f49Smrgdone
50132001f49Smrg
50232001f49Smrg# Local variables:
50332001f49Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
50432001f49Smrg# time-stamp-start: "scriptversion="
50532001f49Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
50632001f49Smrg# time-stamp-time-zone: "UTC"
50732001f49Smrg# time-stamp-end: "; # UTC"
50832001f49Smrg# End:
509