1ffab5952Smrg#!/bin/sh
2ffab5952Smrg# install - install a program, script, or datafile
3ffab5952Smrg
46781a5f7Smrgscriptversion=2020-11-14.01; # UTC
5ffab5952Smrg
6ffab5952Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was
7ffab5952Smrg# later released in X11R6 (xc/config/util/install.sh) with the
8ffab5952Smrg# following copyright and license.
9ffab5952Smrg#
10ffab5952Smrg# Copyright (C) 1994 X Consortium
11ffab5952Smrg#
12ffab5952Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy
13ffab5952Smrg# of this software and associated documentation files (the "Software"), to
14ffab5952Smrg# deal in the Software without restriction, including without limitation the
15ffab5952Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16ffab5952Smrg# sell copies of the Software, and to permit persons to whom the Software is
17ffab5952Smrg# furnished to do so, subject to the following conditions:
18ffab5952Smrg#
19ffab5952Smrg# The above copyright notice and this permission notice shall be included in
20ffab5952Smrg# all copies or substantial portions of the Software.
21ffab5952Smrg#
22ffab5952Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23ffab5952Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24ffab5952Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25ffab5952Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26ffab5952Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27ffab5952Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28ffab5952Smrg#
29ffab5952Smrg# Except as contained in this notice, the name of the X Consortium shall not
30ffab5952Smrg# be used in advertising or otherwise to promote the sale, use or other deal-
31ffab5952Smrg# ings in this Software without prior written authorization from the X Consor-
32ffab5952Smrg# tium.
33ffab5952Smrg#
34ffab5952Smrg#
35ffab5952Smrg# FSF changes to this file are in the public domain.
36ffab5952Smrg#
37ffab5952Smrg# Calling this script install-sh is preferred over install.sh, to prevent
3867e4e4deSmrg# 'make' implicit rules from creating a file called install from it
39ffab5952Smrg# when there is no Makefile.
40ffab5952Smrg#
41ffab5952Smrg# This script is compatible with the BSD install script, but was written
42ffab5952Smrg# from scratch.
43ffab5952Smrg
4467e4e4deSmrgtab='	'
45ffab5952Smrgnl='
46ffab5952Smrg'
4767e4e4deSmrgIFS=" $tab$nl"
48ffab5952Smrg
4967e4e4deSmrg# Set DOITPROG to "echo" to test this script.
50ffab5952Smrg
51ffab5952Smrgdoit=${DOITPROG-}
5267e4e4deSmrgdoit_exec=${doit:-exec}
53ffab5952Smrg
54ffab5952Smrg# Put in absolute file names if you don't have them in your path;
55ffab5952Smrg# or use environment vars.
56ffab5952Smrg
57ffab5952Smrgchgrpprog=${CHGRPPROG-chgrp}
58ffab5952Smrgchmodprog=${CHMODPROG-chmod}
59ffab5952Smrgchownprog=${CHOWNPROG-chown}
60ffab5952Smrgcmpprog=${CMPPROG-cmp}
61ffab5952Smrgcpprog=${CPPROG-cp}
62ffab5952Smrgmkdirprog=${MKDIRPROG-mkdir}
63ffab5952Smrgmvprog=${MVPROG-mv}
64ffab5952Smrgrmprog=${RMPROG-rm}
65ffab5952Smrgstripprog=${STRIPPROG-strip}
66ffab5952Smrg
67ffab5952Smrgposix_mkdir=
68ffab5952Smrg
69ffab5952Smrg# Desired mode of installed file.
70ffab5952Smrgmode=0755
71ffab5952Smrg
726781a5f7Smrg# Create dirs (including intermediate dirs) using mode 755.
736781a5f7Smrg# This is like GNU 'install' as of coreutils 8.32 (2020).
746781a5f7Smrgmkdir_umask=22
756781a5f7Smrg
766781a5f7Smrgbackupsuffix=
77ffab5952Smrgchgrpcmd=
78ffab5952Smrgchmodcmd=$chmodprog
79ffab5952Smrgchowncmd=
80ffab5952Smrgmvcmd=$mvprog
81ffab5952Smrgrmcmd="$rmprog -f"
82ffab5952Smrgstripcmd=
83ffab5952Smrg
84ffab5952Smrgsrc=
85ffab5952Smrgdst=
86ffab5952Smrgdir_arg=
87ffab5952Smrgdst_arg=
88ffab5952Smrg
89ffab5952Smrgcopy_on_change=false
9067e4e4deSmrgis_target_a_directory=possibly
91ffab5952Smrg
92ffab5952Smrgusage="\
93ffab5952SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
94ffab5952Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
95ffab5952Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
96ffab5952Smrg   or: $0 [OPTION]... -d DIRECTORIES...
97ffab5952Smrg
98ffab5952SmrgIn the 1st form, copy SRCFILE to DSTFILE.
99ffab5952SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
100ffab5952SmrgIn the 4th, create DIRECTORIES.
101ffab5952Smrg
102ffab5952SmrgOptions:
103ffab5952Smrg     --help     display this help and exit.
104ffab5952Smrg     --version  display version info and exit.
105ffab5952Smrg
106ffab5952Smrg  -c            (ignored)
1076781a5f7Smrg  -C            install only if different (preserve data modification time)
108ffab5952Smrg  -d            create directories instead of installing files.
109ffab5952Smrg  -g GROUP      $chgrpprog installed files to GROUP.
110ffab5952Smrg  -m MODE       $chmodprog installed files to MODE.
111ffab5952Smrg  -o USER       $chownprog installed files to USER.
1126781a5f7Smrg  -p            pass -p to $cpprog.
113ffab5952Smrg  -s            $stripprog installed files.
1146781a5f7Smrg  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
115ffab5952Smrg  -t DIRECTORY  install into DIRECTORY.
116ffab5952Smrg  -T            report an error if DSTFILE is a directory.
117ffab5952Smrg
118ffab5952SmrgEnvironment variables override the default commands:
119ffab5952Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
120ffab5952Smrg  RMPROG STRIPPROG
1216781a5f7Smrg
1226781a5f7SmrgBy default, rm is invoked with -f; when overridden with RMPROG,
1236781a5f7Smrgit's up to you to specify -f if you want it.
1246781a5f7Smrg
1256781a5f7SmrgIf -S is not specified, no backups are attempted.
1266781a5f7Smrg
1276781a5f7SmrgEmail bug reports to bug-automake@gnu.org.
1286781a5f7SmrgAutomake home page: https://www.gnu.org/software/automake/
129ffab5952Smrg"
130ffab5952Smrg
131ffab5952Smrgwhile test $# -ne 0; do
132ffab5952Smrg  case $1 in
133ffab5952Smrg    -c) ;;
134ffab5952Smrg
135ffab5952Smrg    -C) copy_on_change=true;;
136ffab5952Smrg
137ffab5952Smrg    -d) dir_arg=true;;
138ffab5952Smrg
139ffab5952Smrg    -g) chgrpcmd="$chgrpprog $2"
14067e4e4deSmrg        shift;;
141ffab5952Smrg
142ffab5952Smrg    --help) echo "$usage"; exit $?;;
143ffab5952Smrg
144ffab5952Smrg    -m) mode=$2
14567e4e4deSmrg        case $mode in
14667e4e4deSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
14767e4e4deSmrg            echo "$0: invalid mode: $mode" >&2
14867e4e4deSmrg            exit 1;;
14967e4e4deSmrg        esac
15067e4e4deSmrg        shift;;
151ffab5952Smrg
152ffab5952Smrg    -o) chowncmd="$chownprog $2"
15367e4e4deSmrg        shift;;
154ffab5952Smrg
1556781a5f7Smrg    -p) cpprog="$cpprog -p";;
1566781a5f7Smrg
157ffab5952Smrg    -s) stripcmd=$stripprog;;
158ffab5952Smrg
1596781a5f7Smrg    -S) backupsuffix="$2"
1606781a5f7Smrg        shift;;
1616781a5f7Smrg
16267e4e4deSmrg    -t)
16367e4e4deSmrg        is_target_a_directory=always
16467e4e4deSmrg        dst_arg=$2
16567e4e4deSmrg        # Protect names problematic for 'test' and other utilities.
16667e4e4deSmrg        case $dst_arg in
16767e4e4deSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
16867e4e4deSmrg        esac
16967e4e4deSmrg        shift;;
170ffab5952Smrg
17167e4e4deSmrg    -T) is_target_a_directory=never;;
172ffab5952Smrg
173ffab5952Smrg    --version) echo "$0 $scriptversion"; exit $?;;
174ffab5952Smrg
17567e4e4deSmrg    --) shift
17667e4e4deSmrg        break;;
177ffab5952Smrg
17867e4e4deSmrg    -*) echo "$0: invalid option: $1" >&2
17967e4e4deSmrg        exit 1;;
180ffab5952Smrg
181ffab5952Smrg    *)  break;;
182ffab5952Smrg  esac
183ffab5952Smrg  shift
184ffab5952Smrgdone
185ffab5952Smrg
18667e4e4deSmrg# We allow the use of options -d and -T together, by making -d
18767e4e4deSmrg# take the precedence; this is for compatibility with GNU install.
18867e4e4deSmrg
18967e4e4deSmrgif test -n "$dir_arg"; then
19067e4e4deSmrg  if test -n "$dst_arg"; then
19167e4e4deSmrg    echo "$0: target directory not allowed when installing a directory." >&2
19267e4e4deSmrg    exit 1
19367e4e4deSmrg  fi
19467e4e4deSmrgfi
19567e4e4deSmrg
196ffab5952Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
197ffab5952Smrg  # When -d is used, all remaining arguments are directories to create.
198ffab5952Smrg  # When -t is used, the destination is already specified.
199ffab5952Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
200ffab5952Smrg  for arg
201ffab5952Smrg  do
202ffab5952Smrg    if test -n "$dst_arg"; then
203ffab5952Smrg      # $@ is not empty: it contains at least $arg.
204ffab5952Smrg      set fnord "$@" "$dst_arg"
205ffab5952Smrg      shift # fnord
206ffab5952Smrg    fi
207ffab5952Smrg    shift # arg
208ffab5952Smrg    dst_arg=$arg
20967e4e4deSmrg    # Protect names problematic for 'test' and other utilities.
21043c16309Smrg    case $dst_arg in
21143c16309Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
21243c16309Smrg    esac
213ffab5952Smrg  done
214ffab5952Smrgfi
215ffab5952Smrg
216ffab5952Smrgif test $# -eq 0; then
217ffab5952Smrg  if test -z "$dir_arg"; then
218ffab5952Smrg    echo "$0: no input file specified." >&2
219ffab5952Smrg    exit 1
220ffab5952Smrg  fi
22167e4e4deSmrg  # It's OK to call 'install-sh -d' without argument.
222ffab5952Smrg  # This can happen when creating conditional directories.
223ffab5952Smrg  exit 0
224ffab5952Smrgfi
225ffab5952Smrg
22667e4e4deSmrgif test -z "$dir_arg"; then
22767e4e4deSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
22867e4e4deSmrg    if test ! -d "$dst_arg"; then
22967e4e4deSmrg      echo "$0: $dst_arg: Is not a directory." >&2
23067e4e4deSmrg      exit 1
23167e4e4deSmrg    fi
23267e4e4deSmrg  fi
23367e4e4deSmrgfi
23467e4e4deSmrg
235ffab5952Smrgif test -z "$dir_arg"; then
23643c16309Smrg  do_exit='(exit $ret); exit $ret'
23743c16309Smrg  trap "ret=129; $do_exit" 1
23843c16309Smrg  trap "ret=130; $do_exit" 2
23943c16309Smrg  trap "ret=141; $do_exit" 13
24043c16309Smrg  trap "ret=143; $do_exit" 15
241ffab5952Smrg
242ffab5952Smrg  # Set umask so as not to create temps with too-generous modes.
243ffab5952Smrg  # However, 'strip' requires both read and write access to temps.
244ffab5952Smrg  case $mode in
245ffab5952Smrg    # Optimize common cases.
246ffab5952Smrg    *644) cp_umask=133;;
247ffab5952Smrg    *755) cp_umask=22;;
248ffab5952Smrg
249ffab5952Smrg    *[0-7])
250ffab5952Smrg      if test -z "$stripcmd"; then
25167e4e4deSmrg        u_plus_rw=
252ffab5952Smrg      else
25367e4e4deSmrg        u_plus_rw='% 200'
254ffab5952Smrg      fi
255ffab5952Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
256ffab5952Smrg    *)
257ffab5952Smrg      if test -z "$stripcmd"; then
25867e4e4deSmrg        u_plus_rw=
259ffab5952Smrg      else
26067e4e4deSmrg        u_plus_rw=,u+rw
261ffab5952Smrg      fi
262ffab5952Smrg      cp_umask=$mode$u_plus_rw;;
263ffab5952Smrg  esac
264ffab5952Smrgfi
265ffab5952Smrg
266ffab5952Smrgfor src
267ffab5952Smrgdo
26867e4e4deSmrg  # Protect names problematic for 'test' and other utilities.
269ffab5952Smrg  case $src in
27043c16309Smrg    -* | [=\(\)!]) src=./$src;;
271ffab5952Smrg  esac
272ffab5952Smrg
273ffab5952Smrg  if test -n "$dir_arg"; then
274ffab5952Smrg    dst=$src
275ffab5952Smrg    dstdir=$dst
276ffab5952Smrg    test -d "$dstdir"
277ffab5952Smrg    dstdir_status=$?
2786781a5f7Smrg    # Don't chown directories that already exist.
2796781a5f7Smrg    if test $dstdir_status = 0; then
2806781a5f7Smrg      chowncmd=""
2816781a5f7Smrg    fi
282ffab5952Smrg  else
283ffab5952Smrg
284ffab5952Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
285ffab5952Smrg    # might cause directories to be created, which would be especially bad
286ffab5952Smrg    # if $src (and thus $dsttmp) contains '*'.
287ffab5952Smrg    if test ! -f "$src" && test ! -d "$src"; then
288ffab5952Smrg      echo "$0: $src does not exist." >&2
289ffab5952Smrg      exit 1
290ffab5952Smrg    fi
291ffab5952Smrg
292ffab5952Smrg    if test -z "$dst_arg"; then
293ffab5952Smrg      echo "$0: no destination specified." >&2
294ffab5952Smrg      exit 1
295ffab5952Smrg    fi
296ffab5952Smrg    dst=$dst_arg
297ffab5952Smrg
29845aa2fbfSmrg    # If destination is a directory, append the input filename.
299ffab5952Smrg    if test -d "$dst"; then
30067e4e4deSmrg      if test "$is_target_a_directory" = never; then
30167e4e4deSmrg        echo "$0: $dst_arg: Is a directory" >&2
30267e4e4deSmrg        exit 1
303ffab5952Smrg      fi
304ffab5952Smrg      dstdir=$dst
30545aa2fbfSmrg      dstbase=`basename "$src"`
30645aa2fbfSmrg      case $dst in
30745aa2fbfSmrg	*/) dst=$dst$dstbase;;
30845aa2fbfSmrg	*)  dst=$dst/$dstbase;;
30945aa2fbfSmrg      esac
310ffab5952Smrg      dstdir_status=0
311ffab5952Smrg    else
31267e4e4deSmrg      dstdir=`dirname "$dst"`
313ffab5952Smrg      test -d "$dstdir"
314ffab5952Smrg      dstdir_status=$?
315ffab5952Smrg    fi
316ffab5952Smrg  fi
317ffab5952Smrg
31845aa2fbfSmrg  case $dstdir in
31945aa2fbfSmrg    */) dstdirslash=$dstdir;;
32045aa2fbfSmrg    *)  dstdirslash=$dstdir/;;
32145aa2fbfSmrg  esac
32245aa2fbfSmrg
323ffab5952Smrg  obsolete_mkdir_used=false
324ffab5952Smrg
325ffab5952Smrg  if test $dstdir_status != 0; then
326ffab5952Smrg    case $posix_mkdir in
327ffab5952Smrg      '')
32867e4e4deSmrg        # With -d, create the new directory with the user-specified mode.
32967e4e4deSmrg        # Otherwise, rely on $mkdir_umask.
33067e4e4deSmrg        if test -n "$dir_arg"; then
33167e4e4deSmrg          mkdir_mode=-m$mode
33267e4e4deSmrg        else
33367e4e4deSmrg          mkdir_mode=
33467e4e4deSmrg        fi
33567e4e4deSmrg
33667e4e4deSmrg        posix_mkdir=false
3376781a5f7Smrg	# The $RANDOM variable is not portable (e.g., dash).  Use it
3386781a5f7Smrg	# here however when possible just to lower collision chance.
3396781a5f7Smrg	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
3406781a5f7Smrg
3416781a5f7Smrg	trap '
3426781a5f7Smrg	  ret=$?
3436781a5f7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
3446781a5f7Smrg	  exit $ret
3456781a5f7Smrg	' 0
3466781a5f7Smrg
3476781a5f7Smrg	# Because "mkdir -p" follows existing symlinks and we likely work
3486781a5f7Smrg	# directly in world-writeable /tmp, make sure that the '$tmpdir'
3496781a5f7Smrg	# directory is successfully created first before we actually test
3506781a5f7Smrg	# 'mkdir -p'.
3516781a5f7Smrg	if (umask $mkdir_umask &&
3526781a5f7Smrg	    $mkdirprog $mkdir_mode "$tmpdir" &&
3536781a5f7Smrg	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
3546781a5f7Smrg	then
3556781a5f7Smrg	  if test -z "$dir_arg" || {
3566781a5f7Smrg	       # Check for POSIX incompatibilities with -m.
3576781a5f7Smrg	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
3586781a5f7Smrg	       # other-writable bit of parent directory when it shouldn't.
3596781a5f7Smrg	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
3606781a5f7Smrg	       test_tmpdir="$tmpdir/a"
3616781a5f7Smrg	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
3626781a5f7Smrg	       case $ls_ld_tmpdir in
3636781a5f7Smrg		 d????-?r-*) different_mode=700;;
3646781a5f7Smrg		 d????-?--*) different_mode=755;;
3656781a5f7Smrg		 *) false;;
3666781a5f7Smrg	       esac &&
3676781a5f7Smrg	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
3686781a5f7Smrg		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
3696781a5f7Smrg		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
3706781a5f7Smrg	       }
3716781a5f7Smrg	     }
3726781a5f7Smrg	  then posix_mkdir=:
3736781a5f7Smrg	  fi
3746781a5f7Smrg	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
3756781a5f7Smrg	else
3766781a5f7Smrg	  # Remove any dirs left behind by ancient mkdir implementations.
3776781a5f7Smrg	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
3786781a5f7Smrg	fi
3796781a5f7Smrg	trap '' 0;;
380ffab5952Smrg    esac
381ffab5952Smrg
382ffab5952Smrg    if
383ffab5952Smrg      $posix_mkdir && (
38467e4e4deSmrg        umask $mkdir_umask &&
38567e4e4deSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
386ffab5952Smrg      )
387ffab5952Smrg    then :
388ffab5952Smrg    else
389ffab5952Smrg
3906781a5f7Smrg      # mkdir does not conform to POSIX,
391ffab5952Smrg      # or it failed possibly due to a race condition.  Create the
392ffab5952Smrg      # directory the slow way, step by step, checking for races as we go.
393ffab5952Smrg
394ffab5952Smrg      case $dstdir in
39567e4e4deSmrg        /*) prefix='/';;
39667e4e4deSmrg        [-=\(\)!]*) prefix='./';;
39767e4e4deSmrg        *)  prefix='';;
398ffab5952Smrg      esac
399ffab5952Smrg
400ffab5952Smrg      oIFS=$IFS
401ffab5952Smrg      IFS=/
40267e4e4deSmrg      set -f
403ffab5952Smrg      set fnord $dstdir
404ffab5952Smrg      shift
40567e4e4deSmrg      set +f
406ffab5952Smrg      IFS=$oIFS
407ffab5952Smrg
408ffab5952Smrg      prefixes=
409ffab5952Smrg
410ffab5952Smrg      for d
411ffab5952Smrg      do
41267e4e4deSmrg        test X"$d" = X && continue
41367e4e4deSmrg
41467e4e4deSmrg        prefix=$prefix$d
41567e4e4deSmrg        if test -d "$prefix"; then
41667e4e4deSmrg          prefixes=
41767e4e4deSmrg        else
41867e4e4deSmrg          if $posix_mkdir; then
4196781a5f7Smrg            (umask $mkdir_umask &&
42067e4e4deSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
42167e4e4deSmrg            # Don't fail if two instances are running concurrently.
42267e4e4deSmrg            test -d "$prefix" || exit 1
42367e4e4deSmrg          else
42467e4e4deSmrg            case $prefix in
42567e4e4deSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42667e4e4deSmrg              *) qprefix=$prefix;;
42767e4e4deSmrg            esac
42867e4e4deSmrg            prefixes="$prefixes '$qprefix'"
42967e4e4deSmrg          fi
43067e4e4deSmrg        fi
43167e4e4deSmrg        prefix=$prefix/
432ffab5952Smrg      done
433ffab5952Smrg
434ffab5952Smrg      if test -n "$prefixes"; then
43567e4e4deSmrg        # Don't fail if two instances are running concurrently.
43667e4e4deSmrg        (umask $mkdir_umask &&
43767e4e4deSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43867e4e4deSmrg          test -d "$dstdir" || exit 1
43967e4e4deSmrg        obsolete_mkdir_used=true
440ffab5952Smrg      fi
441ffab5952Smrg    fi
442ffab5952Smrg  fi
443ffab5952Smrg
444ffab5952Smrg  if test -n "$dir_arg"; then
445ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
446ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
447ffab5952Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
448ffab5952Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
449ffab5952Smrg  else
450ffab5952Smrg
451ffab5952Smrg    # Make a couple of temp file names in the proper directory.
45245aa2fbfSmrg    dsttmp=${dstdirslash}_inst.$$_
45345aa2fbfSmrg    rmtmp=${dstdirslash}_rm.$$_
454ffab5952Smrg
455ffab5952Smrg    # Trap to clean up those temp files at exit.
456ffab5952Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
457ffab5952Smrg
458ffab5952Smrg    # Copy the file name to the temp name.
45945aa2fbfSmrg    (umask $cp_umask &&
46045aa2fbfSmrg     { test -z "$stripcmd" || {
46145aa2fbfSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
46245aa2fbfSmrg	 # which would cause strip to fail.
46345aa2fbfSmrg	 if test -z "$doit"; then
46445aa2fbfSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46545aa2fbfSmrg	 else
46645aa2fbfSmrg	   $doit touch "$dsttmp"
46745aa2fbfSmrg	 fi
46845aa2fbfSmrg       }
46945aa2fbfSmrg     } &&
47045aa2fbfSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
471ffab5952Smrg
472ffab5952Smrg    # and set any options; do chmod last to preserve setuid bits.
473ffab5952Smrg    #
474ffab5952Smrg    # If any of these fail, we abort the whole thing.  If we want to
475ffab5952Smrg    # ignore errors from any of these, just make sure not to ignore
476ffab5952Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
477ffab5952Smrg    #
478ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
479ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
480ffab5952Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
481ffab5952Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
482ffab5952Smrg
483ffab5952Smrg    # If -C, don't bother to copy if it wouldn't change the file.
484ffab5952Smrg    if $copy_on_change &&
48567e4e4deSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48667e4e4deSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48767e4e4deSmrg       set -f &&
488ffab5952Smrg       set X $old && old=:$2:$4:$5:$6 &&
489ffab5952Smrg       set X $new && new=:$2:$4:$5:$6 &&
49067e4e4deSmrg       set +f &&
491ffab5952Smrg       test "$old" = "$new" &&
492ffab5952Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
493ffab5952Smrg    then
494ffab5952Smrg      rm -f "$dsttmp"
495ffab5952Smrg    else
4966781a5f7Smrg      # If $backupsuffix is set, and the file being installed
4976781a5f7Smrg      # already exists, attempt a backup.  Don't worry if it fails,
4986781a5f7Smrg      # e.g., if mv doesn't support -f.
4996781a5f7Smrg      if test -n "$backupsuffix" && test -f "$dst"; then
5006781a5f7Smrg        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
5016781a5f7Smrg      fi
5026781a5f7Smrg
503ffab5952Smrg      # Rename the file to the real destination.
504ffab5952Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
505ffab5952Smrg
506ffab5952Smrg      # The rename failed, perhaps because mv can't rename something else
507ffab5952Smrg      # to itself, or perhaps because mv is so ancient that it does not
508ffab5952Smrg      # support -f.
509ffab5952Smrg      {
51067e4e4deSmrg        # Now remove or move aside any old file at destination location.
51167e4e4deSmrg        # We try this two ways since rm can't unlink itself on some
51267e4e4deSmrg        # systems and the destination file might be busy for other
51367e4e4deSmrg        # reasons.  In this case, the final cleanup might fail but the new
51467e4e4deSmrg        # file should still install successfully.
51567e4e4deSmrg        {
51667e4e4deSmrg          test ! -f "$dst" ||
5176781a5f7Smrg          $doit $rmcmd "$dst" 2>/dev/null ||
51867e4e4deSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
5196781a5f7Smrg            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
52067e4e4deSmrg          } ||
52167e4e4deSmrg          { echo "$0: cannot unlink or rename $dst" >&2
52267e4e4deSmrg            (exit 1); exit 1
52367e4e4deSmrg          }
52467e4e4deSmrg        } &&
52567e4e4deSmrg
52667e4e4deSmrg        # Now rename the file to the real destination.
52767e4e4deSmrg        $doit $mvcmd "$dsttmp" "$dst"
528ffab5952Smrg      }
529ffab5952Smrg    fi || exit 1
530ffab5952Smrg
531ffab5952Smrg    trap '' 0
532ffab5952Smrg  fi
533ffab5952Smrgdone
534ffab5952Smrg
535ffab5952Smrg# Local variables:
53645aa2fbfSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
537ffab5952Smrg# time-stamp-start: "scriptversion="
538ffab5952Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
53945aa2fbfSmrg# time-stamp-time-zone: "UTC0"
540ffab5952Smrg# time-stamp-end: "; # UTC"
541ffab5952Smrg# End:
542