install-sh revision 14210e8e
1c35d236eSmrg#!/bin/sh
2c35d236eSmrg# install - install a program, script, or datafile
3c35d236eSmrg
414210e8eSmrgscriptversion=2013-12-25.23; # UTC
5c35d236eSmrg
6c35d236eSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7c35d236eSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8c35d236eSmrg# following copyright and license.
9c35d236eSmrg#
10c35d236eSmrg# Copyright (C) 1994 X Consortium
11c35d236eSmrg#
12c35d236eSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13c35d236eSmrg# of this software and associated documentation files (the "Software"), to
14c35d236eSmrg# deal in the Software without restriction, including without limitation the
15c35d236eSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16c35d236eSmrg# sell copies of the Software, and to permit persons to whom the Software is
17c35d236eSmrg# furnished to do so, subject to the following conditions:
18c35d236eSmrg#
19c35d236eSmrg# The above copyright notice and this permission notice shall be included in
20c35d236eSmrg# all copies or substantial portions of the Software.
21c35d236eSmrg#
22c35d236eSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23c35d236eSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24c35d236eSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25c35d236eSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26c35d236eSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27c35d236eSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28c35d236eSmrg#
29c35d236eSmrg# Except as contained in this notice, the name of the X Consortium shall not
30c35d236eSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31c35d236eSmrg# ings in this Software without prior written authorization from the X Consor-
32c35d236eSmrg# tium.
33c35d236eSmrg#
34c35d236eSmrg#
35c35d236eSmrg# FSF changes to this file are in the public domain.
36c35d236eSmrg#
37c35d236eSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3814210e8eSmrg# 'make' implicit rules from creating a file called install from it
39c35d236eSmrg# when there is no Makefile.
40c35d236eSmrg#
41c35d236eSmrg# This script is compatible with the BSD install script, but was written
424f6cd06fSmrg# from scratch.
434f6cd06fSmrg
4414210e8eSmrgtab='	'
454f6cd06fSmrgnl='
464f6cd06fSmrg'
4714210e8eSmrgIFS=" $tab$nl"
48c35d236eSmrg
4914210e8eSmrg# Set DOITPROG to "echo" to test this script.
50c35d236eSmrg
51f55e6a01Smrgdoit=${DOITPROG-}
5214210e8eSmrgdoit_exec=${doit:-exec}
53c35d236eSmrg
544f6cd06fSmrg# Put in absolute file names if you don't have them in your path;
554f6cd06fSmrg# or use environment vars.
56c35d236eSmrg
57f55e6a01Smrgchgrpprog=${CHGRPPROG-chgrp}
58f55e6a01Smrgchmodprog=${CHMODPROG-chmod}
59f55e6a01Smrgchownprog=${CHOWNPROG-chown}
60f55e6a01Smrgcmpprog=${CMPPROG-cmp}
61f55e6a01Smrgcpprog=${CPPROG-cp}
62f55e6a01Smrgmkdirprog=${MKDIRPROG-mkdir}
63f55e6a01Smrgmvprog=${MVPROG-mv}
64f55e6a01Smrgrmprog=${RMPROG-rm}
65f55e6a01Smrgstripprog=${STRIPPROG-strip}
66f55e6a01Smrg
674f6cd06fSmrgposix_mkdir=
684f6cd06fSmrg
694f6cd06fSmrg# Desired mode of installed file.
704f6cd06fSmrgmode=0755
714f6cd06fSmrg
72f55e6a01Smrgchgrpcmd=
734f6cd06fSmrgchmodcmd=$chmodprog
74c35d236eSmrgchowncmd=
75f55e6a01Smrgmvcmd=$mvprog
76c35d236eSmrgrmcmd="$rmprog -f"
77f55e6a01Smrgstripcmd=
78f55e6a01Smrg
79c35d236eSmrgsrc=
80c35d236eSmrgdst=
81c35d236eSmrgdir_arg=
82f55e6a01Smrgdst_arg=
83f55e6a01Smrg
84f55e6a01Smrgcopy_on_change=false
8514210e8eSmrgis_target_a_directory=possibly
86c35d236eSmrg
87f55e6a01Smrgusage="\
88f55e6a01SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89c35d236eSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90c35d236eSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91c35d236eSmrg   or: $0 [OPTION]... -d DIRECTORIES...
92c35d236eSmrg
93c35d236eSmrgIn the 1st form, copy SRCFILE to DSTFILE.
94c35d236eSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95c35d236eSmrgIn the 4th, create DIRECTORIES.
96c35d236eSmrg
97c35d236eSmrgOptions:
98f55e6a01Smrg     --help     display this help and exit.
99f55e6a01Smrg     --version  display version info and exit.
100f55e6a01Smrg
101f55e6a01Smrg  -c            (ignored)
102f55e6a01Smrg  -C            install only if different (preserve the last data modification time)
103f55e6a01Smrg  -d            create directories instead of installing files.
104f55e6a01Smrg  -g GROUP      $chgrpprog installed files to GROUP.
105f55e6a01Smrg  -m MODE       $chmodprog installed files to MODE.
106f55e6a01Smrg  -o USER       $chownprog installed files to USER.
107f55e6a01Smrg  -s            $stripprog installed files.
108f55e6a01Smrg  -t DIRECTORY  install into DIRECTORY.
109f55e6a01Smrg  -T            report an error if DSTFILE is a directory.
110c35d236eSmrg
111c35d236eSmrgEnvironment variables override the default commands:
112f55e6a01Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113f55e6a01Smrg  RMPROG STRIPPROG
114c35d236eSmrg"
115c35d236eSmrg
1164f6cd06fSmrgwhile test $# -ne 0; do
117c35d236eSmrg  case $1 in
118f55e6a01Smrg    -c) ;;
119f55e6a01Smrg
120f55e6a01Smrg    -C) copy_on_change=true;;
121c35d236eSmrg
122f55e6a01Smrg    -d) dir_arg=true;;
123c35d236eSmrg
124c35d236eSmrg    -g) chgrpcmd="$chgrpprog $2"
12514210e8eSmrg        shift;;
126c35d236eSmrg
127c35d236eSmrg    --help) echo "$usage"; exit $?;;
128c35d236eSmrg
1294f6cd06fSmrg    -m) mode=$2
13014210e8eSmrg        case $mode in
13114210e8eSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
13214210e8eSmrg            echo "$0: invalid mode: $mode" >&2
13314210e8eSmrg            exit 1;;
13414210e8eSmrg        esac
13514210e8eSmrg        shift;;
136c35d236eSmrg
137c35d236eSmrg    -o) chowncmd="$chownprog $2"
13814210e8eSmrg        shift;;
139c35d236eSmrg
140f55e6a01Smrg    -s) stripcmd=$stripprog;;
141c35d236eSmrg
14214210e8eSmrg    -t)
14314210e8eSmrg        is_target_a_directory=always
14414210e8eSmrg        dst_arg=$2
14514210e8eSmrg        # Protect names problematic for 'test' and other utilities.
14614210e8eSmrg        case $dst_arg in
14714210e8eSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14814210e8eSmrg        esac
14914210e8eSmrg        shift;;
150c35d236eSmrg
15114210e8eSmrg    -T) is_target_a_directory=never;;
152c35d236eSmrg
153c35d236eSmrg    --version) echo "$0 $scriptversion"; exit $?;;
154c35d236eSmrg
15514210e8eSmrg    --) shift
15614210e8eSmrg        break;;
1574f6cd06fSmrg
15814210e8eSmrg    -*) echo "$0: invalid option: $1" >&2
15914210e8eSmrg        exit 1;;
1604f6cd06fSmrg
1614f6cd06fSmrg    *)  break;;
162c35d236eSmrg  esac
163f55e6a01Smrg  shift
164c35d236eSmrgdone
165c35d236eSmrg
16614210e8eSmrg# We allow the use of options -d and -T together, by making -d
16714210e8eSmrg# take the precedence; this is for compatibility with GNU install.
16814210e8eSmrg
16914210e8eSmrgif test -n "$dir_arg"; then
17014210e8eSmrg  if test -n "$dst_arg"; then
17114210e8eSmrg    echo "$0: target directory not allowed when installing a directory." >&2
17214210e8eSmrg    exit 1
17314210e8eSmrg  fi
17414210e8eSmrgfi
17514210e8eSmrg
176f55e6a01Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1774f6cd06fSmrg  # When -d is used, all remaining arguments are directories to create.
1784f6cd06fSmrg  # When -t is used, the destination is already specified.
1794f6cd06fSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
1804f6cd06fSmrg  for arg
1814f6cd06fSmrg  do
182f55e6a01Smrg    if test -n "$dst_arg"; then
1834f6cd06fSmrg      # $@ is not empty: it contains at least $arg.
184f55e6a01Smrg      set fnord "$@" "$dst_arg"
1854f6cd06fSmrg      shift # fnord
1864f6cd06fSmrg    fi
1874f6cd06fSmrg    shift # arg
188f55e6a01Smrg    dst_arg=$arg
18914210e8eSmrg    # Protect names problematic for 'test' and other utilities.
1901fb744b4Smrg    case $dst_arg in
1911fb744b4Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
1921fb744b4Smrg    esac
1934f6cd06fSmrg  done
1944f6cd06fSmrgfi
1954f6cd06fSmrg
1964f6cd06fSmrgif test $# -eq 0; then
197c35d236eSmrg  if test -z "$dir_arg"; then
198c35d236eSmrg    echo "$0: no input file specified." >&2
199c35d236eSmrg    exit 1
200c35d236eSmrg  fi
20114210e8eSmrg  # It's OK to call 'install-sh -d' without argument.
202c35d236eSmrg  # This can happen when creating conditional directories.
203c35d236eSmrg  exit 0
204c35d236eSmrgfi
205c35d236eSmrg
20614210e8eSmrgif test -z "$dir_arg"; then
20714210e8eSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20814210e8eSmrg    if test ! -d "$dst_arg"; then
20914210e8eSmrg      echo "$0: $dst_arg: Is not a directory." >&2
21014210e8eSmrg      exit 1
21114210e8eSmrg    fi
21214210e8eSmrg  fi
21314210e8eSmrgfi
21414210e8eSmrg
2154f6cd06fSmrgif test -z "$dir_arg"; then
2161fb744b4Smrg  do_exit='(exit $ret); exit $ret'
2171fb744b4Smrg  trap "ret=129; $do_exit" 1
2181fb744b4Smrg  trap "ret=130; $do_exit" 2
2191fb744b4Smrg  trap "ret=141; $do_exit" 13
2201fb744b4Smrg  trap "ret=143; $do_exit" 15
2214f6cd06fSmrg
2224f6cd06fSmrg  # Set umask so as not to create temps with too-generous modes.
2234f6cd06fSmrg  # However, 'strip' requires both read and write access to temps.
2244f6cd06fSmrg  case $mode in
2254f6cd06fSmrg    # Optimize common cases.
2264f6cd06fSmrg    *644) cp_umask=133;;
2274f6cd06fSmrg    *755) cp_umask=22;;
2284f6cd06fSmrg
2294f6cd06fSmrg    *[0-7])
2304f6cd06fSmrg      if test -z "$stripcmd"; then
23114210e8eSmrg        u_plus_rw=
2324f6cd06fSmrg      else
23314210e8eSmrg        u_plus_rw='% 200'
2344f6cd06fSmrg      fi
2354f6cd06fSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2364f6cd06fSmrg    *)
2374f6cd06fSmrg      if test -z "$stripcmd"; then
23814210e8eSmrg        u_plus_rw=
2394f6cd06fSmrg      else
24014210e8eSmrg        u_plus_rw=,u+rw
2414f6cd06fSmrg      fi
2424f6cd06fSmrg      cp_umask=$mode$u_plus_rw;;
2434f6cd06fSmrg  esac
2444f6cd06fSmrgfi
2454f6cd06fSmrg
246c35d236eSmrgfor src
247c35d236eSmrgdo
24814210e8eSmrg  # Protect names problematic for 'test' and other utilities.
249c35d236eSmrg  case $src in
2501fb744b4Smrg    -* | [=\(\)!]) src=./$src;;
251c35d236eSmrg  esac
252c35d236eSmrg
253c35d236eSmrg  if test -n "$dir_arg"; then
254c35d236eSmrg    dst=$src
2554f6cd06fSmrg    dstdir=$dst
2564f6cd06fSmrg    test -d "$dstdir"
2574f6cd06fSmrg    dstdir_status=$?
258c35d236eSmrg  else
2594f6cd06fSmrg
260c35d236eSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261c35d236eSmrg    # might cause directories to be created, which would be especially bad
262c35d236eSmrg    # if $src (and thus $dsttmp) contains '*'.
263c35d236eSmrg    if test ! -f "$src" && test ! -d "$src"; then
264c35d236eSmrg      echo "$0: $src does not exist." >&2
265c35d236eSmrg      exit 1
266c35d236eSmrg    fi
267c35d236eSmrg
268f55e6a01Smrg    if test -z "$dst_arg"; then
269c35d236eSmrg      echo "$0: no destination specified." >&2
270c35d236eSmrg      exit 1
271c35d236eSmrg    fi
272f55e6a01Smrg    dst=$dst_arg
273c35d236eSmrg
274c35d236eSmrg    # If destination is a directory, append the input filename; won't work
275c35d236eSmrg    # if double slashes aren't ignored.
276c35d236eSmrg    if test -d "$dst"; then
27714210e8eSmrg      if test "$is_target_a_directory" = never; then
27814210e8eSmrg        echo "$0: $dst_arg: Is a directory" >&2
27914210e8eSmrg        exit 1
280c35d236eSmrg      fi
2814f6cd06fSmrg      dstdir=$dst
2824f6cd06fSmrg      dst=$dstdir/`basename "$src"`
2834f6cd06fSmrg      dstdir_status=0
2844f6cd06fSmrg    else
28514210e8eSmrg      dstdir=`dirname "$dst"`
2864f6cd06fSmrg      test -d "$dstdir"
2874f6cd06fSmrg      dstdir_status=$?
288c35d236eSmrg    fi
289c35d236eSmrg  fi
290c35d236eSmrg
2914f6cd06fSmrg  obsolete_mkdir_used=false
2924f6cd06fSmrg
2934f6cd06fSmrg  if test $dstdir_status != 0; then
2944f6cd06fSmrg    case $posix_mkdir in
2954f6cd06fSmrg      '')
29614210e8eSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
29714210e8eSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
29814210e8eSmrg        umask=`umask`
29914210e8eSmrg        case $stripcmd.$umask in
30014210e8eSmrg          # Optimize common cases.
30114210e8eSmrg          *[2367][2367]) mkdir_umask=$umask;;
30214210e8eSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
30314210e8eSmrg
30414210e8eSmrg          *[0-7])
30514210e8eSmrg            mkdir_umask=`expr $umask + 22 \
30614210e8eSmrg              - $umask % 100 % 40 + $umask % 20 \
30714210e8eSmrg              - $umask % 10 % 4 + $umask % 2
30814210e8eSmrg            `;;
30914210e8eSmrg          *) mkdir_umask=$umask,go-w;;
31014210e8eSmrg        esac
31114210e8eSmrg
31214210e8eSmrg        # With -d, create the new directory with the user-specified mode.
31314210e8eSmrg        # Otherwise, rely on $mkdir_umask.
31414210e8eSmrg        if test -n "$dir_arg"; then
31514210e8eSmrg          mkdir_mode=-m$mode
31614210e8eSmrg        else
31714210e8eSmrg          mkdir_mode=
31814210e8eSmrg        fi
31914210e8eSmrg
32014210e8eSmrg        posix_mkdir=false
32114210e8eSmrg        case $umask in
32214210e8eSmrg          *[123567][0-7][0-7])
32314210e8eSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
32414210e8eSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
32514210e8eSmrg            ;;
32614210e8eSmrg          *)
32714210e8eSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
32814210e8eSmrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
32914210e8eSmrg
33014210e8eSmrg            if (umask $mkdir_umask &&
33114210e8eSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
33214210e8eSmrg            then
33314210e8eSmrg              if test -z "$dir_arg" || {
33414210e8eSmrg                   # Check for POSIX incompatibilities with -m.
33514210e8eSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
33614210e8eSmrg                   # other-writable bit of parent directory when it shouldn't.
33714210e8eSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
33814210e8eSmrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
33914210e8eSmrg                   case $ls_ld_tmpdir in
34014210e8eSmrg                     d????-?r-*) different_mode=700;;
34114210e8eSmrg                     d????-?--*) different_mode=755;;
34214210e8eSmrg                     *) false;;
34314210e8eSmrg                   esac &&
34414210e8eSmrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
34514210e8eSmrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
34614210e8eSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
34714210e8eSmrg                   }
34814210e8eSmrg                 }
34914210e8eSmrg              then posix_mkdir=:
35014210e8eSmrg              fi
35114210e8eSmrg              rmdir "$tmpdir/d" "$tmpdir"
35214210e8eSmrg            else
35314210e8eSmrg              # Remove any dirs left behind by ancient mkdir implementations.
35414210e8eSmrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
35514210e8eSmrg            fi
35614210e8eSmrg            trap '' 0;;
35714210e8eSmrg        esac;;
3584f6cd06fSmrg    esac
359c35d236eSmrg
3604f6cd06fSmrg    if
3614f6cd06fSmrg      $posix_mkdir && (
36214210e8eSmrg        umask $mkdir_umask &&
36314210e8eSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3644f6cd06fSmrg      )
3654f6cd06fSmrg    then :
3664f6cd06fSmrg    else
367c35d236eSmrg
3684f6cd06fSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
3694f6cd06fSmrg      # or it failed possibly due to a race condition.  Create the
3704f6cd06fSmrg      # directory the slow way, step by step, checking for races as we go.
3714f6cd06fSmrg
3724f6cd06fSmrg      case $dstdir in
37314210e8eSmrg        /*) prefix='/';;
37414210e8eSmrg        [-=\(\)!]*) prefix='./';;
37514210e8eSmrg        *)  prefix='';;
3764f6cd06fSmrg      esac
3774f6cd06fSmrg
3784f6cd06fSmrg      oIFS=$IFS
3794f6cd06fSmrg      IFS=/
38014210e8eSmrg      set -f
3814f6cd06fSmrg      set fnord $dstdir
382c35d236eSmrg      shift
38314210e8eSmrg      set +f
3844f6cd06fSmrg      IFS=$oIFS
3854f6cd06fSmrg
3864f6cd06fSmrg      prefixes=
3874f6cd06fSmrg
3884f6cd06fSmrg      for d
3894f6cd06fSmrg      do
39014210e8eSmrg        test X"$d" = X && continue
39114210e8eSmrg
39214210e8eSmrg        prefix=$prefix$d
39314210e8eSmrg        if test -d "$prefix"; then
39414210e8eSmrg          prefixes=
39514210e8eSmrg        else
39614210e8eSmrg          if $posix_mkdir; then
39714210e8eSmrg            (umask=$mkdir_umask &&
39814210e8eSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
39914210e8eSmrg            # Don't fail if two instances are running concurrently.
40014210e8eSmrg            test -d "$prefix" || exit 1
40114210e8eSmrg          else
40214210e8eSmrg            case $prefix in
40314210e8eSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
40414210e8eSmrg              *) qprefix=$prefix;;
40514210e8eSmrg            esac
40614210e8eSmrg            prefixes="$prefixes '$qprefix'"
40714210e8eSmrg          fi
40814210e8eSmrg        fi
40914210e8eSmrg        prefix=$prefix/
4104f6cd06fSmrg      done
4114f6cd06fSmrg
4124f6cd06fSmrg      if test -n "$prefixes"; then
41314210e8eSmrg        # Don't fail if two instances are running concurrently.
41414210e8eSmrg        (umask $mkdir_umask &&
41514210e8eSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
41614210e8eSmrg          test -d "$dstdir" || exit 1
41714210e8eSmrg        obsolete_mkdir_used=true
418c35d236eSmrg      fi
4194f6cd06fSmrg    fi
420c35d236eSmrg  fi
421c35d236eSmrg
422c35d236eSmrg  if test -n "$dir_arg"; then
4234f6cd06fSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4244f6cd06fSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4254f6cd06fSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4264f6cd06fSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
427c35d236eSmrg  else
428c35d236eSmrg
429c35d236eSmrg    # Make a couple of temp file names in the proper directory.
430c35d236eSmrg    dsttmp=$dstdir/_inst.$$_
431c35d236eSmrg    rmtmp=$dstdir/_rm.$$_
432c35d236eSmrg
433c35d236eSmrg    # Trap to clean up those temp files at exit.
434c35d236eSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
435c35d236eSmrg
436c35d236eSmrg    # Copy the file name to the temp name.
4374f6cd06fSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
438c35d236eSmrg
439c35d236eSmrg    # and set any options; do chmod last to preserve setuid bits.
440c35d236eSmrg    #
441c35d236eSmrg    # If any of these fail, we abort the whole thing.  If we want to
442c35d236eSmrg    # ignore errors from any of these, just make sure not to ignore
443c35d236eSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
444c35d236eSmrg    #
445f55e6a01Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
446f55e6a01Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
447f55e6a01Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
448f55e6a01Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
449f55e6a01Smrg
450f55e6a01Smrg    # If -C, don't bother to copy if it wouldn't change the file.
451f55e6a01Smrg    if $copy_on_change &&
45214210e8eSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
45314210e8eSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
45414210e8eSmrg       set -f &&
455f55e6a01Smrg       set X $old && old=:$2:$4:$5:$6 &&
456f55e6a01Smrg       set X $new && new=:$2:$4:$5:$6 &&
45714210e8eSmrg       set +f &&
458f55e6a01Smrg       test "$old" = "$new" &&
459f55e6a01Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
460f55e6a01Smrg    then
461f55e6a01Smrg      rm -f "$dsttmp"
462f55e6a01Smrg    else
463f55e6a01Smrg      # Rename the file to the real destination.
464f55e6a01Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
465f55e6a01Smrg
466f55e6a01Smrg      # The rename failed, perhaps because mv can't rename something else
467f55e6a01Smrg      # to itself, or perhaps because mv is so ancient that it does not
468f55e6a01Smrg      # support -f.
469f55e6a01Smrg      {
47014210e8eSmrg        # Now remove or move aside any old file at destination location.
47114210e8eSmrg        # We try this two ways since rm can't unlink itself on some
47214210e8eSmrg        # systems and the destination file might be busy for other
47314210e8eSmrg        # reasons.  In this case, the final cleanup might fail but the new
47414210e8eSmrg        # file should still install successfully.
47514210e8eSmrg        {
47614210e8eSmrg          test ! -f "$dst" ||
47714210e8eSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
47814210e8eSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
47914210e8eSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
48014210e8eSmrg          } ||
48114210e8eSmrg          { echo "$0: cannot unlink or rename $dst" >&2
48214210e8eSmrg            (exit 1); exit 1
48314210e8eSmrg          }
48414210e8eSmrg        } &&
48514210e8eSmrg
48614210e8eSmrg        # Now rename the file to the real destination.
48714210e8eSmrg        $doit $mvcmd "$dsttmp" "$dst"
488f55e6a01Smrg      }
489f55e6a01Smrg    fi || exit 1
490c35d236eSmrg
4914f6cd06fSmrg    trap '' 0
4924f6cd06fSmrg  fi
4934f6cd06fSmrgdone
494c35d236eSmrg
495c35d236eSmrg# Local variables:
496c35d236eSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
497c35d236eSmrg# time-stamp-start: "scriptversion="
498c35d236eSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
499518bcf38Smrg# time-stamp-time-zone: "UTC"
500518bcf38Smrg# time-stamp-end: "; # UTC"
501c35d236eSmrg# End:
502