1876ff6feSmrg#!/bin/sh
2876ff6feSmrg# install - install a program, script, or datafile
3876ff6feSmrg
4d41660beSmrgscriptversion=2016-01-11.22; # UTC
5876ff6feSmrg
6876ff6feSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7876ff6feSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8876ff6feSmrg# following copyright and license.
9876ff6feSmrg#
10876ff6feSmrg# Copyright (C) 1994 X Consortium
11876ff6feSmrg#
12876ff6feSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13876ff6feSmrg# of this software and associated documentation files (the "Software"), to
14876ff6feSmrg# deal in the Software without restriction, including without limitation the
15876ff6feSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16876ff6feSmrg# sell copies of the Software, and to permit persons to whom the Software is
17876ff6feSmrg# furnished to do so, subject to the following conditions:
18876ff6feSmrg#
19876ff6feSmrg# The above copyright notice and this permission notice shall be included in
20876ff6feSmrg# all copies or substantial portions of the Software.
21876ff6feSmrg#
22876ff6feSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23876ff6feSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24876ff6feSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25876ff6feSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26876ff6feSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27876ff6feSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28876ff6feSmrg#
29876ff6feSmrg# Except as contained in this notice, the name of the X Consortium shall not
30876ff6feSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31876ff6feSmrg# ings in this Software without prior written authorization from the X Consor-
32876ff6feSmrg# tium.
33876ff6feSmrg#
34876ff6feSmrg#
35876ff6feSmrg# FSF changes to this file are in the public domain.
36876ff6feSmrg#
37876ff6feSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38d41660beSmrg# 'make' implicit rules from creating a file called install from it
39876ff6feSmrg# when there is no Makefile.
40876ff6feSmrg#
41876ff6feSmrg# This script is compatible with the BSD install script, but was written
42d41660beSmrg# from scratch.
43876ff6feSmrg
44d41660beSmrgtab='	'
45d41660beSmrgnl='
46d41660beSmrg'
47d41660beSmrgIFS=" $tab$nl"
48876ff6feSmrg
49d41660beSmrg# Set DOITPROG to "echo" to test this script.
50876ff6feSmrg
51d41660beSmrgdoit=${DOITPROG-}
52d41660beSmrgdoit_exec=${doit:-exec}
53876ff6feSmrg
54d41660beSmrg# Put in absolute file names if you don't have them in your path;
55d41660beSmrg# or use environment vars.
56d41660beSmrg
57d41660beSmrgchgrpprog=${CHGRPPROG-chgrp}
58d41660beSmrgchmodprog=${CHMODPROG-chmod}
59d41660beSmrgchownprog=${CHOWNPROG-chown}
60d41660beSmrgcmpprog=${CMPPROG-cmp}
61d41660beSmrgcpprog=${CPPROG-cp}
62d41660beSmrgmkdirprog=${MKDIRPROG-mkdir}
63d41660beSmrgmvprog=${MVPROG-mv}
64d41660beSmrgrmprog=${RMPROG-rm}
65d41660beSmrgstripprog=${STRIPPROG-strip}
66d41660beSmrg
67d41660beSmrgposix_mkdir=
68d41660beSmrg
69d41660beSmrg# Desired mode of installed file.
70d41660beSmrgmode=0755
71876ff6feSmrg
72876ff6feSmrgchgrpcmd=
73d41660beSmrgchmodcmd=$chmodprog
74d41660beSmrgchowncmd=
75d41660beSmrgmvcmd=$mvprog
76876ff6feSmrgrmcmd="$rmprog -f"
77d41660beSmrgstripcmd=
78d41660beSmrg
79876ff6feSmrgsrc=
80876ff6feSmrgdst=
81876ff6feSmrgdir_arg=
82d41660beSmrgdst_arg=
83d41660beSmrg
84d41660beSmrgcopy_on_change=false
85d41660beSmrgis_target_a_directory=possibly
86876ff6feSmrg
87d41660beSmrgusage="\
88d41660beSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89876ff6feSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90876ff6feSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91876ff6feSmrg   or: $0 [OPTION]... -d DIRECTORIES...
92876ff6feSmrg
93876ff6feSmrgIn the 1st form, copy SRCFILE to DSTFILE.
94876ff6feSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95876ff6feSmrgIn the 4th, create DIRECTORIES.
96876ff6feSmrg
97876ff6feSmrgOptions:
98d41660beSmrg     --help     display this help and exit.
99d41660beSmrg     --version  display version info and exit.
100d41660beSmrg
101d41660beSmrg  -c            (ignored)
102d41660beSmrg  -C            install only if different (preserve the last data modification time)
103d41660beSmrg  -d            create directories instead of installing files.
104d41660beSmrg  -g GROUP      $chgrpprog installed files to GROUP.
105d41660beSmrg  -m MODE       $chmodprog installed files to MODE.
106d41660beSmrg  -o USER       $chownprog installed files to USER.
107d41660beSmrg  -s            $stripprog installed files.
108d41660beSmrg  -t DIRECTORY  install into DIRECTORY.
109d41660beSmrg  -T            report an error if DSTFILE is a directory.
110876ff6feSmrg
111876ff6feSmrgEnvironment variables override the default commands:
112d41660beSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113d41660beSmrg  RMPROG STRIPPROG
114876ff6feSmrg"
115876ff6feSmrg
116d41660beSmrgwhile test $# -ne 0; do
117876ff6feSmrg  case $1 in
118d41660beSmrg    -c) ;;
119876ff6feSmrg
120d41660beSmrg    -C) copy_on_change=true;;
121d41660beSmrg
122d41660beSmrg    -d) dir_arg=true;;
123876ff6feSmrg
124876ff6feSmrg    -g) chgrpcmd="$chgrpprog $2"
125d41660beSmrg        shift;;
126876ff6feSmrg
127876ff6feSmrg    --help) echo "$usage"; exit $?;;
128876ff6feSmrg
129d41660beSmrg    -m) mode=$2
130d41660beSmrg        case $mode in
131d41660beSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132d41660beSmrg            echo "$0: invalid mode: $mode" >&2
133d41660beSmrg            exit 1;;
134d41660beSmrg        esac
135d41660beSmrg        shift;;
136876ff6feSmrg
137876ff6feSmrg    -o) chowncmd="$chownprog $2"
138d41660beSmrg        shift;;
139876ff6feSmrg
140d41660beSmrg    -s) stripcmd=$stripprog;;
141876ff6feSmrg
142d41660beSmrg    -t)
143d41660beSmrg        is_target_a_directory=always
144d41660beSmrg        dst_arg=$2
145d41660beSmrg        # Protect names problematic for 'test' and other utilities.
146d41660beSmrg        case $dst_arg in
147d41660beSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148d41660beSmrg        esac
149d41660beSmrg        shift;;
150876ff6feSmrg
151d41660beSmrg    -T) is_target_a_directory=never;;
152876ff6feSmrg
153876ff6feSmrg    --version) echo "$0 $scriptversion"; exit $?;;
154876ff6feSmrg
155d41660beSmrg    --) shift
156d41660beSmrg        break;;
157d41660beSmrg
158d41660beSmrg    -*) echo "$0: invalid option: $1" >&2
159d41660beSmrg        exit 1;;
160d41660beSmrg
161d41660beSmrg    *)  break;;
162876ff6feSmrg  esac
163d41660beSmrg  shift
164876ff6feSmrgdone
165876ff6feSmrg
166d41660beSmrg# We allow the use of options -d and -T together, by making -d
167d41660beSmrg# take the precedence; this is for compatibility with GNU install.
168d41660beSmrg
169d41660beSmrgif test -n "$dir_arg"; then
170d41660beSmrg  if test -n "$dst_arg"; then
171d41660beSmrg    echo "$0: target directory not allowed when installing a directory." >&2
172d41660beSmrg    exit 1
173d41660beSmrg  fi
174d41660beSmrgfi
175d41660beSmrg
176d41660beSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177d41660beSmrg  # When -d is used, all remaining arguments are directories to create.
178d41660beSmrg  # When -t is used, the destination is already specified.
179d41660beSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180d41660beSmrg  for arg
181d41660beSmrg  do
182d41660beSmrg    if test -n "$dst_arg"; then
183d41660beSmrg      # $@ is not empty: it contains at least $arg.
184d41660beSmrg      set fnord "$@" "$dst_arg"
185d41660beSmrg      shift # fnord
186d41660beSmrg    fi
187d41660beSmrg    shift # arg
188d41660beSmrg    dst_arg=$arg
189d41660beSmrg    # Protect names problematic for 'test' and other utilities.
190d41660beSmrg    case $dst_arg in
191d41660beSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192d41660beSmrg    esac
193d41660beSmrg  done
194d41660beSmrgfi
195d41660beSmrg
196d41660beSmrgif test $# -eq 0; then
197876ff6feSmrg  if test -z "$dir_arg"; then
198876ff6feSmrg    echo "$0: no input file specified." >&2
199876ff6feSmrg    exit 1
200876ff6feSmrg  fi
201d41660beSmrg  # It's OK to call 'install-sh -d' without argument.
202876ff6feSmrg  # This can happen when creating conditional directories.
203876ff6feSmrg  exit 0
204876ff6feSmrgfi
205876ff6feSmrg
206d41660beSmrgif test -z "$dir_arg"; then
207d41660beSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208d41660beSmrg    if test ! -d "$dst_arg"; then
209d41660beSmrg      echo "$0: $dst_arg: Is not a directory." >&2
210d41660beSmrg      exit 1
211d41660beSmrg    fi
212d41660beSmrg  fi
213d41660beSmrgfi
214d41660beSmrg
215d41660beSmrgif test -z "$dir_arg"; then
216d41660beSmrg  do_exit='(exit $ret); exit $ret'
217d41660beSmrg  trap "ret=129; $do_exit" 1
218d41660beSmrg  trap "ret=130; $do_exit" 2
219d41660beSmrg  trap "ret=141; $do_exit" 13
220d41660beSmrg  trap "ret=143; $do_exit" 15
221d41660beSmrg
222d41660beSmrg  # Set umask so as not to create temps with too-generous modes.
223d41660beSmrg  # However, 'strip' requires both read and write access to temps.
224d41660beSmrg  case $mode in
225d41660beSmrg    # Optimize common cases.
226d41660beSmrg    *644) cp_umask=133;;
227d41660beSmrg    *755) cp_umask=22;;
228d41660beSmrg
229d41660beSmrg    *[0-7])
230d41660beSmrg      if test -z "$stripcmd"; then
231d41660beSmrg        u_plus_rw=
232d41660beSmrg      else
233d41660beSmrg        u_plus_rw='% 200'
234d41660beSmrg      fi
235d41660beSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236d41660beSmrg    *)
237d41660beSmrg      if test -z "$stripcmd"; then
238d41660beSmrg        u_plus_rw=
239d41660beSmrg      else
240d41660beSmrg        u_plus_rw=,u+rw
241d41660beSmrg      fi
242d41660beSmrg      cp_umask=$mode$u_plus_rw;;
243d41660beSmrg  esac
244d41660beSmrgfi
245d41660beSmrg
246876ff6feSmrgfor src
247876ff6feSmrgdo
248d41660beSmrg  # Protect names problematic for 'test' and other utilities.
249876ff6feSmrg  case $src in
250d41660beSmrg    -* | [=\(\)!]) src=./$src;;
251876ff6feSmrg  esac
252876ff6feSmrg
253876ff6feSmrg  if test -n "$dir_arg"; then
254876ff6feSmrg    dst=$src
255d41660beSmrg    dstdir=$dst
256d41660beSmrg    test -d "$dstdir"
257d41660beSmrg    dstdir_status=$?
258876ff6feSmrg  else
259d41660beSmrg
260876ff6feSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261876ff6feSmrg    # might cause directories to be created, which would be especially bad
262876ff6feSmrg    # if $src (and thus $dsttmp) contains '*'.
263876ff6feSmrg    if test ! -f "$src" && test ! -d "$src"; then
264876ff6feSmrg      echo "$0: $src does not exist." >&2
265876ff6feSmrg      exit 1
266876ff6feSmrg    fi
267876ff6feSmrg
268d41660beSmrg    if test -z "$dst_arg"; then
269876ff6feSmrg      echo "$0: no destination specified." >&2
270876ff6feSmrg      exit 1
271876ff6feSmrg    fi
272d41660beSmrg    dst=$dst_arg
273876ff6feSmrg
274876ff6feSmrg    # If destination is a directory, append the input filename; won't work
275876ff6feSmrg    # if double slashes aren't ignored.
276876ff6feSmrg    if test -d "$dst"; then
277d41660beSmrg      if test "$is_target_a_directory" = never; then
278d41660beSmrg        echo "$0: $dst_arg: Is a directory" >&2
279d41660beSmrg        exit 1
280876ff6feSmrg      fi
281d41660beSmrg      dstdir=$dst
282d41660beSmrg      dst=$dstdir/`basename "$src"`
283d41660beSmrg      dstdir_status=0
284d41660beSmrg    else
285d41660beSmrg      dstdir=`dirname "$dst"`
286d41660beSmrg      test -d "$dstdir"
287d41660beSmrg      dstdir_status=$?
288876ff6feSmrg    fi
289876ff6feSmrg  fi
290876ff6feSmrg
291d41660beSmrg  obsolete_mkdir_used=false
292d41660beSmrg
293d41660beSmrg  if test $dstdir_status != 0; then
294d41660beSmrg    case $posix_mkdir in
295d41660beSmrg      '')
296d41660beSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
297d41660beSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
298d41660beSmrg        umask=`umask`
299d41660beSmrg        case $stripcmd.$umask in
300d41660beSmrg          # Optimize common cases.
301d41660beSmrg          *[2367][2367]) mkdir_umask=$umask;;
302d41660beSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303d41660beSmrg
304d41660beSmrg          *[0-7])
305d41660beSmrg            mkdir_umask=`expr $umask + 22 \
306d41660beSmrg              - $umask % 100 % 40 + $umask % 20 \
307d41660beSmrg              - $umask % 10 % 4 + $umask % 2
308d41660beSmrg            `;;
309d41660beSmrg          *) mkdir_umask=$umask,go-w;;
310d41660beSmrg        esac
311d41660beSmrg
312d41660beSmrg        # With -d, create the new directory with the user-specified mode.
313d41660beSmrg        # Otherwise, rely on $mkdir_umask.
314d41660beSmrg        if test -n "$dir_arg"; then
315d41660beSmrg          mkdir_mode=-m$mode
316d41660beSmrg        else
317d41660beSmrg          mkdir_mode=
318d41660beSmrg        fi
319d41660beSmrg
320d41660beSmrg        posix_mkdir=false
321d41660beSmrg        case $umask in
322d41660beSmrg          *[123567][0-7][0-7])
323d41660beSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
324d41660beSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325d41660beSmrg            ;;
326d41660beSmrg          *)
327d41660beSmrg            # $RANDOM is not portable (e.g. dash);  use it when possible to
328d41660beSmrg            # lower collision chance
329d41660beSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
330d41660beSmrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
331d41660beSmrg
332d41660beSmrg            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
333d41660beSmrg            # create the $tmpdir first (and fail if unsuccessful) to make sure
334d41660beSmrg            # that nobody tries to guess the $tmpdir name.
335d41660beSmrg            if (umask $mkdir_umask &&
336d41660beSmrg                $mkdirprog $mkdir_mode "$tmpdir" &&
337d41660beSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
338d41660beSmrg            then
339d41660beSmrg              if test -z "$dir_arg" || {
340d41660beSmrg                   # Check for POSIX incompatibilities with -m.
341d41660beSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
342d41660beSmrg                   # other-writable bit of parent directory when it shouldn't.
343d41660beSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
344d41660beSmrg                   test_tmpdir="$tmpdir/a"
345d41660beSmrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
346d41660beSmrg                   case $ls_ld_tmpdir in
347d41660beSmrg                     d????-?r-*) different_mode=700;;
348d41660beSmrg                     d????-?--*) different_mode=755;;
349d41660beSmrg                     *) false;;
350d41660beSmrg                   esac &&
351d41660beSmrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
352d41660beSmrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
353d41660beSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
354d41660beSmrg                   }
355d41660beSmrg                 }
356d41660beSmrg              then posix_mkdir=:
357d41660beSmrg              fi
358d41660beSmrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
359d41660beSmrg            else
360d41660beSmrg              # Remove any dirs left behind by ancient mkdir implementations.
361d41660beSmrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
362d41660beSmrg            fi
363d41660beSmrg            trap '' 0;;
364d41660beSmrg        esac;;
365d41660beSmrg    esac
366876ff6feSmrg
367d41660beSmrg    if
368d41660beSmrg      $posix_mkdir && (
369d41660beSmrg        umask $mkdir_umask &&
370d41660beSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
371d41660beSmrg      )
372d41660beSmrg    then :
373d41660beSmrg    else
374876ff6feSmrg
375d41660beSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
376d41660beSmrg      # or it failed possibly due to a race condition.  Create the
377d41660beSmrg      # directory the slow way, step by step, checking for races as we go.
378876ff6feSmrg
379d41660beSmrg      case $dstdir in
380d41660beSmrg        /*) prefix='/';;
381d41660beSmrg        [-=\(\)!]*) prefix='./';;
382d41660beSmrg        *)  prefix='';;
383d41660beSmrg      esac
384876ff6feSmrg
385d41660beSmrg      oIFS=$IFS
386d41660beSmrg      IFS=/
387d41660beSmrg      set -f
388d41660beSmrg      set fnord $dstdir
389876ff6feSmrg      shift
390d41660beSmrg      set +f
391d41660beSmrg      IFS=$oIFS
392d41660beSmrg
393d41660beSmrg      prefixes=
394d41660beSmrg
395d41660beSmrg      for d
396d41660beSmrg      do
397d41660beSmrg        test X"$d" = X && continue
398d41660beSmrg
399d41660beSmrg        prefix=$prefix$d
400d41660beSmrg        if test -d "$prefix"; then
401d41660beSmrg          prefixes=
402d41660beSmrg        else
403d41660beSmrg          if $posix_mkdir; then
404d41660beSmrg            (umask=$mkdir_umask &&
405d41660beSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
406d41660beSmrg            # Don't fail if two instances are running concurrently.
407d41660beSmrg            test -d "$prefix" || exit 1
408d41660beSmrg          else
409d41660beSmrg            case $prefix in
410d41660beSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
411d41660beSmrg              *) qprefix=$prefix;;
412d41660beSmrg            esac
413d41660beSmrg            prefixes="$prefixes '$qprefix'"
414d41660beSmrg          fi
415d41660beSmrg        fi
416d41660beSmrg        prefix=$prefix/
417d41660beSmrg      done
418d41660beSmrg
419d41660beSmrg      if test -n "$prefixes"; then
420d41660beSmrg        # Don't fail if two instances are running concurrently.
421d41660beSmrg        (umask $mkdir_umask &&
422d41660beSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
423d41660beSmrg          test -d "$dstdir" || exit 1
424d41660beSmrg        obsolete_mkdir_used=true
425876ff6feSmrg      fi
426d41660beSmrg    fi
427876ff6feSmrg  fi
428876ff6feSmrg
429876ff6feSmrg  if test -n "$dir_arg"; then
430d41660beSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
431d41660beSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
432d41660beSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
433d41660beSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
434876ff6feSmrg  else
435876ff6feSmrg
436876ff6feSmrg    # Make a couple of temp file names in the proper directory.
437876ff6feSmrg    dsttmp=$dstdir/_inst.$$_
438876ff6feSmrg    rmtmp=$dstdir/_rm.$$_
439876ff6feSmrg
440876ff6feSmrg    # Trap to clean up those temp files at exit.
441876ff6feSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
442876ff6feSmrg
443876ff6feSmrg    # Copy the file name to the temp name.
444d41660beSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
445876ff6feSmrg
446876ff6feSmrg    # and set any options; do chmod last to preserve setuid bits.
447876ff6feSmrg    #
448876ff6feSmrg    # If any of these fail, we abort the whole thing.  If we want to
449876ff6feSmrg    # ignore errors from any of these, just make sure not to ignore
450876ff6feSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
451876ff6feSmrg    #
452d41660beSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
453d41660beSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
454d41660beSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
455d41660beSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
456d41660beSmrg
457d41660beSmrg    # If -C, don't bother to copy if it wouldn't change the file.
458d41660beSmrg    if $copy_on_change &&
459d41660beSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
460d41660beSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
461d41660beSmrg       set -f &&
462d41660beSmrg       set X $old && old=:$2:$4:$5:$6 &&
463d41660beSmrg       set X $new && new=:$2:$4:$5:$6 &&
464d41660beSmrg       set +f &&
465d41660beSmrg       test "$old" = "$new" &&
466d41660beSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
467d41660beSmrg    then
468d41660beSmrg      rm -f "$dsttmp"
469d41660beSmrg    else
470d41660beSmrg      # Rename the file to the real destination.
471d41660beSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
472d41660beSmrg
473d41660beSmrg      # The rename failed, perhaps because mv can't rename something else
474d41660beSmrg      # to itself, or perhaps because mv is so ancient that it does not
475d41660beSmrg      # support -f.
476d41660beSmrg      {
477d41660beSmrg        # Now remove or move aside any old file at destination location.
478d41660beSmrg        # We try this two ways since rm can't unlink itself on some
479d41660beSmrg        # systems and the destination file might be busy for other
480d41660beSmrg        # reasons.  In this case, the final cleanup might fail but the new
481d41660beSmrg        # file should still install successfully.
482d41660beSmrg        {
483d41660beSmrg          test ! -f "$dst" ||
484d41660beSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
485d41660beSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
486d41660beSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
487d41660beSmrg          } ||
488d41660beSmrg          { echo "$0: cannot unlink or rename $dst" >&2
489d41660beSmrg            (exit 1); exit 1
490d41660beSmrg          }
491d41660beSmrg        } &&
492d41660beSmrg
493d41660beSmrg        # Now rename the file to the real destination.
494d41660beSmrg        $doit $mvcmd "$dsttmp" "$dst"
495d41660beSmrg      }
496d41660beSmrg    fi || exit 1
497d41660beSmrg
498d41660beSmrg    trap '' 0
499d41660beSmrg  fi
500876ff6feSmrgdone
501876ff6feSmrg
502876ff6feSmrg# Local variables:
503876ff6feSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
504876ff6feSmrg# time-stamp-start: "scriptversion="
505876ff6feSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
506d41660beSmrg# time-stamp-time-zone: "UTC0"
507d41660beSmrg# time-stamp-end: "; # UTC"
508876ff6feSmrg# End:
509