install-sh revision 963d66ac
17e6fb56fSmrg#!/bin/sh
27e6fb56fSmrg# install - install a program, script, or datafile
37e6fb56fSmrg
4963d66acSmrgscriptversion=2013-12-25.23; # UTC
57e6fb56fSmrg
67e6fb56fSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
77e6fb56fSmrg# later released in X11R6 (xc/config/util/install.sh) with the
87e6fb56fSmrg# following copyright and license.
97e6fb56fSmrg#
107e6fb56fSmrg# Copyright (C) 1994 X Consortium
117e6fb56fSmrg#
127e6fb56fSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
137e6fb56fSmrg# of this software and associated documentation files (the "Software"), to
147e6fb56fSmrg# deal in the Software without restriction, including without limitation the
157e6fb56fSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
167e6fb56fSmrg# sell copies of the Software, and to permit persons to whom the Software is
177e6fb56fSmrg# furnished to do so, subject to the following conditions:
187e6fb56fSmrg#
197e6fb56fSmrg# The above copyright notice and this permission notice shall be included in
207e6fb56fSmrg# all copies or substantial portions of the Software.
217e6fb56fSmrg#
227e6fb56fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
237e6fb56fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
247e6fb56fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
257e6fb56fSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
267e6fb56fSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
277e6fb56fSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
287e6fb56fSmrg#
297e6fb56fSmrg# Except as contained in this notice, the name of the X Consortium shall not
307e6fb56fSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
317e6fb56fSmrg# ings in this Software without prior written authorization from the X Consor-
327e6fb56fSmrg# tium.
337e6fb56fSmrg#
347e6fb56fSmrg#
357e6fb56fSmrg# FSF changes to this file are in the public domain.
367e6fb56fSmrg#
377e6fb56fSmrg# Calling this script install-sh is preferred over install.sh, to prevent
3890b17f1bSmrg# 'make' implicit rules from creating a file called install from it
397e6fb56fSmrg# when there is no Makefile.
407e6fb56fSmrg#
417e6fb56fSmrg# This script is compatible with the BSD install script, but was written
427e6fb56fSmrg# from scratch.
437e6fb56fSmrg
44963d66acSmrgtab='	'
457e6fb56fSmrgnl='
467e6fb56fSmrg'
47963d66acSmrgIFS=" $tab$nl"
487e6fb56fSmrg
49963d66acSmrg# Set DOITPROG to "echo" to test this script.
507e6fb56fSmrg
517e6fb56fSmrgdoit=${DOITPROG-}
52963d66acSmrgdoit_exec=${doit:-exec}
537e6fb56fSmrg
547e6fb56fSmrg# Put in absolute file names if you don't have them in your path;
557e6fb56fSmrg# or use environment vars.
567e6fb56fSmrg
577e6fb56fSmrgchgrpprog=${CHGRPPROG-chgrp}
587e6fb56fSmrgchmodprog=${CHMODPROG-chmod}
597e6fb56fSmrgchownprog=${CHOWNPROG-chown}
607e6fb56fSmrgcmpprog=${CMPPROG-cmp}
617e6fb56fSmrgcpprog=${CPPROG-cp}
627e6fb56fSmrgmkdirprog=${MKDIRPROG-mkdir}
637e6fb56fSmrgmvprog=${MVPROG-mv}
647e6fb56fSmrgrmprog=${RMPROG-rm}
657e6fb56fSmrgstripprog=${STRIPPROG-strip}
667e6fb56fSmrg
677e6fb56fSmrgposix_mkdir=
687e6fb56fSmrg
697e6fb56fSmrg# Desired mode of installed file.
707e6fb56fSmrgmode=0755
717e6fb56fSmrg
727e6fb56fSmrgchgrpcmd=
737e6fb56fSmrgchmodcmd=$chmodprog
747e6fb56fSmrgchowncmd=
757e6fb56fSmrgmvcmd=$mvprog
767e6fb56fSmrgrmcmd="$rmprog -f"
777e6fb56fSmrgstripcmd=
787e6fb56fSmrg
797e6fb56fSmrgsrc=
807e6fb56fSmrgdst=
817e6fb56fSmrgdir_arg=
827e6fb56fSmrgdst_arg=
837e6fb56fSmrg
847e6fb56fSmrgcopy_on_change=false
85963d66acSmrgis_target_a_directory=possibly
867e6fb56fSmrg
877e6fb56fSmrgusage="\
887e6fb56fSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
897e6fb56fSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
907e6fb56fSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
917e6fb56fSmrg   or: $0 [OPTION]... -d DIRECTORIES...
927e6fb56fSmrg
937e6fb56fSmrgIn the 1st form, copy SRCFILE to DSTFILE.
947e6fb56fSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
957e6fb56fSmrgIn the 4th, create DIRECTORIES.
967e6fb56fSmrg
977e6fb56fSmrgOptions:
987e6fb56fSmrg     --help     display this help and exit.
997e6fb56fSmrg     --version  display version info and exit.
1007e6fb56fSmrg
1017e6fb56fSmrg  -c            (ignored)
1027e6fb56fSmrg  -C            install only if different (preserve the last data modification time)
1037e6fb56fSmrg  -d            create directories instead of installing files.
1047e6fb56fSmrg  -g GROUP      $chgrpprog installed files to GROUP.
1057e6fb56fSmrg  -m MODE       $chmodprog installed files to MODE.
1067e6fb56fSmrg  -o USER       $chownprog installed files to USER.
1077e6fb56fSmrg  -s            $stripprog installed files.
1087e6fb56fSmrg  -t DIRECTORY  install into DIRECTORY.
1097e6fb56fSmrg  -T            report an error if DSTFILE is a directory.
1107e6fb56fSmrg
1117e6fb56fSmrgEnvironment variables override the default commands:
1127e6fb56fSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1137e6fb56fSmrg  RMPROG STRIPPROG
1147e6fb56fSmrg"
1157e6fb56fSmrg
1167e6fb56fSmrgwhile test $# -ne 0; do
1177e6fb56fSmrg  case $1 in
1187e6fb56fSmrg    -c) ;;
1197e6fb56fSmrg
1207e6fb56fSmrg    -C) copy_on_change=true;;
1217e6fb56fSmrg
1227e6fb56fSmrg    -d) dir_arg=true;;
1237e6fb56fSmrg
1247e6fb56fSmrg    -g) chgrpcmd="$chgrpprog $2"
125963d66acSmrg        shift;;
1267e6fb56fSmrg
1277e6fb56fSmrg    --help) echo "$usage"; exit $?;;
1287e6fb56fSmrg
1297e6fb56fSmrg    -m) mode=$2
130963d66acSmrg        case $mode in
131963d66acSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132963d66acSmrg            echo "$0: invalid mode: $mode" >&2
133963d66acSmrg            exit 1;;
134963d66acSmrg        esac
135963d66acSmrg        shift;;
1367e6fb56fSmrg
1377e6fb56fSmrg    -o) chowncmd="$chownprog $2"
138963d66acSmrg        shift;;
1397e6fb56fSmrg
1407e6fb56fSmrg    -s) stripcmd=$stripprog;;
1417e6fb56fSmrg
142963d66acSmrg    -t)
143963d66acSmrg        is_target_a_directory=always
144963d66acSmrg        dst_arg=$2
145963d66acSmrg        # Protect names problematic for 'test' and other utilities.
146963d66acSmrg        case $dst_arg in
147963d66acSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148963d66acSmrg        esac
149963d66acSmrg        shift;;
1507e6fb56fSmrg
151963d66acSmrg    -T) is_target_a_directory=never;;
1527e6fb56fSmrg
1537e6fb56fSmrg    --version) echo "$0 $scriptversion"; exit $?;;
1547e6fb56fSmrg
155963d66acSmrg    --) shift
156963d66acSmrg        break;;
1577e6fb56fSmrg
158963d66acSmrg    -*) echo "$0: invalid option: $1" >&2
159963d66acSmrg        exit 1;;
1607e6fb56fSmrg
1617e6fb56fSmrg    *)  break;;
1627e6fb56fSmrg  esac
1637e6fb56fSmrg  shift
1647e6fb56fSmrgdone
1657e6fb56fSmrg
166963d66acSmrg# We allow the use of options -d and -T together, by making -d
167963d66acSmrg# take the precedence; this is for compatibility with GNU install.
168963d66acSmrg
169963d66acSmrgif test -n "$dir_arg"; then
170963d66acSmrg  if test -n "$dst_arg"; then
171963d66acSmrg    echo "$0: target directory not allowed when installing a directory." >&2
172963d66acSmrg    exit 1
173963d66acSmrg  fi
174963d66acSmrgfi
175963d66acSmrg
1767e6fb56fSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1777e6fb56fSmrg  # When -d is used, all remaining arguments are directories to create.
1787e6fb56fSmrg  # When -t is used, the destination is already specified.
1797e6fb56fSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
1807e6fb56fSmrg  for arg
1817e6fb56fSmrg  do
1827e6fb56fSmrg    if test -n "$dst_arg"; then
1837e6fb56fSmrg      # $@ is not empty: it contains at least $arg.
1847e6fb56fSmrg      set fnord "$@" "$dst_arg"
1857e6fb56fSmrg      shift # fnord
1867e6fb56fSmrg    fi
1877e6fb56fSmrg    shift # arg
1887e6fb56fSmrg    dst_arg=$arg
18990b17f1bSmrg    # Protect names problematic for 'test' and other utilities.
19090b17f1bSmrg    case $dst_arg in
19190b17f1bSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19290b17f1bSmrg    esac
1937e6fb56fSmrg  done
1947e6fb56fSmrgfi
1957e6fb56fSmrg
1967e6fb56fSmrgif test $# -eq 0; then
1977e6fb56fSmrg  if test -z "$dir_arg"; then
1987e6fb56fSmrg    echo "$0: no input file specified." >&2
1997e6fb56fSmrg    exit 1
2007e6fb56fSmrg  fi
20190b17f1bSmrg  # It's OK to call 'install-sh -d' without argument.
2027e6fb56fSmrg  # This can happen when creating conditional directories.
2037e6fb56fSmrg  exit 0
2047e6fb56fSmrgfi
2057e6fb56fSmrg
206963d66acSmrgif test -z "$dir_arg"; then
207963d66acSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208963d66acSmrg    if test ! -d "$dst_arg"; then
209963d66acSmrg      echo "$0: $dst_arg: Is not a directory." >&2
210963d66acSmrg      exit 1
211963d66acSmrg    fi
212963d66acSmrg  fi
213963d66acSmrgfi
214963d66acSmrg
2157e6fb56fSmrgif test -z "$dir_arg"; then
21690b17f1bSmrg  do_exit='(exit $ret); exit $ret'
21790b17f1bSmrg  trap "ret=129; $do_exit" 1
21890b17f1bSmrg  trap "ret=130; $do_exit" 2
21990b17f1bSmrg  trap "ret=141; $do_exit" 13
22090b17f1bSmrg  trap "ret=143; $do_exit" 15
2217e6fb56fSmrg
2227e6fb56fSmrg  # Set umask so as not to create temps with too-generous modes.
2237e6fb56fSmrg  # However, 'strip' requires both read and write access to temps.
2247e6fb56fSmrg  case $mode in
2257e6fb56fSmrg    # Optimize common cases.
2267e6fb56fSmrg    *644) cp_umask=133;;
2277e6fb56fSmrg    *755) cp_umask=22;;
2287e6fb56fSmrg
2297e6fb56fSmrg    *[0-7])
2307e6fb56fSmrg      if test -z "$stripcmd"; then
231963d66acSmrg        u_plus_rw=
2327e6fb56fSmrg      else
233963d66acSmrg        u_plus_rw='% 200'
2347e6fb56fSmrg      fi
2357e6fb56fSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2367e6fb56fSmrg    *)
2377e6fb56fSmrg      if test -z "$stripcmd"; then
238963d66acSmrg        u_plus_rw=
2397e6fb56fSmrg      else
240963d66acSmrg        u_plus_rw=,u+rw
2417e6fb56fSmrg      fi
2427e6fb56fSmrg      cp_umask=$mode$u_plus_rw;;
2437e6fb56fSmrg  esac
2447e6fb56fSmrgfi
2457e6fb56fSmrg
2467e6fb56fSmrgfor src
2477e6fb56fSmrgdo
24890b17f1bSmrg  # Protect names problematic for 'test' and other utilities.
2497e6fb56fSmrg  case $src in
25090b17f1bSmrg    -* | [=\(\)!]) src=./$src;;
2517e6fb56fSmrg  esac
2527e6fb56fSmrg
2537e6fb56fSmrg  if test -n "$dir_arg"; then
2547e6fb56fSmrg    dst=$src
2557e6fb56fSmrg    dstdir=$dst
2567e6fb56fSmrg    test -d "$dstdir"
2577e6fb56fSmrg    dstdir_status=$?
2587e6fb56fSmrg  else
2597e6fb56fSmrg
2607e6fb56fSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2617e6fb56fSmrg    # might cause directories to be created, which would be especially bad
2627e6fb56fSmrg    # if $src (and thus $dsttmp) contains '*'.
2637e6fb56fSmrg    if test ! -f "$src" && test ! -d "$src"; then
2647e6fb56fSmrg      echo "$0: $src does not exist." >&2
2657e6fb56fSmrg      exit 1
2667e6fb56fSmrg    fi
2677e6fb56fSmrg
2687e6fb56fSmrg    if test -z "$dst_arg"; then
2697e6fb56fSmrg      echo "$0: no destination specified." >&2
2707e6fb56fSmrg      exit 1
2717e6fb56fSmrg    fi
2727e6fb56fSmrg    dst=$dst_arg
2737e6fb56fSmrg
2747e6fb56fSmrg    # If destination is a directory, append the input filename; won't work
2757e6fb56fSmrg    # if double slashes aren't ignored.
2767e6fb56fSmrg    if test -d "$dst"; then
277963d66acSmrg      if test "$is_target_a_directory" = never; then
278963d66acSmrg        echo "$0: $dst_arg: Is a directory" >&2
279963d66acSmrg        exit 1
2807e6fb56fSmrg      fi
2817e6fb56fSmrg      dstdir=$dst
2827e6fb56fSmrg      dst=$dstdir/`basename "$src"`
2837e6fb56fSmrg      dstdir_status=0
2847e6fb56fSmrg    else
285963d66acSmrg      dstdir=`dirname "$dst"`
2867e6fb56fSmrg      test -d "$dstdir"
2877e6fb56fSmrg      dstdir_status=$?
2887e6fb56fSmrg    fi
2897e6fb56fSmrg  fi
2907e6fb56fSmrg
2917e6fb56fSmrg  obsolete_mkdir_used=false
2927e6fb56fSmrg
2937e6fb56fSmrg  if test $dstdir_status != 0; then
2947e6fb56fSmrg    case $posix_mkdir in
2957e6fb56fSmrg      '')
296963d66acSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
297963d66acSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
298963d66acSmrg        umask=`umask`
299963d66acSmrg        case $stripcmd.$umask in
300963d66acSmrg          # Optimize common cases.
301963d66acSmrg          *[2367][2367]) mkdir_umask=$umask;;
302963d66acSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303963d66acSmrg
304963d66acSmrg          *[0-7])
305963d66acSmrg            mkdir_umask=`expr $umask + 22 \
306963d66acSmrg              - $umask % 100 % 40 + $umask % 20 \
307963d66acSmrg              - $umask % 10 % 4 + $umask % 2
308963d66acSmrg            `;;
309963d66acSmrg          *) mkdir_umask=$umask,go-w;;
310963d66acSmrg        esac
311963d66acSmrg
312963d66acSmrg        # With -d, create the new directory with the user-specified mode.
313963d66acSmrg        # Otherwise, rely on $mkdir_umask.
314963d66acSmrg        if test -n "$dir_arg"; then
315963d66acSmrg          mkdir_mode=-m$mode
316963d66acSmrg        else
317963d66acSmrg          mkdir_mode=
318963d66acSmrg        fi
319963d66acSmrg
320963d66acSmrg        posix_mkdir=false
321963d66acSmrg        case $umask in
322963d66acSmrg          *[123567][0-7][0-7])
323963d66acSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
324963d66acSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325963d66acSmrg            ;;
326963d66acSmrg          *)
327963d66acSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
328963d66acSmrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
329963d66acSmrg
330963d66acSmrg            if (umask $mkdir_umask &&
331963d66acSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
332963d66acSmrg            then
333963d66acSmrg              if test -z "$dir_arg" || {
334963d66acSmrg                   # Check for POSIX incompatibilities with -m.
335963d66acSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
336963d66acSmrg                   # other-writable bit of parent directory when it shouldn't.
337963d66acSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
338963d66acSmrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
339963d66acSmrg                   case $ls_ld_tmpdir in
340963d66acSmrg                     d????-?r-*) different_mode=700;;
341963d66acSmrg                     d????-?--*) different_mode=755;;
342963d66acSmrg                     *) false;;
343963d66acSmrg                   esac &&
344963d66acSmrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
345963d66acSmrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
346963d66acSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
347963d66acSmrg                   }
348963d66acSmrg                 }
349963d66acSmrg              then posix_mkdir=:
350963d66acSmrg              fi
351963d66acSmrg              rmdir "$tmpdir/d" "$tmpdir"
352963d66acSmrg            else
353963d66acSmrg              # Remove any dirs left behind by ancient mkdir implementations.
354963d66acSmrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
355963d66acSmrg            fi
356963d66acSmrg            trap '' 0;;
357963d66acSmrg        esac;;
3587e6fb56fSmrg    esac
3597e6fb56fSmrg
3607e6fb56fSmrg    if
3617e6fb56fSmrg      $posix_mkdir && (
362963d66acSmrg        umask $mkdir_umask &&
363963d66acSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3647e6fb56fSmrg      )
3657e6fb56fSmrg    then :
3667e6fb56fSmrg    else
3677e6fb56fSmrg
3687e6fb56fSmrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
3697e6fb56fSmrg      # or it failed possibly due to a race condition.  Create the
3707e6fb56fSmrg      # directory the slow way, step by step, checking for races as we go.
3717e6fb56fSmrg
3727e6fb56fSmrg      case $dstdir in
373963d66acSmrg        /*) prefix='/';;
374963d66acSmrg        [-=\(\)!]*) prefix='./';;
375963d66acSmrg        *)  prefix='';;
3767e6fb56fSmrg      esac
3777e6fb56fSmrg
3787e6fb56fSmrg      oIFS=$IFS
3797e6fb56fSmrg      IFS=/
380963d66acSmrg      set -f
3817e6fb56fSmrg      set fnord $dstdir
3827e6fb56fSmrg      shift
383963d66acSmrg      set +f
3847e6fb56fSmrg      IFS=$oIFS
3857e6fb56fSmrg
3867e6fb56fSmrg      prefixes=
3877e6fb56fSmrg
3887e6fb56fSmrg      for d
3897e6fb56fSmrg      do
390963d66acSmrg        test X"$d" = X && continue
391963d66acSmrg
392963d66acSmrg        prefix=$prefix$d
393963d66acSmrg        if test -d "$prefix"; then
394963d66acSmrg          prefixes=
395963d66acSmrg        else
396963d66acSmrg          if $posix_mkdir; then
397963d66acSmrg            (umask=$mkdir_umask &&
398963d66acSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
399963d66acSmrg            # Don't fail if two instances are running concurrently.
400963d66acSmrg            test -d "$prefix" || exit 1
401963d66acSmrg          else
402963d66acSmrg            case $prefix in
403963d66acSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
404963d66acSmrg              *) qprefix=$prefix;;
405963d66acSmrg            esac
406963d66acSmrg            prefixes="$prefixes '$qprefix'"
407963d66acSmrg          fi
408963d66acSmrg        fi
409963d66acSmrg        prefix=$prefix/
4107e6fb56fSmrg      done
4117e6fb56fSmrg
4127e6fb56fSmrg      if test -n "$prefixes"; then
413963d66acSmrg        # Don't fail if two instances are running concurrently.
414963d66acSmrg        (umask $mkdir_umask &&
415963d66acSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
416963d66acSmrg          test -d "$dstdir" || exit 1
417963d66acSmrg        obsolete_mkdir_used=true
4187e6fb56fSmrg      fi
4197e6fb56fSmrg    fi
4207e6fb56fSmrg  fi
4217e6fb56fSmrg
4227e6fb56fSmrg  if test -n "$dir_arg"; then
4237e6fb56fSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4247e6fb56fSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4257e6fb56fSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4267e6fb56fSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4277e6fb56fSmrg  else
4287e6fb56fSmrg
4297e6fb56fSmrg    # Make a couple of temp file names in the proper directory.
4307e6fb56fSmrg    dsttmp=$dstdir/_inst.$$_
4317e6fb56fSmrg    rmtmp=$dstdir/_rm.$$_
4327e6fb56fSmrg
4337e6fb56fSmrg    # Trap to clean up those temp files at exit.
4347e6fb56fSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4357e6fb56fSmrg
4367e6fb56fSmrg    # Copy the file name to the temp name.
4377e6fb56fSmrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
4387e6fb56fSmrg
4397e6fb56fSmrg    # and set any options; do chmod last to preserve setuid bits.
4407e6fb56fSmrg    #
4417e6fb56fSmrg    # If any of these fail, we abort the whole thing.  If we want to
4427e6fb56fSmrg    # ignore errors from any of these, just make sure not to ignore
4437e6fb56fSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4447e6fb56fSmrg    #
4457e6fb56fSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4467e6fb56fSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4477e6fb56fSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4487e6fb56fSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4497e6fb56fSmrg
4507e6fb56fSmrg    # If -C, don't bother to copy if it wouldn't change the file.
4517e6fb56fSmrg    if $copy_on_change &&
452963d66acSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
453963d66acSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
454963d66acSmrg       set -f &&
4557e6fb56fSmrg       set X $old && old=:$2:$4:$5:$6 &&
4567e6fb56fSmrg       set X $new && new=:$2:$4:$5:$6 &&
457963d66acSmrg       set +f &&
4587e6fb56fSmrg       test "$old" = "$new" &&
4597e6fb56fSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4607e6fb56fSmrg    then
4617e6fb56fSmrg      rm -f "$dsttmp"
4627e6fb56fSmrg    else
4637e6fb56fSmrg      # Rename the file to the real destination.
4647e6fb56fSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4657e6fb56fSmrg
4667e6fb56fSmrg      # The rename failed, perhaps because mv can't rename something else
4677e6fb56fSmrg      # to itself, or perhaps because mv is so ancient that it does not
4687e6fb56fSmrg      # support -f.
4697e6fb56fSmrg      {
470963d66acSmrg        # Now remove or move aside any old file at destination location.
471963d66acSmrg        # We try this two ways since rm can't unlink itself on some
472963d66acSmrg        # systems and the destination file might be busy for other
473963d66acSmrg        # reasons.  In this case, the final cleanup might fail but the new
474963d66acSmrg        # file should still install successfully.
475963d66acSmrg        {
476963d66acSmrg          test ! -f "$dst" ||
477963d66acSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
478963d66acSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
479963d66acSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
480963d66acSmrg          } ||
481963d66acSmrg          { echo "$0: cannot unlink or rename $dst" >&2
482963d66acSmrg            (exit 1); exit 1
483963d66acSmrg          }
484963d66acSmrg        } &&
485963d66acSmrg
486963d66acSmrg        # Now rename the file to the real destination.
487963d66acSmrg        $doit $mvcmd "$dsttmp" "$dst"
4887e6fb56fSmrg      }
4897e6fb56fSmrg    fi || exit 1
4907e6fb56fSmrg
4917e6fb56fSmrg    trap '' 0
4927e6fb56fSmrg  fi
4937e6fb56fSmrgdone
4947e6fb56fSmrg
4957e6fb56fSmrg# Local variables:
4967e6fb56fSmrg# eval: (add-hook 'write-file-hooks 'time-stamp)
4977e6fb56fSmrg# time-stamp-start: "scriptversion="
4987e6fb56fSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
4997e6fb56fSmrg# time-stamp-time-zone: "UTC"
5007e6fb56fSmrg# time-stamp-end: "; # UTC"
5017e6fb56fSmrg# End:
502