install-sh revision b8414663
17d5e3a19Smrg#!/bin/sh
27d5e3a19Smrg# install - install a program, script, or datafile
37d5e3a19Smrg
4b8414663Smrgscriptversion=2013-12-25.23; # UTC
57d5e3a19Smrg
67d5e3a19Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
77d5e3a19Smrg# later released in X11R6 (xc/config/util/install.sh) with the
87d5e3a19Smrg# following copyright and license.
97d5e3a19Smrg#
107d5e3a19Smrg# Copyright (C) 1994 X Consortium
117d5e3a19Smrg#
127d5e3a19Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
137d5e3a19Smrg# of this software and associated documentation files (the "Software"), to
147d5e3a19Smrg# deal in the Software without restriction, including without limitation the
157d5e3a19Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
167d5e3a19Smrg# sell copies of the Software, and to permit persons to whom the Software is
177d5e3a19Smrg# furnished to do so, subject to the following conditions:
187d5e3a19Smrg#
197d5e3a19Smrg# The above copyright notice and this permission notice shall be included in
207d5e3a19Smrg# all copies or substantial portions of the Software.
217d5e3a19Smrg#
227d5e3a19Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
237d5e3a19Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
247d5e3a19Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
257d5e3a19Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
267d5e3a19Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
277d5e3a19Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
287d5e3a19Smrg#
297d5e3a19Smrg# Except as contained in this notice, the name of the X Consortium shall not
307d5e3a19Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
317d5e3a19Smrg# ings in this Software without prior written authorization from the X Consor-
327d5e3a19Smrg# tium.
337d5e3a19Smrg#
347d5e3a19Smrg#
357d5e3a19Smrg# FSF changes to this file are in the public domain.
367d5e3a19Smrg#
377d5e3a19Smrg# Calling this script install-sh is preferred over install.sh, to prevent
38b8414663Smrg# 'make' implicit rules from creating a file called install from it
397d5e3a19Smrg# when there is no Makefile.
407d5e3a19Smrg#
417d5e3a19Smrg# This script is compatible with the BSD install script, but was written
427d5e3a19Smrg# from scratch.
437d5e3a19Smrg
44b8414663Smrgtab='	'
457d5e3a19Smrgnl='
467d5e3a19Smrg'
47b8414663SmrgIFS=" $tab$nl"
487d5e3a19Smrg
49b8414663Smrg# Set DOITPROG to "echo" to test this script.
507d5e3a19Smrg
511568b75bSmrgdoit=${DOITPROG-}
52b8414663Smrgdoit_exec=${doit:-exec}
537d5e3a19Smrg
547d5e3a19Smrg# Put in absolute file names if you don't have them in your path;
557d5e3a19Smrg# or use environment vars.
567d5e3a19Smrg
571568b75bSmrgchgrpprog=${CHGRPPROG-chgrp}
581568b75bSmrgchmodprog=${CHMODPROG-chmod}
591568b75bSmrgchownprog=${CHOWNPROG-chown}
601568b75bSmrgcmpprog=${CMPPROG-cmp}
611568b75bSmrgcpprog=${CPPROG-cp}
621568b75bSmrgmkdirprog=${MKDIRPROG-mkdir}
631568b75bSmrgmvprog=${MVPROG-mv}
641568b75bSmrgrmprog=${RMPROG-rm}
651568b75bSmrgstripprog=${STRIPPROG-strip}
661568b75bSmrg
677d5e3a19Smrgposix_mkdir=
687d5e3a19Smrg
697d5e3a19Smrg# Desired mode of installed file.
707d5e3a19Smrgmode=0755
717d5e3a19Smrg
721568b75bSmrgchgrpcmd=
737d5e3a19Smrgchmodcmd=$chmodprog
747d5e3a19Smrgchowncmd=
751568b75bSmrgmvcmd=$mvprog
767d5e3a19Smrgrmcmd="$rmprog -f"
771568b75bSmrgstripcmd=
781568b75bSmrg
797d5e3a19Smrgsrc=
807d5e3a19Smrgdst=
817d5e3a19Smrgdir_arg=
821568b75bSmrgdst_arg=
831568b75bSmrg
841568b75bSmrgcopy_on_change=false
85b8414663Smrgis_target_a_directory=possibly
867d5e3a19Smrg
871568b75bSmrgusage="\
881568b75bSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
897d5e3a19Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
907d5e3a19Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
917d5e3a19Smrg   or: $0 [OPTION]... -d DIRECTORIES...
927d5e3a19Smrg
937d5e3a19SmrgIn the 1st form, copy SRCFILE to DSTFILE.
947d5e3a19SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
957d5e3a19SmrgIn the 4th, create DIRECTORIES.
967d5e3a19Smrg
977d5e3a19SmrgOptions:
981568b75bSmrg     --help     display this help and exit.
991568b75bSmrg     --version  display version info and exit.
1001568b75bSmrg
1011568b75bSmrg  -c            (ignored)
1021568b75bSmrg  -C            install only if different (preserve the last data modification time)
1031568b75bSmrg  -d            create directories instead of installing files.
1041568b75bSmrg  -g GROUP      $chgrpprog installed files to GROUP.
1051568b75bSmrg  -m MODE       $chmodprog installed files to MODE.
1061568b75bSmrg  -o USER       $chownprog installed files to USER.
1071568b75bSmrg  -s            $stripprog installed files.
1081568b75bSmrg  -t DIRECTORY  install into DIRECTORY.
1091568b75bSmrg  -T            report an error if DSTFILE is a directory.
1107d5e3a19Smrg
1117d5e3a19SmrgEnvironment variables override the default commands:
1121568b75bSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
1131568b75bSmrg  RMPROG STRIPPROG
1147d5e3a19Smrg"
1157d5e3a19Smrg
1167d5e3a19Smrgwhile test $# -ne 0; do
1177d5e3a19Smrg  case $1 in
1181568b75bSmrg    -c) ;;
1191568b75bSmrg
1201568b75bSmrg    -C) copy_on_change=true;;
1217d5e3a19Smrg
1221568b75bSmrg    -d) dir_arg=true;;
1237d5e3a19Smrg
1247d5e3a19Smrg    -g) chgrpcmd="$chgrpprog $2"
125b8414663Smrg        shift;;
1267d5e3a19Smrg
1277d5e3a19Smrg    --help) echo "$usage"; exit $?;;
1287d5e3a19Smrg
1297d5e3a19Smrg    -m) mode=$2
130b8414663Smrg        case $mode in
131b8414663Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132b8414663Smrg            echo "$0: invalid mode: $mode" >&2
133b8414663Smrg            exit 1;;
134b8414663Smrg        esac
135b8414663Smrg        shift;;
1367d5e3a19Smrg
1377d5e3a19Smrg    -o) chowncmd="$chownprog $2"
138b8414663Smrg        shift;;
1397d5e3a19Smrg
1401568b75bSmrg    -s) stripcmd=$stripprog;;
1417d5e3a19Smrg
142b8414663Smrg    -t)
143b8414663Smrg        is_target_a_directory=always
144b8414663Smrg        dst_arg=$2
145b8414663Smrg        # Protect names problematic for 'test' and other utilities.
146b8414663Smrg        case $dst_arg in
147b8414663Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
148b8414663Smrg        esac
149b8414663Smrg        shift;;
1507d5e3a19Smrg
151b8414663Smrg    -T) is_target_a_directory=never;;
1527d5e3a19Smrg
1537d5e3a19Smrg    --version) echo "$0 $scriptversion"; exit $?;;
1547d5e3a19Smrg
155b8414663Smrg    --) shift
156b8414663Smrg        break;;
1577d5e3a19Smrg
158b8414663Smrg    -*) echo "$0: invalid option: $1" >&2
159b8414663Smrg        exit 1;;
1607d5e3a19Smrg
1617d5e3a19Smrg    *)  break;;
1627d5e3a19Smrg  esac
1631568b75bSmrg  shift
1647d5e3a19Smrgdone
1657d5e3a19Smrg
166b8414663Smrg# We allow the use of options -d and -T together, by making -d
167b8414663Smrg# take the precedence; this is for compatibility with GNU install.
168b8414663Smrg
169b8414663Smrgif test -n "$dir_arg"; then
170b8414663Smrg  if test -n "$dst_arg"; then
171b8414663Smrg    echo "$0: target directory not allowed when installing a directory." >&2
172b8414663Smrg    exit 1
173b8414663Smrg  fi
174b8414663Smrgfi
175b8414663Smrg
1761568b75bSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
1777d5e3a19Smrg  # When -d is used, all remaining arguments are directories to create.
1787d5e3a19Smrg  # When -t is used, the destination is already specified.
1797d5e3a19Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
1807d5e3a19Smrg  for arg
1817d5e3a19Smrg  do
1821568b75bSmrg    if test -n "$dst_arg"; then
1837d5e3a19Smrg      # $@ is not empty: it contains at least $arg.
1841568b75bSmrg      set fnord "$@" "$dst_arg"
1857d5e3a19Smrg      shift # fnord
1867d5e3a19Smrg    fi
1877d5e3a19Smrg    shift # arg
1881568b75bSmrg    dst_arg=$arg
189b8414663Smrg    # Protect names problematic for 'test' and other utilities.
190b8414663Smrg    case $dst_arg in
191b8414663Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
192b8414663Smrg    esac
1937d5e3a19Smrg  done
1947d5e3a19Smrgfi
1957d5e3a19Smrg
1967d5e3a19Smrgif test $# -eq 0; then
1977d5e3a19Smrg  if test -z "$dir_arg"; then
1987d5e3a19Smrg    echo "$0: no input file specified." >&2
1997d5e3a19Smrg    exit 1
2007d5e3a19Smrg  fi
201b8414663Smrg  # It's OK to call 'install-sh -d' without argument.
2027d5e3a19Smrg  # This can happen when creating conditional directories.
2037d5e3a19Smrg  exit 0
2047d5e3a19Smrgfi
2057d5e3a19Smrg
2067d5e3a19Smrgif test -z "$dir_arg"; then
207b8414663Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
208b8414663Smrg    if test ! -d "$dst_arg"; then
209b8414663Smrg      echo "$0: $dst_arg: Is not a directory." >&2
210b8414663Smrg      exit 1
211b8414663Smrg    fi
212b8414663Smrg  fi
213b8414663Smrgfi
214b8414663Smrg
215b8414663Smrgif test -z "$dir_arg"; then
216b8414663Smrg  do_exit='(exit $ret); exit $ret'
217b8414663Smrg  trap "ret=129; $do_exit" 1
218b8414663Smrg  trap "ret=130; $do_exit" 2
219b8414663Smrg  trap "ret=141; $do_exit" 13
220b8414663Smrg  trap "ret=143; $do_exit" 15
2217d5e3a19Smrg
2227d5e3a19Smrg  # Set umask so as not to create temps with too-generous modes.
2237d5e3a19Smrg  # However, 'strip' requires both read and write access to temps.
2247d5e3a19Smrg  case $mode in
2257d5e3a19Smrg    # Optimize common cases.
2267d5e3a19Smrg    *644) cp_umask=133;;
2277d5e3a19Smrg    *755) cp_umask=22;;
2287d5e3a19Smrg
2297d5e3a19Smrg    *[0-7])
2307d5e3a19Smrg      if test -z "$stripcmd"; then
231b8414663Smrg        u_plus_rw=
2327d5e3a19Smrg      else
233b8414663Smrg        u_plus_rw='% 200'
2347d5e3a19Smrg      fi
2357d5e3a19Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2367d5e3a19Smrg    *)
2377d5e3a19Smrg      if test -z "$stripcmd"; then
238b8414663Smrg        u_plus_rw=
2397d5e3a19Smrg      else
240b8414663Smrg        u_plus_rw=,u+rw
2417d5e3a19Smrg      fi
2427d5e3a19Smrg      cp_umask=$mode$u_plus_rw;;
2437d5e3a19Smrg  esac
2447d5e3a19Smrgfi
2457d5e3a19Smrg
2467d5e3a19Smrgfor src
2477d5e3a19Smrgdo
248b8414663Smrg  # Protect names problematic for 'test' and other utilities.
2497d5e3a19Smrg  case $src in
250b8414663Smrg    -* | [=\(\)!]) src=./$src;;
2517d5e3a19Smrg  esac
2527d5e3a19Smrg
2537d5e3a19Smrg  if test -n "$dir_arg"; then
2547d5e3a19Smrg    dst=$src
2557d5e3a19Smrg    dstdir=$dst
2567d5e3a19Smrg    test -d "$dstdir"
2577d5e3a19Smrg    dstdir_status=$?
2587d5e3a19Smrg  else
2597d5e3a19Smrg
2607d5e3a19Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
2617d5e3a19Smrg    # might cause directories to be created, which would be especially bad
2627d5e3a19Smrg    # if $src (and thus $dsttmp) contains '*'.
2637d5e3a19Smrg    if test ! -f "$src" && test ! -d "$src"; then
2647d5e3a19Smrg      echo "$0: $src does not exist." >&2
2657d5e3a19Smrg      exit 1
2667d5e3a19Smrg    fi
2677d5e3a19Smrg
2681568b75bSmrg    if test -z "$dst_arg"; then
2697d5e3a19Smrg      echo "$0: no destination specified." >&2
2707d5e3a19Smrg      exit 1
2717d5e3a19Smrg    fi
2721568b75bSmrg    dst=$dst_arg
2737d5e3a19Smrg
2747d5e3a19Smrg    # If destination is a directory, append the input filename; won't work
2757d5e3a19Smrg    # if double slashes aren't ignored.
2767d5e3a19Smrg    if test -d "$dst"; then
277b8414663Smrg      if test "$is_target_a_directory" = never; then
278b8414663Smrg        echo "$0: $dst_arg: Is a directory" >&2
279b8414663Smrg        exit 1
2807d5e3a19Smrg      fi
2817d5e3a19Smrg      dstdir=$dst
2827d5e3a19Smrg      dst=$dstdir/`basename "$src"`
2837d5e3a19Smrg      dstdir_status=0
2847d5e3a19Smrg    else
285b8414663Smrg      dstdir=`dirname "$dst"`
2867d5e3a19Smrg      test -d "$dstdir"
2877d5e3a19Smrg      dstdir_status=$?
2887d5e3a19Smrg    fi
2897d5e3a19Smrg  fi
2907d5e3a19Smrg
2917d5e3a19Smrg  obsolete_mkdir_used=false
2927d5e3a19Smrg
2937d5e3a19Smrg  if test $dstdir_status != 0; then
2947d5e3a19Smrg    case $posix_mkdir in
2957d5e3a19Smrg      '')
296b8414663Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
297b8414663Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
298b8414663Smrg        umask=`umask`
299b8414663Smrg        case $stripcmd.$umask in
300b8414663Smrg          # Optimize common cases.
301b8414663Smrg          *[2367][2367]) mkdir_umask=$umask;;
302b8414663Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
303b8414663Smrg
304b8414663Smrg          *[0-7])
305b8414663Smrg            mkdir_umask=`expr $umask + 22 \
306b8414663Smrg              - $umask % 100 % 40 + $umask % 20 \
307b8414663Smrg              - $umask % 10 % 4 + $umask % 2
308b8414663Smrg            `;;
309b8414663Smrg          *) mkdir_umask=$umask,go-w;;
310b8414663Smrg        esac
311b8414663Smrg
312b8414663Smrg        # With -d, create the new directory with the user-specified mode.
313b8414663Smrg        # Otherwise, rely on $mkdir_umask.
314b8414663Smrg        if test -n "$dir_arg"; then
315b8414663Smrg          mkdir_mode=-m$mode
316b8414663Smrg        else
317b8414663Smrg          mkdir_mode=
318b8414663Smrg        fi
319b8414663Smrg
320b8414663Smrg        posix_mkdir=false
321b8414663Smrg        case $umask in
322b8414663Smrg          *[123567][0-7][0-7])
323b8414663Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
324b8414663Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
325b8414663Smrg            ;;
326b8414663Smrg          *)
327b8414663Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
328b8414663Smrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
329b8414663Smrg
330b8414663Smrg            if (umask $mkdir_umask &&
331b8414663Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
332b8414663Smrg            then
333b8414663Smrg              if test -z "$dir_arg" || {
334b8414663Smrg                   # Check for POSIX incompatibilities with -m.
335b8414663Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
336b8414663Smrg                   # other-writable bit of parent directory when it shouldn't.
337b8414663Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
338b8414663Smrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
339b8414663Smrg                   case $ls_ld_tmpdir in
340b8414663Smrg                     d????-?r-*) different_mode=700;;
341b8414663Smrg                     d????-?--*) different_mode=755;;
342b8414663Smrg                     *) false;;
343b8414663Smrg                   esac &&
344b8414663Smrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
345b8414663Smrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
346b8414663Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
347b8414663Smrg                   }
348b8414663Smrg                 }
349b8414663Smrg              then posix_mkdir=:
350b8414663Smrg              fi
351b8414663Smrg              rmdir "$tmpdir/d" "$tmpdir"
352b8414663Smrg            else
353b8414663Smrg              # Remove any dirs left behind by ancient mkdir implementations.
354b8414663Smrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
355b8414663Smrg            fi
356b8414663Smrg            trap '' 0;;
357b8414663Smrg        esac;;
3587d5e3a19Smrg    esac
3597d5e3a19Smrg
3607d5e3a19Smrg    if
3617d5e3a19Smrg      $posix_mkdir && (
362b8414663Smrg        umask $mkdir_umask &&
363b8414663Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
3647d5e3a19Smrg      )
3657d5e3a19Smrg    then :
3667d5e3a19Smrg    else
3677d5e3a19Smrg
3687d5e3a19Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
3697d5e3a19Smrg      # or it failed possibly due to a race condition.  Create the
3707d5e3a19Smrg      # directory the slow way, step by step, checking for races as we go.
3717d5e3a19Smrg
3727d5e3a19Smrg      case $dstdir in
373b8414663Smrg        /*) prefix='/';;
374b8414663Smrg        [-=\(\)!]*) prefix='./';;
375b8414663Smrg        *)  prefix='';;
3767d5e3a19Smrg      esac
3777d5e3a19Smrg
3787d5e3a19Smrg      oIFS=$IFS
3797d5e3a19Smrg      IFS=/
380b8414663Smrg      set -f
3817d5e3a19Smrg      set fnord $dstdir
3827d5e3a19Smrg      shift
383b8414663Smrg      set +f
3847d5e3a19Smrg      IFS=$oIFS
3857d5e3a19Smrg
3867d5e3a19Smrg      prefixes=
3877d5e3a19Smrg
3887d5e3a19Smrg      for d
3897d5e3a19Smrg      do
390b8414663Smrg        test X"$d" = X && continue
391b8414663Smrg
392b8414663Smrg        prefix=$prefix$d
393b8414663Smrg        if test -d "$prefix"; then
394b8414663Smrg          prefixes=
395b8414663Smrg        else
396b8414663Smrg          if $posix_mkdir; then
397b8414663Smrg            (umask=$mkdir_umask &&
398b8414663Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
399b8414663Smrg            # Don't fail if two instances are running concurrently.
400b8414663Smrg            test -d "$prefix" || exit 1
401b8414663Smrg          else
402b8414663Smrg            case $prefix in
403b8414663Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
404b8414663Smrg              *) qprefix=$prefix;;
405b8414663Smrg            esac
406b8414663Smrg            prefixes="$prefixes '$qprefix'"
407b8414663Smrg          fi
408b8414663Smrg        fi
409b8414663Smrg        prefix=$prefix/
4107d5e3a19Smrg      done
4117d5e3a19Smrg
4127d5e3a19Smrg      if test -n "$prefixes"; then
413b8414663Smrg        # Don't fail if two instances are running concurrently.
414b8414663Smrg        (umask $mkdir_umask &&
415b8414663Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
416b8414663Smrg          test -d "$dstdir" || exit 1
417b8414663Smrg        obsolete_mkdir_used=true
4187d5e3a19Smrg      fi
4197d5e3a19Smrg    fi
4207d5e3a19Smrg  fi
4217d5e3a19Smrg
4227d5e3a19Smrg  if test -n "$dir_arg"; then
4237d5e3a19Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
4247d5e3a19Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
4257d5e3a19Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
4267d5e3a19Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
4277d5e3a19Smrg  else
4287d5e3a19Smrg
4297d5e3a19Smrg    # Make a couple of temp file names in the proper directory.
4307d5e3a19Smrg    dsttmp=$dstdir/_inst.$$_
4317d5e3a19Smrg    rmtmp=$dstdir/_rm.$$_
4327d5e3a19Smrg
4337d5e3a19Smrg    # Trap to clean up those temp files at exit.
4347d5e3a19Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4357d5e3a19Smrg
4367d5e3a19Smrg    # Copy the file name to the temp name.
4377d5e3a19Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
4387d5e3a19Smrg
4397d5e3a19Smrg    # and set any options; do chmod last to preserve setuid bits.
4407d5e3a19Smrg    #
4417d5e3a19Smrg    # If any of these fail, we abort the whole thing.  If we want to
4427d5e3a19Smrg    # ignore errors from any of these, just make sure not to ignore
4437d5e3a19Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4447d5e3a19Smrg    #
4451568b75bSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
4461568b75bSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4471568b75bSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4481568b75bSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4491568b75bSmrg
4501568b75bSmrg    # If -C, don't bother to copy if it wouldn't change the file.
4511568b75bSmrg    if $copy_on_change &&
452b8414663Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
453b8414663Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
454b8414663Smrg       set -f &&
4551568b75bSmrg       set X $old && old=:$2:$4:$5:$6 &&
4561568b75bSmrg       set X $new && new=:$2:$4:$5:$6 &&
457b8414663Smrg       set +f &&
4581568b75bSmrg       test "$old" = "$new" &&
4591568b75bSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
4601568b75bSmrg    then
4611568b75bSmrg      rm -f "$dsttmp"
4621568b75bSmrg    else
4631568b75bSmrg      # Rename the file to the real destination.
4641568b75bSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4651568b75bSmrg
4661568b75bSmrg      # The rename failed, perhaps because mv can't rename something else
4671568b75bSmrg      # to itself, or perhaps because mv is so ancient that it does not
4681568b75bSmrg      # support -f.
4691568b75bSmrg      {
470b8414663Smrg        # Now remove or move aside any old file at destination location.
471b8414663Smrg        # We try this two ways since rm can't unlink itself on some
472b8414663Smrg        # systems and the destination file might be busy for other
473b8414663Smrg        # reasons.  In this case, the final cleanup might fail but the new
474b8414663Smrg        # file should still install successfully.
475b8414663Smrg        {
476b8414663Smrg          test ! -f "$dst" ||
477b8414663Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
478b8414663Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
479b8414663Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
480b8414663Smrg          } ||
481b8414663Smrg          { echo "$0: cannot unlink or rename $dst" >&2
482b8414663Smrg            (exit 1); exit 1
483b8414663Smrg          }
484b8414663Smrg        } &&
485b8414663Smrg
486b8414663Smrg        # Now rename the file to the real destination.
487b8414663Smrg        $doit $mvcmd "$dsttmp" "$dst"
4881568b75bSmrg      }
4891568b75bSmrg    fi || exit 1
4907d5e3a19Smrg
4917d5e3a19Smrg    trap '' 0
4927d5e3a19Smrg  fi
4937d5e3a19Smrgdone
4947d5e3a19Smrg
4957d5e3a19Smrg# Local variables:
4967d5e3a19Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
4977d5e3a19Smrg# time-stamp-start: "scriptversion="
4987d5e3a19Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
499765486e8Smrg# time-stamp-time-zone: "UTC"
500765486e8Smrg# time-stamp-end: "; # UTC"
5017d5e3a19Smrg# End:
502