1bb9c676aSmrg#!/bin/sh
2bb9c676aSmrg# install - install a program, script, or datafile
3bb9c676aSmrg
4f672524fSmrgscriptversion=2009-04-28.21; # UTC
5bb9c676aSmrg
6bb9c676aSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7bb9c676aSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8bb9c676aSmrg# following copyright and license.
9bb9c676aSmrg#
10bb9c676aSmrg# Copyright (C) 1994 X Consortium
11bb9c676aSmrg#
12bb9c676aSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13bb9c676aSmrg# of this software and associated documentation files (the "Software"), to
14bb9c676aSmrg# deal in the Software without restriction, including without limitation the
15bb9c676aSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16bb9c676aSmrg# sell copies of the Software, and to permit persons to whom the Software is
17bb9c676aSmrg# furnished to do so, subject to the following conditions:
18bb9c676aSmrg#
19bb9c676aSmrg# The above copyright notice and this permission notice shall be included in
20bb9c676aSmrg# all copies or substantial portions of the Software.
21bb9c676aSmrg#
22bb9c676aSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23bb9c676aSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24bb9c676aSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25bb9c676aSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26bb9c676aSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27bb9c676aSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28bb9c676aSmrg#
29bb9c676aSmrg# Except as contained in this notice, the name of the X Consortium shall not
30bb9c676aSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31bb9c676aSmrg# ings in this Software without prior written authorization from the X Consor-
32bb9c676aSmrg# tium.
33bb9c676aSmrg#
34bb9c676aSmrg#
35bb9c676aSmrg# FSF changes to this file are in the public domain.
36bb9c676aSmrg#
37bb9c676aSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38bb9c676aSmrg# `make' implicit rules from creating a file called install from it
39bb9c676aSmrg# when there is no Makefile.
40bb9c676aSmrg#
41bb9c676aSmrg# This script is compatible with the BSD install script, but was written
42f672524fSmrg# from scratch.
43f672524fSmrg
44f672524fSmrgnl='
45f672524fSmrg'
46f672524fSmrgIFS=" ""	$nl"
47bb9c676aSmrg
48bb9c676aSmrg# set DOITPROG to echo to test this script
49bb9c676aSmrg
50bb9c676aSmrg# Don't use :- since 4.3BSD and earlier shells don't like it.
51f672524fSmrgdoit=${DOITPROG-}
52f672524fSmrgif test -z "$doit"; then
53f672524fSmrg  doit_exec=exec
54f672524fSmrgelse
55f672524fSmrg  doit_exec=$doit
56f672524fSmrgfi
57bb9c676aSmrg
58f672524fSmrg# Put in absolute file names if you don't have them in your path;
59f672524fSmrg# or use environment vars.
60f672524fSmrg
61f672524fSmrgchgrpprog=${CHGRPPROG-chgrp}
62f672524fSmrgchmodprog=${CHMODPROG-chmod}
63f672524fSmrgchownprog=${CHOWNPROG-chown}
64f672524fSmrgcmpprog=${CMPPROG-cmp}
65f672524fSmrgcpprog=${CPPROG-cp}
66f672524fSmrgmkdirprog=${MKDIRPROG-mkdir}
67f672524fSmrgmvprog=${MVPROG-mv}
68f672524fSmrgrmprog=${RMPROG-rm}
69f672524fSmrgstripprog=${STRIPPROG-strip}
70f672524fSmrg
71f672524fSmrgposix_glob='?'
72f672524fSmrginitialize_posix_glob='
73f672524fSmrg  test "$posix_glob" != "?" || {
74f672524fSmrg    if (set -f) 2>/dev/null; then
75f672524fSmrg      posix_glob=
76f672524fSmrg    else
77f672524fSmrg      posix_glob=:
78f672524fSmrg    fi
79f672524fSmrg  }
80f672524fSmrg'
81bb9c676aSmrg
82f672524fSmrgposix_mkdir=
83f672524fSmrg
84f672524fSmrg# Desired mode of installed file.
85f672524fSmrgmode=0755
86bb9c676aSmrg
87bb9c676aSmrgchgrpcmd=
88f672524fSmrgchmodcmd=$chmodprog
89f672524fSmrgchowncmd=
90f672524fSmrgmvcmd=$mvprog
91bb9c676aSmrgrmcmd="$rmprog -f"
92f672524fSmrgstripcmd=
93f672524fSmrg
94bb9c676aSmrgsrc=
95bb9c676aSmrgdst=
96bb9c676aSmrgdir_arg=
97f672524fSmrgdst_arg=
98f672524fSmrg
99f672524fSmrgcopy_on_change=false
100bb9c676aSmrgno_target_directory=
101bb9c676aSmrg
102f672524fSmrgusage="\
103f672524fSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
104bb9c676aSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
105bb9c676aSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
106bb9c676aSmrg   or: $0 [OPTION]... -d DIRECTORIES...
107bb9c676aSmrg
108bb9c676aSmrgIn the 1st form, copy SRCFILE to DSTFILE.
109bb9c676aSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
110bb9c676aSmrgIn the 4th, create DIRECTORIES.
111bb9c676aSmrg
112bb9c676aSmrgOptions:
113f672524fSmrg     --help     display this help and exit.
114f672524fSmrg     --version  display version info and exit.
115f672524fSmrg
116f672524fSmrg  -c            (ignored)
117f672524fSmrg  -C            install only if different (preserve the last data modification time)
118f672524fSmrg  -d            create directories instead of installing files.
119f672524fSmrg  -g GROUP      $chgrpprog installed files to GROUP.
120f672524fSmrg  -m MODE       $chmodprog installed files to MODE.
121f672524fSmrg  -o USER       $chownprog installed files to USER.
122f672524fSmrg  -s            $stripprog installed files.
123f672524fSmrg  -t DIRECTORY  install into DIRECTORY.
124f672524fSmrg  -T            report an error if DSTFILE is a directory.
125bb9c676aSmrg
126bb9c676aSmrgEnvironment variables override the default commands:
127f672524fSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
128f672524fSmrg  RMPROG STRIPPROG
129bb9c676aSmrg"
130bb9c676aSmrg
131f672524fSmrgwhile test $# -ne 0; do
132bb9c676aSmrg  case $1 in
133f672524fSmrg    -c) ;;
134f672524fSmrg
135f672524fSmrg    -C) copy_on_change=true;;
136bb9c676aSmrg
137f672524fSmrg    -d) dir_arg=true;;
138bb9c676aSmrg
139bb9c676aSmrg    -g) chgrpcmd="$chgrpprog $2"
140f672524fSmrg	shift;;
141bb9c676aSmrg
142bb9c676aSmrg    --help) echo "$usage"; exit $?;;
143bb9c676aSmrg
144f672524fSmrg    -m) mode=$2
145f672524fSmrg	case $mode in
146f672524fSmrg	  *' '* | *'	'* | *'
147f672524fSmrg'*	  | *'*'* | *'?'* | *'['*)
148f672524fSmrg	    echo "$0: invalid mode: $mode" >&2
149f672524fSmrg	    exit 1;;
150f672524fSmrg	esac
151f672524fSmrg	shift;;
152bb9c676aSmrg
153bb9c676aSmrg    -o) chowncmd="$chownprog $2"
154f672524fSmrg	shift;;
155bb9c676aSmrg
156f672524fSmrg    -s) stripcmd=$stripprog;;
157bb9c676aSmrg
158f672524fSmrg    -t) dst_arg=$2
159f672524fSmrg	shift;;
160bb9c676aSmrg
161f672524fSmrg    -T) no_target_directory=true;;
162bb9c676aSmrg
163bb9c676aSmrg    --version) echo "$0 $scriptversion"; exit $?;;
164bb9c676aSmrg
165f672524fSmrg    --)	shift
166bb9c676aSmrg	break;;
167f672524fSmrg
168f672524fSmrg    -*)	echo "$0: invalid option: $1" >&2
169f672524fSmrg	exit 1;;
170f672524fSmrg
171f672524fSmrg    *)  break;;
172bb9c676aSmrg  esac
173f672524fSmrg  shift
174bb9c676aSmrgdone
175bb9c676aSmrg
176f672524fSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177f672524fSmrg  # When -d is used, all remaining arguments are directories to create.
178f672524fSmrg  # When -t is used, the destination is already specified.
179f672524fSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180f672524fSmrg  for arg
181f672524fSmrg  do
182f672524fSmrg    if test -n "$dst_arg"; then
183f672524fSmrg      # $@ is not empty: it contains at least $arg.
184f672524fSmrg      set fnord "$@" "$dst_arg"
185f672524fSmrg      shift # fnord
186f672524fSmrg    fi
187f672524fSmrg    shift # arg
188f672524fSmrg    dst_arg=$arg
189f672524fSmrg  done
190f672524fSmrgfi
191f672524fSmrg
192f672524fSmrgif test $# -eq 0; then
193bb9c676aSmrg  if test -z "$dir_arg"; then
194bb9c676aSmrg    echo "$0: no input file specified." >&2
195bb9c676aSmrg    exit 1
196bb9c676aSmrg  fi
197bb9c676aSmrg  # It's OK to call `install-sh -d' without argument.
198bb9c676aSmrg  # This can happen when creating conditional directories.
199bb9c676aSmrg  exit 0
200bb9c676aSmrgfi
201bb9c676aSmrg
202f672524fSmrgif test -z "$dir_arg"; then
203f672524fSmrg  trap '(exit $?); exit' 1 2 13 15
204f672524fSmrg
205f672524fSmrg  # Set umask so as not to create temps with too-generous modes.
206f672524fSmrg  # However, 'strip' requires both read and write access to temps.
207f672524fSmrg  case $mode in
208f672524fSmrg    # Optimize common cases.
209f672524fSmrg    *644) cp_umask=133;;
210f672524fSmrg    *755) cp_umask=22;;
211f672524fSmrg
212f672524fSmrg    *[0-7])
213f672524fSmrg      if test -z "$stripcmd"; then
214f672524fSmrg	u_plus_rw=
215f672524fSmrg      else
216f672524fSmrg	u_plus_rw='% 200'
217f672524fSmrg      fi
218f672524fSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
219f672524fSmrg    *)
220f672524fSmrg      if test -z "$stripcmd"; then
221f672524fSmrg	u_plus_rw=
222f672524fSmrg      else
223f672524fSmrg	u_plus_rw=,u+rw
224f672524fSmrg      fi
225f672524fSmrg      cp_umask=$mode$u_plus_rw;;
226f672524fSmrg  esac
227f672524fSmrgfi
228f672524fSmrg
229bb9c676aSmrgfor src
230bb9c676aSmrgdo
231bb9c676aSmrg  # Protect names starting with `-'.
232bb9c676aSmrg  case $src in
233f672524fSmrg    -*) src=./$src;;
234bb9c676aSmrg  esac
235bb9c676aSmrg
236bb9c676aSmrg  if test -n "$dir_arg"; then
237bb9c676aSmrg    dst=$src
238f672524fSmrg    dstdir=$dst
239f672524fSmrg    test -d "$dstdir"
240f672524fSmrg    dstdir_status=$?
241bb9c676aSmrg  else
242f672524fSmrg
243bb9c676aSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
244bb9c676aSmrg    # might cause directories to be created, which would be especially bad
245bb9c676aSmrg    # if $src (and thus $dsttmp) contains '*'.
246bb9c676aSmrg    if test ! -f "$src" && test ! -d "$src"; then
247bb9c676aSmrg      echo "$0: $src does not exist." >&2
248bb9c676aSmrg      exit 1
249bb9c676aSmrg    fi
250bb9c676aSmrg
251f672524fSmrg    if test -z "$dst_arg"; then
252bb9c676aSmrg      echo "$0: no destination specified." >&2
253bb9c676aSmrg      exit 1
254bb9c676aSmrg    fi
255bb9c676aSmrg
256f672524fSmrg    dst=$dst_arg
257bb9c676aSmrg    # Protect names starting with `-'.
258bb9c676aSmrg    case $dst in
259f672524fSmrg      -*) dst=./$dst;;
260bb9c676aSmrg    esac
261bb9c676aSmrg
262bb9c676aSmrg    # If destination is a directory, append the input filename; won't work
263bb9c676aSmrg    # if double slashes aren't ignored.
264bb9c676aSmrg    if test -d "$dst"; then
265bb9c676aSmrg      if test -n "$no_target_directory"; then
266f672524fSmrg	echo "$0: $dst_arg: Is a directory" >&2
267bb9c676aSmrg	exit 1
268bb9c676aSmrg      fi
269f672524fSmrg      dstdir=$dst
270f672524fSmrg      dst=$dstdir/`basename "$src"`
271f672524fSmrg      dstdir_status=0
272f672524fSmrg    else
273f672524fSmrg      # Prefer dirname, but fall back on a substitute if dirname fails.
274f672524fSmrg      dstdir=`
275f672524fSmrg	(dirname "$dst") 2>/dev/null ||
276f672524fSmrg	expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
277f672524fSmrg	     X"$dst" : 'X\(//\)[^/]' \| \
278f672524fSmrg	     X"$dst" : 'X\(//\)$' \| \
279f672524fSmrg	     X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
280f672524fSmrg	echo X"$dst" |
281f672524fSmrg	    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
282f672524fSmrg		   s//\1/
283f672524fSmrg		   q
284f672524fSmrg		 }
285f672524fSmrg		 /^X\(\/\/\)[^/].*/{
286f672524fSmrg		   s//\1/
287f672524fSmrg		   q
288f672524fSmrg		 }
289f672524fSmrg		 /^X\(\/\/\)$/{
290f672524fSmrg		   s//\1/
291f672524fSmrg		   q
292f672524fSmrg		 }
293f672524fSmrg		 /^X\(\/\).*/{
294f672524fSmrg		   s//\1/
295f672524fSmrg		   q
296f672524fSmrg		 }
297f672524fSmrg		 s/.*/./; q'
298f672524fSmrg      `
299f672524fSmrg
300f672524fSmrg      test -d "$dstdir"
301f672524fSmrg      dstdir_status=$?
302bb9c676aSmrg    fi
303bb9c676aSmrg  fi
304bb9c676aSmrg
305f672524fSmrg  obsolete_mkdir_used=false
306f672524fSmrg
307f672524fSmrg  if test $dstdir_status != 0; then
308f672524fSmrg    case $posix_mkdir in
309f672524fSmrg      '')
310f672524fSmrg	# Create intermediate dirs using mode 755 as modified by the umask.
311f672524fSmrg	# This is like FreeBSD 'install' as of 1997-10-28.
312f672524fSmrg	umask=`umask`
313f672524fSmrg	case $stripcmd.$umask in
314f672524fSmrg	  # Optimize common cases.
315f672524fSmrg	  *[2367][2367]) mkdir_umask=$umask;;
316f672524fSmrg	  .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
317f672524fSmrg
318f672524fSmrg	  *[0-7])
319f672524fSmrg	    mkdir_umask=`expr $umask + 22 \
320f672524fSmrg	      - $umask % 100 % 40 + $umask % 20 \
321f672524fSmrg	      - $umask % 10 % 4 + $umask % 2
322f672524fSmrg	    `;;
323f672524fSmrg	  *) mkdir_umask=$umask,go-w;;
324f672524fSmrg	esac
325f672524fSmrg
326f672524fSmrg	# With -d, create the new directory with the user-specified mode.
327f672524fSmrg	# Otherwise, rely on $mkdir_umask.
328f672524fSmrg	if test -n "$dir_arg"; then
329f672524fSmrg	  mkdir_mode=-m$mode
330f672524fSmrg	else
331f672524fSmrg	  mkdir_mode=
332f672524fSmrg	fi
333f672524fSmrg
334f672524fSmrg	posix_mkdir=false
335f672524fSmrg	case $umask in
336f672524fSmrg	  *[123567][0-7][0-7])
337f672524fSmrg	    # POSIX mkdir -p sets u+wx bits regardless of umask, which
338f672524fSmrg	    # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
339f672524fSmrg	    ;;
340f672524fSmrg	  *)
341f672524fSmrg	    tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
342f672524fSmrg	    trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
343f672524fSmrg
344f672524fSmrg	    if (umask $mkdir_umask &&
345f672524fSmrg		exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
346f672524fSmrg	    then
347f672524fSmrg	      if test -z "$dir_arg" || {
348f672524fSmrg		   # Check for POSIX incompatibilities with -m.
349f672524fSmrg		   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
350f672524fSmrg		   # other-writeable bit of parent directory when it shouldn't.
351f672524fSmrg		   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
352f672524fSmrg		   ls_ld_tmpdir=`ls -ld "$tmpdir"`
353f672524fSmrg		   case $ls_ld_tmpdir in
354f672524fSmrg		     d????-?r-*) different_mode=700;;
355f672524fSmrg		     d????-?--*) different_mode=755;;
356f672524fSmrg		     *) false;;
357f672524fSmrg		   esac &&
358f672524fSmrg		   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
359f672524fSmrg		     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
360f672524fSmrg		     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
361f672524fSmrg		   }
362f672524fSmrg		 }
363f672524fSmrg	      then posix_mkdir=:
364f672524fSmrg	      fi
365f672524fSmrg	      rmdir "$tmpdir/d" "$tmpdir"
366f672524fSmrg	    else
367f672524fSmrg	      # Remove any dirs left behind by ancient mkdir implementations.
368f672524fSmrg	      rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
369f672524fSmrg	    fi
370f672524fSmrg	    trap '' 0;;
371f672524fSmrg	esac;;
372f672524fSmrg    esac
373bb9c676aSmrg
374f672524fSmrg    if
375f672524fSmrg      $posix_mkdir && (
376f672524fSmrg	umask $mkdir_umask &&
377f672524fSmrg	$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
378f672524fSmrg      )
379f672524fSmrg    then :
380f672524fSmrg    else
381bb9c676aSmrg
382f672524fSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
383f672524fSmrg      # or it failed possibly due to a race condition.  Create the
384f672524fSmrg      # directory the slow way, step by step, checking for races as we go.
385bb9c676aSmrg
386f672524fSmrg      case $dstdir in
387f672524fSmrg	/*) prefix='/';;
388f672524fSmrg	-*) prefix='./';;
389f672524fSmrg	*)  prefix='';;
390f672524fSmrg      esac
391bb9c676aSmrg
392f672524fSmrg      eval "$initialize_posix_glob"
393bb9c676aSmrg
394f672524fSmrg      oIFS=$IFS
395f672524fSmrg      IFS=/
396f672524fSmrg      $posix_glob set -f
397f672524fSmrg      set fnord $dstdir
398bb9c676aSmrg      shift
399f672524fSmrg      $posix_glob set +f
400f672524fSmrg      IFS=$oIFS
401f672524fSmrg
402f672524fSmrg      prefixes=
403f672524fSmrg
404f672524fSmrg      for d
405f672524fSmrg      do
406f672524fSmrg	test -z "$d" && continue
407f672524fSmrg
408f672524fSmrg	prefix=$prefix$d
409f672524fSmrg	if test -d "$prefix"; then
410f672524fSmrg	  prefixes=
411f672524fSmrg	else
412f672524fSmrg	  if $posix_mkdir; then
413f672524fSmrg	    (umask=$mkdir_umask &&
414f672524fSmrg	     $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
415f672524fSmrg	    # Don't fail if two instances are running concurrently.
416f672524fSmrg	    test -d "$prefix" || exit 1
417f672524fSmrg	  else
418f672524fSmrg	    case $prefix in
419f672524fSmrg	      *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
420f672524fSmrg	      *) qprefix=$prefix;;
421f672524fSmrg	    esac
422f672524fSmrg	    prefixes="$prefixes '$qprefix'"
423f672524fSmrg	  fi
424f672524fSmrg	fi
425f672524fSmrg	prefix=$prefix/
426f672524fSmrg      done
427f672524fSmrg
428f672524fSmrg      if test -n "$prefixes"; then
429f672524fSmrg	# Don't fail if two instances are running concurrently.
430f672524fSmrg	(umask $mkdir_umask &&
431f672524fSmrg	 eval "\$doit_exec \$mkdirprog $prefixes") ||
432f672524fSmrg	  test -d "$dstdir" || exit 1
433f672524fSmrg	obsolete_mkdir_used=true
434bb9c676aSmrg      fi
435f672524fSmrg    fi
436bb9c676aSmrg  fi
437bb9c676aSmrg
438bb9c676aSmrg  if test -n "$dir_arg"; then
439f672524fSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
440f672524fSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
441f672524fSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
442f672524fSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
443bb9c676aSmrg  else
444bb9c676aSmrg
445bb9c676aSmrg    # Make a couple of temp file names in the proper directory.
446bb9c676aSmrg    dsttmp=$dstdir/_inst.$$_
447bb9c676aSmrg    rmtmp=$dstdir/_rm.$$_
448bb9c676aSmrg
449bb9c676aSmrg    # Trap to clean up those temp files at exit.
450bb9c676aSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
451bb9c676aSmrg
452bb9c676aSmrg    # Copy the file name to the temp name.
453f672524fSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
454bb9c676aSmrg
455bb9c676aSmrg    # and set any options; do chmod last to preserve setuid bits.
456bb9c676aSmrg    #
457bb9c676aSmrg    # If any of these fail, we abort the whole thing.  If we want to
458bb9c676aSmrg    # ignore errors from any of these, just make sure not to ignore
459bb9c676aSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
460bb9c676aSmrg    #
461f672524fSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
462f672524fSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
463f672524fSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
464f672524fSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
465f672524fSmrg
466f672524fSmrg    # If -C, don't bother to copy if it wouldn't change the file.
467f672524fSmrg    if $copy_on_change &&
468f672524fSmrg       old=`LC_ALL=C ls -dlL "$dst"	2>/dev/null` &&
469f672524fSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"	2>/dev/null` &&
470f672524fSmrg
471f672524fSmrg       eval "$initialize_posix_glob" &&
472f672524fSmrg       $posix_glob set -f &&
473f672524fSmrg       set X $old && old=:$2:$4:$5:$6 &&
474f672524fSmrg       set X $new && new=:$2:$4:$5:$6 &&
475f672524fSmrg       $posix_glob set +f &&
476f672524fSmrg
477f672524fSmrg       test "$old" = "$new" &&
478f672524fSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
479f672524fSmrg    then
480f672524fSmrg      rm -f "$dsttmp"
481f672524fSmrg    else
482f672524fSmrg      # Rename the file to the real destination.
483f672524fSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
484f672524fSmrg
485f672524fSmrg      # The rename failed, perhaps because mv can't rename something else
486f672524fSmrg      # to itself, or perhaps because mv is so ancient that it does not
487f672524fSmrg      # support -f.
488f672524fSmrg      {
489f672524fSmrg	# Now remove or move aside any old file at destination location.
490f672524fSmrg	# We try this two ways since rm can't unlink itself on some
491f672524fSmrg	# systems and the destination file might be busy for other
492f672524fSmrg	# reasons.  In this case, the final cleanup might fail but the new
493f672524fSmrg	# file should still install successfully.
494f672524fSmrg	{
495f672524fSmrg	  test ! -f "$dst" ||
496f672524fSmrg	  $doit $rmcmd -f "$dst" 2>/dev/null ||
497f672524fSmrg	  { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
498f672524fSmrg	    { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
499f672524fSmrg	  } ||
500f672524fSmrg	  { echo "$0: cannot unlink or rename $dst" >&2
501f672524fSmrg	    (exit 1); exit 1
502f672524fSmrg	  }
503f672524fSmrg	} &&
504f672524fSmrg
505f672524fSmrg	# Now rename the file to the real destination.
506f672524fSmrg	$doit $mvcmd "$dsttmp" "$dst"
507f672524fSmrg      }
508f672524fSmrg    fi || exit 1
509f672524fSmrg
510f672524fSmrg    trap '' 0
511f672524fSmrg  fi
512bb9c676aSmrgdone
513bb9c676aSmrg
514bb9c676aSmrg# Local variables:
515bb9c676aSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
516bb9c676aSmrg# time-stamp-start: "scriptversion="
517bb9c676aSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
518f672524fSmrg# time-stamp-time-zone: "UTC"
519f672524fSmrg# time-stamp-end: "; # UTC"
520bb9c676aSmrg# End:
521