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