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