1a6fdc6faSmrg#!/bin/sh
2a6fdc6faSmrg# install - install a program, script, or datafile
335d5702bSmrg
4541411ceSmrgscriptversion=2020-11-14.01; # UTC
535d5702bSmrg
6a6fdc6faSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7a6fdc6faSmrg# later released in X11R6 (xc/config/util/install.sh) with the
8a6fdc6faSmrg# following copyright and license.
9a6fdc6faSmrg#
10a6fdc6faSmrg# Copyright (C) 1994 X Consortium
11a6fdc6faSmrg#
12a6fdc6faSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13a6fdc6faSmrg# of this software and associated documentation files (the "Software"), to
14a6fdc6faSmrg# deal in the Software without restriction, including without limitation the
15a6fdc6faSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16a6fdc6faSmrg# sell copies of the Software, and to permit persons to whom the Software is
17a6fdc6faSmrg# furnished to do so, subject to the following conditions:
18a6fdc6faSmrg#
19a6fdc6faSmrg# The above copyright notice and this permission notice shall be included in
20a6fdc6faSmrg# all copies or substantial portions of the Software.
21a6fdc6faSmrg#
22a6fdc6faSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23a6fdc6faSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24a6fdc6faSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25a6fdc6faSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26a6fdc6faSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27a6fdc6faSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28a6fdc6faSmrg#
29a6fdc6faSmrg# Except as contained in this notice, the name of the X Consortium shall not
30a6fdc6faSmrg# be used in advertising or otherwise to promote the sale, use or other deal-
31a6fdc6faSmrg# ings in this Software without prior written authorization from the X Consor-
32a6fdc6faSmrg# tium.
33a6fdc6faSmrg#
34a6fdc6faSmrg#
35a6fdc6faSmrg# FSF changes to this file are in the public domain.
36a6fdc6faSmrg#
37a6fdc6faSmrg# Calling this script install-sh is preferred over install.sh, to prevent
38541411ceSmrg# 'make' implicit rules from creating a file called install from it
39a6fdc6faSmrg# when there is no Makefile.
40a6fdc6faSmrg#
41a6fdc6faSmrg# This script is compatible with the BSD install script, but was written
4235d5702bSmrg# from scratch.
43a6fdc6faSmrg
44541411ceSmrgtab='	'
4535d5702bSmrgnl='
4635d5702bSmrg'
47541411ceSmrgIFS=" $tab$nl"
48a6fdc6faSmrg
49541411ceSmrg# Set DOITPROG to "echo" to test this script.
50a6fdc6faSmrg
5135d5702bSmrgdoit=${DOITPROG-}
52541411ceSmrgdoit_exec=${doit:-exec}
53a6fdc6faSmrg
5435d5702bSmrg# Put in absolute file names if you don't have them in your path;
5535d5702bSmrg# or use environment vars.
5635d5702bSmrg
5735d5702bSmrgchgrpprog=${CHGRPPROG-chgrp}
5835d5702bSmrgchmodprog=${CHMODPROG-chmod}
5935d5702bSmrgchownprog=${CHOWNPROG-chown}
6035d5702bSmrgcmpprog=${CMPPROG-cmp}
6135d5702bSmrgcpprog=${CPPROG-cp}
6235d5702bSmrgmkdirprog=${MKDIRPROG-mkdir}
6335d5702bSmrgmvprog=${MVPROG-mv}
6435d5702bSmrgrmprog=${RMPROG-rm}
6535d5702bSmrgstripprog=${STRIPPROG-strip}
6635d5702bSmrg
6735d5702bSmrgposix_mkdir=
6835d5702bSmrg
6935d5702bSmrg# Desired mode of installed file.
7035d5702bSmrgmode=0755
7135d5702bSmrg
72541411ceSmrg# Create dirs (including intermediate dirs) using mode 755.
73541411ceSmrg# This is like GNU 'install' as of coreutils 8.32 (2020).
74541411ceSmrgmkdir_umask=22
75541411ceSmrg
76541411ceSmrgbackupsuffix=
7735d5702bSmrgchgrpcmd=
7835d5702bSmrgchmodcmd=$chmodprog
7935d5702bSmrgchowncmd=
8035d5702bSmrgmvcmd=$mvprog
8135d5702bSmrgrmcmd="$rmprog -f"
8235d5702bSmrgstripcmd=
83a6fdc6faSmrg
8435d5702bSmrgsrc=
8535d5702bSmrgdst=
8635d5702bSmrgdir_arg=
8735d5702bSmrgdst_arg=
88a6fdc6faSmrg
8935d5702bSmrgcopy_on_change=false
90541411ceSmrgis_target_a_directory=possibly
91a6fdc6faSmrg
9235d5702bSmrgusage="\
9335d5702bSmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
9435d5702bSmrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
9535d5702bSmrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
9635d5702bSmrg   or: $0 [OPTION]... -d DIRECTORIES...
97a6fdc6faSmrg
9835d5702bSmrgIn the 1st form, copy SRCFILE to DSTFILE.
9935d5702bSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
10035d5702bSmrgIn the 4th, create DIRECTORIES.
101a6fdc6faSmrg
10235d5702bSmrgOptions:
10335d5702bSmrg     --help     display this help and exit.
10435d5702bSmrg     --version  display version info and exit.
105a6fdc6faSmrg
10635d5702bSmrg  -c            (ignored)
107541411ceSmrg  -C            install only if different (preserve data modification time)
10835d5702bSmrg  -d            create directories instead of installing files.
10935d5702bSmrg  -g GROUP      $chgrpprog installed files to GROUP.
11035d5702bSmrg  -m MODE       $chmodprog installed files to MODE.
11135d5702bSmrg  -o USER       $chownprog installed files to USER.
112541411ceSmrg  -p            pass -p to $cpprog.
11335d5702bSmrg  -s            $stripprog installed files.
114541411ceSmrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
11535d5702bSmrg  -t DIRECTORY  install into DIRECTORY.
11635d5702bSmrg  -T            report an error if DSTFILE is a directory.
117a6fdc6faSmrg
11835d5702bSmrgEnvironment variables override the default commands:
11935d5702bSmrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
12035d5702bSmrg  RMPROG STRIPPROG
121541411ceSmrg
122541411ceSmrgBy default, rm is invoked with -f; when overridden with RMPROG,
123541411ceSmrgit's up to you to specify -f if you want it.
124541411ceSmrg
125541411ceSmrgIf -S is not specified, no backups are attempted.
126541411ceSmrg
127541411ceSmrgEmail bug reports to bug-automake@gnu.org.
128541411ceSmrgAutomake home page: https://www.gnu.org/software/automake/
12935d5702bSmrg"
130a6fdc6faSmrg
13135d5702bSmrgwhile test $# -ne 0; do
13235d5702bSmrg  case $1 in
13335d5702bSmrg    -c) ;;
134a6fdc6faSmrg
13535d5702bSmrg    -C) copy_on_change=true;;
136a6fdc6faSmrg
13735d5702bSmrg    -d) dir_arg=true;;
138a6fdc6faSmrg
13935d5702bSmrg    -g) chgrpcmd="$chgrpprog $2"
140541411ceSmrg        shift;;
141a6fdc6faSmrg
14235d5702bSmrg    --help) echo "$usage"; exit $?;;
143a6fdc6faSmrg
14435d5702bSmrg    -m) mode=$2
145541411ceSmrg        case $mode in
146541411ceSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
147541411ceSmrg            echo "$0: invalid mode: $mode" >&2
148541411ceSmrg            exit 1;;
149541411ceSmrg        esac
150541411ceSmrg        shift;;
151a6fdc6faSmrg
15235d5702bSmrg    -o) chowncmd="$chownprog $2"
153541411ceSmrg        shift;;
154541411ceSmrg
155541411ceSmrg    -p) cpprog="$cpprog -p";;
156a6fdc6faSmrg
15735d5702bSmrg    -s) stripcmd=$stripprog;;
158a6fdc6faSmrg
159541411ceSmrg    -S) backupsuffix="$2"
160541411ceSmrg        shift;;
161541411ceSmrg
162541411ceSmrg    -t)
163541411ceSmrg        is_target_a_directory=always
164541411ceSmrg        dst_arg=$2
165541411ceSmrg        # Protect names problematic for 'test' and other utilities.
166541411ceSmrg        case $dst_arg in
167541411ceSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
168541411ceSmrg        esac
169541411ceSmrg        shift;;
170a6fdc6faSmrg
171541411ceSmrg    -T) is_target_a_directory=never;;
172a6fdc6faSmrg
17335d5702bSmrg    --version) echo "$0 $scriptversion"; exit $?;;
174a6fdc6faSmrg
175541411ceSmrg    --) shift
176541411ceSmrg        break;;
177a6fdc6faSmrg
178541411ceSmrg    -*) echo "$0: invalid option: $1" >&2
179541411ceSmrg        exit 1;;
180a6fdc6faSmrg
18135d5702bSmrg    *)  break;;
18235d5702bSmrg  esac
18335d5702bSmrg  shift
18435d5702bSmrgdone
185a6fdc6faSmrg
186541411ceSmrg# We allow the use of options -d and -T together, by making -d
187541411ceSmrg# take the precedence; this is for compatibility with GNU install.
188541411ceSmrg
189541411ceSmrgif test -n "$dir_arg"; then
190541411ceSmrg  if test -n "$dst_arg"; then
191541411ceSmrg    echo "$0: target directory not allowed when installing a directory." >&2
192541411ceSmrg    exit 1
193541411ceSmrg  fi
194541411ceSmrgfi
195541411ceSmrg
19635d5702bSmrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
19735d5702bSmrg  # When -d is used, all remaining arguments are directories to create.
19835d5702bSmrg  # When -t is used, the destination is already specified.
19935d5702bSmrg  # Otherwise, the last argument is the destination.  Remove it from $@.
20035d5702bSmrg  for arg
20135d5702bSmrg  do
20235d5702bSmrg    if test -n "$dst_arg"; then
20335d5702bSmrg      # $@ is not empty: it contains at least $arg.
20435d5702bSmrg      set fnord "$@" "$dst_arg"
20535d5702bSmrg      shift # fnord
20635d5702bSmrg    fi
20735d5702bSmrg    shift # arg
20835d5702bSmrg    dst_arg=$arg
209541411ceSmrg    # Protect names problematic for 'test' and other utilities.
210541411ceSmrg    case $dst_arg in
211541411ceSmrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
212541411ceSmrg    esac
21335d5702bSmrg  done
21435d5702bSmrgfi
215a6fdc6faSmrg
21635d5702bSmrgif test $# -eq 0; then
21735d5702bSmrg  if test -z "$dir_arg"; then
21835d5702bSmrg    echo "$0: no input file specified." >&2
21935d5702bSmrg    exit 1
22035d5702bSmrg  fi
221541411ceSmrg  # It's OK to call 'install-sh -d' without argument.
22235d5702bSmrg  # This can happen when creating conditional directories.
22335d5702bSmrg  exit 0
22435d5702bSmrgfi
225a6fdc6faSmrg
22635d5702bSmrgif test -z "$dir_arg"; then
227541411ceSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
228541411ceSmrg    if test ! -d "$dst_arg"; then
229541411ceSmrg      echo "$0: $dst_arg: Is not a directory." >&2
230541411ceSmrg      exit 1
231541411ceSmrg    fi
232541411ceSmrg  fi
233541411ceSmrgfi
234541411ceSmrg
235541411ceSmrgif test -z "$dir_arg"; then
236541411ceSmrg  do_exit='(exit $ret); exit $ret'
237541411ceSmrg  trap "ret=129; $do_exit" 1
238541411ceSmrg  trap "ret=130; $do_exit" 2
239541411ceSmrg  trap "ret=141; $do_exit" 13
240541411ceSmrg  trap "ret=143; $do_exit" 15
24135d5702bSmrg
24235d5702bSmrg  # Set umask so as not to create temps with too-generous modes.
24335d5702bSmrg  # However, 'strip' requires both read and write access to temps.
24435d5702bSmrg  case $mode in
24535d5702bSmrg    # Optimize common cases.
24635d5702bSmrg    *644) cp_umask=133;;
24735d5702bSmrg    *755) cp_umask=22;;
24835d5702bSmrg
24935d5702bSmrg    *[0-7])
25035d5702bSmrg      if test -z "$stripcmd"; then
251541411ceSmrg        u_plus_rw=
25235d5702bSmrg      else
253541411ceSmrg        u_plus_rw='% 200'
25435d5702bSmrg      fi
25535d5702bSmrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
25635d5702bSmrg    *)
25735d5702bSmrg      if test -z "$stripcmd"; then
258541411ceSmrg        u_plus_rw=
25935d5702bSmrg      else
260541411ceSmrg        u_plus_rw=,u+rw
26135d5702bSmrg      fi
26235d5702bSmrg      cp_umask=$mode$u_plus_rw;;
26335d5702bSmrg  esac
26435d5702bSmrgfi
265a6fdc6faSmrg
26635d5702bSmrgfor src
26735d5702bSmrgdo
268541411ceSmrg  # Protect names problematic for 'test' and other utilities.
26935d5702bSmrg  case $src in
270541411ceSmrg    -* | [=\(\)!]) src=./$src;;
27135d5702bSmrg  esac
27235d5702bSmrg
27335d5702bSmrg  if test -n "$dir_arg"; then
27435d5702bSmrg    dst=$src
27535d5702bSmrg    dstdir=$dst
27635d5702bSmrg    test -d "$dstdir"
27735d5702bSmrg    dstdir_status=$?
278541411ceSmrg    # Don't chown directories that already exist.
279541411ceSmrg    if test $dstdir_status = 0; then
280541411ceSmrg      chowncmd=""
281541411ceSmrg    fi
28235d5702bSmrg  else
28335d5702bSmrg
28435d5702bSmrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
28535d5702bSmrg    # might cause directories to be created, which would be especially bad
28635d5702bSmrg    # if $src (and thus $dsttmp) contains '*'.
28735d5702bSmrg    if test ! -f "$src" && test ! -d "$src"; then
28835d5702bSmrg      echo "$0: $src does not exist." >&2
28935d5702bSmrg      exit 1
29035d5702bSmrg    fi
29135d5702bSmrg
29235d5702bSmrg    if test -z "$dst_arg"; then
29335d5702bSmrg      echo "$0: no destination specified." >&2
29435d5702bSmrg      exit 1
29535d5702bSmrg    fi
29635d5702bSmrg    dst=$dst_arg
297a6fdc6faSmrg
298541411ceSmrg    # If destination is a directory, append the input filename.
29935d5702bSmrg    if test -d "$dst"; then
300541411ceSmrg      if test "$is_target_a_directory" = never; then
301541411ceSmrg        echo "$0: $dst_arg: Is a directory" >&2
302541411ceSmrg        exit 1
30335d5702bSmrg      fi
30435d5702bSmrg      dstdir=$dst
305541411ceSmrg      dstbase=`basename "$src"`
306541411ceSmrg      case $dst in
307541411ceSmrg	*/) dst=$dst$dstbase;;
308541411ceSmrg	*)  dst=$dst/$dstbase;;
309541411ceSmrg      esac
31035d5702bSmrg      dstdir_status=0
31135d5702bSmrg    else
312541411ceSmrg      dstdir=`dirname "$dst"`
31335d5702bSmrg      test -d "$dstdir"
31435d5702bSmrg      dstdir_status=$?
31535d5702bSmrg    fi
31635d5702bSmrg  fi
31735d5702bSmrg
318541411ceSmrg  case $dstdir in
319541411ceSmrg    */) dstdirslash=$dstdir;;
320541411ceSmrg    *)  dstdirslash=$dstdir/;;
321541411ceSmrg  esac
322541411ceSmrg
32335d5702bSmrg  obsolete_mkdir_used=false
32435d5702bSmrg
32535d5702bSmrg  if test $dstdir_status != 0; then
32635d5702bSmrg    case $posix_mkdir in
32735d5702bSmrg      '')
328541411ceSmrg        # With -d, create the new directory with the user-specified mode.
329541411ceSmrg        # Otherwise, rely on $mkdir_umask.
330541411ceSmrg        if test -n "$dir_arg"; then
331541411ceSmrg          mkdir_mode=-m$mode
332541411ceSmrg        else
333541411ceSmrg          mkdir_mode=
334541411ceSmrg        fi
335541411ceSmrg
336541411ceSmrg        posix_mkdir=false
337541411ceSmrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
338541411ceSmrg	# here however when possible just to lower collision chance.
339541411ceSmrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
340541411ceSmrg
341541411ceSmrg	trap '
342541411ceSmrg	  ret=$?
343541411ceSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
344541411ceSmrg	  exit $ret
345541411ceSmrg	' 0
346541411ceSmrg
347541411ceSmrg	# Because "mkdir -p" follows existing symlinks and we likely work
348541411ceSmrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
349541411ceSmrg	# directory is successfully created first before we actually test
350541411ceSmrg	# 'mkdir -p'.
351541411ceSmrg	if (umask $mkdir_umask &&
352541411ceSmrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
353541411ceSmrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
354541411ceSmrg	then
355541411ceSmrg	  if test -z "$dir_arg" || {
356541411ceSmrg	       # Check for POSIX incompatibilities with -m.
357541411ceSmrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
358541411ceSmrg	       # other-writable bit of parent directory when it shouldn't.
359541411ceSmrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
360541411ceSmrg	       test_tmpdir="$tmpdir/a"
361541411ceSmrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
362541411ceSmrg	       case $ls_ld_tmpdir in
363541411ceSmrg		 d????-?r-*) different_mode=700;;
364541411ceSmrg		 d????-?--*) different_mode=755;;
365541411ceSmrg		 *) false;;
366541411ceSmrg	       esac &&
367541411ceSmrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
368541411ceSmrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
369541411ceSmrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
370541411ceSmrg	       }
371541411ceSmrg	     }
372541411ceSmrg	  then posix_mkdir=:
373541411ceSmrg	  fi
374541411ceSmrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
375a6fdc6faSmrg	else
376541411ceSmrg	  # Remove any dirs left behind by ancient mkdir implementations.
377541411ceSmrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
378a6fdc6faSmrg	fi
379541411ceSmrg	trap '' 0;;
38035d5702bSmrg    esac
381a6fdc6faSmrg
38235d5702bSmrg    if
38335d5702bSmrg      $posix_mkdir && (
384541411ceSmrg        umask $mkdir_umask &&
385541411ceSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
38635d5702bSmrg      )
38735d5702bSmrg    then :
38835d5702bSmrg    else
38935d5702bSmrg
390541411ceSmrg      # mkdir does not conform to POSIX,
39135d5702bSmrg      # or it failed possibly due to a race condition.  Create the
39235d5702bSmrg      # directory the slow way, step by step, checking for races as we go.
39335d5702bSmrg
39435d5702bSmrg      case $dstdir in
395541411ceSmrg        /*) prefix='/';;
396541411ceSmrg        [-=\(\)!]*) prefix='./';;
397541411ceSmrg        *)  prefix='';;
39835d5702bSmrg      esac
39935d5702bSmrg
40035d5702bSmrg      oIFS=$IFS
40135d5702bSmrg      IFS=/
402541411ceSmrg      set -f
40335d5702bSmrg      set fnord $dstdir
40435d5702bSmrg      shift
405541411ceSmrg      set +f
40635d5702bSmrg      IFS=$oIFS
40735d5702bSmrg
40835d5702bSmrg      prefixes=
40935d5702bSmrg
41035d5702bSmrg      for d
41135d5702bSmrg      do
412541411ceSmrg        test X"$d" = X && continue
413541411ceSmrg
414541411ceSmrg        prefix=$prefix$d
415541411ceSmrg        if test -d "$prefix"; then
416541411ceSmrg          prefixes=
417541411ceSmrg        else
418541411ceSmrg          if $posix_mkdir; then
419541411ceSmrg            (umask $mkdir_umask &&
420541411ceSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
421541411ceSmrg            # Don't fail if two instances are running concurrently.
422541411ceSmrg            test -d "$prefix" || exit 1
423541411ceSmrg          else
424541411ceSmrg            case $prefix in
425541411ceSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
426541411ceSmrg              *) qprefix=$prefix;;
427541411ceSmrg            esac
428541411ceSmrg            prefixes="$prefixes '$qprefix'"
429541411ceSmrg          fi
430541411ceSmrg        fi
431541411ceSmrg        prefix=$prefix/
43235d5702bSmrg      done
43335d5702bSmrg
43435d5702bSmrg      if test -n "$prefixes"; then
435541411ceSmrg        # Don't fail if two instances are running concurrently.
436541411ceSmrg        (umask $mkdir_umask &&
437541411ceSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
438541411ceSmrg          test -d "$dstdir" || exit 1
439541411ceSmrg        obsolete_mkdir_used=true
44035d5702bSmrg      fi
44135d5702bSmrg    fi
44235d5702bSmrg  fi
44335d5702bSmrg
44435d5702bSmrg  if test -n "$dir_arg"; then
44535d5702bSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
44635d5702bSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
44735d5702bSmrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
44835d5702bSmrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
44935d5702bSmrg  else
45035d5702bSmrg
45135d5702bSmrg    # Make a couple of temp file names in the proper directory.
452541411ceSmrg    dsttmp=${dstdirslash}_inst.$$_
453541411ceSmrg    rmtmp=${dstdirslash}_rm.$$_
45435d5702bSmrg
45535d5702bSmrg    # Trap to clean up those temp files at exit.
45635d5702bSmrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
45735d5702bSmrg
45835d5702bSmrg    # Copy the file name to the temp name.
459541411ceSmrg    (umask $cp_umask &&
460541411ceSmrg     { test -z "$stripcmd" || {
461541411ceSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
462541411ceSmrg	 # which would cause strip to fail.
463541411ceSmrg	 if test -z "$doit"; then
464541411ceSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
465541411ceSmrg	 else
466541411ceSmrg	   $doit touch "$dsttmp"
467541411ceSmrg	 fi
468541411ceSmrg       }
469541411ceSmrg     } &&
470541411ceSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
47135d5702bSmrg
47235d5702bSmrg    # and set any options; do chmod last to preserve setuid bits.
47335d5702bSmrg    #
47435d5702bSmrg    # If any of these fail, we abort the whole thing.  If we want to
47535d5702bSmrg    # ignore errors from any of these, just make sure not to ignore
47635d5702bSmrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
47735d5702bSmrg    #
47835d5702bSmrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
47935d5702bSmrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
48035d5702bSmrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
48135d5702bSmrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
48235d5702bSmrg
48335d5702bSmrg    # If -C, don't bother to copy if it wouldn't change the file.
48435d5702bSmrg    if $copy_on_change &&
485541411ceSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
486541411ceSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
487541411ceSmrg       set -f &&
48835d5702bSmrg       set X $old && old=:$2:$4:$5:$6 &&
48935d5702bSmrg       set X $new && new=:$2:$4:$5:$6 &&
490541411ceSmrg       set +f &&
49135d5702bSmrg       test "$old" = "$new" &&
49235d5702bSmrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
49335d5702bSmrg    then
49435d5702bSmrg      rm -f "$dsttmp"
49535d5702bSmrg    else
496541411ceSmrg      # If $backupsuffix is set, and the file being installed
497541411ceSmrg      # already exists, attempt a backup.  Don't worry if it fails,
498541411ceSmrg      # e.g., if mv doesn't support -f.
499541411ceSmrg      if test -n "$backupsuffix" && test -f "$dst"; then
500541411ceSmrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
501541411ceSmrg      fi
502541411ceSmrg
50335d5702bSmrg      # Rename the file to the real destination.
50435d5702bSmrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
50535d5702bSmrg
50635d5702bSmrg      # The rename failed, perhaps because mv can't rename something else
50735d5702bSmrg      # to itself, or perhaps because mv is so ancient that it does not
50835d5702bSmrg      # support -f.
50935d5702bSmrg      {
510541411ceSmrg        # Now remove or move aside any old file at destination location.
511541411ceSmrg        # We try this two ways since rm can't unlink itself on some
512541411ceSmrg        # systems and the destination file might be busy for other
513541411ceSmrg        # reasons.  In this case, the final cleanup might fail but the new
514541411ceSmrg        # file should still install successfully.
515541411ceSmrg        {
516541411ceSmrg          test ! -f "$dst" ||
517541411ceSmrg          $doit $rmcmd "$dst" 2>/dev/null ||
518541411ceSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
519541411ceSmrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
520541411ceSmrg          } ||
521541411ceSmrg          { echo "$0: cannot unlink or rename $dst" >&2
522541411ceSmrg            (exit 1); exit 1
523541411ceSmrg          }
524541411ceSmrg        } &&
525541411ceSmrg
526541411ceSmrg        # Now rename the file to the real destination.
527541411ceSmrg        $doit $mvcmd "$dsttmp" "$dst"
52835d5702bSmrg      }
52935d5702bSmrg    fi || exit 1
53035d5702bSmrg
53135d5702bSmrg    trap '' 0
53235d5702bSmrg  fi
53335d5702bSmrgdone
534a6fdc6faSmrg
53535d5702bSmrg# Local variables:
536541411ceSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
53735d5702bSmrg# time-stamp-start: "scriptversion="
53835d5702bSmrg# time-stamp-format: "%:y-%02m-%02d.%02H"
539541411ceSmrg# time-stamp-time-zone: "UTC0"
54035d5702bSmrg# time-stamp-end: "; # UTC"
54135d5702bSmrg# End:
542