install-sh revision 0d16fef4
1de2362d3Smrg#!/bin/sh
2de2362d3Smrg# install - install a program, script, or datafile
3de2362d3Smrg
40d16fef4Smrgscriptversion=2014-09-12.12; # UTC
5de2362d3Smrg
6de2362d3Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7de2362d3Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8de2362d3Smrg# following copyright and license.
9de2362d3Smrg#
10de2362d3Smrg# Copyright (C) 1994 X Consortium
11de2362d3Smrg#
12de2362d3Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13de2362d3Smrg# of this software and associated documentation files (the "Software"), to
14de2362d3Smrg# deal in the Software without restriction, including without limitation the
15de2362d3Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16de2362d3Smrg# sell copies of the Software, and to permit persons to whom the Software is
17de2362d3Smrg# furnished to do so, subject to the following conditions:
18de2362d3Smrg#
19de2362d3Smrg# The above copyright notice and this permission notice shall be included in
20de2362d3Smrg# all copies or substantial portions of the Software.
21de2362d3Smrg#
22de2362d3Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23de2362d3Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24de2362d3Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25de2362d3Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26de2362d3Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27de2362d3Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28de2362d3Smrg#
29de2362d3Smrg# Except as contained in this notice, the name of the X Consortium shall not
30de2362d3Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31de2362d3Smrg# ings in this Software without prior written authorization from the X Consor-
32de2362d3Smrg# tium.
33de2362d3Smrg#
34de2362d3Smrg#
35de2362d3Smrg# FSF changes to this file are in the public domain.
36de2362d3Smrg#
37de2362d3Smrg# Calling this script install-sh is preferred over install.sh, to prevent
380d16fef4Smrg# 'make' implicit rules from creating a file called install from it
39de2362d3Smrg# when there is no Makefile.
40de2362d3Smrg#
41de2362d3Smrg# This script is compatible with the BSD install script, but was written
42de2362d3Smrg# from scratch.
43de2362d3Smrg
440d16fef4Smrgtab='	'
45de2362d3Smrgnl='
46de2362d3Smrg'
470d16fef4SmrgIFS=" $tab$nl"
48de2362d3Smrg
490d16fef4Smrg# Set DOITPROG to "echo" to test this script.
50de2362d3Smrg
51de2362d3Smrgdoit=${DOITPROG-}
520d16fef4Smrgdoit_exec=${doit:-exec}
53de2362d3Smrg
54de2362d3Smrg# Put in absolute file names if you don't have them in your path;
55de2362d3Smrg# or use environment vars.
56de2362d3Smrg
57de2362d3Smrgchgrpprog=${CHGRPPROG-chgrp}
58de2362d3Smrgchmodprog=${CHMODPROG-chmod}
59de2362d3Smrgchownprog=${CHOWNPROG-chown}
60de2362d3Smrgcmpprog=${CMPPROG-cmp}
61de2362d3Smrgcpprog=${CPPROG-cp}
62de2362d3Smrgmkdirprog=${MKDIRPROG-mkdir}
63de2362d3Smrgmvprog=${MVPROG-mv}
64de2362d3Smrgrmprog=${RMPROG-rm}
65de2362d3Smrgstripprog=${STRIPPROG-strip}
66de2362d3Smrg
67de2362d3Smrgposix_mkdir=
68de2362d3Smrg
69de2362d3Smrg# Desired mode of installed file.
70de2362d3Smrgmode=0755
71de2362d3Smrg
72de2362d3Smrgchgrpcmd=
73de2362d3Smrgchmodcmd=$chmodprog
74de2362d3Smrgchowncmd=
75de2362d3Smrgmvcmd=$mvprog
76de2362d3Smrgrmcmd="$rmprog -f"
77de2362d3Smrgstripcmd=
78de2362d3Smrg
79de2362d3Smrgsrc=
80de2362d3Smrgdst=
81de2362d3Smrgdir_arg=
82de2362d3Smrgdst_arg=
83de2362d3Smrg
84de2362d3Smrgcopy_on_change=false
850d16fef4Smrgis_target_a_directory=possibly
86de2362d3Smrg
87de2362d3Smrgusage="\
88de2362d3SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89de2362d3Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90de2362d3Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91de2362d3Smrg   or: $0 [OPTION]... -d DIRECTORIES...
92de2362d3Smrg
93de2362d3SmrgIn the 1st form, copy SRCFILE to DSTFILE.
94de2362d3SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95de2362d3SmrgIn the 4th, create DIRECTORIES.
96de2362d3Smrg
97de2362d3SmrgOptions:
98de2362d3Smrg     --help     display this help and exit.
99de2362d3Smrg     --version  display version info and exit.
100de2362d3Smrg
101de2362d3Smrg  -c            (ignored)
102de2362d3Smrg  -C            install only if different (preserve the last data modification time)
103de2362d3Smrg  -d            create directories instead of installing files.
104de2362d3Smrg  -g GROUP      $chgrpprog installed files to GROUP.
105de2362d3Smrg  -m MODE       $chmodprog installed files to MODE.
106de2362d3Smrg  -o USER       $chownprog installed files to USER.
107de2362d3Smrg  -s            $stripprog installed files.
108de2362d3Smrg  -t DIRECTORY  install into DIRECTORY.
109de2362d3Smrg  -T            report an error if DSTFILE is a directory.
110de2362d3Smrg
111de2362d3SmrgEnvironment variables override the default commands:
112de2362d3Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113de2362d3Smrg  RMPROG STRIPPROG
114de2362d3Smrg"
115de2362d3Smrg
116de2362d3Smrgwhile test $# -ne 0; do
117de2362d3Smrg  case $1 in
118de2362d3Smrg    -c) ;;
119de2362d3Smrg
120de2362d3Smrg    -C) copy_on_change=true;;
121de2362d3Smrg
122de2362d3Smrg    -d) dir_arg=true;;
123de2362d3Smrg
124de2362d3Smrg    -g) chgrpcmd="$chgrpprog $2"
1250d16fef4Smrg        shift;;
126de2362d3Smrg
127de2362d3Smrg    --help) echo "$usage"; exit $?;;
128de2362d3Smrg
129de2362d3Smrg    -m) mode=$2
1300d16fef4Smrg        case $mode in
1310d16fef4Smrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
1320d16fef4Smrg            echo "$0: invalid mode: $mode" >&2
1330d16fef4Smrg            exit 1;;
1340d16fef4Smrg        esac
1350d16fef4Smrg        shift;;
136de2362d3Smrg
137de2362d3Smrg    -o) chowncmd="$chownprog $2"
1380d16fef4Smrg        shift;;
139de2362d3Smrg
140de2362d3Smrg    -s) stripcmd=$stripprog;;
141de2362d3Smrg
1420d16fef4Smrg    -t)
1430d16fef4Smrg        is_target_a_directory=always
1440d16fef4Smrg        dst_arg=$2
1450d16fef4Smrg        # Protect names problematic for 'test' and other utilities.
1460d16fef4Smrg        case $dst_arg in
1470d16fef4Smrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
1480d16fef4Smrg        esac
1490d16fef4Smrg        shift;;
150de2362d3Smrg
1510d16fef4Smrg    -T) is_target_a_directory=never;;
152de2362d3Smrg
153de2362d3Smrg    --version) echo "$0 $scriptversion"; exit $?;;
154de2362d3Smrg
1550d16fef4Smrg    --) shift
1560d16fef4Smrg        break;;
157de2362d3Smrg
1580d16fef4Smrg    -*) echo "$0: invalid option: $1" >&2
1590d16fef4Smrg        exit 1;;
160de2362d3Smrg
161de2362d3Smrg    *)  break;;
162de2362d3Smrg  esac
163de2362d3Smrg  shift
164de2362d3Smrgdone
165de2362d3Smrg
1660d16fef4Smrg# We allow the use of options -d and -T together, by making -d
1670d16fef4Smrg# take the precedence; this is for compatibility with GNU install.
1680d16fef4Smrg
1690d16fef4Smrgif test -n "$dir_arg"; then
1700d16fef4Smrg  if test -n "$dst_arg"; then
1710d16fef4Smrg    echo "$0: target directory not allowed when installing a directory." >&2
1720d16fef4Smrg    exit 1
1730d16fef4Smrg  fi
1740d16fef4Smrgfi
1750d16fef4Smrg
176de2362d3Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177de2362d3Smrg  # When -d is used, all remaining arguments are directories to create.
178de2362d3Smrg  # When -t is used, the destination is already specified.
179de2362d3Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180de2362d3Smrg  for arg
181de2362d3Smrg  do
182de2362d3Smrg    if test -n "$dst_arg"; then
183de2362d3Smrg      # $@ is not empty: it contains at least $arg.
184de2362d3Smrg      set fnord "$@" "$dst_arg"
185de2362d3Smrg      shift # fnord
186de2362d3Smrg    fi
187de2362d3Smrg    shift # arg
188de2362d3Smrg    dst_arg=$arg
1890d16fef4Smrg    # Protect names problematic for 'test' and other utilities.
1900d16fef4Smrg    case $dst_arg in
1910d16fef4Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
1920d16fef4Smrg    esac
193de2362d3Smrg  done
194de2362d3Smrgfi
195de2362d3Smrg
196de2362d3Smrgif test $# -eq 0; then
197de2362d3Smrg  if test -z "$dir_arg"; then
198de2362d3Smrg    echo "$0: no input file specified." >&2
199de2362d3Smrg    exit 1
200de2362d3Smrg  fi
2010d16fef4Smrg  # It's OK to call 'install-sh -d' without argument.
202de2362d3Smrg  # This can happen when creating conditional directories.
203de2362d3Smrg  exit 0
204de2362d3Smrgfi
205de2362d3Smrg
206de2362d3Smrgif test -z "$dir_arg"; then
2070d16fef4Smrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
2080d16fef4Smrg    if test ! -d "$dst_arg"; then
2090d16fef4Smrg      echo "$0: $dst_arg: Is not a directory." >&2
2100d16fef4Smrg      exit 1
2110d16fef4Smrg    fi
2120d16fef4Smrg  fi
2130d16fef4Smrgfi
2140d16fef4Smrg
2150d16fef4Smrgif test -z "$dir_arg"; then
2160d16fef4Smrg  do_exit='(exit $ret); exit $ret'
2170d16fef4Smrg  trap "ret=129; $do_exit" 1
2180d16fef4Smrg  trap "ret=130; $do_exit" 2
2190d16fef4Smrg  trap "ret=141; $do_exit" 13
2200d16fef4Smrg  trap "ret=143; $do_exit" 15
221de2362d3Smrg
222de2362d3Smrg  # Set umask so as not to create temps with too-generous modes.
223de2362d3Smrg  # However, 'strip' requires both read and write access to temps.
224de2362d3Smrg  case $mode in
225de2362d3Smrg    # Optimize common cases.
226de2362d3Smrg    *644) cp_umask=133;;
227de2362d3Smrg    *755) cp_umask=22;;
228de2362d3Smrg
229de2362d3Smrg    *[0-7])
230de2362d3Smrg      if test -z "$stripcmd"; then
2310d16fef4Smrg        u_plus_rw=
232de2362d3Smrg      else
2330d16fef4Smrg        u_plus_rw='% 200'
234de2362d3Smrg      fi
235de2362d3Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236de2362d3Smrg    *)
237de2362d3Smrg      if test -z "$stripcmd"; then
2380d16fef4Smrg        u_plus_rw=
239de2362d3Smrg      else
2400d16fef4Smrg        u_plus_rw=,u+rw
241de2362d3Smrg      fi
242de2362d3Smrg      cp_umask=$mode$u_plus_rw;;
243de2362d3Smrg  esac
244de2362d3Smrgfi
245de2362d3Smrg
246de2362d3Smrgfor src
247de2362d3Smrgdo
2480d16fef4Smrg  # Protect names problematic for 'test' and other utilities.
249de2362d3Smrg  case $src in
2500d16fef4Smrg    -* | [=\(\)!]) src=./$src;;
251de2362d3Smrg  esac
252de2362d3Smrg
253de2362d3Smrg  if test -n "$dir_arg"; then
254de2362d3Smrg    dst=$src
255de2362d3Smrg    dstdir=$dst
256de2362d3Smrg    test -d "$dstdir"
257de2362d3Smrg    dstdir_status=$?
258de2362d3Smrg  else
259de2362d3Smrg
260de2362d3Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261de2362d3Smrg    # might cause directories to be created, which would be especially bad
262de2362d3Smrg    # if $src (and thus $dsttmp) contains '*'.
263de2362d3Smrg    if test ! -f "$src" && test ! -d "$src"; then
264de2362d3Smrg      echo "$0: $src does not exist." >&2
265de2362d3Smrg      exit 1
266de2362d3Smrg    fi
267de2362d3Smrg
268de2362d3Smrg    if test -z "$dst_arg"; then
269de2362d3Smrg      echo "$0: no destination specified." >&2
270de2362d3Smrg      exit 1
271de2362d3Smrg    fi
272de2362d3Smrg    dst=$dst_arg
273de2362d3Smrg
274de2362d3Smrg    # If destination is a directory, append the input filename; won't work
275de2362d3Smrg    # if double slashes aren't ignored.
276de2362d3Smrg    if test -d "$dst"; then
2770d16fef4Smrg      if test "$is_target_a_directory" = never; then
2780d16fef4Smrg        echo "$0: $dst_arg: Is a directory" >&2
2790d16fef4Smrg        exit 1
280de2362d3Smrg      fi
281de2362d3Smrg      dstdir=$dst
282de2362d3Smrg      dst=$dstdir/`basename "$src"`
283de2362d3Smrg      dstdir_status=0
284de2362d3Smrg    else
2850d16fef4Smrg      dstdir=`dirname "$dst"`
286de2362d3Smrg      test -d "$dstdir"
287de2362d3Smrg      dstdir_status=$?
288de2362d3Smrg    fi
289de2362d3Smrg  fi
290de2362d3Smrg
291de2362d3Smrg  obsolete_mkdir_used=false
292de2362d3Smrg
293de2362d3Smrg  if test $dstdir_status != 0; then
294de2362d3Smrg    case $posix_mkdir in
295de2362d3Smrg      '')
2960d16fef4Smrg        # Create intermediate dirs using mode 755 as modified by the umask.
2970d16fef4Smrg        # This is like FreeBSD 'install' as of 1997-10-28.
2980d16fef4Smrg        umask=`umask`
2990d16fef4Smrg        case $stripcmd.$umask in
3000d16fef4Smrg          # Optimize common cases.
3010d16fef4Smrg          *[2367][2367]) mkdir_umask=$umask;;
3020d16fef4Smrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
3030d16fef4Smrg
3040d16fef4Smrg          *[0-7])
3050d16fef4Smrg            mkdir_umask=`expr $umask + 22 \
3060d16fef4Smrg              - $umask % 100 % 40 + $umask % 20 \
3070d16fef4Smrg              - $umask % 10 % 4 + $umask % 2
3080d16fef4Smrg            `;;
3090d16fef4Smrg          *) mkdir_umask=$umask,go-w;;
3100d16fef4Smrg        esac
3110d16fef4Smrg
3120d16fef4Smrg        # With -d, create the new directory with the user-specified mode.
3130d16fef4Smrg        # Otherwise, rely on $mkdir_umask.
3140d16fef4Smrg        if test -n "$dir_arg"; then
3150d16fef4Smrg          mkdir_mode=-m$mode
3160d16fef4Smrg        else
3170d16fef4Smrg          mkdir_mode=
3180d16fef4Smrg        fi
3190d16fef4Smrg
3200d16fef4Smrg        posix_mkdir=false
3210d16fef4Smrg        case $umask in
3220d16fef4Smrg          *[123567][0-7][0-7])
3230d16fef4Smrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
3240d16fef4Smrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
3250d16fef4Smrg            ;;
3260d16fef4Smrg          *)
3270d16fef4Smrg            # $RANDOM is not portable (e.g. dash);  use it when possible to
3280d16fef4Smrg            # lower collision chance
3290d16fef4Smrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3300d16fef4Smrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
3310d16fef4Smrg
3320d16fef4Smrg            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
3330d16fef4Smrg            # create the $tmpdir first (and fail if unsuccessful) to make sure
3340d16fef4Smrg            # that nobody tries to guess the $tmpdir name.
3350d16fef4Smrg            if (umask $mkdir_umask &&
3360d16fef4Smrg                $mkdirprog $mkdir_mode "$tmpdir" &&
3370d16fef4Smrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3380d16fef4Smrg            then
3390d16fef4Smrg              if test -z "$dir_arg" || {
3400d16fef4Smrg                   # Check for POSIX incompatibilities with -m.
3410d16fef4Smrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3420d16fef4Smrg                   # other-writable bit of parent directory when it shouldn't.
3430d16fef4Smrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3440d16fef4Smrg                   test_tmpdir="$tmpdir/a"
3450d16fef4Smrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3460d16fef4Smrg                   case $ls_ld_tmpdir in
3470d16fef4Smrg                     d????-?r-*) different_mode=700;;
3480d16fef4Smrg                     d????-?--*) different_mode=755;;
3490d16fef4Smrg                     *) false;;
3500d16fef4Smrg                   esac &&
3510d16fef4Smrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3520d16fef4Smrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3530d16fef4Smrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3540d16fef4Smrg                   }
3550d16fef4Smrg                 }
3560d16fef4Smrg              then posix_mkdir=:
3570d16fef4Smrg              fi
3580d16fef4Smrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3590d16fef4Smrg            else
3600d16fef4Smrg              # Remove any dirs left behind by ancient mkdir implementations.
3610d16fef4Smrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3620d16fef4Smrg            fi
3630d16fef4Smrg            trap '' 0;;
3640d16fef4Smrg        esac;;
365de2362d3Smrg    esac
366de2362d3Smrg
367de2362d3Smrg    if
368de2362d3Smrg      $posix_mkdir && (
3690d16fef4Smrg        umask $mkdir_umask &&
3700d16fef4Smrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
371de2362d3Smrg      )
372de2362d3Smrg    then :
373de2362d3Smrg    else
374de2362d3Smrg
375de2362d3Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
376de2362d3Smrg      # or it failed possibly due to a race condition.  Create the
377de2362d3Smrg      # directory the slow way, step by step, checking for races as we go.
378de2362d3Smrg
379de2362d3Smrg      case $dstdir in
3800d16fef4Smrg        /*) prefix='/';;
3810d16fef4Smrg        [-=\(\)!]*) prefix='./';;
3820d16fef4Smrg        *)  prefix='';;
383de2362d3Smrg      esac
384de2362d3Smrg
385de2362d3Smrg      oIFS=$IFS
386de2362d3Smrg      IFS=/
3870d16fef4Smrg      set -f
388de2362d3Smrg      set fnord $dstdir
389de2362d3Smrg      shift
3900d16fef4Smrg      set +f
391de2362d3Smrg      IFS=$oIFS
392de2362d3Smrg
393de2362d3Smrg      prefixes=
394de2362d3Smrg
395de2362d3Smrg      for d
396de2362d3Smrg      do
3970d16fef4Smrg        test X"$d" = X && continue
3980d16fef4Smrg
3990d16fef4Smrg        prefix=$prefix$d
4000d16fef4Smrg        if test -d "$prefix"; then
4010d16fef4Smrg          prefixes=
4020d16fef4Smrg        else
4030d16fef4Smrg          if $posix_mkdir; then
4040d16fef4Smrg            (umask=$mkdir_umask &&
4050d16fef4Smrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
4060d16fef4Smrg            # Don't fail if two instances are running concurrently.
4070d16fef4Smrg            test -d "$prefix" || exit 1
4080d16fef4Smrg          else
4090d16fef4Smrg            case $prefix in
4100d16fef4Smrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
4110d16fef4Smrg              *) qprefix=$prefix;;
4120d16fef4Smrg            esac
4130d16fef4Smrg            prefixes="$prefixes '$qprefix'"
4140d16fef4Smrg          fi
4150d16fef4Smrg        fi
4160d16fef4Smrg        prefix=$prefix/
417de2362d3Smrg      done
418de2362d3Smrg
419de2362d3Smrg      if test -n "$prefixes"; then
4200d16fef4Smrg        # Don't fail if two instances are running concurrently.
4210d16fef4Smrg        (umask $mkdir_umask &&
4220d16fef4Smrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
4230d16fef4Smrg          test -d "$dstdir" || exit 1
4240d16fef4Smrg        obsolete_mkdir_used=true
425de2362d3Smrg      fi
426de2362d3Smrg    fi
427de2362d3Smrg  fi
428de2362d3Smrg
429de2362d3Smrg  if test -n "$dir_arg"; then
430de2362d3Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
431de2362d3Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
432de2362d3Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
433de2362d3Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
434de2362d3Smrg  else
435de2362d3Smrg
436de2362d3Smrg    # Make a couple of temp file names in the proper directory.
437de2362d3Smrg    dsttmp=$dstdir/_inst.$$_
438de2362d3Smrg    rmtmp=$dstdir/_rm.$$_
439de2362d3Smrg
440de2362d3Smrg    # Trap to clean up those temp files at exit.
441de2362d3Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
442de2362d3Smrg
443de2362d3Smrg    # Copy the file name to the temp name.
444de2362d3Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
445de2362d3Smrg
446de2362d3Smrg    # and set any options; do chmod last to preserve setuid bits.
447de2362d3Smrg    #
448de2362d3Smrg    # If any of these fail, we abort the whole thing.  If we want to
449de2362d3Smrg    # ignore errors from any of these, just make sure not to ignore
450de2362d3Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
451de2362d3Smrg    #
452de2362d3Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
453de2362d3Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
454de2362d3Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
455de2362d3Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
456de2362d3Smrg
457de2362d3Smrg    # If -C, don't bother to copy if it wouldn't change the file.
458de2362d3Smrg    if $copy_on_change &&
4590d16fef4Smrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
4600d16fef4Smrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
4610d16fef4Smrg       set -f &&
462de2362d3Smrg       set X $old && old=:$2:$4:$5:$6 &&
463de2362d3Smrg       set X $new && new=:$2:$4:$5:$6 &&
4640d16fef4Smrg       set +f &&
465de2362d3Smrg       test "$old" = "$new" &&
466de2362d3Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
467de2362d3Smrg    then
468de2362d3Smrg      rm -f "$dsttmp"
469de2362d3Smrg    else
470de2362d3Smrg      # Rename the file to the real destination.
471de2362d3Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
472de2362d3Smrg
473de2362d3Smrg      # The rename failed, perhaps because mv can't rename something else
474de2362d3Smrg      # to itself, or perhaps because mv is so ancient that it does not
475de2362d3Smrg      # support -f.
476de2362d3Smrg      {
4770d16fef4Smrg        # Now remove or move aside any old file at destination location.
4780d16fef4Smrg        # We try this two ways since rm can't unlink itself on some
4790d16fef4Smrg        # systems and the destination file might be busy for other
4800d16fef4Smrg        # reasons.  In this case, the final cleanup might fail but the new
4810d16fef4Smrg        # file should still install successfully.
4820d16fef4Smrg        {
4830d16fef4Smrg          test ! -f "$dst" ||
4840d16fef4Smrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
4850d16fef4Smrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
4860d16fef4Smrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
4870d16fef4Smrg          } ||
4880d16fef4Smrg          { echo "$0: cannot unlink or rename $dst" >&2
4890d16fef4Smrg            (exit 1); exit 1
4900d16fef4Smrg          }
4910d16fef4Smrg        } &&
4920d16fef4Smrg
4930d16fef4Smrg        # Now rename the file to the real destination.
4940d16fef4Smrg        $doit $mvcmd "$dsttmp" "$dst"
495de2362d3Smrg      }
496de2362d3Smrg    fi || exit 1
497de2362d3Smrg
498de2362d3Smrg    trap '' 0
499de2362d3Smrg  fi
500de2362d3Smrgdone
501de2362d3Smrg
502de2362d3Smrg# Local variables:
503de2362d3Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
504de2362d3Smrg# time-stamp-start: "scriptversion="
505de2362d3Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
5060d16fef4Smrg# time-stamp-time-zone: "UTC"
5070d16fef4Smrg# time-stamp-end: "; # UTC"
508de2362d3Smrg# End:
509