install-sh revision 298453a4
1ba6a1819Smrg#!/bin/sh
2ba6a1819Smrg# install - install a program, script, or datafile
3ba6a1819Smrg
4298453a4Smrgscriptversion=2013-12-25.23; # UTC
5ba6a1819Smrg
6ba6a1819Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7ba6a1819Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8ba6a1819Smrg# following copyright and license.
9ba6a1819Smrg#
10ba6a1819Smrg# Copyright (C) 1994 X Consortium
11ba6a1819Smrg#
12ba6a1819Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13ba6a1819Smrg# of this software and associated documentation files (the "Software"), to
14ba6a1819Smrg# deal in the Software without restriction, including without limitation the
15ba6a1819Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16ba6a1819Smrg# sell copies of the Software, and to permit persons to whom the Software is
17ba6a1819Smrg# furnished to do so, subject to the following conditions:
18ba6a1819Smrg#
19ba6a1819Smrg# The above copyright notice and this permission notice shall be included in
20ba6a1819Smrg# all copies or substantial portions of the Software.
21ba6a1819Smrg#
22ba6a1819Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23ba6a1819Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24ba6a1819Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25ba6a1819Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26ba6a1819Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27ba6a1819Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28ba6a1819Smrg#
29ba6a1819Smrg# Except as contained in this notice, the name of the X Consortium shall not
30ba6a1819Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31ba6a1819Smrg# ings in this Software without prior written authorization from the X Consor-
32ba6a1819Smrg# tium.
33ba6a1819Smrg#
34ba6a1819Smrg#
35ba6a1819Smrg# FSF changes to this file are in the public domain.
36ba6a1819Smrg#
37ba6a1819Smrg# Calling this script install-sh is preferred over install.sh, to prevent
381bedbe3fSmrg# 'make' implicit rules from creating a file called install from it
39ba6a1819Smrg# when there is no Makefile.
40ba6a1819Smrg#
41ba6a1819Smrg# This script is compatible with the BSD install script, but was written
42ba6a1819Smrg# from scratch.
43ba6a1819Smrg
44298453a4Smrgtab='	'
45ba6a1819Smrgnl='
46ba6a1819Smrg'
47298453a4SmrgIFS=" $tab$nl"
48ba6a1819Smrg
49298453a4Smrg# Set DOITPROG to "echo" to test this script.
50ba6a1819Smrg
51549e21daSmrgdoit=${DOITPROG-}
52298453a4Smrgdoit_exec=${doit:-exec}
53ba6a1819Smrg
54ba6a1819Smrg# Put in absolute file names if you don't have them in your path;
55ba6a1819Smrg# or use environment vars.
56ba6a1819Smrg
57549e21daSmrgchgrpprog=${CHGRPPROG-chgrp}
58549e21daSmrgchmodprog=${CHMODPROG-chmod}
59549e21daSmrgchownprog=${CHOWNPROG-chown}
60549e21daSmrgcmpprog=${CMPPROG-cmp}
61549e21daSmrgcpprog=${CPPROG-cp}
62549e21daSmrgmkdirprog=${MKDIRPROG-mkdir}
63549e21daSmrgmvprog=${MVPROG-mv}
64549e21daSmrgrmprog=${RMPROG-rm}
65549e21daSmrgstripprog=${STRIPPROG-strip}
66549e21daSmrg
67ba6a1819Smrgposix_mkdir=
68ba6a1819Smrg
69ba6a1819Smrg# Desired mode of installed file.
70ba6a1819Smrgmode=0755
71ba6a1819Smrg
72549e21daSmrgchgrpcmd=
73ba6a1819Smrgchmodcmd=$chmodprog
74ba6a1819Smrgchowncmd=
75549e21daSmrgmvcmd=$mvprog
76ba6a1819Smrgrmcmd="$rmprog -f"
77549e21daSmrgstripcmd=
78549e21daSmrg
79ba6a1819Smrgsrc=
80ba6a1819Smrgdst=
81ba6a1819Smrgdir_arg=
82549e21daSmrgdst_arg=
83549e21daSmrg
84549e21daSmrgcopy_on_change=false
85298453a4Smrgis_target_a_directory=possibly
86ba6a1819Smrg
87549e21daSmrgusage="\
88549e21daSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89ba6a1819Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90ba6a1819Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91ba6a1819Smrg   or: $0 [OPTION]... -d DIRECTORIES...
92ba6a1819Smrg
93ba6a1819SmrgIn the 1st form, copy SRCFILE to DSTFILE.
94ba6a1819SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95ba6a1819SmrgIn the 4th, create DIRECTORIES.
96ba6a1819Smrg
97ba6a1819SmrgOptions:
98549e21daSmrg     --help     display this help and exit.
99549e21daSmrg     --version  display version info and exit.
100549e21daSmrg
101549e21daSmrg  -c            (ignored)
102549e21daSmrg  -C            install only if different (preserve the last data modification time)
103549e21daSmrg  -d            create directories instead of installing files.
104549e21daSmrg  -g GROUP      $chgrpprog installed files to GROUP.
105549e21daSmrg  -m MODE       $chmodprog installed files to MODE.
106549e21daSmrg  -o USER       $chownprog installed files to USER.
107549e21daSmrg  -s            $stripprog installed files.
108549e21daSmrg  -t DIRECTORY  install into DIRECTORY.
109549e21daSmrg  -T            report an error if DSTFILE is a directory.
110ba6a1819Smrg
111ba6a1819SmrgEnvironment variables override the default commands:
112549e21daSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113549e21daSmrg  RMPROG STRIPPROG
114ba6a1819Smrg"
115ba6a1819Smrg
116ba6a1819Smrgwhile test $# -ne 0; do
117ba6a1819Smrg  case $1 in
118549e21daSmrg    -c) ;;
119549e21daSmrg
120549e21daSmrg    -C) copy_on_change=true;;
121ba6a1819Smrg
122549e21daSmrg    -d) dir_arg=true;;
123ba6a1819Smrg
124ba6a1819Smrg    -g) chgrpcmd="$chgrpprog $2"
125298453a4Smrg        shift;;
126ba6a1819Smrg
127ba6a1819Smrg    --help) echo "$usage"; exit $?;;
128ba6a1819Smrg
129ba6a1819Smrg    -m) mode=$2
130298453a4Smrg        case $mode in
131298453a4Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132298453a4Smrg            echo "$0: invalid mode: $mode" >&2
133298453a4Smrg            exit 1;;
134298453a4Smrg        esac
135298453a4Smrg        shift;;
136ba6a1819Smrg
137ba6a1819Smrg    -o) chowncmd="$chownprog $2"
138298453a4Smrg        shift;;
139ba6a1819Smrg
140549e21daSmrg    -s) stripcmd=$stripprog;;
141ba6a1819Smrg
142298453a4Smrg    -t)
143298453a4Smrg        is_target_a_directory=always
144298453a4Smrg        dst_arg=$2
145298453a4Smrg        # Protect names problematic for 'test' and other utilities.
146298453a4Smrg        case $dst_arg in
147298453a4Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148298453a4Smrg        esac
149298453a4Smrg        shift;;
150ba6a1819Smrg
151298453a4Smrg    -T) is_target_a_directory=never;;
152ba6a1819Smrg
153ba6a1819Smrg    --version) echo "$0 $scriptversion"; exit $?;;
154ba6a1819Smrg
155298453a4Smrg    --) shift
156298453a4Smrg        break;;
157ba6a1819Smrg
158298453a4Smrg    -*) echo "$0: invalid option: $1" >&2
159298453a4Smrg        exit 1;;
160ba6a1819Smrg
161ba6a1819Smrg    *)  break;;
162ba6a1819Smrg  esac
163549e21daSmrg  shift
164ba6a1819Smrgdone
165ba6a1819Smrg
166298453a4Smrg# We allow the use of options -d and -T together, by making -d
167298453a4Smrg# take the precedence; this is for compatibility with GNU install.
168298453a4Smrg
169298453a4Smrgif test -n "$dir_arg"; then
170298453a4Smrg  if test -n "$dst_arg"; then
171298453a4Smrg    echo "$0: target directory not allowed when installing a directory." >&2
172298453a4Smrg    exit 1
173298453a4Smrg  fi
174298453a4Smrgfi
175298453a4Smrg
176549e21daSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177ba6a1819Smrg  # When -d is used, all remaining arguments are directories to create.
178ba6a1819Smrg  # When -t is used, the destination is already specified.
179ba6a1819Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180ba6a1819Smrg  for arg
181ba6a1819Smrg  do
182549e21daSmrg    if test -n "$dst_arg"; then
183ba6a1819Smrg      # $@ is not empty: it contains at least $arg.
184549e21daSmrg      set fnord "$@" "$dst_arg"
185ba6a1819Smrg      shift # fnord
186ba6a1819Smrg    fi
187ba6a1819Smrg    shift # arg
188549e21daSmrg    dst_arg=$arg
1891bedbe3fSmrg    # Protect names problematic for 'test' and other utilities.
1901bedbe3fSmrg    case $dst_arg in
1911bedbe3fSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
1921bedbe3fSmrg    esac
193ba6a1819Smrg  done
194ba6a1819Smrgfi
195ba6a1819Smrg
196ba6a1819Smrgif test $# -eq 0; then
197ba6a1819Smrg  if test -z "$dir_arg"; then
198ba6a1819Smrg    echo "$0: no input file specified." >&2
199ba6a1819Smrg    exit 1
200ba6a1819Smrg  fi
2011bedbe3fSmrg  # It's OK to call 'install-sh -d' without argument.
202ba6a1819Smrg  # This can happen when creating conditional directories.
203ba6a1819Smrg  exit 0
204ba6a1819Smrgfi
205ba6a1819Smrg
206298453a4Smrgif test -z "$dir_arg"; then
207298453a4Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208298453a4Smrg    if test ! -d "$dst_arg"; then
209298453a4Smrg      echo "$0: $dst_arg: Is not a directory." >&2
210298453a4Smrg      exit 1
211298453a4Smrg    fi
212298453a4Smrg  fi
213298453a4Smrgfi
214298453a4Smrg
215ba6a1819Smrgif test -z "$dir_arg"; then
2161bedbe3fSmrg  do_exit='(exit $ret); exit $ret'
2171bedbe3fSmrg  trap "ret=129; $do_exit" 1
2181bedbe3fSmrg  trap "ret=130; $do_exit" 2
2191bedbe3fSmrg  trap "ret=141; $do_exit" 13
2201bedbe3fSmrg  trap "ret=143; $do_exit" 15
221ba6a1819Smrg
222ba6a1819Smrg  # Set umask so as not to create temps with too-generous modes.
223ba6a1819Smrg  # However, 'strip' requires both read and write access to temps.
224ba6a1819Smrg  case $mode in
225ba6a1819Smrg    # Optimize common cases.
226ba6a1819Smrg    *644) cp_umask=133;;
227ba6a1819Smrg    *755) cp_umask=22;;
228ba6a1819Smrg
229ba6a1819Smrg    *[0-7])
230ba6a1819Smrg      if test -z "$stripcmd"; then
231298453a4Smrg        u_plus_rw=
232ba6a1819Smrg      else
233298453a4Smrg        u_plus_rw='% 200'
234ba6a1819Smrg      fi
235ba6a1819Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236ba6a1819Smrg    *)
237ba6a1819Smrg      if test -z "$stripcmd"; then
238298453a4Smrg        u_plus_rw=
239ba6a1819Smrg      else
240298453a4Smrg        u_plus_rw=,u+rw
241ba6a1819Smrg      fi
242ba6a1819Smrg      cp_umask=$mode$u_plus_rw;;
243ba6a1819Smrg  esac
244ba6a1819Smrgfi
245ba6a1819Smrg
246ba6a1819Smrgfor src
247ba6a1819Smrgdo
2481bedbe3fSmrg  # Protect names problematic for 'test' and other utilities.
249ba6a1819Smrg  case $src in
2501bedbe3fSmrg    -* | [=\(\)!]) src=./$src;;
251ba6a1819Smrg  esac
252ba6a1819Smrg
253ba6a1819Smrg  if test -n "$dir_arg"; then
254ba6a1819Smrg    dst=$src
255ba6a1819Smrg    dstdir=$dst
256ba6a1819Smrg    test -d "$dstdir"
257ba6a1819Smrg    dstdir_status=$?
258ba6a1819Smrg  else
259ba6a1819Smrg
260ba6a1819Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261ba6a1819Smrg    # might cause directories to be created, which would be especially bad
262ba6a1819Smrg    # if $src (and thus $dsttmp) contains '*'.
263ba6a1819Smrg    if test ! -f "$src" && test ! -d "$src"; then
264ba6a1819Smrg      echo "$0: $src does not exist." >&2
265ba6a1819Smrg      exit 1
266ba6a1819Smrg    fi
267ba6a1819Smrg
268549e21daSmrg    if test -z "$dst_arg"; then
269ba6a1819Smrg      echo "$0: no destination specified." >&2
270ba6a1819Smrg      exit 1
271ba6a1819Smrg    fi
272549e21daSmrg    dst=$dst_arg
273ba6a1819Smrg
274ba6a1819Smrg    # If destination is a directory, append the input filename; won't work
275ba6a1819Smrg    # if double slashes aren't ignored.
276ba6a1819Smrg    if test -d "$dst"; then
277298453a4Smrg      if test "$is_target_a_directory" = never; then
278298453a4Smrg        echo "$0: $dst_arg: Is a directory" >&2
279298453a4Smrg        exit 1
280ba6a1819Smrg      fi
281ba6a1819Smrg      dstdir=$dst
282ba6a1819Smrg      dst=$dstdir/`basename "$src"`
283ba6a1819Smrg      dstdir_status=0
284ba6a1819Smrg    else
285298453a4Smrg      dstdir=`dirname "$dst"`
286ba6a1819Smrg      test -d "$dstdir"
287ba6a1819Smrg      dstdir_status=$?
288ba6a1819Smrg    fi
289ba6a1819Smrg  fi
290ba6a1819Smrg
291ba6a1819Smrg  obsolete_mkdir_used=false
292ba6a1819Smrg
293ba6a1819Smrg  if test $dstdir_status != 0; then
294ba6a1819Smrg    case $posix_mkdir in
295ba6a1819Smrg      '')
296298453a4Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
297298453a4Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
298298453a4Smrg        umask=`umask`
299298453a4Smrg        case $stripcmd.$umask in
300298453a4Smrg          # Optimize common cases.
301298453a4Smrg          *[2367][2367]) mkdir_umask=$umask;;
302298453a4Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303298453a4Smrg
304298453a4Smrg          *[0-7])
305298453a4Smrg            mkdir_umask=`expr $umask + 22 \
306298453a4Smrg              - $umask % 100 % 40 + $umask % 20 \
307298453a4Smrg              - $umask % 10 % 4 + $umask % 2
308298453a4Smrg            `;;
309298453a4Smrg          *) mkdir_umask=$umask,go-w;;
310298453a4Smrg        esac
311298453a4Smrg
312298453a4Smrg        # With -d, create the new directory with the user-specified mode.
313298453a4Smrg        # Otherwise, rely on $mkdir_umask.
314298453a4Smrg        if test -n "$dir_arg"; then
315298453a4Smrg          mkdir_mode=-m$mode
316298453a4Smrg        else
317298453a4Smrg          mkdir_mode=
318298453a4Smrg        fi
319298453a4Smrg
320298453a4Smrg        posix_mkdir=false
321298453a4Smrg        case $umask in
322298453a4Smrg          *[123567][0-7][0-7])
323298453a4Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
324298453a4Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325298453a4Smrg            ;;
326298453a4Smrg          *)
327298453a4Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
328298453a4Smrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
329298453a4Smrg
330298453a4Smrg            if (umask $mkdir_umask &&
331298453a4Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
332298453a4Smrg            then
333298453a4Smrg              if test -z "$dir_arg" || {
334298453a4Smrg                   # Check for POSIX incompatibilities with -m.
335298453a4Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
336298453a4Smrg                   # other-writable bit of parent directory when it shouldn't.
337298453a4Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
338298453a4Smrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
339298453a4Smrg                   case $ls_ld_tmpdir in
340298453a4Smrg                     d????-?r-*) different_mode=700;;
341298453a4Smrg                     d????-?--*) different_mode=755;;
342298453a4Smrg                     *) false;;
343298453a4Smrg                   esac &&
344298453a4Smrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
345298453a4Smrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
346298453a4Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
347298453a4Smrg                   }
348298453a4Smrg                 }
349298453a4Smrg              then posix_mkdir=:
350298453a4Smrg              fi
351298453a4Smrg              rmdir "$tmpdir/d" "$tmpdir"
352298453a4Smrg            else
353298453a4Smrg              # Remove any dirs left behind by ancient mkdir implementations.
354298453a4Smrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
355298453a4Smrg            fi
356298453a4Smrg            trap '' 0;;
357298453a4Smrg        esac;;
358ba6a1819Smrg    esac
359ba6a1819Smrg
360ba6a1819Smrg    if
361ba6a1819Smrg      $posix_mkdir && (
362298453a4Smrg        umask $mkdir_umask &&
363298453a4Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
364ba6a1819Smrg      )
365ba6a1819Smrg    then :
366ba6a1819Smrg    else
367ba6a1819Smrg
368ba6a1819Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
369ba6a1819Smrg      # or it failed possibly due to a race condition.  Create the
370ba6a1819Smrg      # directory the slow way, step by step, checking for races as we go.
371ba6a1819Smrg
372ba6a1819Smrg      case $dstdir in
373298453a4Smrg        /*) prefix='/';;
374298453a4Smrg        [-=\(\)!]*) prefix='./';;
375298453a4Smrg        *)  prefix='';;
376ba6a1819Smrg      esac
377ba6a1819Smrg
378ba6a1819Smrg      oIFS=$IFS
379ba6a1819Smrg      IFS=/
380298453a4Smrg      set -f
381ba6a1819Smrg      set fnord $dstdir
382ba6a1819Smrg      shift
383298453a4Smrg      set +f
384ba6a1819Smrg      IFS=$oIFS
385ba6a1819Smrg
386ba6a1819Smrg      prefixes=
387ba6a1819Smrg
388ba6a1819Smrg      for d
389ba6a1819Smrg      do
390298453a4Smrg        test X"$d" = X && continue
391298453a4Smrg
392298453a4Smrg        prefix=$prefix$d
393298453a4Smrg        if test -d "$prefix"; then
394298453a4Smrg          prefixes=
395298453a4Smrg        else
396298453a4Smrg          if $posix_mkdir; then
397298453a4Smrg            (umask=$mkdir_umask &&
398298453a4Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
399298453a4Smrg            # Don't fail if two instances are running concurrently.
400298453a4Smrg            test -d "$prefix" || exit 1
401298453a4Smrg          else
402298453a4Smrg            case $prefix in
403298453a4Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
404298453a4Smrg              *) qprefix=$prefix;;
405298453a4Smrg            esac
406298453a4Smrg            prefixes="$prefixes '$qprefix'"
407298453a4Smrg          fi
408298453a4Smrg        fi
409298453a4Smrg        prefix=$prefix/
410ba6a1819Smrg      done
411ba6a1819Smrg
412ba6a1819Smrg      if test -n "$prefixes"; then
413298453a4Smrg        # Don't fail if two instances are running concurrently.
414298453a4Smrg        (umask $mkdir_umask &&
415298453a4Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
416298453a4Smrg          test -d "$dstdir" || exit 1
417298453a4Smrg        obsolete_mkdir_used=true
418ba6a1819Smrg      fi
419ba6a1819Smrg    fi
420ba6a1819Smrg  fi
421ba6a1819Smrg
422ba6a1819Smrg  if test -n "$dir_arg"; then
423ba6a1819Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
424ba6a1819Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
425ba6a1819Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
426ba6a1819Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
427ba6a1819Smrg  else
428ba6a1819Smrg
429ba6a1819Smrg    # Make a couple of temp file names in the proper directory.
430ba6a1819Smrg    dsttmp=$dstdir/_inst.$$_
431ba6a1819Smrg    rmtmp=$dstdir/_rm.$$_
432ba6a1819Smrg
433ba6a1819Smrg    # Trap to clean up those temp files at exit.
434ba6a1819Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
435ba6a1819Smrg
436ba6a1819Smrg    # Copy the file name to the temp name.
437ba6a1819Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
438ba6a1819Smrg
439ba6a1819Smrg    # and set any options; do chmod last to preserve setuid bits.
440ba6a1819Smrg    #
441ba6a1819Smrg    # If any of these fail, we abort the whole thing.  If we want to
442ba6a1819Smrg    # ignore errors from any of these, just make sure not to ignore
443ba6a1819Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
444ba6a1819Smrg    #
445549e21daSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
446549e21daSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
447549e21daSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
448549e21daSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
449549e21daSmrg
450549e21daSmrg    # If -C, don't bother to copy if it wouldn't change the file.
451549e21daSmrg    if $copy_on_change &&
452298453a4Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
453298453a4Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
454298453a4Smrg       set -f &&
455549e21daSmrg       set X $old && old=:$2:$4:$5:$6 &&
456549e21daSmrg       set X $new && new=:$2:$4:$5:$6 &&
457298453a4Smrg       set +f &&
458549e21daSmrg       test "$old" = "$new" &&
459549e21daSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
460549e21daSmrg    then
461549e21daSmrg      rm -f "$dsttmp"
462549e21daSmrg    else
463549e21daSmrg      # Rename the file to the real destination.
464549e21daSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
465549e21daSmrg
466549e21daSmrg      # The rename failed, perhaps because mv can't rename something else
467549e21daSmrg      # to itself, or perhaps because mv is so ancient that it does not
468549e21daSmrg      # support -f.
469549e21daSmrg      {
470298453a4Smrg        # Now remove or move aside any old file at destination location.
471298453a4Smrg        # We try this two ways since rm can't unlink itself on some
472298453a4Smrg        # systems and the destination file might be busy for other
473298453a4Smrg        # reasons.  In this case, the final cleanup might fail but the new
474298453a4Smrg        # file should still install successfully.
475298453a4Smrg        {
476298453a4Smrg          test ! -f "$dst" ||
477298453a4Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
478298453a4Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
479298453a4Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
480298453a4Smrg          } ||
481298453a4Smrg          { echo "$0: cannot unlink or rename $dst" >&2
482298453a4Smrg            (exit 1); exit 1
483298453a4Smrg          }
484298453a4Smrg        } &&
485298453a4Smrg
486298453a4Smrg        # Now rename the file to the real destination.
487298453a4Smrg        $doit $mvcmd "$dsttmp" "$dst"
488549e21daSmrg      }
489549e21daSmrg    fi || exit 1
490ba6a1819Smrg
491ba6a1819Smrg    trap '' 0
492ba6a1819Smrg  fi
493ba6a1819Smrgdone
494ba6a1819Smrg
495ba6a1819Smrg# Local variables:
496ba6a1819Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
497ba6a1819Smrg# time-stamp-start: "scriptversion="
498ba6a1819Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
499549e21daSmrg# time-stamp-time-zone: "UTC"
500549e21daSmrg# time-stamp-end: "; # UTC"
501ba6a1819Smrg# End:
502