install-sh revision 5b28e182
1dcae5b9eSmrg#!/bin/sh
2dcae5b9eSmrg# install - install a program, script, or datafile
35b28e182Smrg
45b28e182Smrgscriptversion=2009-04-28.21; # UTC
55b28e182Smrg
6dcae5b9eSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7dcae5b9eSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8dcae5b9eSmrg# following copyright and license.
9dcae5b9eSmrg#
10dcae5b9eSmrg# Copyright (C) 1994 X Consortium
11dcae5b9eSmrg#
12dcae5b9eSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13dcae5b9eSmrg# of this software and associated documentation files (the "Software"), to
14dcae5b9eSmrg# deal in the Software without restriction, including without limitation the
15dcae5b9eSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16dcae5b9eSmrg# sell copies of the Software, and to permit persons to whom the Software is
17dcae5b9eSmrg# furnished to do so, subject to the following conditions:
18dcae5b9eSmrg#
19dcae5b9eSmrg# The above copyright notice and this permission notice shall be included in
20dcae5b9eSmrg# all copies or substantial portions of the Software.
21dcae5b9eSmrg#
22dcae5b9eSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23dcae5b9eSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24dcae5b9eSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25dcae5b9eSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26dcae5b9eSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27dcae5b9eSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28dcae5b9eSmrg#
29dcae5b9eSmrg# Except as contained in this notice, the name of the X Consortium shall not
30dcae5b9eSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31dcae5b9eSmrg# ings in this Software without prior written authorization from the X Consor-
32dcae5b9eSmrg# tium.
33dcae5b9eSmrg#
34dcae5b9eSmrg#
35dcae5b9eSmrg# FSF changes to this file are in the public domain.
36dcae5b9eSmrg#
37dcae5b9eSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38dcae5b9eSmrg# `make' implicit rules from creating a file called install from it
39dcae5b9eSmrg# when there is no Makefile.
40dcae5b9eSmrg#
41dcae5b9eSmrg# This script is compatible with the BSD install script, but was written
425b28e182Smrg# from scratch.
43dcae5b9eSmrg
445b28e182Smrgnl='
455b28e182Smrg'
465b28e182SmrgIFS=" ""	$nl"
47dcae5b9eSmrg
48dcae5b9eSmrg# set DOITPROG to echo to test this script
49dcae5b9eSmrg
50dcae5b9eSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
515b28e182Smrgdoit=${DOITPROG-}
525b28e182Smrgif test -z "$doit"; then
535b28e182Smrg  doit_exec=exec
54dcae5b9eSmrgelse
555b28e182Smrg  doit_exec=$doit
56dcae5b9eSmrgfi
57dcae5b9eSmrg
585b28e182Smrg# Put in absolute file names if you don't have them in your path;
595b28e182Smrg# or use environment vars.
605b28e182Smrg
615b28e182Smrgchgrpprog=${CHGRPPROG-chgrp}
625b28e182Smrgchmodprog=${CHMODPROG-chmod}
635b28e182Smrgchownprog=${CHOWNPROG-chown}
645b28e182Smrgcmpprog=${CMPPROG-cmp}
655b28e182Smrgcpprog=${CPPROG-cp}
665b28e182Smrgmkdirprog=${MKDIRPROG-mkdir}
675b28e182Smrgmvprog=${MVPROG-mv}
685b28e182Smrgrmprog=${RMPROG-rm}
695b28e182Smrgstripprog=${STRIPPROG-strip}
705b28e182Smrg
715b28e182Smrgposix_glob='?'
725b28e182Smrginitialize_posix_glob='
735b28e182Smrg  test "$posix_glob" != "?" || {
745b28e182Smrg    if (set -f) 2>/dev/null; then
755b28e182Smrg      posix_glob=
765b28e182Smrg    else
775b28e182Smrg      posix_glob=:
785b28e182Smrg    fi
795b28e182Smrg  }
805b28e182Smrg'
815b28e182Smrg
825b28e182Smrgposix_mkdir=
835b28e182Smrg
845b28e182Smrg# Desired mode of installed file.
855b28e182Smrgmode=0755
865b28e182Smrg
875b28e182Smrgchgrpcmd=
885b28e182Smrgchmodcmd=$chmodprog
895b28e182Smrgchowncmd=
905b28e182Smrgmvcmd=$mvprog
915b28e182Smrgrmcmd="$rmprog -f"
925b28e182Smrgstripcmd=
93dcae5b9eSmrg
945b28e182Smrgsrc=
955b28e182Smrgdst=
965b28e182Smrgdir_arg=
975b28e182Smrgdst_arg=
98dcae5b9eSmrg
995b28e182Smrgcopy_on_change=false
1005b28e182Smrgno_target_directory=
101dcae5b9eSmrg
1025b28e182Smrgusage="\
1035b28e182SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
1045b28e182Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
1055b28e182Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
1065b28e182Smrg   or: $0 [OPTION]... -d DIRECTORIES...
107dcae5b9eSmrg
1085b28e182SmrgIn the 1st form, copy SRCFILE to DSTFILE.
1095b28e182SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
1105b28e182SmrgIn the 4th, create DIRECTORIES.
111dcae5b9eSmrg
1125b28e182SmrgOptions:
1135b28e182Smrg     --help     display this help and exit.
1145b28e182Smrg     --version  display version info and exit.
115dcae5b9eSmrg
1165b28e182Smrg  -c            (ignored)
1175b28e182Smrg  -C            install only if different (preserve the last data modification time)
1185b28e182Smrg  -d            create directories instead of installing files.
1195b28e182Smrg  -g GROUP      $chgrpprog installed files to GROUP.
1205b28e182Smrg  -m MODE       $chmodprog installed files to MODE.
1215b28e182Smrg  -o USER       $chownprog installed files to USER.
1225b28e182Smrg  -s            $stripprog installed files.
1235b28e182Smrg  -t DIRECTORY  install into DIRECTORY.
1245b28e182Smrg  -T            report an error if DSTFILE is a directory.
125dcae5b9eSmrg
1265b28e182SmrgEnvironment variables override the default commands:
1275b28e182Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1285b28e182Smrg  RMPROG STRIPPROG
1295b28e182Smrg"
130dcae5b9eSmrg
1315b28e182Smrgwhile test $# -ne 0; do
1325b28e182Smrg  case $1 in
1335b28e182Smrg    -c) ;;
134dcae5b9eSmrg
1355b28e182Smrg    -C) copy_on_change=true;;
136dcae5b9eSmrg
1375b28e182Smrg    -d) dir_arg=true;;
138dcae5b9eSmrg
1395b28e182Smrg    -g) chgrpcmd="$chgrpprog $2"
1405b28e182Smrg	shift;;
141dcae5b9eSmrg
1425b28e182Smrg    --help) echo "$usage"; exit $?;;
143dcae5b9eSmrg
1445b28e182Smrg    -m) mode=$2
1455b28e182Smrg	case $mode in
1465b28e182Smrg	  *' '* | *'	'* | *'
1475b28e182Smrg'*	  | *'*'* | *'?'* | *'['*)
1485b28e182Smrg	    echo "$0: invalid mode: $mode" >&2
1495b28e182Smrg	    exit 1;;
1505b28e182Smrg	esac
1515b28e182Smrg	shift;;
152dcae5b9eSmrg
1535b28e182Smrg    -o) chowncmd="$chownprog $2"
1545b28e182Smrg	shift;;
155dcae5b9eSmrg
1565b28e182Smrg    -s) stripcmd=$stripprog;;
157dcae5b9eSmrg
1585b28e182Smrg    -t) dst_arg=$2
1595b28e182Smrg	shift;;
160dcae5b9eSmrg
1615b28e182Smrg    -T) no_target_directory=true;;
162dcae5b9eSmrg
1635b28e182Smrg    --version) echo "$0 $scriptversion"; exit $?;;
164dcae5b9eSmrg
1655b28e182Smrg    --)	shift
1665b28e182Smrg	break;;
167dcae5b9eSmrg
1685b28e182Smrg    -*)	echo "$0: invalid option: $1" >&2
1695b28e182Smrg	exit 1;;
170dcae5b9eSmrg
1715b28e182Smrg    *)  break;;
1725b28e182Smrg  esac
1735b28e182Smrg  shift
1745b28e182Smrgdone
175dcae5b9eSmrg
1765b28e182Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1775b28e182Smrg  # When -d is used, all remaining arguments are directories to create.
1785b28e182Smrg  # When -t is used, the destination is already specified.
1795b28e182Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
1805b28e182Smrg  for arg
1815b28e182Smrg  do
1825b28e182Smrg    if test -n "$dst_arg"; then
1835b28e182Smrg      # $@ is not empty: it contains at least $arg.
1845b28e182Smrg      set fnord "$@" "$dst_arg"
1855b28e182Smrg      shift # fnord
1865b28e182Smrg    fi
1875b28e182Smrg    shift # arg
1885b28e182Smrg    dst_arg=$arg
1895b28e182Smrg  done
1905b28e182Smrgfi
191dcae5b9eSmrg
1925b28e182Smrgif test $# -eq 0; then
1935b28e182Smrg  if test -z "$dir_arg"; then
1945b28e182Smrg    echo "$0: no input file specified." >&2
1955b28e182Smrg    exit 1
1965b28e182Smrg  fi
1975b28e182Smrg  # It's OK to call `install-sh -d' without argument.
1985b28e182Smrg  # This can happen when creating conditional directories.
1995b28e182Smrg  exit 0
2005b28e182Smrgfi
201dcae5b9eSmrg
2025b28e182Smrgif test -z "$dir_arg"; then
2035b28e182Smrg  trap '(exit $?); exit' 1 2 13 15
2045b28e182Smrg
2055b28e182Smrg  # Set umask so as not to create temps with too-generous modes.
2065b28e182Smrg  # However, 'strip' requires both read and write access to temps.
2075b28e182Smrg  case $mode in
2085b28e182Smrg    # Optimize common cases.
2095b28e182Smrg    *644) cp_umask=133;;
2105b28e182Smrg    *755) cp_umask=22;;
2115b28e182Smrg
2125b28e182Smrg    *[0-7])
2135b28e182Smrg      if test -z "$stripcmd"; then
2145b28e182Smrg	u_plus_rw=
2155b28e182Smrg      else
2165b28e182Smrg	u_plus_rw='% 200'
2175b28e182Smrg      fi
2185b28e182Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2195b28e182Smrg    *)
2205b28e182Smrg      if test -z "$stripcmd"; then
2215b28e182Smrg	u_plus_rw=
2225b28e182Smrg      else
2235b28e182Smrg	u_plus_rw=,u+rw
2245b28e182Smrg      fi
2255b28e182Smrg      cp_umask=$mode$u_plus_rw;;
2265b28e182Smrg  esac
2275b28e182Smrgfi
228dcae5b9eSmrg
2295b28e182Smrgfor src
2305b28e182Smrgdo
2315b28e182Smrg  # Protect names starting with `-'.
2325b28e182Smrg  case $src in
2335b28e182Smrg    -*) src=./$src;;
2345b28e182Smrg  esac
2355b28e182Smrg
2365b28e182Smrg  if test -n "$dir_arg"; then
2375b28e182Smrg    dst=$src
2385b28e182Smrg    dstdir=$dst
2395b28e182Smrg    test -d "$dstdir"
2405b28e182Smrg    dstdir_status=$?
2415b28e182Smrg  else
2425b28e182Smrg
2435b28e182Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2445b28e182Smrg    # might cause directories to be created, which would be especially bad
2455b28e182Smrg    # if $src (and thus $dsttmp) contains '*'.
2465b28e182Smrg    if test ! -f "$src" && test ! -d "$src"; then
2475b28e182Smrg      echo "$0: $src does not exist." >&2
2485b28e182Smrg      exit 1
2495b28e182Smrg    fi
2505b28e182Smrg
2515b28e182Smrg    if test -z "$dst_arg"; then
2525b28e182Smrg      echo "$0: no destination specified." >&2
2535b28e182Smrg      exit 1
2545b28e182Smrg    fi
2555b28e182Smrg
2565b28e182Smrg    dst=$dst_arg
2575b28e182Smrg    # Protect names starting with `-'.
2585b28e182Smrg    case $dst in
2595b28e182Smrg      -*) dst=./$dst;;
2605b28e182Smrg    esac
261dcae5b9eSmrg
2625b28e182Smrg    # If destination is a directory, append the input filename; won't work
2635b28e182Smrg    # if double slashes aren't ignored.
2645b28e182Smrg    if test -d "$dst"; then
2655b28e182Smrg      if test -n "$no_target_directory"; then
2665b28e182Smrg	echo "$0: $dst_arg: Is a directory" >&2
2675b28e182Smrg	exit 1
2685b28e182Smrg      fi
2695b28e182Smrg      dstdir=$dst
2705b28e182Smrg      dst=$dstdir/`basename "$src"`
2715b28e182Smrg      dstdir_status=0
2725b28e182Smrg    else
2735b28e182Smrg      # Prefer dirname, but fall back on a substitute if dirname fails.
2745b28e182Smrg      dstdir=`
2755b28e182Smrg	(dirname "$dst") 2>/dev/null ||
2765b28e182Smrg	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
2775b28e182Smrg	     X"$dst" : 'X\(//\)[^/]' \| \
2785b28e182Smrg	     X"$dst" : 'X\(//\)$' \| \
2795b28e182Smrg	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
2805b28e182Smrg	echo X"$dst" |
2815b28e182Smrg	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
2825b28e182Smrg		   s//\1/
2835b28e182Smrg		   q
2845b28e182Smrg		 }
2855b28e182Smrg		 /^X\(\/\/\)[^/].*/{
2865b28e182Smrg		   s//\1/
2875b28e182Smrg		   q
2885b28e182Smrg		 }
2895b28e182Smrg		 /^X\(\/\/\)$/{
2905b28e182Smrg		   s//\1/
2915b28e182Smrg		   q
2925b28e182Smrg		 }
2935b28e182Smrg		 /^X\(\/\).*/{
2945b28e182Smrg		   s//\1/
2955b28e182Smrg		   q
2965b28e182Smrg		 }
2975b28e182Smrg		 s/.*/./; q'
2985b28e182Smrg      `
2995b28e182Smrg
3005b28e182Smrg      test -d "$dstdir"
3015b28e182Smrg      dstdir_status=$?
3025b28e182Smrg    fi
3035b28e182Smrg  fi
3045b28e182Smrg
3055b28e182Smrg  obsolete_mkdir_used=false
3065b28e182Smrg
3075b28e182Smrg  if test $dstdir_status != 0; then
3085b28e182Smrg    case $posix_mkdir in
3095b28e182Smrg      '')
3105b28e182Smrg	# Create intermediate dirs using mode 755 as modified by the umask.
3115b28e182Smrg	# This is like FreeBSD 'install' as of 1997-10-28.
3125b28e182Smrg	umask=`umask`
3135b28e182Smrg	case $stripcmd.$umask in
3145b28e182Smrg	  # Optimize common cases.
3155b28e182Smrg	  *[2367][2367]) mkdir_umask=$umask;;
3165b28e182Smrg	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3175b28e182Smrg
3185b28e182Smrg	  *[0-7])
3195b28e182Smrg	    mkdir_umask=`expr $umask + 22 \
3205b28e182Smrg	      - $umask % 100 % 40 + $umask % 20 \
3215b28e182Smrg	      - $umask % 10 % 4 + $umask % 2
3225b28e182Smrg	    `;;
3235b28e182Smrg	  *) mkdir_umask=$umask,go-w;;
3245b28e182Smrg	esac
3255b28e182Smrg
3265b28e182Smrg	# With -d, create the new directory with the user-specified mode.
3275b28e182Smrg	# Otherwise, rely on $mkdir_umask.
3285b28e182Smrg	if test -n "$dir_arg"; then
3295b28e182Smrg	  mkdir_mode=-m$mode
330dcae5b9eSmrg	else
3315b28e182Smrg	  mkdir_mode=
332dcae5b9eSmrg	fi
333dcae5b9eSmrg
3345b28e182Smrg	posix_mkdir=false
3355b28e182Smrg	case $umask in
3365b28e182Smrg	  *[123567][0-7][0-7])
3375b28e182Smrg	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
3385b28e182Smrg	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
3395b28e182Smrg	    ;;
3405b28e182Smrg	  *)
3415b28e182Smrg	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3425b28e182Smrg	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
3435b28e182Smrg
3445b28e182Smrg	    if (umask $mkdir_umask &&
3455b28e182Smrg		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
3465b28e182Smrg	    then
3475b28e182Smrg	      if test -z "$dir_arg" || {
3485b28e182Smrg		   # Check for POSIX incompatibilities with -m.
3495b28e182Smrg		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3505b28e182Smrg		   # other-writeable bit of parent directory when it shouldn't.
3515b28e182Smrg		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3525b28e182Smrg		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
3535b28e182Smrg		   case $ls_ld_tmpdir in
3545b28e182Smrg		     d????-?r-*) different_mode=700;;
3555b28e182Smrg		     d????-?--*) different_mode=755;;
3565b28e182Smrg		     *) false;;
3575b28e182Smrg		   esac &&
3585b28e182Smrg		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
3595b28e182Smrg		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
3605b28e182Smrg		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3615b28e182Smrg		   }
3625b28e182Smrg		 }
3635b28e182Smrg	      then posix_mkdir=:
3645b28e182Smrg	      fi
3655b28e182Smrg	      rmdir "$tmpdir/d" "$tmpdir"
3665b28e182Smrg	    else
3675b28e182Smrg	      # Remove any dirs left behind by ancient mkdir implementations.
3685b28e182Smrg	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
3695b28e182Smrg	    fi
3705b28e182Smrg	    trap '' 0;;
3715b28e182Smrg	esac;;
3725b28e182Smrg    esac
373dcae5b9eSmrg
3745b28e182Smrg    if
3755b28e182Smrg      $posix_mkdir && (
3765b28e182Smrg	umask $mkdir_umask &&
3775b28e182Smrg	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3785b28e182Smrg      )
3795b28e182Smrg    then :
3805b28e182Smrg    else
3815b28e182Smrg
3825b28e182Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
3835b28e182Smrg      # or it failed possibly due to a race condition.  Create the
3845b28e182Smrg      # directory the slow way, step by step, checking for races as we go.
3855b28e182Smrg
3865b28e182Smrg      case $dstdir in
3875b28e182Smrg	/*) prefix='/';;
3885b28e182Smrg	-*) prefix='./';;
3895b28e182Smrg	*)  prefix='';;
3905b28e182Smrg      esac
3915b28e182Smrg
3925b28e182Smrg      eval "$initialize_posix_glob"
3935b28e182Smrg
3945b28e182Smrg      oIFS=$IFS
3955b28e182Smrg      IFS=/
3965b28e182Smrg      $posix_glob set -f
3975b28e182Smrg      set fnord $dstdir
3985b28e182Smrg      shift
3995b28e182Smrg      $posix_glob set +f
4005b28e182Smrg      IFS=$oIFS
4015b28e182Smrg
4025b28e182Smrg      prefixes=
4035b28e182Smrg
4045b28e182Smrg      for d
4055b28e182Smrg      do
4065b28e182Smrg	test -z "$d" && continue
4075b28e182Smrg
4085b28e182Smrg	prefix=$prefix$d
4095b28e182Smrg	if test -d "$prefix"; then
4105b28e182Smrg	  prefixes=
4115b28e182Smrg	else
4125b28e182Smrg	  if $posix_mkdir; then
4135b28e182Smrg	    (umask=$mkdir_umask &&
4145b28e182Smrg	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4155b28e182Smrg	    # Don't fail if two instances are running concurrently.
4165b28e182Smrg	    test -d "$prefix" || exit 1
4175b28e182Smrg	  else
4185b28e182Smrg	    case $prefix in
4195b28e182Smrg	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4205b28e182Smrg	      *) qprefix=$prefix;;
4215b28e182Smrg	    esac
4225b28e182Smrg	    prefixes="$prefixes '$qprefix'"
4235b28e182Smrg	  fi
4245b28e182Smrg	fi
4255b28e182Smrg	prefix=$prefix/
4265b28e182Smrg      done
4275b28e182Smrg
4285b28e182Smrg      if test -n "$prefixes"; then
4295b28e182Smrg	# Don't fail if two instances are running concurrently.
4305b28e182Smrg	(umask $mkdir_umask &&
4315b28e182Smrg	 eval "\$doit_exec \$mkdirprog $prefixes") ||
4325b28e182Smrg	  test -d "$dstdir" || exit 1
4335b28e182Smrg	obsolete_mkdir_used=true
4345b28e182Smrg      fi
4355b28e182Smrg    fi
4365b28e182Smrg  fi
4375b28e182Smrg
4385b28e182Smrg  if test -n "$dir_arg"; then
4395b28e182Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4405b28e182Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4415b28e182Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4425b28e182Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4435b28e182Smrg  else
4445b28e182Smrg
4455b28e182Smrg    # Make a couple of temp file names in the proper directory.
4465b28e182Smrg    dsttmp=$dstdir/_inst.$$_
4475b28e182Smrg    rmtmp=$dstdir/_rm.$$_
4485b28e182Smrg
4495b28e182Smrg    # Trap to clean up those temp files at exit.
4505b28e182Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4515b28e182Smrg
4525b28e182Smrg    # Copy the file name to the temp name.
4535b28e182Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
4545b28e182Smrg
4555b28e182Smrg    # and set any options; do chmod last to preserve setuid bits.
4565b28e182Smrg    #
4575b28e182Smrg    # If any of these fail, we abort the whole thing.  If we want to
4585b28e182Smrg    # ignore errors from any of these, just make sure not to ignore
4595b28e182Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4605b28e182Smrg    #
4615b28e182Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4625b28e182Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4635b28e182Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4645b28e182Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4655b28e182Smrg
4665b28e182Smrg    # If -C, don't bother to copy if it wouldn't change the file.
4675b28e182Smrg    if $copy_on_change &&
4685b28e182Smrg       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
4695b28e182Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
4705b28e182Smrg
4715b28e182Smrg       eval "$initialize_posix_glob" &&
4725b28e182Smrg       $posix_glob set -f &&
4735b28e182Smrg       set X $old && old=:$2:$4:$5:$6 &&
4745b28e182Smrg       set X $new && new=:$2:$4:$5:$6 &&
4755b28e182Smrg       $posix_glob set +f &&
4765b28e182Smrg
4775b28e182Smrg       test "$old" = "$new" &&
4785b28e182Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4795b28e182Smrg    then
4805b28e182Smrg      rm -f "$dsttmp"
4815b28e182Smrg    else
4825b28e182Smrg      # Rename the file to the real destination.
4835b28e182Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4845b28e182Smrg
4855b28e182Smrg      # The rename failed, perhaps because mv can't rename something else
4865b28e182Smrg      # to itself, or perhaps because mv is so ancient that it does not
4875b28e182Smrg      # support -f.
4885b28e182Smrg      {
4895b28e182Smrg	# Now remove or move aside any old file at destination location.
4905b28e182Smrg	# We try this two ways since rm can't unlink itself on some
4915b28e182Smrg	# systems and the destination file might be busy for other
4925b28e182Smrg	# reasons.  In this case, the final cleanup might fail but the new
4935b28e182Smrg	# file should still install successfully.
4945b28e182Smrg	{
4955b28e182Smrg	  test ! -f "$dst" ||
4965b28e182Smrg	  $doit $rmcmd -f "$dst" 2>/dev/null ||
4975b28e182Smrg	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
4985b28e182Smrg	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
4995b28e182Smrg	  } ||
5005b28e182Smrg	  { echo "$0: cannot unlink or rename $dst" >&2
5015b28e182Smrg	    (exit 1); exit 1
5025b28e182Smrg	  }
5035b28e182Smrg	} &&
5045b28e182Smrg
5055b28e182Smrg	# Now rename the file to the real destination.
5065b28e182Smrg	$doit $mvcmd "$dsttmp" "$dst"
5075b28e182Smrg      }
5085b28e182Smrg    fi || exit 1
5095b28e182Smrg
5105b28e182Smrg    trap '' 0
5115b28e182Smrg  fi
5125b28e182Smrgdone
513dcae5b9eSmrg
5145b28e182Smrg# Local variables:
5155b28e182Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
5165b28e182Smrg# time-stamp-start: "scriptversion="
5175b28e182Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
5185b28e182Smrg# time-stamp-time-zone: "UTC"
5195b28e182Smrg# time-stamp-end: "; # UTC"
5205b28e182Smrg# End:
521