ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/Search/trunk/install-sh
(Generate patch)

Comparing Search/trunk/install-sh (file contents):
Revision 386 by douglas, 2008-08-23T02:30:47-07:00 vs.
Revision 387 by douglas, 2011-12-30T16:21:06-08:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines