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