install-sh revision d94624a0
14b0ead49Smrg#!/bin/sh
24b0ead49Smrg# install - install a program, script, or datafile
34b0ead49Smrg
4c3e29c03Smrgscriptversion=2014-09-12.12; # UTC
54b0ead49Smrg
64b0ead49Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
74b0ead49Smrg# later released in X11R6 (xc/config/util/install.sh) with the
84b0ead49Smrg# following copyright and license.
94b0ead49Smrg#
104b0ead49Smrg# Copyright (C) 1994 X Consortium
114b0ead49Smrg#
124b0ead49Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
134b0ead49Smrg# of this software and associated documentation files (the "Software"), to
144b0ead49Smrg# deal in the Software without restriction, including without limitation the
154b0ead49Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
164b0ead49Smrg# sell copies of the Software, and to permit persons to whom the Software is
174b0ead49Smrg# furnished to do so, subject to the following conditions:
184b0ead49Smrg#
194b0ead49Smrg# The above copyright notice and this permission notice shall be included in
204b0ead49Smrg# all copies or substantial portions of the Software.
214b0ead49Smrg#
224b0ead49Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
234b0ead49Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
244b0ead49Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
254b0ead49Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
264b0ead49Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
274b0ead49Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
284b0ead49Smrg#
294b0ead49Smrg# Except as contained in this notice, the name of the X Consortium shall not
304b0ead49Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
314b0ead49Smrg# ings in this Software without prior written authorization from the X Consor-
324b0ead49Smrg# tium.
334b0ead49Smrg#
344b0ead49Smrg#
354b0ead49Smrg# FSF changes to this file are in the public domain.
364b0ead49Smrg#
374b0ead49Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3826372658Smrg# 'make' implicit rules from creating a file called install from it
394b0ead49Smrg# when there is no Makefile.
404b0ead49Smrg#
414b0ead49Smrg# This script is compatible with the BSD install script, but was written
4252b01e16Smrg# from scratch.
4352b01e16Smrg
4426372658Smrgtab='	'
4552b01e16Smrgnl='
4652b01e16Smrg'
4726372658SmrgIFS=" $tab$nl"
484b0ead49Smrg
4926372658Smrg# Set DOITPROG to "echo" to test this script.
504b0ead49Smrg
5152b01e16Smrgdoit=${DOITPROG-}
5226372658Smrgdoit_exec=${doit:-exec}
534b0ead49Smrg
5452b01e16Smrg# Put in absolute file names if you don't have them in your path;
5552b01e16Smrg# or use environment vars.
5652b01e16Smrg
5752b01e16Smrgchgrpprog=${CHGRPPROG-chgrp}
5852b01e16Smrgchmodprog=${CHMODPROG-chmod}
5952b01e16Smrgchownprog=${CHOWNPROG-chown}
6052b01e16Smrgcmpprog=${CMPPROG-cmp}
6152b01e16Smrgcpprog=${CPPROG-cp}
6252b01e16Smrgmkdirprog=${MKDIRPROG-mkdir}
6352b01e16Smrgmvprog=${MVPROG-mv}
6452b01e16Smrgrmprog=${RMPROG-rm}
6552b01e16Smrgstripprog=${STRIPPROG-strip}
6652b01e16Smrg
6752b01e16Smrgposix_mkdir=
6852b01e16Smrg
6952b01e16Smrg# Desired mode of installed file.
7052b01e16Smrgmode=0755
714b0ead49Smrg
72c3e29c03Smrgchgrpcmd=
73c3e29c03Smrgchmodcmd=$chmodprog
74c3e29c03Smrgchowncmd=
75c3e29c03Smrgmvcmd=$mvprog
76c3e29c03Smrgrmcmd="$rmprog -f"
774b0ead49Smrgstripcmd=
7852b01e16Smrg
7952b01e16Smrgsrc=
8052b01e16Smrgdst=
814b0ead49Smrgdir_arg=
8252b01e16Smrgdst_arg=
8352b01e16Smrg
844b0ead49Smrgcopy_on_change=false
854b0ead49Smrgis_target_a_directory=possibly
864b0ead49Smrg
8752b01e16Smrgusage="\
8852b01e16SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
8952b01e16Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9026372658Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
914b0ead49Smrg   or: $0 [OPTION]... -d DIRECTORIES...
9252b01e16Smrg
9352b01e16SmrgIn the 1st form, copy SRCFILE to DSTFILE.
944b0ead49SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
954b0ead49SmrgIn the 4th, create DIRECTORIES.
964b0ead49Smrg
974b0ead49SmrgOptions:
984b0ead49Smrg     --help     display this help and exit.
994b0ead49Smrg     --version  display version info and exit.
1004b0ead49Smrg
1014b0ead49Smrg  -c            (ignored)
1024b0ead49Smrg  -C            install only if different (preserve the last data modification time)
10352b01e16Smrg  -d            create directories instead of installing files.
10452b01e16Smrg  -g GROUP      $chgrpprog installed files to GROUP.
10552b01e16Smrg  -m MODE       $chmodprog installed files to MODE.
10652b01e16Smrg  -o USER       $chownprog installed files to USER.
107c3e29c03Smrg  -s            $stripprog installed files.
10852b01e16Smrg  -t DIRECTORY  install into DIRECTORY.
10952b01e16Smrg  -T            report an error if DSTFILE is a directory.
11052b01e16Smrg
11152b01e16SmrgEnvironment variables override the default commands:
112c3e29c03Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
11352b01e16Smrg  RMPROG STRIPPROG
114c3e29c03Smrg"
11552b01e16Smrg
11652b01e16Smrgwhile test $# -ne 0; do
1174b0ead49Smrg  case $1 in
1184b0ead49Smrg    -c) ;;
11952b01e16Smrg
12052b01e16Smrg    -C) copy_on_change=true;;
121c3e29c03Smrg
122c3e29c03Smrg    -d) dir_arg=true;;
123c3e29c03Smrg
124c3e29c03Smrg    -g) chgrpcmd="$chgrpprog $2"
125c3e29c03Smrg        shift;;
126c3e29c03Smrg
127c3e29c03Smrg    --help) echo "$usage"; exit $?;;
128c3e29c03Smrg
1294b0ead49Smrg    -m) mode=$2
1304b0ead49Smrg        case $mode in
13152b01e16Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1324b0ead49Smrg            echo "$0: invalid mode: $mode" >&2
13352b01e16Smrg            exit 1;;
13452b01e16Smrg        esac
13552b01e16Smrg        shift;;
1364b0ead49Smrg
13752b01e16Smrg    -o) chowncmd="$chownprog $2"
1384b0ead49Smrg        shift;;
1394b0ead49Smrg
14026372658Smrg    -s) stripcmd=$stripprog;;
1414b0ead49Smrg
1424b0ead49Smrg    -t)
1434b0ead49Smrg        is_target_a_directory=always
14452b01e16Smrg        dst_arg=$2
14526372658Smrg        # Protect names problematic for 'test' and other utilities.
14626372658Smrg        case $dst_arg in
14726372658Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14826372658Smrg        esac
14926372658Smrg        shift;;
15026372658Smrg
1514b0ead49Smrg    -T) is_target_a_directory=never;;
1524b0ead49Smrg
15326372658Smrg    --version) echo "$0 $scriptversion"; exit $?;;
1544b0ead49Smrg
155c3e29c03Smrg    --) shift
156c3e29c03Smrg        break;;
15752b01e16Smrg
1584b0ead49Smrg    -*) echo "$0: invalid option: $1" >&2
159c3e29c03Smrg        exit 1;;
160c3e29c03Smrg
161c3e29c03Smrg    *)  break;;
16226372658Smrg  esac
16326372658Smrg  shift
16426372658Smrgdone
16526372658Smrg
16626372658Smrg# We allow the use of options -d and -T together, by making -d
16726372658Smrg# take the precedence; this is for compatibility with GNU install.
16826372658Smrg
16926372658Smrgif test -n "$dir_arg"; then
1704b0ead49Smrg  if test -n "$dst_arg"; then
17126372658Smrg    echo "$0: target directory not allowed when installing a directory." >&2
1724b0ead49Smrg    exit 1
1734b0ead49Smrg  fi
1744b0ead49Smrgfi
17526372658Smrg
17626372658Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
17752b01e16Smrg  # When -d is used, all remaining arguments are directories to create.
17826372658Smrg  # When -t is used, the destination is already specified.
17926372658Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
18052b01e16Smrg  for arg
18152b01e16Smrg  do
1824b0ead49Smrg    if test -n "$dst_arg"; then
18352b01e16Smrg      # $@ is not empty: it contains at least $arg.
1844b0ead49Smrg      set fnord "$@" "$dst_arg"
1854b0ead49Smrg      shift # fnord
18626372658Smrg    fi
18726372658Smrg    shift # arg
18826372658Smrg    dst_arg=$arg
18926372658Smrg    # Protect names problematic for 'test' and other utilities.
19026372658Smrg    case $dst_arg in
19126372658Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19226372658Smrg    esac
19326372658Smrg  done
19426372658Smrgfi
19526372658Smrg
19652b01e16Smrgif test $# -eq 0; then
19752b01e16Smrg  if test -z "$dir_arg"; then
19852b01e16Smrg    echo "$0: no input file specified." >&2
19952b01e16Smrg    exit 1
20052b01e16Smrg  fi
20152b01e16Smrg  # It's OK to call 'install-sh -d' without argument.
20252b01e16Smrg  # This can happen when creating conditional directories.
20352b01e16Smrg  exit 0
20452b01e16Smrgfi
20552b01e16Smrg
20652b01e16Smrgif test -z "$dir_arg"; then
20752b01e16Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20852b01e16Smrg    if test ! -d "$dst_arg"; then
20926372658Smrg      echo "$0: $dst_arg: Is not a directory." >&2
2104e7590efSmrg      exit 1
2114e7590efSmrg    fi
2124e7590efSmrg  fi
21352b01e16Smrgfi
21452b01e16Smrg
21552b01e16Smrgif test -z "$dir_arg"; then
21652b01e16Smrg  do_exit='(exit $ret); exit $ret'
2174b0ead49Smrg  trap "ret=129; $do_exit" 1
2184b0ead49Smrg  trap "ret=130; $do_exit" 2
2194b0ead49Smrg  trap "ret=141; $do_exit" 13
2204b0ead49Smrg  trap "ret=143; $do_exit" 15
22126372658Smrg
2224b0ead49Smrg  # Set umask so as not to create temps with too-generous modes.
2234b0ead49Smrg  # However, 'strip' requires both read and write access to temps.
2244b0ead49Smrg  case $mode in
2254b0ead49Smrg    # Optimize common cases.
22626372658Smrg    *644) cp_umask=133;;
22726372658Smrg    *755) cp_umask=22;;
22826372658Smrg
22926372658Smrg    *[0-7])
23026372658Smrg      if test -z "$stripcmd"; then
23126372658Smrg        u_plus_rw=
23226372658Smrg      else
23326372658Smrg        u_plus_rw='% 200'
23426372658Smrg      fi
23552b01e16Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
2364e7590efSmrg    *)
2374e7590efSmrg      if test -z "$stripcmd"; then
2384e7590efSmrg        u_plus_rw=
2394e7590efSmrg      else
2404e7590efSmrg        u_plus_rw=,u+rw
24152b01e16Smrg      fi
24252b01e16Smrg      cp_umask=$mode$u_plus_rw;;
24352b01e16Smrg  esac
24452b01e16Smrgfi
24552b01e16Smrg
24652b01e16Smrgfor src
24752b01e16Smrgdo
24852b01e16Smrg  # Protect names problematic for 'test' and other utilities.
24952b01e16Smrg  case $src in
25052b01e16Smrg    -* | [=\(\)!]) src=./$src;;
25126372658Smrg  esac
25252b01e16Smrg
25326372658Smrg  if test -n "$dir_arg"; then
25452b01e16Smrg    dst=$src
25552b01e16Smrg    dstdir=$dst
25652b01e16Smrg    test -d "$dstdir"
25752b01e16Smrg    dstdir_status=$?
25826372658Smrg  else
25952b01e16Smrg
26026372658Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
26152b01e16Smrg    # might cause directories to be created, which would be especially bad
26252b01e16Smrg    # if $src (and thus $dsttmp) contains '*'.
26352b01e16Smrg    if test ! -f "$src" && test ! -d "$src"; then
26452b01e16Smrg      echo "$0: $src does not exist." >&2
26552b01e16Smrg      exit 1
2664b0ead49Smrg    fi
2674b0ead49Smrg
26826372658Smrg    if test -z "$dst_arg"; then
2694b0ead49Smrg      echo "$0: no destination specified." >&2
2704e7590efSmrg      exit 1
2714b0ead49Smrg    fi
2724b0ead49Smrg    dst=$dst_arg
2734b0ead49Smrg
2744b0ead49Smrg    # If destination is a directory, append the input filename; won't work
27552b01e16Smrg    # if double slashes aren't ignored.
27652b01e16Smrg    if test -d "$dst"; then
27752b01e16Smrg      if test "$is_target_a_directory" = never; then
278c3e29c03Smrg        echo "$0: $dst_arg: Is a directory" >&2
279c3e29c03Smrg        exit 1
280c3e29c03Smrg      fi
281c3e29c03Smrg      dstdir=$dst
2824b0ead49Smrg      dst=$dstdir/`basename "$src"`
28352b01e16Smrg      dstdir_status=0
2844b0ead49Smrg    else
2854b0ead49Smrg      dstdir=`dirname "$dst"`
2864b0ead49Smrg      test -d "$dstdir"
2874b0ead49Smrg      dstdir_status=$?
2884b0ead49Smrg    fi
2894b0ead49Smrg  fi
2904b0ead49Smrg
2914b0ead49Smrg  obsolete_mkdir_used=false
29252b01e16Smrg
2934b0ead49Smrg  if test $dstdir_status != 0; then
2944b0ead49Smrg    case $posix_mkdir in
2954b0ead49Smrg      '')
29652b01e16Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
2974b0ead49Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
298c3e29c03Smrg        umask=`umask`
2994b0ead49Smrg        case $stripcmd.$umask in
30026372658Smrg          # Optimize common cases.
30126372658Smrg          *[2367][2367]) mkdir_umask=$umask;;
30226372658Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3034b0ead49Smrg
30452b01e16Smrg          *[0-7])
305c3e29c03Smrg            mkdir_umask=`expr $umask + 22 \
306c3e29c03Smrg              - $umask % 100 % 40 + $umask % 20 \
307c3e29c03Smrg              - $umask % 10 % 4 + $umask % 2
308c3e29c03Smrg            `;;
309c3e29c03Smrg          *) mkdir_umask=$umask,go-w;;
31052b01e16Smrg        esac
31152b01e16Smrg
31226372658Smrg        # With -d, create the new directory with the user-specified mode.
31352b01e16Smrg        # Otherwise, rely on $mkdir_umask.
31452b01e16Smrg        if test -n "$dir_arg"; then
3154b0ead49Smrg          mkdir_mode=-m$mode
3164b0ead49Smrg        else
3174b0ead49Smrg          mkdir_mode=
318c3e29c03Smrg        fi
319c3e29c03Smrg
320c3e29c03Smrg        posix_mkdir=false
321c3e29c03Smrg        case $umask in
322c3e29c03Smrg          *[123567][0-7][0-7])
32352b01e16Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
32452b01e16Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
32552b01e16Smrg            ;;
32652b01e16Smrg          *)
32752b01e16Smrg            # $RANDOM is not portable (e.g. dash);  use it when possible to
32826372658Smrg            # lower collision chance
32926372658Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
33026372658Smrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
33126372658Smrg
33226372658Smrg            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
33326372658Smrg            # create the $tmpdir first (and fail if unsuccessful) to make sure
33426372658Smrg            # that nobody tries to guess the $tmpdir name.
33526372658Smrg            if (umask $mkdir_umask &&
33626372658Smrg                $mkdirprog $mkdir_mode "$tmpdir" &&
337c3e29c03Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
338c3e29c03Smrg            then
339c3e29c03Smrg              if test -z "$dir_arg" || {
340c3e29c03Smrg                   # Check for POSIX incompatibilities with -m.
341c3e29c03Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
342c3e29c03Smrg                   # other-writable bit of parent directory when it shouldn't.
343c3e29c03Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
344c3e29c03Smrg                   test_tmpdir="$tmpdir/a"
345c3e29c03Smrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
346c3e29c03Smrg                   case $ls_ld_tmpdir in
347c3e29c03Smrg                     d????-?r-*) different_mode=700;;
348c3e29c03Smrg                     d????-?--*) different_mode=755;;
349c3e29c03Smrg                     *) false;;
350c3e29c03Smrg                   esac &&
351c3e29c03Smrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
352c3e29c03Smrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
353c3e29c03Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
354c3e29c03Smrg                   }
355c3e29c03Smrg                 }
356c3e29c03Smrg              then posix_mkdir=:
357c3e29c03Smrg              fi
358c3e29c03Smrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
359c3e29c03Smrg            else
360c3e29c03Smrg              # Remove any dirs left behind by ancient mkdir implementations.
361c3e29c03Smrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
362c3e29c03Smrg            fi
363c3e29c03Smrg            trap '' 0;;
364c3e29c03Smrg        esac;;
365c3e29c03Smrg    esac
366c3e29c03Smrg
367c3e29c03Smrg    if
368c3e29c03Smrg      $posix_mkdir && (
369c3e29c03Smrg        umask $mkdir_umask &&
370c3e29c03Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
371c3e29c03Smrg      )
372c3e29c03Smrg    then :
373c3e29c03Smrg    else
374c3e29c03Smrg
375c3e29c03Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
376c3e29c03Smrg      # or it failed possibly due to a race condition.  Create the
377c3e29c03Smrg      # directory the slow way, step by step, checking for races as we go.
378c3e29c03Smrg
379c3e29c03Smrg      case $dstdir in
38052b01e16Smrg        /*) prefix='/';;
3814b0ead49Smrg        [-=\(\)!]*) prefix='./';;
38252b01e16Smrg        *)  prefix='';;
38352b01e16Smrg      esac
38426372658Smrg
38526372658Smrg      oIFS=$IFS
38652b01e16Smrg      IFS=/
38752b01e16Smrg      set -f
38852b01e16Smrg      set fnord $dstdir
3894b0ead49Smrg      shift
390c3e29c03Smrg      set +f
39152b01e16Smrg      IFS=$oIFS
39252b01e16Smrg
3934b0ead49Smrg      prefixes=
39452b01e16Smrg
39526372658Smrg      for d
39626372658Smrg      do
39726372658Smrg        test X"$d" = X && continue
39852b01e16Smrg
3994b0ead49Smrg        prefix=$prefix$d
40052b01e16Smrg        if test -d "$prefix"; then
40152b01e16Smrg          prefixes=
40226372658Smrg        else
40352b01e16Smrg          if $posix_mkdir; then
4044b0ead49Smrg            (umask=$mkdir_umask &&
40526372658Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
40652b01e16Smrg            # Don't fail if two instances are running concurrently.
40752b01e16Smrg            test -d "$prefix" || exit 1
40852b01e16Smrg          else
40952b01e16Smrg            case $prefix in
41052b01e16Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
41152b01e16Smrg              *) qprefix=$prefix;;
41226372658Smrg            esac
41326372658Smrg            prefixes="$prefixes '$qprefix'"
41426372658Smrg          fi
41526372658Smrg        fi
41626372658Smrg        prefix=$prefix/
41726372658Smrg      done
41826372658Smrg
419c3e29c03Smrg      if test -n "$prefixes"; then
42026372658Smrg        # Don't fail if two instances are running concurrently.
42126372658Smrg        (umask $mkdir_umask &&
42226372658Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
42326372658Smrg          test -d "$dstdir" || exit 1
42426372658Smrg        obsolete_mkdir_used=true
42526372658Smrg      fi
42626372658Smrg    fi
42726372658Smrg  fi
42826372658Smrg
42926372658Smrg  if test -n "$dir_arg"; then
43026372658Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
43126372658Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
43252b01e16Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
43352b01e16Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
43452b01e16Smrg  else
43526372658Smrg
43626372658Smrg    # Make a couple of temp file names in the proper directory.
43726372658Smrg    dsttmp=$dstdir/_inst.$$_
43826372658Smrg    rmtmp=$dstdir/_rm.$$_
43926372658Smrg
4404b0ead49Smrg    # Trap to clean up those temp files at exit.
44152b01e16Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
4424b0ead49Smrg
4434b0ead49Smrg    # Copy the file name to the temp name.
4444b0ead49Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
44552b01e16Smrg
44652b01e16Smrg    # and set any options; do chmod last to preserve setuid bits.
44752b01e16Smrg    #
44852b01e16Smrg    # If any of these fail, we abort the whole thing.  If we want to
4494b0ead49Smrg    # ignore errors from any of these, just make sure not to ignore
4504b0ead49Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
4514b0ead49Smrg    #
452c3e29c03Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
453c3e29c03Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
4544b0ead49Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
4554b0ead49Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
4564b0ead49Smrg
4574b0ead49Smrg    # If -C, don't bother to copy if it wouldn't change the file.
4584b0ead49Smrg    if $copy_on_change &&
459c3e29c03Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
460c3e29c03Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
461c3e29c03Smrg       set -f &&
462c3e29c03Smrg       set X $old && old=:$2:$4:$5:$6 &&
463c3e29c03Smrg       set X $new && new=:$2:$4:$5:$6 &&
464c3e29c03Smrg       set +f &&
465c3e29c03Smrg       test "$old" = "$new" &&
466c3e29c03Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
467c3e29c03Smrg    then
468c3e29c03Smrg      rm -f "$dsttmp"
469c3e29c03Smrg    else
470c3e29c03Smrg      # Rename the file to the real destination.
4714b0ead49Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
4724b0ead49Smrg
4734b0ead49Smrg      # The rename failed, perhaps because mv can't rename something else
4744b0ead49Smrg      # to itself, or perhaps because mv is so ancient that it does not
4754b0ead49Smrg      # support -f.
4764b0ead49Smrg      {
4774b0ead49Smrg        # Now remove or move aside any old file at destination location.
47852b01e16Smrg        # We try this two ways since rm can't unlink itself on some
47952b01e16Smrg        # systems and the destination file might be busy for other
48052b01e16Smrg        # reasons.  In this case, the final cleanup might fail but the new
48152b01e16Smrg        # file should still install successfully.
48252b01e16Smrg        {
48352b01e16Smrg          test ! -f "$dst" ||
48452b01e16Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
48526372658Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
48626372658Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
48726372658Smrg          } ||
48852b01e16Smrg          { echo "$0: cannot unlink or rename $dst" >&2
48952b01e16Smrg            (exit 1); exit 1
49026372658Smrg          }
49152b01e16Smrg        } &&
49252b01e16Smrg
49352b01e16Smrg        # Now rename the file to the real destination.
49452b01e16Smrg        $doit $mvcmd "$dsttmp" "$dst"
49552b01e16Smrg      }
496c3e29c03Smrg    fi || exit 1
497c3e29c03Smrg
498c3e29c03Smrg    trap '' 0
499c3e29c03Smrg  fi
500c3e29c03Smrgdone
501c3e29c03Smrg
502c3e29c03Smrg# Local variables:
50352b01e16Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
50452b01e16Smrg# time-stamp-start: "scriptversion="
50552b01e16Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
50652b01e16Smrg# time-stamp-time-zone: "UTC"
50752b01e16Smrg# time-stamp-end: "; # UTC"
50852b01e16Smrg# End:
50952b01e16Smrg