install-sh revision 45aa2fbf
1ffab5952Smrg#!/bin/sh
2ffab5952Smrg# install - install a program, script, or datafile
3ffab5952Smrg
445aa2fbfSmrgscriptversion=2018-03-11.20; # 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
72ffab5952Smrgchgrpcmd=
73ffab5952Smrgchmodcmd=$chmodprog
74ffab5952Smrgchowncmd=
75ffab5952Smrgmvcmd=$mvprog
76ffab5952Smrgrmcmd="$rmprog -f"
77ffab5952Smrgstripcmd=
78ffab5952Smrg
79ffab5952Smrgsrc=
80ffab5952Smrgdst=
81ffab5952Smrgdir_arg=
82ffab5952Smrgdst_arg=
83ffab5952Smrg
84ffab5952Smrgcopy_on_change=false
8567e4e4deSmrgis_target_a_directory=possibly
86ffab5952Smrg
87ffab5952Smrgusage="\
88ffab5952SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89ffab5952Smrg   or: $0 [OPTION]... SRCFILES... DIRECTORY
90ffab5952Smrg   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91ffab5952Smrg   or: $0 [OPTION]... -d DIRECTORIES...
92ffab5952Smrg
93ffab5952SmrgIn the 1st form, copy SRCFILE to DSTFILE.
94ffab5952SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95ffab5952SmrgIn the 4th, create DIRECTORIES.
96ffab5952Smrg
97ffab5952SmrgOptions:
98ffab5952Smrg     --help     display this help and exit.
99ffab5952Smrg     --version  display version info and exit.
100ffab5952Smrg
101ffab5952Smrg  -c            (ignored)
102ffab5952Smrg  -C            install only if different (preserve the last data modification time)
103ffab5952Smrg  -d            create directories instead of installing files.
104ffab5952Smrg  -g GROUP      $chgrpprog installed files to GROUP.
105ffab5952Smrg  -m MODE       $chmodprog installed files to MODE.
106ffab5952Smrg  -o USER       $chownprog installed files to USER.
107ffab5952Smrg  -s            $stripprog installed files.
108ffab5952Smrg  -t DIRECTORY  install into DIRECTORY.
109ffab5952Smrg  -T            report an error if DSTFILE is a directory.
110ffab5952Smrg
111ffab5952SmrgEnvironment variables override the default commands:
112ffab5952Smrg  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113ffab5952Smrg  RMPROG STRIPPROG
114ffab5952Smrg"
115ffab5952Smrg
116ffab5952Smrgwhile test $# -ne 0; do
117ffab5952Smrg  case $1 in
118ffab5952Smrg    -c) ;;
119ffab5952Smrg
120ffab5952Smrg    -C) copy_on_change=true;;
121ffab5952Smrg
122ffab5952Smrg    -d) dir_arg=true;;
123ffab5952Smrg
124ffab5952Smrg    -g) chgrpcmd="$chgrpprog $2"
12567e4e4deSmrg        shift;;
126ffab5952Smrg
127ffab5952Smrg    --help) echo "$usage"; exit $?;;
128ffab5952Smrg
129ffab5952Smrg    -m) mode=$2
13067e4e4deSmrg        case $mode in
13167e4e4deSmrg          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
13267e4e4deSmrg            echo "$0: invalid mode: $mode" >&2
13367e4e4deSmrg            exit 1;;
13467e4e4deSmrg        esac
13567e4e4deSmrg        shift;;
136ffab5952Smrg
137ffab5952Smrg    -o) chowncmd="$chownprog $2"
13867e4e4deSmrg        shift;;
139ffab5952Smrg
140ffab5952Smrg    -s) stripcmd=$stripprog;;
141ffab5952Smrg
14267e4e4deSmrg    -t)
14367e4e4deSmrg        is_target_a_directory=always
14467e4e4deSmrg        dst_arg=$2
14567e4e4deSmrg        # Protect names problematic for 'test' and other utilities.
14667e4e4deSmrg        case $dst_arg in
14767e4e4deSmrg          -* | [=\(\)!]) dst_arg=./$dst_arg;;
14867e4e4deSmrg        esac
14967e4e4deSmrg        shift;;
150ffab5952Smrg
15167e4e4deSmrg    -T) is_target_a_directory=never;;
152ffab5952Smrg
153ffab5952Smrg    --version) echo "$0 $scriptversion"; exit $?;;
154ffab5952Smrg
15567e4e4deSmrg    --) shift
15667e4e4deSmrg        break;;
157ffab5952Smrg
15867e4e4deSmrg    -*) echo "$0: invalid option: $1" >&2
15967e4e4deSmrg        exit 1;;
160ffab5952Smrg
161ffab5952Smrg    *)  break;;
162ffab5952Smrg  esac
163ffab5952Smrg  shift
164ffab5952Smrgdone
165ffab5952Smrg
16667e4e4deSmrg# We allow the use of options -d and -T together, by making -d
16767e4e4deSmrg# take the precedence; this is for compatibility with GNU install.
16867e4e4deSmrg
16967e4e4deSmrgif test -n "$dir_arg"; then
17067e4e4deSmrg  if test -n "$dst_arg"; then
17167e4e4deSmrg    echo "$0: target directory not allowed when installing a directory." >&2
17267e4e4deSmrg    exit 1
17367e4e4deSmrg  fi
17467e4e4deSmrgfi
17567e4e4deSmrg
176ffab5952Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
177ffab5952Smrg  # When -d is used, all remaining arguments are directories to create.
178ffab5952Smrg  # When -t is used, the destination is already specified.
179ffab5952Smrg  # Otherwise, the last argument is the destination.  Remove it from $@.
180ffab5952Smrg  for arg
181ffab5952Smrg  do
182ffab5952Smrg    if test -n "$dst_arg"; then
183ffab5952Smrg      # $@ is not empty: it contains at least $arg.
184ffab5952Smrg      set fnord "$@" "$dst_arg"
185ffab5952Smrg      shift # fnord
186ffab5952Smrg    fi
187ffab5952Smrg    shift # arg
188ffab5952Smrg    dst_arg=$arg
18967e4e4deSmrg    # Protect names problematic for 'test' and other utilities.
19043c16309Smrg    case $dst_arg in
19143c16309Smrg      -* | [=\(\)!]) dst_arg=./$dst_arg;;
19243c16309Smrg    esac
193ffab5952Smrg  done
194ffab5952Smrgfi
195ffab5952Smrg
196ffab5952Smrgif test $# -eq 0; then
197ffab5952Smrg  if test -z "$dir_arg"; then
198ffab5952Smrg    echo "$0: no input file specified." >&2
199ffab5952Smrg    exit 1
200ffab5952Smrg  fi
20167e4e4deSmrg  # It's OK to call 'install-sh -d' without argument.
202ffab5952Smrg  # This can happen when creating conditional directories.
203ffab5952Smrg  exit 0
204ffab5952Smrgfi
205ffab5952Smrg
20667e4e4deSmrgif test -z "$dir_arg"; then
20767e4e4deSmrg  if test $# -gt 1 || test "$is_target_a_directory" = always; then
20867e4e4deSmrg    if test ! -d "$dst_arg"; then
20967e4e4deSmrg      echo "$0: $dst_arg: Is not a directory." >&2
21067e4e4deSmrg      exit 1
21167e4e4deSmrg    fi
21267e4e4deSmrg  fi
21367e4e4deSmrgfi
21467e4e4deSmrg
215ffab5952Smrgif test -z "$dir_arg"; then
21643c16309Smrg  do_exit='(exit $ret); exit $ret'
21743c16309Smrg  trap "ret=129; $do_exit" 1
21843c16309Smrg  trap "ret=130; $do_exit" 2
21943c16309Smrg  trap "ret=141; $do_exit" 13
22043c16309Smrg  trap "ret=143; $do_exit" 15
221ffab5952Smrg
222ffab5952Smrg  # Set umask so as not to create temps with too-generous modes.
223ffab5952Smrg  # However, 'strip' requires both read and write access to temps.
224ffab5952Smrg  case $mode in
225ffab5952Smrg    # Optimize common cases.
226ffab5952Smrg    *644) cp_umask=133;;
227ffab5952Smrg    *755) cp_umask=22;;
228ffab5952Smrg
229ffab5952Smrg    *[0-7])
230ffab5952Smrg      if test -z "$stripcmd"; then
23167e4e4deSmrg        u_plus_rw=
232ffab5952Smrg      else
23367e4e4deSmrg        u_plus_rw='% 200'
234ffab5952Smrg      fi
235ffab5952Smrg      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
236ffab5952Smrg    *)
237ffab5952Smrg      if test -z "$stripcmd"; then
23867e4e4deSmrg        u_plus_rw=
239ffab5952Smrg      else
24067e4e4deSmrg        u_plus_rw=,u+rw
241ffab5952Smrg      fi
242ffab5952Smrg      cp_umask=$mode$u_plus_rw;;
243ffab5952Smrg  esac
244ffab5952Smrgfi
245ffab5952Smrg
246ffab5952Smrgfor src
247ffab5952Smrgdo
24867e4e4deSmrg  # Protect names problematic for 'test' and other utilities.
249ffab5952Smrg  case $src in
25043c16309Smrg    -* | [=\(\)!]) src=./$src;;
251ffab5952Smrg  esac
252ffab5952Smrg
253ffab5952Smrg  if test -n "$dir_arg"; then
254ffab5952Smrg    dst=$src
255ffab5952Smrg    dstdir=$dst
256ffab5952Smrg    test -d "$dstdir"
257ffab5952Smrg    dstdir_status=$?
258ffab5952Smrg  else
259ffab5952Smrg
260ffab5952Smrg    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
261ffab5952Smrg    # might cause directories to be created, which would be especially bad
262ffab5952Smrg    # if $src (and thus $dsttmp) contains '*'.
263ffab5952Smrg    if test ! -f "$src" && test ! -d "$src"; then
264ffab5952Smrg      echo "$0: $src does not exist." >&2
265ffab5952Smrg      exit 1
266ffab5952Smrg    fi
267ffab5952Smrg
268ffab5952Smrg    if test -z "$dst_arg"; then
269ffab5952Smrg      echo "$0: no destination specified." >&2
270ffab5952Smrg      exit 1
271ffab5952Smrg    fi
272ffab5952Smrg    dst=$dst_arg
273ffab5952Smrg
27445aa2fbfSmrg    # If destination is a directory, append the input filename.
275ffab5952Smrg    if test -d "$dst"; then
27667e4e4deSmrg      if test "$is_target_a_directory" = never; then
27767e4e4deSmrg        echo "$0: $dst_arg: Is a directory" >&2
27867e4e4deSmrg        exit 1
279ffab5952Smrg      fi
280ffab5952Smrg      dstdir=$dst
28145aa2fbfSmrg      dstbase=`basename "$src"`
28245aa2fbfSmrg      case $dst in
28345aa2fbfSmrg	*/) dst=$dst$dstbase;;
28445aa2fbfSmrg	*)  dst=$dst/$dstbase;;
28545aa2fbfSmrg      esac
286ffab5952Smrg      dstdir_status=0
287ffab5952Smrg    else
28867e4e4deSmrg      dstdir=`dirname "$dst"`
289ffab5952Smrg      test -d "$dstdir"
290ffab5952Smrg      dstdir_status=$?
291ffab5952Smrg    fi
292ffab5952Smrg  fi
293ffab5952Smrg
29445aa2fbfSmrg  case $dstdir in
29545aa2fbfSmrg    */) dstdirslash=$dstdir;;
29645aa2fbfSmrg    *)  dstdirslash=$dstdir/;;
29745aa2fbfSmrg  esac
29845aa2fbfSmrg
299ffab5952Smrg  obsolete_mkdir_used=false
300ffab5952Smrg
301ffab5952Smrg  if test $dstdir_status != 0; then
302ffab5952Smrg    case $posix_mkdir in
303ffab5952Smrg      '')
30467e4e4deSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
30567e4e4deSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
30667e4e4deSmrg        umask=`umask`
30767e4e4deSmrg        case $stripcmd.$umask in
30867e4e4deSmrg          # Optimize common cases.
30967e4e4deSmrg          *[2367][2367]) mkdir_umask=$umask;;
31067e4e4deSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
31167e4e4deSmrg
31267e4e4deSmrg          *[0-7])
31367e4e4deSmrg            mkdir_umask=`expr $umask + 22 \
31467e4e4deSmrg              - $umask % 100 % 40 + $umask % 20 \
31567e4e4deSmrg              - $umask % 10 % 4 + $umask % 2
31667e4e4deSmrg            `;;
31767e4e4deSmrg          *) mkdir_umask=$umask,go-w;;
31867e4e4deSmrg        esac
31967e4e4deSmrg
32067e4e4deSmrg        # With -d, create the new directory with the user-specified mode.
32167e4e4deSmrg        # Otherwise, rely on $mkdir_umask.
32267e4e4deSmrg        if test -n "$dir_arg"; then
32367e4e4deSmrg          mkdir_mode=-m$mode
32467e4e4deSmrg        else
32567e4e4deSmrg          mkdir_mode=
32667e4e4deSmrg        fi
32767e4e4deSmrg
32867e4e4deSmrg        posix_mkdir=false
32967e4e4deSmrg        case $umask in
33067e4e4deSmrg          *[123567][0-7][0-7])
33167e4e4deSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
33267e4e4deSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
33367e4e4deSmrg            ;;
33467e4e4deSmrg          *)
33545aa2fbfSmrg            # Note that $RANDOM variable is not portable (e.g. dash);  Use it
33645aa2fbfSmrg            # here however when possible just to lower collision chance.
33767e4e4deSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
33867e4e4deSmrg
33945aa2fbfSmrg            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
34045aa2fbfSmrg
34145aa2fbfSmrg            # Because "mkdir -p" follows existing symlinks and we likely work
34245aa2fbfSmrg            # directly in world-writeable /tmp, make sure that the '$tmpdir'
34345aa2fbfSmrg            # directory is successfully created first before we actually test
34445aa2fbfSmrg            # 'mkdir -p' feature.
34567e4e4deSmrg            if (umask $mkdir_umask &&
34645aa2fbfSmrg                $mkdirprog $mkdir_mode "$tmpdir" &&
34745aa2fbfSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
34867e4e4deSmrg            then
34967e4e4deSmrg              if test -z "$dir_arg" || {
35067e4e4deSmrg                   # Check for POSIX incompatibilities with -m.
35167e4e4deSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
35267e4e4deSmrg                   # other-writable bit of parent directory when it shouldn't.
35367e4e4deSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
35445aa2fbfSmrg                   test_tmpdir="$tmpdir/a"
35545aa2fbfSmrg                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
35667e4e4deSmrg                   case $ls_ld_tmpdir in
35767e4e4deSmrg                     d????-?r-*) different_mode=700;;
35867e4e4deSmrg                     d????-?--*) different_mode=755;;
35967e4e4deSmrg                     *) false;;
36067e4e4deSmrg                   esac &&
36145aa2fbfSmrg                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
36245aa2fbfSmrg                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
36367e4e4deSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
36467e4e4deSmrg                   }
36567e4e4deSmrg                 }
36667e4e4deSmrg              then posix_mkdir=:
36767e4e4deSmrg              fi
36845aa2fbfSmrg              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
36967e4e4deSmrg            else
37067e4e4deSmrg              # Remove any dirs left behind by ancient mkdir implementations.
37145aa2fbfSmrg              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
37267e4e4deSmrg            fi
37367e4e4deSmrg            trap '' 0;;
37467e4e4deSmrg        esac;;
375ffab5952Smrg    esac
376ffab5952Smrg
377ffab5952Smrg    if
378ffab5952Smrg      $posix_mkdir && (
37967e4e4deSmrg        umask $mkdir_umask &&
38067e4e4deSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
381ffab5952Smrg      )
382ffab5952Smrg    then :
383ffab5952Smrg    else
384ffab5952Smrg
385ffab5952Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
386ffab5952Smrg      # or it failed possibly due to a race condition.  Create the
387ffab5952Smrg      # directory the slow way, step by step, checking for races as we go.
388ffab5952Smrg
389ffab5952Smrg      case $dstdir in
39067e4e4deSmrg        /*) prefix='/';;
39167e4e4deSmrg        [-=\(\)!]*) prefix='./';;
39267e4e4deSmrg        *)  prefix='';;
393ffab5952Smrg      esac
394ffab5952Smrg
395ffab5952Smrg      oIFS=$IFS
396ffab5952Smrg      IFS=/
39767e4e4deSmrg      set -f
398ffab5952Smrg      set fnord $dstdir
399ffab5952Smrg      shift
40067e4e4deSmrg      set +f
401ffab5952Smrg      IFS=$oIFS
402ffab5952Smrg
403ffab5952Smrg      prefixes=
404ffab5952Smrg
405ffab5952Smrg      for d
406ffab5952Smrg      do
40767e4e4deSmrg        test X"$d" = X && continue
40867e4e4deSmrg
40967e4e4deSmrg        prefix=$prefix$d
41067e4e4deSmrg        if test -d "$prefix"; then
41167e4e4deSmrg          prefixes=
41267e4e4deSmrg        else
41367e4e4deSmrg          if $posix_mkdir; then
41467e4e4deSmrg            (umask=$mkdir_umask &&
41567e4e4deSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
41667e4e4deSmrg            # Don't fail if two instances are running concurrently.
41767e4e4deSmrg            test -d "$prefix" || exit 1
41867e4e4deSmrg          else
41967e4e4deSmrg            case $prefix in
42067e4e4deSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
42167e4e4deSmrg              *) qprefix=$prefix;;
42267e4e4deSmrg            esac
42367e4e4deSmrg            prefixes="$prefixes '$qprefix'"
42467e4e4deSmrg          fi
42567e4e4deSmrg        fi
42667e4e4deSmrg        prefix=$prefix/
427ffab5952Smrg      done
428ffab5952Smrg
429ffab5952Smrg      if test -n "$prefixes"; then
43067e4e4deSmrg        # Don't fail if two instances are running concurrently.
43167e4e4deSmrg        (umask $mkdir_umask &&
43267e4e4deSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
43367e4e4deSmrg          test -d "$dstdir" || exit 1
43467e4e4deSmrg        obsolete_mkdir_used=true
435ffab5952Smrg      fi
436ffab5952Smrg    fi
437ffab5952Smrg  fi
438ffab5952Smrg
439ffab5952Smrg  if test -n "$dir_arg"; then
440ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
441ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
442ffab5952Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
443ffab5952Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
444ffab5952Smrg  else
445ffab5952Smrg
446ffab5952Smrg    # Make a couple of temp file names in the proper directory.
44745aa2fbfSmrg    dsttmp=${dstdirslash}_inst.$$_
44845aa2fbfSmrg    rmtmp=${dstdirslash}_rm.$$_
449ffab5952Smrg
450ffab5952Smrg    # Trap to clean up those temp files at exit.
451ffab5952Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
452ffab5952Smrg
453ffab5952Smrg    # Copy the file name to the temp name.
45445aa2fbfSmrg    (umask $cp_umask &&
45545aa2fbfSmrg     { test -z "$stripcmd" || {
45645aa2fbfSmrg	 # Create $dsttmp read-write so that cp doesn't create it read-only,
45745aa2fbfSmrg	 # which would cause strip to fail.
45845aa2fbfSmrg	 if test -z "$doit"; then
45945aa2fbfSmrg	   : >"$dsttmp" # No need to fork-exec 'touch'.
46045aa2fbfSmrg	 else
46145aa2fbfSmrg	   $doit touch "$dsttmp"
46245aa2fbfSmrg	 fi
46345aa2fbfSmrg       }
46445aa2fbfSmrg     } &&
46545aa2fbfSmrg     $doit_exec $cpprog "$src" "$dsttmp") &&
466ffab5952Smrg
467ffab5952Smrg    # and set any options; do chmod last to preserve setuid bits.
468ffab5952Smrg    #
469ffab5952Smrg    # If any of these fail, we abort the whole thing.  If we want to
470ffab5952Smrg    # ignore errors from any of these, just make sure not to ignore
471ffab5952Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
472ffab5952Smrg    #
473ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
474ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
475ffab5952Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
476ffab5952Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
477ffab5952Smrg
478ffab5952Smrg    # If -C, don't bother to copy if it wouldn't change the file.
479ffab5952Smrg    if $copy_on_change &&
48067e4e4deSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
48167e4e4deSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
48267e4e4deSmrg       set -f &&
483ffab5952Smrg       set X $old && old=:$2:$4:$5:$6 &&
484ffab5952Smrg       set X $new && new=:$2:$4:$5:$6 &&
48567e4e4deSmrg       set +f &&
486ffab5952Smrg       test "$old" = "$new" &&
487ffab5952Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
488ffab5952Smrg    then
489ffab5952Smrg      rm -f "$dsttmp"
490ffab5952Smrg    else
491ffab5952Smrg      # Rename the file to the real destination.
492ffab5952Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
493ffab5952Smrg
494ffab5952Smrg      # The rename failed, perhaps because mv can't rename something else
495ffab5952Smrg      # to itself, or perhaps because mv is so ancient that it does not
496ffab5952Smrg      # support -f.
497ffab5952Smrg      {
49867e4e4deSmrg        # Now remove or move aside any old file at destination location.
49967e4e4deSmrg        # We try this two ways since rm can't unlink itself on some
50067e4e4deSmrg        # systems and the destination file might be busy for other
50167e4e4deSmrg        # reasons.  In this case, the final cleanup might fail but the new
50267e4e4deSmrg        # file should still install successfully.
50367e4e4deSmrg        {
50467e4e4deSmrg          test ! -f "$dst" ||
50567e4e4deSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
50667e4e4deSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
50767e4e4deSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
50867e4e4deSmrg          } ||
50967e4e4deSmrg          { echo "$0: cannot unlink or rename $dst" >&2
51067e4e4deSmrg            (exit 1); exit 1
51167e4e4deSmrg          }
51267e4e4deSmrg        } &&
51367e4e4deSmrg
51467e4e4deSmrg        # Now rename the file to the real destination.
51567e4e4deSmrg        $doit $mvcmd "$dsttmp" "$dst"
516ffab5952Smrg      }
517ffab5952Smrg    fi || exit 1
518ffab5952Smrg
519ffab5952Smrg    trap '' 0
520ffab5952Smrg  fi
521ffab5952Smrgdone
522ffab5952Smrg
523ffab5952Smrg# Local variables:
52445aa2fbfSmrg# eval: (add-hook 'before-save-hook 'time-stamp)
525ffab5952Smrg# time-stamp-start: "scriptversion="
526ffab5952Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
52745aa2fbfSmrg# time-stamp-time-zone: "UTC0"
528ffab5952Smrg# time-stamp-end: "; # UTC"
529ffab5952Smrg# End:
530