install-sh revision 33dddc75
172b4363aSmrg#!/bin/sh
272b4363aSmrg# install - install a program, script, or datafile
372b4363aSmrg
433dddc75Smrgscriptversion=2013-12-25.23; # UTC
572b4363aSmrg
672b4363aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
772b4363aSmrg# later released in X11R6 (xc/config/util/install.sh) with the
872b4363aSmrg# following copyright and license.
972b4363aSmrg#
1072b4363aSmrg# Copyright (C) 1994 X Consortium
1172b4363aSmrg#
1272b4363aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1372b4363aSmrg# of this software and associated documentation files (the "Software"), to
1472b4363aSmrg# deal in the Software without restriction, including without limitation the
1572b4363aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1672b4363aSmrg# sell copies of the Software, and to permit persons to whom the Software is
1772b4363aSmrg# furnished to do so, subject to the following conditions:
1872b4363aSmrg#
1972b4363aSmrg# The above copyright notice and this permission notice shall be included in
2072b4363aSmrg# all copies or substantial portions of the Software.
2172b4363aSmrg#
2272b4363aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2372b4363aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2472b4363aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2572b4363aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2672b4363aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2772b4363aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2872b4363aSmrg#
2972b4363aSmrg# Except as contained in this notice, the name of the X Consortium shall not
3072b4363aSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3172b4363aSmrg# ings in this Software without prior written authorization from the X Consor-
3272b4363aSmrg# tium.
3372b4363aSmrg#
3472b4363aSmrg#
3572b4363aSmrg# FSF changes to this file are in the public domain.
3672b4363aSmrg#
3772b4363aSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3833dddc75Smrg# 'make' implicit rules from creating a file called install from it
3972b4363aSmrg# when there is no Makefile.
4072b4363aSmrg#
4172b4363aSmrg# This script is compatible with the BSD install script, but was written
4272b4363aSmrg# from scratch.
4372b4363aSmrg
4433dddc75Smrgtab='	'
4572b4363aSmrgnl='
4672b4363aSmrg'
4733dddc75SmrgIFS=" $tab$nl"
4872b4363aSmrg
4933dddc75Smrg# Set DOITPROG to "echo" to test this script.
5072b4363aSmrg
51dd77ae96Smrgdoit=${DOITPROG-}
5233dddc75Smrgdoit_exec=${doit:-exec}
5372b4363aSmrg
5472b4363aSmrg# Put in absolute file names if you don't have them in your path;
5572b4363aSmrg# or use environment vars.
5672b4363aSmrg
57dd77ae96Smrgchgrpprog=${CHGRPPROG-chgrp}
58dd77ae96Smrgchmodprog=${CHMODPROG-chmod}
59dd77ae96Smrgchownprog=${CHOWNPROG-chown}
60dd77ae96Smrgcmpprog=${CMPPROG-cmp}
61dd77ae96Smrgcpprog=${CPPROG-cp}
62dd77ae96Smrgmkdirprog=${MKDIRPROG-mkdir}
63dd77ae96Smrgmvprog=${MVPROG-mv}
64dd77ae96Smrgrmprog=${RMPROG-rm}
65dd77ae96Smrgstripprog=${STRIPPROG-strip}
66dd77ae96Smrg
6772b4363aSmrgposix_mkdir=
6872b4363aSmrg
6972b4363aSmrg# Desired mode of installed file.
7072b4363aSmrgmode=0755
7172b4363aSmrg
72dd77ae96Smrgchgrpcmd=
7372b4363aSmrgchmodcmd=$chmodprog
7472b4363aSmrgchowncmd=
75dd77ae96Smrgmvcmd=$mvprog
7672b4363aSmrgrmcmd="$rmprog -f"
77dd77ae96Smrgstripcmd=
78dd77ae96Smrg
7972b4363aSmrgsrc=
8072b4363aSmrgdst=
8172b4363aSmrgdir_arg=
82dd77ae96Smrgdst_arg=
83dd77ae96Smrg
84dd77ae96Smrgcopy_on_change=false
8533dddc75Smrgis_target_a_directory=possibly
8672b4363aSmrg
87dd77ae96Smrgusage="\
88dd77ae96SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8972b4363aSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9072b4363aSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9172b4363aSmrg   or: $0 [OPTION]... -d DIRECTORIES...
9272b4363aSmrg
9372b4363aSmrgIn the 1st form, copy SRCFILE to DSTFILE.
9472b4363aSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
9572b4363aSmrgIn the 4th, create DIRECTORIES.
9672b4363aSmrg
9772b4363aSmrgOptions:
98dd77ae96Smrg     --help     display this help and exit.
99dd77ae96Smrg     --version  display version info and exit.
100dd77ae96Smrg
101dd77ae96Smrg  -c            (ignored)
102dd77ae96Smrg  -C            install only if different (preserve the last data modification time)
103dd77ae96Smrg  -d            create directories instead of installing files.
104dd77ae96Smrg  -g GROUP      $chgrpprog installed files to GROUP.
105dd77ae96Smrg  -m MODE       $chmodprog installed files to MODE.
106dd77ae96Smrg  -o USER       $chownprog installed files to USER.
107dd77ae96Smrg  -s            $stripprog installed files.
108dd77ae96Smrg  -t DIRECTORY  install into DIRECTORY.
109dd77ae96Smrg  -T            report an error if DSTFILE is a directory.
11072b4363aSmrg
11172b4363aSmrgEnvironment variables override the default commands:
112dd77ae96Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113dd77ae96Smrg  RMPROG STRIPPROG
11472b4363aSmrg"
11572b4363aSmrg
11672b4363aSmrgwhile test $# -ne 0; do
11772b4363aSmrg  case $1 in
118dd77ae96Smrg    -c) ;;
119dd77ae96Smrg
120dd77ae96Smrg    -C) copy_on_change=true;;
12172b4363aSmrg
122dd77ae96Smrg    -d) dir_arg=true;;
12372b4363aSmrg
12472b4363aSmrg    -g) chgrpcmd="$chgrpprog $2"
12533dddc75Smrg        shift;;
12672b4363aSmrg
12772b4363aSmrg    --help) echo "$usage"; exit $?;;
12872b4363aSmrg
12972b4363aSmrg    -m) mode=$2
13033dddc75Smrg        case $mode in
13133dddc75Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
13233dddc75Smrg            echo "$0: invalid mode: $mode" >&2
13333dddc75Smrg            exit 1;;
13433dddc75Smrg        esac
13533dddc75Smrg        shift;;
13672b4363aSmrg
13772b4363aSmrg    -o) chowncmd="$chownprog $2"
13833dddc75Smrg        shift;;
13972b4363aSmrg
140dd77ae96Smrg    -s) stripcmd=$stripprog;;
14172b4363aSmrg
14233dddc75Smrg    -t)
14333dddc75Smrg        is_target_a_directory=always
14433dddc75Smrg        dst_arg=$2
14533dddc75Smrg        # Protect names problematic for 'test' and other utilities.
14633dddc75Smrg        case $dst_arg in
14733dddc75Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14833dddc75Smrg        esac
14933dddc75Smrg        shift;;
15072b4363aSmrg
15133dddc75Smrg    -T) is_target_a_directory=never;;
15272b4363aSmrg
15372b4363aSmrg    --version) echo "$0 $scriptversion"; exit $?;;
15472b4363aSmrg
15533dddc75Smrg    --) shift
15633dddc75Smrg        break;;
15772b4363aSmrg
15833dddc75Smrg    -*) echo "$0: invalid option: $1" >&2
15933dddc75Smrg        exit 1;;
16072b4363aSmrg
16172b4363aSmrg    *)  break;;
16272b4363aSmrg  esac
163dd77ae96Smrg  shift
16472b4363aSmrgdone
16572b4363aSmrg
16633dddc75Smrg# We allow the use of options -d and -T together, by making -d
16733dddc75Smrg# take the precedence; this is for compatibility with GNU install.
16833dddc75Smrg
16933dddc75Smrgif test -n "$dir_arg"; then
17033dddc75Smrg  if test -n "$dst_arg"; then
17133dddc75Smrg    echo "$0: target directory not allowed when installing a directory." >&2
17233dddc75Smrg    exit 1
17333dddc75Smrg  fi
17433dddc75Smrgfi
17533dddc75Smrg
176dd77ae96Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
17772b4363aSmrg  # When -d is used, all remaining arguments are directories to create.
17872b4363aSmrg  # When -t is used, the destination is already specified.
17972b4363aSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
18072b4363aSmrg  for arg
18172b4363aSmrg  do
182dd77ae96Smrg    if test -n "$dst_arg"; then
18372b4363aSmrg      # $@ is not empty: it contains at least $arg.
184dd77ae96Smrg      set fnord "$@" "$dst_arg"
18572b4363aSmrg      shift # fnord
18672b4363aSmrg    fi
18772b4363aSmrg    shift # arg
188dd77ae96Smrg    dst_arg=$arg
18933dddc75Smrg    # Protect names problematic for 'test' and other utilities.
19033dddc75Smrg    case $dst_arg in
19133dddc75Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19233dddc75Smrg    esac
19372b4363aSmrg  done
19472b4363aSmrgfi
19572b4363aSmrg
19672b4363aSmrgif test $# -eq 0; then
19772b4363aSmrg  if test -z "$dir_arg"; then
19872b4363aSmrg    echo "$0: no input file specified." >&2
19972b4363aSmrg    exit 1
20072b4363aSmrg  fi
20133dddc75Smrg  # It's OK to call 'install-sh -d' without argument.
20272b4363aSmrg  # This can happen when creating conditional directories.
20372b4363aSmrg  exit 0
20472b4363aSmrgfi
20572b4363aSmrg
20672b4363aSmrgif test -z "$dir_arg"; then
20733dddc75Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20833dddc75Smrg    if test ! -d "$dst_arg"; then
20933dddc75Smrg      echo "$0: $dst_arg: Is not a directory." >&2
21033dddc75Smrg      exit 1
21133dddc75Smrg    fi
21233dddc75Smrg  fi
21333dddc75Smrgfi
21433dddc75Smrg
21533dddc75Smrgif test -z "$dir_arg"; then
21633dddc75Smrg  do_exit='(exit $ret); exit $ret'
21733dddc75Smrg  trap "ret=129; $do_exit" 1
21833dddc75Smrg  trap "ret=130; $do_exit" 2
21933dddc75Smrg  trap "ret=141; $do_exit" 13
22033dddc75Smrg  trap "ret=143; $do_exit" 15
22172b4363aSmrg
22272b4363aSmrg  # Set umask so as not to create temps with too-generous modes.
22372b4363aSmrg  # However, 'strip' requires both read and write access to temps.
22472b4363aSmrg  case $mode in
22572b4363aSmrg    # Optimize common cases.
22672b4363aSmrg    *644) cp_umask=133;;
22772b4363aSmrg    *755) cp_umask=22;;
22872b4363aSmrg
22972b4363aSmrg    *[0-7])
23072b4363aSmrg      if test -z "$stripcmd"; then
23133dddc75Smrg        u_plus_rw=
23272b4363aSmrg      else
23333dddc75Smrg        u_plus_rw='% 200'
23472b4363aSmrg      fi
23572b4363aSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
23672b4363aSmrg    *)
23772b4363aSmrg      if test -z "$stripcmd"; then
23833dddc75Smrg        u_plus_rw=
23972b4363aSmrg      else
24033dddc75Smrg        u_plus_rw=,u+rw
24172b4363aSmrg      fi
24272b4363aSmrg      cp_umask=$mode$u_plus_rw;;
24372b4363aSmrg  esac
24472b4363aSmrgfi
24572b4363aSmrg
24672b4363aSmrgfor src
24772b4363aSmrgdo
24833dddc75Smrg  # Protect names problematic for 'test' and other utilities.
24972b4363aSmrg  case $src in
25033dddc75Smrg    -* | [=\(\)!]) src=./$src;;
25172b4363aSmrg  esac
25272b4363aSmrg
25372b4363aSmrg  if test -n "$dir_arg"; then
25472b4363aSmrg    dst=$src
25572b4363aSmrg    dstdir=$dst
25672b4363aSmrg    test -d "$dstdir"
25772b4363aSmrg    dstdir_status=$?
25872b4363aSmrg  else
25972b4363aSmrg
26072b4363aSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26172b4363aSmrg    # might cause directories to be created, which would be especially bad
26272b4363aSmrg    # if $src (and thus $dsttmp) contains '*'.
26372b4363aSmrg    if test ! -f "$src" && test ! -d "$src"; then
26472b4363aSmrg      echo "$0: $src does not exist." >&2
26572b4363aSmrg      exit 1
26672b4363aSmrg    fi
26772b4363aSmrg
268dd77ae96Smrg    if test -z "$dst_arg"; then
26972b4363aSmrg      echo "$0: no destination specified." >&2
27072b4363aSmrg      exit 1
27172b4363aSmrg    fi
272dd77ae96Smrg    dst=$dst_arg
27372b4363aSmrg
27472b4363aSmrg    # If destination is a directory, append the input filename; won't work
27572b4363aSmrg    # if double slashes aren't ignored.
27672b4363aSmrg    if test -d "$dst"; then
27733dddc75Smrg      if test "$is_target_a_directory" = never; then
27833dddc75Smrg        echo "$0: $dst_arg: Is a directory" >&2
27933dddc75Smrg        exit 1
28072b4363aSmrg      fi
28172b4363aSmrg      dstdir=$dst
28272b4363aSmrg      dst=$dstdir/`basename "$src"`
28372b4363aSmrg      dstdir_status=0
28472b4363aSmrg    else
28533dddc75Smrg      dstdir=`dirname "$dst"`
28672b4363aSmrg      test -d "$dstdir"
28772b4363aSmrg      dstdir_status=$?
28872b4363aSmrg    fi
28972b4363aSmrg  fi
29072b4363aSmrg
29172b4363aSmrg  obsolete_mkdir_used=false
29272b4363aSmrg
29372b4363aSmrg  if test $dstdir_status != 0; then
29472b4363aSmrg    case $posix_mkdir in
29572b4363aSmrg      '')
29633dddc75Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
29733dddc75Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
29833dddc75Smrg        umask=`umask`
29933dddc75Smrg        case $stripcmd.$umask in
30033dddc75Smrg          # Optimize common cases.
30133dddc75Smrg          *[2367][2367]) mkdir_umask=$umask;;
30233dddc75Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
30333dddc75Smrg
30433dddc75Smrg          *[0-7])
30533dddc75Smrg            mkdir_umask=`expr $umask + 22 \
30633dddc75Smrg              - $umask % 100 % 40 + $umask % 20 \
30733dddc75Smrg              - $umask % 10 % 4 + $umask % 2
30833dddc75Smrg            `;;
30933dddc75Smrg          *) mkdir_umask=$umask,go-w;;
31033dddc75Smrg        esac
31133dddc75Smrg
31233dddc75Smrg        # With -d, create the new directory with the user-specified mode.
31333dddc75Smrg        # Otherwise, rely on $mkdir_umask.
31433dddc75Smrg        if test -n "$dir_arg"; then
31533dddc75Smrg          mkdir_mode=-m$mode
31633dddc75Smrg        else
31733dddc75Smrg          mkdir_mode=
31833dddc75Smrg        fi
31933dddc75Smrg
32033dddc75Smrg        posix_mkdir=false
32133dddc75Smrg        case $umask in
32233dddc75Smrg          *[123567][0-7][0-7])
32333dddc75Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
32433dddc75Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
32533dddc75Smrg            ;;
32633dddc75Smrg          *)
32733dddc75Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
32833dddc75Smrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
32933dddc75Smrg
33033dddc75Smrg            if (umask $mkdir_umask &&
33133dddc75Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
33233dddc75Smrg            then
33333dddc75Smrg              if test -z "$dir_arg" || {
33433dddc75Smrg                   # Check for POSIX incompatibilities with -m.
33533dddc75Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
33633dddc75Smrg                   # other-writable bit of parent directory when it shouldn't.
33733dddc75Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
33833dddc75Smrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
33933dddc75Smrg                   case $ls_ld_tmpdir in
34033dddc75Smrg                     d????-?r-*) different_mode=700;;
34133dddc75Smrg                     d????-?--*) different_mode=755;;
34233dddc75Smrg                     *) false;;
34333dddc75Smrg                   esac &&
34433dddc75Smrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
34533dddc75Smrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
34633dddc75Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
34733dddc75Smrg                   }
34833dddc75Smrg                 }
34933dddc75Smrg              then posix_mkdir=:
35033dddc75Smrg              fi
35133dddc75Smrg              rmdir "$tmpdir/d" "$tmpdir"
35233dddc75Smrg            else
35333dddc75Smrg              # Remove any dirs left behind by ancient mkdir implementations.
35433dddc75Smrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
35533dddc75Smrg            fi
35633dddc75Smrg            trap '' 0;;
35733dddc75Smrg        esac;;
35872b4363aSmrg    esac
35972b4363aSmrg
36072b4363aSmrg    if
36172b4363aSmrg      $posix_mkdir && (
36233dddc75Smrg        umask $mkdir_umask &&
36333dddc75Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
36472b4363aSmrg      )
36572b4363aSmrg    then :
36672b4363aSmrg    else
36772b4363aSmrg
36872b4363aSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
36972b4363aSmrg      # or it failed possibly due to a race condition.  Create the
37072b4363aSmrg      # directory the slow way, step by step, checking for races as we go.
37172b4363aSmrg
37272b4363aSmrg      case $dstdir in
37333dddc75Smrg        /*) prefix='/';;
37433dddc75Smrg        [-=\(\)!]*) prefix='./';;
37533dddc75Smrg        *)  prefix='';;
37672b4363aSmrg      esac
37772b4363aSmrg
37872b4363aSmrg      oIFS=$IFS
37972b4363aSmrg      IFS=/
38033dddc75Smrg      set -f
38172b4363aSmrg      set fnord $dstdir
38272b4363aSmrg      shift
38333dddc75Smrg      set +f
38472b4363aSmrg      IFS=$oIFS
38572b4363aSmrg
38672b4363aSmrg      prefixes=
38772b4363aSmrg
38872b4363aSmrg      for d
38972b4363aSmrg      do
39033dddc75Smrg        test X"$d" = X && continue
39133dddc75Smrg
39233dddc75Smrg        prefix=$prefix$d
39333dddc75Smrg        if test -d "$prefix"; then
39433dddc75Smrg          prefixes=
39533dddc75Smrg        else
39633dddc75Smrg          if $posix_mkdir; then
39733dddc75Smrg            (umask=$mkdir_umask &&
39833dddc75Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
39933dddc75Smrg            # Don't fail if two instances are running concurrently.
40033dddc75Smrg            test -d "$prefix" || exit 1
40133dddc75Smrg          else
40233dddc75Smrg            case $prefix in
40333dddc75Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
40433dddc75Smrg              *) qprefix=$prefix;;
40533dddc75Smrg            esac
40633dddc75Smrg            prefixes="$prefixes '$qprefix'"
40733dddc75Smrg          fi
40833dddc75Smrg        fi
40933dddc75Smrg        prefix=$prefix/
41072b4363aSmrg      done
41172b4363aSmrg
41272b4363aSmrg      if test -n "$prefixes"; then
41333dddc75Smrg        # Don't fail if two instances are running concurrently.
41433dddc75Smrg        (umask $mkdir_umask &&
41533dddc75Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
41633dddc75Smrg          test -d "$dstdir" || exit 1
41733dddc75Smrg        obsolete_mkdir_used=true
41872b4363aSmrg      fi
41972b4363aSmrg    fi
42072b4363aSmrg  fi
42172b4363aSmrg
42272b4363aSmrg  if test -n "$dir_arg"; then
42372b4363aSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
42472b4363aSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
42572b4363aSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
42672b4363aSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
42772b4363aSmrg  else
42872b4363aSmrg
42972b4363aSmrg    # Make a couple of temp file names in the proper directory.
43072b4363aSmrg    dsttmp=$dstdir/_inst.$$_
43172b4363aSmrg    rmtmp=$dstdir/_rm.$$_
43272b4363aSmrg
43372b4363aSmrg    # Trap to clean up those temp files at exit.
43472b4363aSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
43572b4363aSmrg
43672b4363aSmrg    # Copy the file name to the temp name.
43772b4363aSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
43872b4363aSmrg
43972b4363aSmrg    # and set any options; do chmod last to preserve setuid bits.
44072b4363aSmrg    #
44172b4363aSmrg    # If any of these fail, we abort the whole thing.  If we want to
44272b4363aSmrg    # ignore errors from any of these, just make sure not to ignore
44372b4363aSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
44472b4363aSmrg    #
445dd77ae96Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
446dd77ae96Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
447dd77ae96Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
448dd77ae96Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
449dd77ae96Smrg
450dd77ae96Smrg    # If -C, don't bother to copy if it wouldn't change the file.
451dd77ae96Smrg    if $copy_on_change &&
45233dddc75Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
45333dddc75Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
45433dddc75Smrg       set -f &&
455dd77ae96Smrg       set X $old && old=:$2:$4:$5:$6 &&
456dd77ae96Smrg       set X $new && new=:$2:$4:$5:$6 &&
45733dddc75Smrg       set +f &&
458dd77ae96Smrg       test "$old" = "$new" &&
459dd77ae96Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
460dd77ae96Smrg    then
461dd77ae96Smrg      rm -f "$dsttmp"
462dd77ae96Smrg    else
463dd77ae96Smrg      # Rename the file to the real destination.
464dd77ae96Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
465dd77ae96Smrg
466dd77ae96Smrg      # The rename failed, perhaps because mv can't rename something else
467dd77ae96Smrg      # to itself, or perhaps because mv is so ancient that it does not
468dd77ae96Smrg      # support -f.
469dd77ae96Smrg      {
47033dddc75Smrg        # Now remove or move aside any old file at destination location.
47133dddc75Smrg        # We try this two ways since rm can't unlink itself on some
47233dddc75Smrg        # systems and the destination file might be busy for other
47333dddc75Smrg        # reasons.  In this case, the final cleanup might fail but the new
47433dddc75Smrg        # file should still install successfully.
47533dddc75Smrg        {
47633dddc75Smrg          test ! -f "$dst" ||
47733dddc75Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
47833dddc75Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
47933dddc75Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
48033dddc75Smrg          } ||
48133dddc75Smrg          { echo "$0: cannot unlink or rename $dst" >&2
48233dddc75Smrg            (exit 1); exit 1
48333dddc75Smrg          }
48433dddc75Smrg        } &&
48533dddc75Smrg
48633dddc75Smrg        # Now rename the file to the real destination.
48733dddc75Smrg        $doit $mvcmd "$dsttmp" "$dst"
488dd77ae96Smrg      }
489dd77ae96Smrg    fi || exit 1
49072b4363aSmrg
49172b4363aSmrg    trap '' 0
49272b4363aSmrg  fi
49372b4363aSmrgdone
49472b4363aSmrg
49572b4363aSmrg# Local variables:
49672b4363aSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
49772b4363aSmrg# time-stamp-start: "scriptversion="
49872b4363aSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
499dd77ae96Smrg# time-stamp-time-zone: "UTC"
500dd77ae96Smrg# time-stamp-end: "; # UTC"
50172b4363aSmrg# End:
502