102be438aSmrg#!/bin/sh
202be438aSmrg# install - install a program, script, or datafile
302be438aSmrg
4f3f7d111Smrgscriptversion=2014-09-12.12; # UTC
502be438aSmrg
602be438aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
702be438aSmrg# later released in X11R6 (xc/config/util/install.sh) with the
802be438aSmrg# following copyright and license.
902be438aSmrg#
1002be438aSmrg# Copyright (C) 1994 X Consortium
1102be438aSmrg#
1202be438aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
1302be438aSmrg# of this software and associated documentation files (the "Software"), to
1402be438aSmrg# deal in the Software without restriction, including without limitation the
1502be438aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1602be438aSmrg# sell copies of the Software, and to permit persons to whom the Software is
1702be438aSmrg# furnished to do so, subject to the following conditions:
1802be438aSmrg#
1902be438aSmrg# The above copyright notice and this permission notice shall be included in
2002be438aSmrg# all copies or substantial portions of the Software.
2102be438aSmrg#
2202be438aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2302be438aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2402be438aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2502be438aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2602be438aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
2702be438aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2802be438aSmrg#
2902be438aSmrg# Except as contained in this notice, the name of the X Consortium shall not
3002be438aSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
3102be438aSmrg# ings in this Software without prior written authorization from the X Consor-
3202be438aSmrg# tium.
3302be438aSmrg#
3402be438aSmrg#
3502be438aSmrg# FSF changes to this file are in the public domain.
3602be438aSmrg#
3702be438aSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38e2463426Smrg# 'make' implicit rules from creating a file called install from it
3902be438aSmrg# when there is no Makefile.
4002be438aSmrg#
4102be438aSmrg# This script is compatible with the BSD install script, but was written
42880ed95aSmrg# from scratch.
43880ed95aSmrg
44adb5514aSmrgtab='	'
45880ed95aSmrgnl='
46880ed95aSmrg'
47adb5514aSmrgIFS=" $tab$nl"
4802be438aSmrg
49adb5514aSmrg# Set DOITPROG to "echo" to test this script.
5002be438aSmrg
51880ed95aSmrgdoit=${DOITPROG-}
52adb5514aSmrgdoit_exec=${doit:-exec}
5302be438aSmrg
54880ed95aSmrg# Put in absolute file names if you don't have them in your path;
55880ed95aSmrg# or use environment vars.
56880ed95aSmrg
57880ed95aSmrgchgrpprog=${CHGRPPROG-chgrp}
58880ed95aSmrgchmodprog=${CHMODPROG-chmod}
59880ed95aSmrgchownprog=${CHOWNPROG-chown}
60880ed95aSmrgcmpprog=${CMPPROG-cmp}
61880ed95aSmrgcpprog=${CPPROG-cp}
62880ed95aSmrgmkdirprog=${MKDIRPROG-mkdir}
63880ed95aSmrgmvprog=${MVPROG-mv}
64880ed95aSmrgrmprog=${RMPROG-rm}
65880ed95aSmrgstripprog=${STRIPPROG-strip}
66880ed95aSmrg
67880ed95aSmrgposix_mkdir=
68880ed95aSmrg
69880ed95aSmrg# Desired mode of installed file.
70880ed95aSmrgmode=0755
7102be438aSmrg
7202be438aSmrgchgrpcmd=
73880ed95aSmrgchmodcmd=$chmodprog
74880ed95aSmrgchowncmd=
75880ed95aSmrgmvcmd=$mvprog
7602be438aSmrgrmcmd="$rmprog -f"
77880ed95aSmrgstripcmd=
78880ed95aSmrg
7902be438aSmrgsrc=
8002be438aSmrgdst=
8102be438aSmrgdir_arg=
82880ed95aSmrgdst_arg=
83880ed95aSmrg
84880ed95aSmrgcopy_on_change=false
85adb5514aSmrgis_target_a_directory=possibly
8602be438aSmrg
87880ed95aSmrgusage="\
88880ed95aSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8902be438aSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9002be438aSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9102be438aSmrg   or: $0 [OPTION]... -d DIRECTORIES...
9202be438aSmrg
9302be438aSmrgIn the 1st form, copy SRCFILE to DSTFILE.
9402be438aSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
9502be438aSmrgIn the 4th, create DIRECTORIES.
9602be438aSmrg
9702be438aSmrgOptions:
98880ed95aSmrg     --help     display this help and exit.
99880ed95aSmrg     --version  display version info and exit.
100880ed95aSmrg
101880ed95aSmrg  -c            (ignored)
102880ed95aSmrg  -C            install only if different (preserve the last data modification time)
103880ed95aSmrg  -d            create directories instead of installing files.
104880ed95aSmrg  -g GROUP      $chgrpprog installed files to GROUP.
105880ed95aSmrg  -m MODE       $chmodprog installed files to MODE.
106880ed95aSmrg  -o USER       $chownprog installed files to USER.
107880ed95aSmrg  -s            $stripprog installed files.
108880ed95aSmrg  -t DIRECTORY  install into DIRECTORY.
109880ed95aSmrg  -T            report an error if DSTFILE is a directory.
11002be438aSmrg
11102be438aSmrgEnvironment variables override the default commands:
112880ed95aSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113880ed95aSmrg  RMPROG STRIPPROG
11402be438aSmrg"
11502be438aSmrg
116880ed95aSmrgwhile test $# -ne 0; do
11702be438aSmrg  case $1 in
118880ed95aSmrg    -c) ;;
119880ed95aSmrg
120880ed95aSmrg    -C) copy_on_change=true;;
12102be438aSmrg
122880ed95aSmrg    -d) dir_arg=true;;
12302be438aSmrg
12402be438aSmrg    -g) chgrpcmd="$chgrpprog $2"
125adb5514aSmrg        shift;;
12602be438aSmrg
12702be438aSmrg    --help) echo "$usage"; exit $?;;
12802be438aSmrg
129880ed95aSmrg    -m) mode=$2
130adb5514aSmrg        case $mode in
131adb5514aSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132adb5514aSmrg            echo "$0: invalid mode: $mode" >&2
133adb5514aSmrg            exit 1;;
134adb5514aSmrg        esac
135adb5514aSmrg        shift;;
13602be438aSmrg
13702be438aSmrg    -o) chowncmd="$chownprog $2"
138adb5514aSmrg        shift;;
13902be438aSmrg
140880ed95aSmrg    -s) stripcmd=$stripprog;;
14102be438aSmrg
142adb5514aSmrg    -t)
143adb5514aSmrg        is_target_a_directory=always
144adb5514aSmrg        dst_arg=$2
145adb5514aSmrg        # Protect names problematic for 'test' and other utilities.
146adb5514aSmrg        case $dst_arg in
147adb5514aSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148adb5514aSmrg        esac
149adb5514aSmrg        shift;;
15002be438aSmrg
151adb5514aSmrg    -T) is_target_a_directory=never;;
15202be438aSmrg
15302be438aSmrg    --version) echo "$0 $scriptversion"; exit $?;;
15402be438aSmrg
155adb5514aSmrg    --) shift
156adb5514aSmrg        break;;
157880ed95aSmrg
158adb5514aSmrg    -*) echo "$0: invalid option: $1" >&2
159adb5514aSmrg        exit 1;;
160880ed95aSmrg
161880ed95aSmrg    *)  break;;
16202be438aSmrg  esac
163880ed95aSmrg  shift
16402be438aSmrgdone
16502be438aSmrg
166adb5514aSmrg# We allow the use of options -d and -T together, by making -d
167adb5514aSmrg# take the precedence; this is for compatibility with GNU install.
168adb5514aSmrg
169adb5514aSmrgif test -n "$dir_arg"; then
170adb5514aSmrg  if test -n "$dst_arg"; then
171adb5514aSmrg    echo "$0: target directory not allowed when installing a directory." >&2
172adb5514aSmrg    exit 1
173adb5514aSmrg  fi
174adb5514aSmrgfi
175adb5514aSmrg
176880ed95aSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177880ed95aSmrg  # When -d is used, all remaining arguments are directories to create.
178880ed95aSmrg  # When -t is used, the destination is already specified.
179880ed95aSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180880ed95aSmrg  for arg
181880ed95aSmrg  do
182880ed95aSmrg    if test -n "$dst_arg"; then
183880ed95aSmrg      # $@ is not empty: it contains at least $arg.
184880ed95aSmrg      set fnord "$@" "$dst_arg"
185880ed95aSmrg      shift # fnord
186880ed95aSmrg    fi
187880ed95aSmrg    shift # arg
188880ed95aSmrg    dst_arg=$arg
189e2463426Smrg    # Protect names problematic for 'test' and other utilities.
190909209eeSmrg    case $dst_arg in
191909209eeSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192909209eeSmrg    esac
193880ed95aSmrg  done
194880ed95aSmrgfi
195880ed95aSmrg
196880ed95aSmrgif test $# -eq 0; then
19702be438aSmrg  if test -z "$dir_arg"; then
19802be438aSmrg    echo "$0: no input file specified." >&2
19902be438aSmrg    exit 1
20002be438aSmrg  fi
201e2463426Smrg  # It's OK to call 'install-sh -d' without argument.
20202be438aSmrg  # This can happen when creating conditional directories.
20302be438aSmrg  exit 0
20402be438aSmrgfi
20502be438aSmrg
206adb5514aSmrgif test -z "$dir_arg"; then
207adb5514aSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208adb5514aSmrg    if test ! -d "$dst_arg"; then
209adb5514aSmrg      echo "$0: $dst_arg: Is not a directory." >&2
210adb5514aSmrg      exit 1
211adb5514aSmrg    fi
212adb5514aSmrg  fi
213adb5514aSmrgfi
214adb5514aSmrg
215880ed95aSmrgif test -z "$dir_arg"; then
216909209eeSmrg  do_exit='(exit $ret); exit $ret'
217909209eeSmrg  trap "ret=129; $do_exit" 1
218909209eeSmrg  trap "ret=130; $do_exit" 2
219909209eeSmrg  trap "ret=141; $do_exit" 13
220909209eeSmrg  trap "ret=143; $do_exit" 15
221880ed95aSmrg
222880ed95aSmrg  # Set umask so as not to create temps with too-generous modes.
223880ed95aSmrg  # However, 'strip' requires both read and write access to temps.
224880ed95aSmrg  case $mode in
225880ed95aSmrg    # Optimize common cases.
226880ed95aSmrg    *644) cp_umask=133;;
227880ed95aSmrg    *755) cp_umask=22;;
228880ed95aSmrg
229880ed95aSmrg    *[0-7])
230880ed95aSmrg      if test -z "$stripcmd"; then
231adb5514aSmrg        u_plus_rw=
232880ed95aSmrg      else
233adb5514aSmrg        u_plus_rw='% 200'
234880ed95aSmrg      fi
235880ed95aSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236880ed95aSmrg    *)
237880ed95aSmrg      if test -z "$stripcmd"; then
238adb5514aSmrg        u_plus_rw=
239880ed95aSmrg      else
240adb5514aSmrg        u_plus_rw=,u+rw
241880ed95aSmrg      fi
242880ed95aSmrg      cp_umask=$mode$u_plus_rw;;
243880ed95aSmrg  esac
244880ed95aSmrgfi
245880ed95aSmrg
24602be438aSmrgfor src
24702be438aSmrgdo
248e2463426Smrg  # Protect names problematic for 'test' and other utilities.
24902be438aSmrg  case $src in
250909209eeSmrg    -* | [=\(\)!]) src=./$src;;
25102be438aSmrg  esac
25202be438aSmrg
25302be438aSmrg  if test -n "$dir_arg"; then
25402be438aSmrg    dst=$src
255880ed95aSmrg    dstdir=$dst
256880ed95aSmrg    test -d "$dstdir"
257880ed95aSmrg    dstdir_status=$?
25802be438aSmrg  else
259880ed95aSmrg
26002be438aSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26102be438aSmrg    # might cause directories to be created, which would be especially bad
26202be438aSmrg    # if $src (and thus $dsttmp) contains '*'.
26302be438aSmrg    if test ! -f "$src" && test ! -d "$src"; then
26402be438aSmrg      echo "$0: $src does not exist." >&2
26502be438aSmrg      exit 1
26602be438aSmrg    fi
26702be438aSmrg
268880ed95aSmrg    if test -z "$dst_arg"; then
26902be438aSmrg      echo "$0: no destination specified." >&2
27002be438aSmrg      exit 1
27102be438aSmrg    fi
272880ed95aSmrg    dst=$dst_arg
27302be438aSmrg
27402be438aSmrg    # If destination is a directory, append the input filename; won't work
27502be438aSmrg    # if double slashes aren't ignored.
27602be438aSmrg    if test -d "$dst"; then
277adb5514aSmrg      if test "$is_target_a_directory" = never; then
278adb5514aSmrg        echo "$0: $dst_arg: Is a directory" >&2
279adb5514aSmrg        exit 1
28002be438aSmrg      fi
281880ed95aSmrg      dstdir=$dst
282880ed95aSmrg      dst=$dstdir/`basename "$src"`
283880ed95aSmrg      dstdir_status=0
284880ed95aSmrg    else
285adb5514aSmrg      dstdir=`dirname "$dst"`
286880ed95aSmrg      test -d "$dstdir"
287880ed95aSmrg      dstdir_status=$?
28802be438aSmrg    fi
28902be438aSmrg  fi
29002be438aSmrg
291880ed95aSmrg  obsolete_mkdir_used=false
292880ed95aSmrg
293880ed95aSmrg  if test $dstdir_status != 0; then
294880ed95aSmrg    case $posix_mkdir in
295880ed95aSmrg      '')
296adb5514aSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
297adb5514aSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
298adb5514aSmrg        umask=`umask`
299adb5514aSmrg        case $stripcmd.$umask in
300adb5514aSmrg          # Optimize common cases.
301adb5514aSmrg          *[2367][2367]) mkdir_umask=$umask;;
302adb5514aSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303adb5514aSmrg
304adb5514aSmrg          *[0-7])
305adb5514aSmrg            mkdir_umask=`expr $umask + 22 \
306adb5514aSmrg              - $umask % 100 % 40 + $umask % 20 \
307adb5514aSmrg              - $umask % 10 % 4 + $umask % 2
308adb5514aSmrg            `;;
309adb5514aSmrg          *) mkdir_umask=$umask,go-w;;
310adb5514aSmrg        esac
311adb5514aSmrg
312adb5514aSmrg        # With -d, create the new directory with the user-specified mode.
313adb5514aSmrg        # Otherwise, rely on $mkdir_umask.
314adb5514aSmrg        if test -n "$dir_arg"; then
315adb5514aSmrg          mkdir_mode=-m$mode
316adb5514aSmrg        else
317adb5514aSmrg          mkdir_mode=
318adb5514aSmrg        fi
319adb5514aSmrg
320adb5514aSmrg        posix_mkdir=false
321adb5514aSmrg        case $umask in
322adb5514aSmrg          *[123567][0-7][0-7])
323adb5514aSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
324adb5514aSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325adb5514aSmrg            ;;
326adb5514aSmrg          *)
327f3f7d111Smrg            # $RANDOM is not portable (e.g. dash);  use it when possible to
328f3f7d111Smrg            # lower collision chance
329adb5514aSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
330f3f7d111Smrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
331adb5514aSmrg
332f3f7d111Smrg            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
333f3f7d111Smrg            # create the $tmpdir first (and fail if unsuccessful) to make sure
334f3f7d111Smrg            # that nobody tries to guess the $tmpdir name.
335adb5514aSmrg            if (umask $mkdir_umask &&
336f3f7d111Smrg                $mkdirprog $mkdir_mode "$tmpdir" &&
337f3f7d111Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
338adb5514aSmrg            then
339adb5514aSmrg              if test -z "$dir_arg" || {
340adb5514aSmrg                   # Check for POSIX incompatibilities with -m.
341adb5514aSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
342adb5514aSmrg                   # other-writable bit of parent directory when it shouldn't.
343adb5514aSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
344f3f7d111Smrg                   test_tmpdir="$tmpdir/a"
345f3f7d111Smrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
346adb5514aSmrg                   case $ls_ld_tmpdir in
347adb5514aSmrg                     d????-?r-*) different_mode=700;;
348adb5514aSmrg                     d????-?--*) different_mode=755;;
349adb5514aSmrg                     *) false;;
350adb5514aSmrg                   esac &&
351f3f7d111Smrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
352f3f7d111Smrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
353adb5514aSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
354adb5514aSmrg                   }
355adb5514aSmrg                 }
356adb5514aSmrg              then posix_mkdir=:
357adb5514aSmrg              fi
358f3f7d111Smrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
359adb5514aSmrg            else
360adb5514aSmrg              # Remove any dirs left behind by ancient mkdir implementations.
361f3f7d111Smrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
362adb5514aSmrg            fi
363adb5514aSmrg            trap '' 0;;
364adb5514aSmrg        esac;;
365880ed95aSmrg    esac
36602be438aSmrg
367880ed95aSmrg    if
368880ed95aSmrg      $posix_mkdir && (
369adb5514aSmrg        umask $mkdir_umask &&
370adb5514aSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
371880ed95aSmrg      )
372880ed95aSmrg    then :
373880ed95aSmrg    else
37402be438aSmrg
375880ed95aSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
376880ed95aSmrg      # or it failed possibly due to a race condition.  Create the
377880ed95aSmrg      # directory the slow way, step by step, checking for races as we go.
37802be438aSmrg
379880ed95aSmrg      case $dstdir in
380adb5514aSmrg        /*) prefix='/';;
381adb5514aSmrg        [-=\(\)!]*) prefix='./';;
382adb5514aSmrg        *)  prefix='';;
383880ed95aSmrg      esac
38402be438aSmrg
385880ed95aSmrg      oIFS=$IFS
386880ed95aSmrg      IFS=/
387adb5514aSmrg      set -f
388880ed95aSmrg      set fnord $dstdir
38902be438aSmrg      shift
390adb5514aSmrg      set +f
391880ed95aSmrg      IFS=$oIFS
392880ed95aSmrg
393880ed95aSmrg      prefixes=
394880ed95aSmrg
395880ed95aSmrg      for d
396880ed95aSmrg      do
397adb5514aSmrg        test X"$d" = X && continue
398adb5514aSmrg
399adb5514aSmrg        prefix=$prefix$d
400adb5514aSmrg        if test -d "$prefix"; then
401adb5514aSmrg          prefixes=
402adb5514aSmrg        else
403adb5514aSmrg          if $posix_mkdir; then
404adb5514aSmrg            (umask=$mkdir_umask &&
405adb5514aSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
406adb5514aSmrg            # Don't fail if two instances are running concurrently.
407adb5514aSmrg            test -d "$prefix" || exit 1
408adb5514aSmrg          else
409adb5514aSmrg            case $prefix in
410adb5514aSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
411adb5514aSmrg              *) qprefix=$prefix;;
412adb5514aSmrg            esac
413adb5514aSmrg            prefixes="$prefixes '$qprefix'"
414adb5514aSmrg          fi
415adb5514aSmrg        fi
416adb5514aSmrg        prefix=$prefix/
417880ed95aSmrg      done
418880ed95aSmrg
419880ed95aSmrg      if test -n "$prefixes"; then
420adb5514aSmrg        # Don't fail if two instances are running concurrently.
421adb5514aSmrg        (umask $mkdir_umask &&
422adb5514aSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
423adb5514aSmrg          test -d "$dstdir" || exit 1
424adb5514aSmrg        obsolete_mkdir_used=true
42502be438aSmrg      fi
426880ed95aSmrg    fi
42702be438aSmrg  fi
42802be438aSmrg
42902be438aSmrg  if test -n "$dir_arg"; then
430880ed95aSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
431880ed95aSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
432880ed95aSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
433880ed95aSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
43402be438aSmrg  else
43502be438aSmrg
43602be438aSmrg    # Make a couple of temp file names in the proper directory.
43702be438aSmrg    dsttmp=$dstdir/_inst.$$_
43802be438aSmrg    rmtmp=$dstdir/_rm.$$_
43902be438aSmrg
44002be438aSmrg    # Trap to clean up those temp files at exit.
44102be438aSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
44202be438aSmrg
44302be438aSmrg    # Copy the file name to the temp name.
444880ed95aSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
44502be438aSmrg
44602be438aSmrg    # and set any options; do chmod last to preserve setuid bits.
44702be438aSmrg    #
44802be438aSmrg    # If any of these fail, we abort the whole thing.  If we want to
44902be438aSmrg    # ignore errors from any of these, just make sure not to ignore
45002be438aSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
45102be438aSmrg    #
452880ed95aSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
453880ed95aSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
454880ed95aSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
455880ed95aSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
456880ed95aSmrg
457880ed95aSmrg    # If -C, don't bother to copy if it wouldn't change the file.
458880ed95aSmrg    if $copy_on_change &&
459adb5514aSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
460adb5514aSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
461adb5514aSmrg       set -f &&
462880ed95aSmrg       set X $old && old=:$2:$4:$5:$6 &&
463880ed95aSmrg       set X $new && new=:$2:$4:$5:$6 &&
464adb5514aSmrg       set +f &&
465880ed95aSmrg       test "$old" = "$new" &&
466880ed95aSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
467880ed95aSmrg    then
468880ed95aSmrg      rm -f "$dsttmp"
469880ed95aSmrg    else
470880ed95aSmrg      # Rename the file to the real destination.
471880ed95aSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
472880ed95aSmrg
473880ed95aSmrg      # The rename failed, perhaps because mv can't rename something else
474880ed95aSmrg      # to itself, or perhaps because mv is so ancient that it does not
475880ed95aSmrg      # support -f.
476880ed95aSmrg      {
477adb5514aSmrg        # Now remove or move aside any old file at destination location.
478adb5514aSmrg        # We try this two ways since rm can't unlink itself on some
479adb5514aSmrg        # systems and the destination file might be busy for other
480adb5514aSmrg        # reasons.  In this case, the final cleanup might fail but the new
481adb5514aSmrg        # file should still install successfully.
482adb5514aSmrg        {
483adb5514aSmrg          test ! -f "$dst" ||
484adb5514aSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
485adb5514aSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
486adb5514aSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
487adb5514aSmrg          } ||
488adb5514aSmrg          { echo "$0: cannot unlink or rename $dst" >&2
489adb5514aSmrg            (exit 1); exit 1
490adb5514aSmrg          }
491adb5514aSmrg        } &&
492adb5514aSmrg
493adb5514aSmrg        # Now rename the file to the real destination.
494adb5514aSmrg        $doit $mvcmd "$dsttmp" "$dst"
495880ed95aSmrg      }
496880ed95aSmrg    fi || exit 1
497880ed95aSmrg
498880ed95aSmrg    trap '' 0
499880ed95aSmrg  fi
50002be438aSmrgdone
50102be438aSmrg
50202be438aSmrg# Local variables:
50302be438aSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
50402be438aSmrg# time-stamp-start: "scriptversion="
50502be438aSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
50661dc2d86Smrg# time-stamp-time-zone: "UTC"
50761dc2d86Smrg# time-stamp-end: "; # UTC"
50802be438aSmrg# End:
509