12b3787f6Schristos#!/bin/sh
22b3787f6Schristos# install - install a program, script, or datafile
32b3787f6Schristos
4*0454d1b2Schristosscriptversion=2013-12-25.23; # UTC
52b3787f6Schristos
62b3787f6Schristos# This originates from X11R5 (mit/util/scripts/install.sh), which was
72b3787f6Schristos# later released in X11R6 (xc/config/util/install.sh) with the
82b3787f6Schristos# following copyright and license.
92b3787f6Schristos#
102b3787f6Schristos# Copyright (C) 1994 X Consortium
112b3787f6Schristos#
122b3787f6Schristos# Permission is hereby granted, free of charge, to any person obtaining a copy
132b3787f6Schristos# of this software and associated documentation files (the "Software"), to
142b3787f6Schristos# deal in the Software without restriction, including without limitation the
152b3787f6Schristos# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
162b3787f6Schristos# sell copies of the Software, and to permit persons to whom the Software is
172b3787f6Schristos# furnished to do so, subject to the following conditions:
182b3787f6Schristos#
192b3787f6Schristos# The above copyright notice and this permission notice shall be included in
202b3787f6Schristos# all copies or substantial portions of the Software.
212b3787f6Schristos#
222b3787f6Schristos# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
232b3787f6Schristos# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
242b3787f6Schristos# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
252b3787f6Schristos# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
262b3787f6Schristos# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
272b3787f6Schristos# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
282b3787f6Schristos#
292b3787f6Schristos# Except as contained in this notice, the name of the X Consortium shall not
302b3787f6Schristos# be used in advertising or otherwise to promote the sale, use or other deal-
312b3787f6Schristos# ings in this Software without prior written authorization from the X Consor-
322b3787f6Schristos# tium.
332b3787f6Schristos#
342b3787f6Schristos#
352b3787f6Schristos# FSF changes to this file are in the public domain.
362b3787f6Schristos#
372b3787f6Schristos# Calling this script install-sh is preferred over install.sh, to prevent
38*0454d1b2Schristos# 'make' implicit rules from creating a file called install from it
392b3787f6Schristos# when there is no Makefile.
402b3787f6Schristos#
412b3787f6Schristos# This script is compatible with the BSD install script, but was written
422b3787f6Schristos# from scratch.
432b3787f6Schristos
44*0454d1b2Schristostab='	'
452b3787f6Schristosnl='
462b3787f6Schristos'
47*0454d1b2SchristosIFS=" $tab$nl"
482b3787f6Schristos
49*0454d1b2Schristos# Set DOITPROG to "echo" to test this script.
502b3787f6Schristos
512b3787f6Schristosdoit=${DOITPROG-}
52*0454d1b2Schristosdoit_exec=${doit:-exec}
532b3787f6Schristos
542b3787f6Schristos# Put in absolute file names if you don't have them in your path;
552b3787f6Schristos# or use environment vars.
562b3787f6Schristos
572b3787f6Schristoschgrpprog=${CHGRPPROG-chgrp}
582b3787f6Schristoschmodprog=${CHMODPROG-chmod}
592b3787f6Schristoschownprog=${CHOWNPROG-chown}
602b3787f6Schristoscmpprog=${CMPPROG-cmp}
612b3787f6Schristoscpprog=${CPPROG-cp}
622b3787f6Schristosmkdirprog=${MKDIRPROG-mkdir}
632b3787f6Schristosmvprog=${MVPROG-mv}
642b3787f6Schristosrmprog=${RMPROG-rm}
652b3787f6Schristosstripprog=${STRIPPROG-strip}
662b3787f6Schristos
672b3787f6Schristosposix_mkdir=
682b3787f6Schristos
692b3787f6Schristos# Desired mode of installed file.
702b3787f6Schristosmode=0755
712b3787f6Schristos
722b3787f6Schristoschgrpcmd=
732b3787f6Schristoschmodcmd=$chmodprog
742b3787f6Schristoschowncmd=
752b3787f6Schristosmvcmd=$mvprog
762b3787f6Schristosrmcmd="$rmprog -f"
772b3787f6Schristosstripcmd=
782b3787f6Schristos
792b3787f6Schristossrc=
802b3787f6Schristosdst=
812b3787f6Schristosdir_arg=
822b3787f6Schristosdst_arg=
832b3787f6Schristos
842b3787f6Schristoscopy_on_change=false
85*0454d1b2Schristosis_target_a_directory=possibly
862b3787f6Schristos
872b3787f6Schristosusage="\
882b3787f6SchristosUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
892b3787f6Schristos   or: $0 [OPTION]... SRCFILES... DIRECTORY
902b3787f6Schristos   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
912b3787f6Schristos   or: $0 [OPTION]... -d DIRECTORIES...
922b3787f6Schristos
932b3787f6SchristosIn the 1st form, copy SRCFILE to DSTFILE.
942b3787f6SchristosIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
952b3787f6SchristosIn the 4th, create DIRECTORIES.
962b3787f6Schristos
972b3787f6SchristosOptions:
982b3787f6Schristos     --help     display this help and exit.
992b3787f6Schristos     --version  display version info and exit.
1002b3787f6Schristos
1012b3787f6Schristos  -c            (ignored)
1022b3787f6Schristos  -C            install only if different (preserve the last data modification time)
1032b3787f6Schristos  -d            create directories instead of installing files.
1042b3787f6Schristos  -g GROUP      $chgrpprog installed files to GROUP.
1052b3787f6Schristos  -m MODE       $chmodprog installed files to MODE.
1062b3787f6Schristos  -o USER       $chownprog installed files to USER.
1072b3787f6Schristos  -s            $stripprog installed files.
1082b3787f6Schristos  -t DIRECTORY  install into DIRECTORY.
1092b3787f6Schristos  -T            report an error if DSTFILE is a directory.
1102b3787f6Schristos
1112b3787f6SchristosEnvironment variables override the default commands:
1122b3787f6Schristos  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1132b3787f6Schristos  RMPROG STRIPPROG
1142b3787f6Schristos"
1152b3787f6Schristos
1162b3787f6Schristoswhile test $# -ne 0; do
1172b3787f6Schristos  case $1 in
1182b3787f6Schristos    -c) ;;
1192b3787f6Schristos
1202b3787f6Schristos    -C) copy_on_change=true;;
1212b3787f6Schristos
1222b3787f6Schristos    -d) dir_arg=true;;
1232b3787f6Schristos
1242b3787f6Schristos    -g) chgrpcmd="$chgrpprog $2"
1252b3787f6Schristos        shift;;
1262b3787f6Schristos
1272b3787f6Schristos    --help) echo "$usage"; exit $?;;
1282b3787f6Schristos
1292b3787f6Schristos    -m) mode=$2
1302b3787f6Schristos        case $mode in
131*0454d1b2Schristos          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1322b3787f6Schristos            echo "$0: invalid mode: $mode" >&2
1332b3787f6Schristos            exit 1;;
1342b3787f6Schristos        esac
1352b3787f6Schristos        shift;;
1362b3787f6Schristos
1372b3787f6Schristos    -o) chowncmd="$chownprog $2"
1382b3787f6Schristos        shift;;
1392b3787f6Schristos
1402b3787f6Schristos    -s) stripcmd=$stripprog;;
1412b3787f6Schristos
142*0454d1b2Schristos    -t)
143*0454d1b2Schristos        is_target_a_directory=always
144*0454d1b2Schristos        dst_arg=$2
145*0454d1b2Schristos        # Protect names problematic for 'test' and other utilities.
146*0454d1b2Schristos        case $dst_arg in
147*0454d1b2Schristos          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148*0454d1b2Schristos        esac
1492b3787f6Schristos        shift;;
1502b3787f6Schristos
151*0454d1b2Schristos    -T) is_target_a_directory=never;;
1522b3787f6Schristos
1532b3787f6Schristos    --version) echo "$0 $scriptversion"; exit $?;;
1542b3787f6Schristos
1552b3787f6Schristos    --) shift
1562b3787f6Schristos        break;;
1572b3787f6Schristos
1582b3787f6Schristos    -*) echo "$0: invalid option: $1" >&2
1592b3787f6Schristos        exit 1;;
1602b3787f6Schristos
1612b3787f6Schristos    *)  break;;
1622b3787f6Schristos  esac
1632b3787f6Schristos  shift
1642b3787f6Schristosdone
1652b3787f6Schristos
166*0454d1b2Schristos# We allow the use of options -d and -T together, by making -d
167*0454d1b2Schristos# take the precedence; this is for compatibility with GNU install.
168*0454d1b2Schristos
169*0454d1b2Schristosif test -n "$dir_arg"; then
170*0454d1b2Schristos  if test -n "$dst_arg"; then
171*0454d1b2Schristos    echo "$0: target directory not allowed when installing a directory." >&2
172*0454d1b2Schristos    exit 1
173*0454d1b2Schristos  fi
174*0454d1b2Schristosfi
175*0454d1b2Schristos
1762b3787f6Schristosif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1772b3787f6Schristos  # When -d is used, all remaining arguments are directories to create.
1782b3787f6Schristos  # When -t is used, the destination is already specified.
1792b3787f6Schristos  # Otherwise, the last argument is the destination.  Remove it from $@.
1802b3787f6Schristos  for arg
1812b3787f6Schristos  do
1822b3787f6Schristos    if test -n "$dst_arg"; then
1832b3787f6Schristos      # $@ is not empty: it contains at least $arg.
1842b3787f6Schristos      set fnord "$@" "$dst_arg"
1852b3787f6Schristos      shift # fnord
1862b3787f6Schristos    fi
1872b3787f6Schristos    shift # arg
1882b3787f6Schristos    dst_arg=$arg
189*0454d1b2Schristos    # Protect names problematic for 'test' and other utilities.
190*0454d1b2Schristos    case $dst_arg in
191*0454d1b2Schristos      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192*0454d1b2Schristos    esac
1932b3787f6Schristos  done
1942b3787f6Schristosfi
1952b3787f6Schristos
1962b3787f6Schristosif test $# -eq 0; then
1972b3787f6Schristos  if test -z "$dir_arg"; then
1982b3787f6Schristos    echo "$0: no input file specified." >&2
1992b3787f6Schristos    exit 1
2002b3787f6Schristos  fi
201*0454d1b2Schristos  # It's OK to call 'install-sh -d' without argument.
2022b3787f6Schristos  # This can happen when creating conditional directories.
2032b3787f6Schristos  exit 0
2042b3787f6Schristosfi
2052b3787f6Schristos
2062b3787f6Schristosif test -z "$dir_arg"; then
207*0454d1b2Schristos  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208*0454d1b2Schristos    if test ! -d "$dst_arg"; then
209*0454d1b2Schristos      echo "$0: $dst_arg: Is not a directory." >&2
210*0454d1b2Schristos      exit 1
211*0454d1b2Schristos    fi
212*0454d1b2Schristos  fi
213*0454d1b2Schristosfi
214*0454d1b2Schristos
215*0454d1b2Schristosif test -z "$dir_arg"; then
216*0454d1b2Schristos  do_exit='(exit $ret); exit $ret'
217*0454d1b2Schristos  trap "ret=129; $do_exit" 1
218*0454d1b2Schristos  trap "ret=130; $do_exit" 2
219*0454d1b2Schristos  trap "ret=141; $do_exit" 13
220*0454d1b2Schristos  trap "ret=143; $do_exit" 15
2212b3787f6Schristos
2222b3787f6Schristos  # Set umask so as not to create temps with too-generous modes.
2232b3787f6Schristos  # However, 'strip' requires both read and write access to temps.
2242b3787f6Schristos  case $mode in
2252b3787f6Schristos    # Optimize common cases.
2262b3787f6Schristos    *644) cp_umask=133;;
2272b3787f6Schristos    *755) cp_umask=22;;
2282b3787f6Schristos
2292b3787f6Schristos    *[0-7])
2302b3787f6Schristos      if test -z "$stripcmd"; then
2312b3787f6Schristos        u_plus_rw=
2322b3787f6Schristos      else
2332b3787f6Schristos        u_plus_rw='% 200'
2342b3787f6Schristos      fi
2352b3787f6Schristos      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2362b3787f6Schristos    *)
2372b3787f6Schristos      if test -z "$stripcmd"; then
2382b3787f6Schristos        u_plus_rw=
2392b3787f6Schristos      else
2402b3787f6Schristos        u_plus_rw=,u+rw
2412b3787f6Schristos      fi
2422b3787f6Schristos      cp_umask=$mode$u_plus_rw;;
2432b3787f6Schristos  esac
2442b3787f6Schristosfi
2452b3787f6Schristos
2462b3787f6Schristosfor src
2472b3787f6Schristosdo
248*0454d1b2Schristos  # Protect names problematic for 'test' and other utilities.
2492b3787f6Schristos  case $src in
250*0454d1b2Schristos    -* | [=\(\)!]) src=./$src;;
2512b3787f6Schristos  esac
2522b3787f6Schristos
2532b3787f6Schristos  if test -n "$dir_arg"; then
2542b3787f6Schristos    dst=$src
2552b3787f6Schristos    dstdir=$dst
2562b3787f6Schristos    test -d "$dstdir"
2572b3787f6Schristos    dstdir_status=$?
2582b3787f6Schristos  else
2592b3787f6Schristos
2602b3787f6Schristos    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2612b3787f6Schristos    # might cause directories to be created, which would be especially bad
2622b3787f6Schristos    # if $src (and thus $dsttmp) contains '*'.
2632b3787f6Schristos    if test ! -f "$src" && test ! -d "$src"; then
2642b3787f6Schristos      echo "$0: $src does not exist." >&2
2652b3787f6Schristos      exit 1
2662b3787f6Schristos    fi
2672b3787f6Schristos
2682b3787f6Schristos    if test -z "$dst_arg"; then
2692b3787f6Schristos      echo "$0: no destination specified." >&2
2702b3787f6Schristos      exit 1
2712b3787f6Schristos    fi
2722b3787f6Schristos    dst=$dst_arg
2732b3787f6Schristos
2742b3787f6Schristos    # If destination is a directory, append the input filename; won't work
2752b3787f6Schristos    # if double slashes aren't ignored.
2762b3787f6Schristos    if test -d "$dst"; then
277*0454d1b2Schristos      if test "$is_target_a_directory" = never; then
2782b3787f6Schristos        echo "$0: $dst_arg: Is a directory" >&2
2792b3787f6Schristos        exit 1
2802b3787f6Schristos      fi
2812b3787f6Schristos      dstdir=$dst
2822b3787f6Schristos      dst=$dstdir/`basename "$src"`
2832b3787f6Schristos      dstdir_status=0
2842b3787f6Schristos    else
285*0454d1b2Schristos      dstdir=`dirname "$dst"`
2862b3787f6Schristos      test -d "$dstdir"
2872b3787f6Schristos      dstdir_status=$?
2882b3787f6Schristos    fi
2892b3787f6Schristos  fi
2902b3787f6Schristos
2912b3787f6Schristos  obsolete_mkdir_used=false
2922b3787f6Schristos
2932b3787f6Schristos  if test $dstdir_status != 0; then
2942b3787f6Schristos    case $posix_mkdir in
2952b3787f6Schristos      '')
2962b3787f6Schristos        # Create intermediate dirs using mode 755 as modified by the umask.
2972b3787f6Schristos        # This is like FreeBSD 'install' as of 1997-10-28.
2982b3787f6Schristos        umask=`umask`
2992b3787f6Schristos        case $stripcmd.$umask in
3002b3787f6Schristos          # Optimize common cases.
3012b3787f6Schristos          *[2367][2367]) mkdir_umask=$umask;;
3022b3787f6Schristos          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3032b3787f6Schristos
3042b3787f6Schristos          *[0-7])
3052b3787f6Schristos            mkdir_umask=`expr $umask + 22 \
3062b3787f6Schristos              - $umask % 100 % 40 + $umask % 20 \
3072b3787f6Schristos              - $umask % 10 % 4 + $umask % 2
3082b3787f6Schristos            `;;
3092b3787f6Schristos          *) mkdir_umask=$umask,go-w;;
3102b3787f6Schristos        esac
3112b3787f6Schristos
3122b3787f6Schristos        # With -d, create the new directory with the user-specified mode.
3132b3787f6Schristos        # Otherwise, rely on $mkdir_umask.
3142b3787f6Schristos        if test -n "$dir_arg"; then
3152b3787f6Schristos          mkdir_mode=-m$mode
3162b3787f6Schristos        else
3172b3787f6Schristos          mkdir_mode=
3182b3787f6Schristos        fi
3192b3787f6Schristos
3202b3787f6Schristos        posix_mkdir=false
3212b3787f6Schristos        case $umask in
3222b3787f6Schristos          *[123567][0-7][0-7])
3232b3787f6Schristos            # POSIX mkdir -p sets u+wx bits regardless of umask, which
3242b3787f6Schristos            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
3252b3787f6Schristos            ;;
3262b3787f6Schristos          *)
3272b3787f6Schristos            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3282b3787f6Schristos            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
3292b3787f6Schristos
3302b3787f6Schristos            if (umask $mkdir_umask &&
3312b3787f6Schristos                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
3322b3787f6Schristos            then
3332b3787f6Schristos              if test -z "$dir_arg" || {
3342b3787f6Schristos                   # Check for POSIX incompatibilities with -m.
3352b3787f6Schristos                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
336*0454d1b2Schristos                   # other-writable bit of parent directory when it shouldn't.
3372b3787f6Schristos                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3382b3787f6Schristos                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
3392b3787f6Schristos                   case $ls_ld_tmpdir in
3402b3787f6Schristos                     d????-?r-*) different_mode=700;;
3412b3787f6Schristos                     d????-?--*) different_mode=755;;
3422b3787f6Schristos                     *) false;;
3432b3787f6Schristos                   esac &&
3442b3787f6Schristos                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
3452b3787f6Schristos                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
3462b3787f6Schristos                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3472b3787f6Schristos                   }
3482b3787f6Schristos                 }
3492b3787f6Schristos              then posix_mkdir=:
3502b3787f6Schristos              fi
3512b3787f6Schristos              rmdir "$tmpdir/d" "$tmpdir"
3522b3787f6Schristos            else
3532b3787f6Schristos              # Remove any dirs left behind by ancient mkdir implementations.
3542b3787f6Schristos              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
3552b3787f6Schristos            fi
3562b3787f6Schristos            trap '' 0;;
3572b3787f6Schristos        esac;;
3582b3787f6Schristos    esac
3592b3787f6Schristos
3602b3787f6Schristos    if
3612b3787f6Schristos      $posix_mkdir && (
3622b3787f6Schristos        umask $mkdir_umask &&
3632b3787f6Schristos        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3642b3787f6Schristos      )
3652b3787f6Schristos    then :
3662b3787f6Schristos    else
3672b3787f6Schristos
3682b3787f6Schristos      # The umask is ridiculous, or mkdir does not conform to POSIX,
3692b3787f6Schristos      # or it failed possibly due to a race condition.  Create the
3702b3787f6Schristos      # directory the slow way, step by step, checking for races as we go.
3712b3787f6Schristos
3722b3787f6Schristos      case $dstdir in
3732b3787f6Schristos        /*) prefix='/';;
374*0454d1b2Schristos        [-=\(\)!]*) prefix='./';;
3752b3787f6Schristos        *)  prefix='';;
3762b3787f6Schristos      esac
3772b3787f6Schristos
3782b3787f6Schristos      oIFS=$IFS
3792b3787f6Schristos      IFS=/
380*0454d1b2Schristos      set -f
3812b3787f6Schristos      set fnord $dstdir
3822b3787f6Schristos      shift
383*0454d1b2Schristos      set +f
3842b3787f6Schristos      IFS=$oIFS
3852b3787f6Schristos
3862b3787f6Schristos      prefixes=
3872b3787f6Schristos
3882b3787f6Schristos      for d
3892b3787f6Schristos      do
390*0454d1b2Schristos        test X"$d" = X && continue
3912b3787f6Schristos
3922b3787f6Schristos        prefix=$prefix$d
3932b3787f6Schristos        if test -d "$prefix"; then
3942b3787f6Schristos          prefixes=
3952b3787f6Schristos        else
3962b3787f6Schristos          if $posix_mkdir; then
3972b3787f6Schristos            (umask=$mkdir_umask &&
3982b3787f6Schristos             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
3992b3787f6Schristos            # Don't fail if two instances are running concurrently.
4002b3787f6Schristos            test -d "$prefix" || exit 1
4012b3787f6Schristos          else
4022b3787f6Schristos            case $prefix in
4032b3787f6Schristos              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4042b3787f6Schristos              *) qprefix=$prefix;;
4052b3787f6Schristos            esac
4062b3787f6Schristos            prefixes="$prefixes '$qprefix'"
4072b3787f6Schristos          fi
4082b3787f6Schristos        fi
4092b3787f6Schristos        prefix=$prefix/
4102b3787f6Schristos      done
4112b3787f6Schristos
4122b3787f6Schristos      if test -n "$prefixes"; then
4132b3787f6Schristos        # Don't fail if two instances are running concurrently.
4142b3787f6Schristos        (umask $mkdir_umask &&
4152b3787f6Schristos         eval "\$doit_exec \$mkdirprog $prefixes") ||
4162b3787f6Schristos          test -d "$dstdir" || exit 1
4172b3787f6Schristos        obsolete_mkdir_used=true
4182b3787f6Schristos      fi
4192b3787f6Schristos    fi
4202b3787f6Schristos  fi
4212b3787f6Schristos
4222b3787f6Schristos  if test -n "$dir_arg"; then
4232b3787f6Schristos    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4242b3787f6Schristos    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4252b3787f6Schristos    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4262b3787f6Schristos      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4272b3787f6Schristos  else
4282b3787f6Schristos
4292b3787f6Schristos    # Make a couple of temp file names in the proper directory.
4302b3787f6Schristos    dsttmp=$dstdir/_inst.$$_
4312b3787f6Schristos    rmtmp=$dstdir/_rm.$$_
4322b3787f6Schristos
4332b3787f6Schristos    # Trap to clean up those temp files at exit.
4342b3787f6Schristos    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4352b3787f6Schristos
4362b3787f6Schristos    # Copy the file name to the temp name.
4372b3787f6Schristos    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
4382b3787f6Schristos
4392b3787f6Schristos    # and set any options; do chmod last to preserve setuid bits.
4402b3787f6Schristos    #
4412b3787f6Schristos    # If any of these fail, we abort the whole thing.  If we want to
4422b3787f6Schristos    # ignore errors from any of these, just make sure not to ignore
4432b3787f6Schristos    # errors from the above "$doit $cpprog $src $dsttmp" command.
4442b3787f6Schristos    #
4452b3787f6Schristos    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4462b3787f6Schristos    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4472b3787f6Schristos    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4482b3787f6Schristos    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4492b3787f6Schristos
4502b3787f6Schristos    # If -C, don't bother to copy if it wouldn't change the file.
4512b3787f6Schristos    if $copy_on_change &&
4522b3787f6Schristos       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4532b3787f6Schristos       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
454*0454d1b2Schristos       set -f &&
4552b3787f6Schristos       set X $old && old=:$2:$4:$5:$6 &&
4562b3787f6Schristos       set X $new && new=:$2:$4:$5:$6 &&
457*0454d1b2Schristos       set +f &&
4582b3787f6Schristos       test "$old" = "$new" &&
4592b3787f6Schristos       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4602b3787f6Schristos    then
4612b3787f6Schristos      rm -f "$dsttmp"
4622b3787f6Schristos    else
4632b3787f6Schristos      # Rename the file to the real destination.
4642b3787f6Schristos      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4652b3787f6Schristos
4662b3787f6Schristos      # The rename failed, perhaps because mv can't rename something else
4672b3787f6Schristos      # to itself, or perhaps because mv is so ancient that it does not
4682b3787f6Schristos      # support -f.
4692b3787f6Schristos      {
4702b3787f6Schristos        # Now remove or move aside any old file at destination location.
4712b3787f6Schristos        # We try this two ways since rm can't unlink itself on some
4722b3787f6Schristos        # systems and the destination file might be busy for other
4732b3787f6Schristos        # reasons.  In this case, the final cleanup might fail but the new
4742b3787f6Schristos        # file should still install successfully.
4752b3787f6Schristos        {
4762b3787f6Schristos          test ! -f "$dst" ||
4772b3787f6Schristos          $doit $rmcmd -f "$dst" 2>/dev/null ||
4782b3787f6Schristos          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
4792b3787f6Schristos            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
4802b3787f6Schristos          } ||
4812b3787f6Schristos          { echo "$0: cannot unlink or rename $dst" >&2
4822b3787f6Schristos            (exit 1); exit 1
4832b3787f6Schristos          }
4842b3787f6Schristos        } &&
4852b3787f6Schristos
4862b3787f6Schristos        # Now rename the file to the real destination.
4872b3787f6Schristos        $doit $mvcmd "$dsttmp" "$dst"
4882b3787f6Schristos      }
4892b3787f6Schristos    fi || exit 1
4902b3787f6Schristos
4912b3787f6Schristos    trap '' 0
4922b3787f6Schristos  fi
4932b3787f6Schristosdone
4942b3787f6Schristos
4952b3787f6Schristos# Local variables:
4962b3787f6Schristos# eval: (add-hook 'write-file-hooks 'time-stamp)
4972b3787f6Schristos# time-stamp-start: "scriptversion="
4982b3787f6Schristos# time-stamp-format: "%:y-%02m-%02d.%02H"
4992b3787f6Schristos# time-stamp-time-zone: "UTC"
5002b3787f6Schristos# time-stamp-end: "; # UTC"
5012b3787f6Schristos# End:
502