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