install-sh revision 67e4e4de
1ffab5952Smrg#!/bin/sh
2ffab5952Smrg# install - install a program, script, or datafile
3ffab5952Smrg
467e4e4deSmrgscriptversion=2013-12-25.23; # 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
274ffab5952Smrg    # If destination is a directory, append the input filename; won't work
275ffab5952Smrg    # if double slashes aren't ignored.
276ffab5952Smrg    if test -d "$dst"; then
27767e4e4deSmrg      if test "$is_target_a_directory" = never; then
27867e4e4deSmrg        echo "$0: $dst_arg: Is a directory" >&2
27967e4e4deSmrg        exit 1
280ffab5952Smrg      fi
281ffab5952Smrg      dstdir=$dst
282ffab5952Smrg      dst=$dstdir/`basename "$src"`
283ffab5952Smrg      dstdir_status=0
284ffab5952Smrg    else
28567e4e4deSmrg      dstdir=`dirname "$dst"`
286ffab5952Smrg      test -d "$dstdir"
287ffab5952Smrg      dstdir_status=$?
288ffab5952Smrg    fi
289ffab5952Smrg  fi
290ffab5952Smrg
291ffab5952Smrg  obsolete_mkdir_used=false
292ffab5952Smrg
293ffab5952Smrg  if test $dstdir_status != 0; then
294ffab5952Smrg    case $posix_mkdir in
295ffab5952Smrg      '')
29667e4e4deSmrg        # Create intermediate dirs using mode 755 as modified by the umask.
29767e4e4deSmrg        # This is like FreeBSD 'install' as of 1997-10-28.
29867e4e4deSmrg        umask=`umask`
29967e4e4deSmrg        case $stripcmd.$umask in
30067e4e4deSmrg          # Optimize common cases.
30167e4e4deSmrg          *[2367][2367]) mkdir_umask=$umask;;
30267e4e4deSmrg          .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
30367e4e4deSmrg
30467e4e4deSmrg          *[0-7])
30567e4e4deSmrg            mkdir_umask=`expr $umask + 22 \
30667e4e4deSmrg              - $umask % 100 % 40 + $umask % 20 \
30767e4e4deSmrg              - $umask % 10 % 4 + $umask % 2
30867e4e4deSmrg            `;;
30967e4e4deSmrg          *) mkdir_umask=$umask,go-w;;
31067e4e4deSmrg        esac
31167e4e4deSmrg
31267e4e4deSmrg        # With -d, create the new directory with the user-specified mode.
31367e4e4deSmrg        # Otherwise, rely on $mkdir_umask.
31467e4e4deSmrg        if test -n "$dir_arg"; then
31567e4e4deSmrg          mkdir_mode=-m$mode
31667e4e4deSmrg        else
31767e4e4deSmrg          mkdir_mode=
31867e4e4deSmrg        fi
31967e4e4deSmrg
32067e4e4deSmrg        posix_mkdir=false
32167e4e4deSmrg        case $umask in
32267e4e4deSmrg          *[123567][0-7][0-7])
32367e4e4deSmrg            # POSIX mkdir -p sets u+wx bits regardless of umask, which
32467e4e4deSmrg            # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
32567e4e4deSmrg            ;;
32667e4e4deSmrg          *)
32767e4e4deSmrg            tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
32867e4e4deSmrg            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
32967e4e4deSmrg
33067e4e4deSmrg            if (umask $mkdir_umask &&
33167e4e4deSmrg                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
33267e4e4deSmrg            then
33367e4e4deSmrg              if test -z "$dir_arg" || {
33467e4e4deSmrg                   # Check for POSIX incompatibilities with -m.
33567e4e4deSmrg                   # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
33667e4e4deSmrg                   # other-writable bit of parent directory when it shouldn't.
33767e4e4deSmrg                   # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
33867e4e4deSmrg                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
33967e4e4deSmrg                   case $ls_ld_tmpdir in
34067e4e4deSmrg                     d????-?r-*) different_mode=700;;
34167e4e4deSmrg                     d????-?--*) different_mode=755;;
34267e4e4deSmrg                     *) false;;
34367e4e4deSmrg                   esac &&
34467e4e4deSmrg                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
34567e4e4deSmrg                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
34667e4e4deSmrg                     test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
34767e4e4deSmrg                   }
34867e4e4deSmrg                 }
34967e4e4deSmrg              then posix_mkdir=:
35067e4e4deSmrg              fi
35167e4e4deSmrg              rmdir "$tmpdir/d" "$tmpdir"
35267e4e4deSmrg            else
35367e4e4deSmrg              # Remove any dirs left behind by ancient mkdir implementations.
35467e4e4deSmrg              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
35567e4e4deSmrg            fi
35667e4e4deSmrg            trap '' 0;;
35767e4e4deSmrg        esac;;
358ffab5952Smrg    esac
359ffab5952Smrg
360ffab5952Smrg    if
361ffab5952Smrg      $posix_mkdir && (
36267e4e4deSmrg        umask $mkdir_umask &&
36367e4e4deSmrg        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
364ffab5952Smrg      )
365ffab5952Smrg    then :
366ffab5952Smrg    else
367ffab5952Smrg
368ffab5952Smrg      # The umask is ridiculous, or mkdir does not conform to POSIX,
369ffab5952Smrg      # or it failed possibly due to a race condition.  Create the
370ffab5952Smrg      # directory the slow way, step by step, checking for races as we go.
371ffab5952Smrg
372ffab5952Smrg      case $dstdir in
37367e4e4deSmrg        /*) prefix='/';;
37467e4e4deSmrg        [-=\(\)!]*) prefix='./';;
37567e4e4deSmrg        *)  prefix='';;
376ffab5952Smrg      esac
377ffab5952Smrg
378ffab5952Smrg      oIFS=$IFS
379ffab5952Smrg      IFS=/
38067e4e4deSmrg      set -f
381ffab5952Smrg      set fnord $dstdir
382ffab5952Smrg      shift
38367e4e4deSmrg      set +f
384ffab5952Smrg      IFS=$oIFS
385ffab5952Smrg
386ffab5952Smrg      prefixes=
387ffab5952Smrg
388ffab5952Smrg      for d
389ffab5952Smrg      do
39067e4e4deSmrg        test X"$d" = X && continue
39167e4e4deSmrg
39267e4e4deSmrg        prefix=$prefix$d
39367e4e4deSmrg        if test -d "$prefix"; then
39467e4e4deSmrg          prefixes=
39567e4e4deSmrg        else
39667e4e4deSmrg          if $posix_mkdir; then
39767e4e4deSmrg            (umask=$mkdir_umask &&
39867e4e4deSmrg             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
39967e4e4deSmrg            # Don't fail if two instances are running concurrently.
40067e4e4deSmrg            test -d "$prefix" || exit 1
40167e4e4deSmrg          else
40267e4e4deSmrg            case $prefix in
40367e4e4deSmrg              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
40467e4e4deSmrg              *) qprefix=$prefix;;
40567e4e4deSmrg            esac
40667e4e4deSmrg            prefixes="$prefixes '$qprefix'"
40767e4e4deSmrg          fi
40867e4e4deSmrg        fi
40967e4e4deSmrg        prefix=$prefix/
410ffab5952Smrg      done
411ffab5952Smrg
412ffab5952Smrg      if test -n "$prefixes"; then
41367e4e4deSmrg        # Don't fail if two instances are running concurrently.
41467e4e4deSmrg        (umask $mkdir_umask &&
41567e4e4deSmrg         eval "\$doit_exec \$mkdirprog $prefixes") ||
41667e4e4deSmrg          test -d "$dstdir" || exit 1
41767e4e4deSmrg        obsolete_mkdir_used=true
418ffab5952Smrg      fi
419ffab5952Smrg    fi
420ffab5952Smrg  fi
421ffab5952Smrg
422ffab5952Smrg  if test -n "$dir_arg"; then
423ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
424ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
425ffab5952Smrg    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
426ffab5952Smrg      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
427ffab5952Smrg  else
428ffab5952Smrg
429ffab5952Smrg    # Make a couple of temp file names in the proper directory.
430ffab5952Smrg    dsttmp=$dstdir/_inst.$$_
431ffab5952Smrg    rmtmp=$dstdir/_rm.$$_
432ffab5952Smrg
433ffab5952Smrg    # Trap to clean up those temp files at exit.
434ffab5952Smrg    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
435ffab5952Smrg
436ffab5952Smrg    # Copy the file name to the temp name.
437ffab5952Smrg    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
438ffab5952Smrg
439ffab5952Smrg    # and set any options; do chmod last to preserve setuid bits.
440ffab5952Smrg    #
441ffab5952Smrg    # If any of these fail, we abort the whole thing.  If we want to
442ffab5952Smrg    # ignore errors from any of these, just make sure not to ignore
443ffab5952Smrg    # errors from the above "$doit $cpprog $src $dsttmp" command.
444ffab5952Smrg    #
445ffab5952Smrg    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
446ffab5952Smrg    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
447ffab5952Smrg    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
448ffab5952Smrg    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
449ffab5952Smrg
450ffab5952Smrg    # If -C, don't bother to copy if it wouldn't change the file.
451ffab5952Smrg    if $copy_on_change &&
45267e4e4deSmrg       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
45367e4e4deSmrg       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
45467e4e4deSmrg       set -f &&
455ffab5952Smrg       set X $old && old=:$2:$4:$5:$6 &&
456ffab5952Smrg       set X $new && new=:$2:$4:$5:$6 &&
45767e4e4deSmrg       set +f &&
458ffab5952Smrg       test "$old" = "$new" &&
459ffab5952Smrg       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
460ffab5952Smrg    then
461ffab5952Smrg      rm -f "$dsttmp"
462ffab5952Smrg    else
463ffab5952Smrg      # Rename the file to the real destination.
464ffab5952Smrg      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
465ffab5952Smrg
466ffab5952Smrg      # The rename failed, perhaps because mv can't rename something else
467ffab5952Smrg      # to itself, or perhaps because mv is so ancient that it does not
468ffab5952Smrg      # support -f.
469ffab5952Smrg      {
47067e4e4deSmrg        # Now remove or move aside any old file at destination location.
47167e4e4deSmrg        # We try this two ways since rm can't unlink itself on some
47267e4e4deSmrg        # systems and the destination file might be busy for other
47367e4e4deSmrg        # reasons.  In this case, the final cleanup might fail but the new
47467e4e4deSmrg        # file should still install successfully.
47567e4e4deSmrg        {
47667e4e4deSmrg          test ! -f "$dst" ||
47767e4e4deSmrg          $doit $rmcmd -f "$dst" 2>/dev/null ||
47867e4e4deSmrg          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
47967e4e4deSmrg            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
48067e4e4deSmrg          } ||
48167e4e4deSmrg          { echo "$0: cannot unlink or rename $dst" >&2
48267e4e4deSmrg            (exit 1); exit 1
48367e4e4deSmrg          }
48467e4e4deSmrg        } &&
48567e4e4deSmrg
48667e4e4deSmrg        # Now rename the file to the real destination.
48767e4e4deSmrg        $doit $mvcmd "$dsttmp" "$dst"
488ffab5952Smrg      }
489ffab5952Smrg    fi || exit 1
490ffab5952Smrg
491ffab5952Smrg    trap '' 0
492ffab5952Smrg  fi
493ffab5952Smrgdone
494ffab5952Smrg
495ffab5952Smrg# Local variables:
496ffab5952Smrg# eval: (add-hook 'write-file-hooks 'time-stamp)
497ffab5952Smrg# time-stamp-start: "scriptversion="
498ffab5952Smrg# time-stamp-format: "%:y-%02m-%02d.%02H"
499ffab5952Smrg# time-stamp-time-zone: "UTC"
500ffab5952Smrg# time-stamp-end: "; # UTC"
501ffab5952Smrg# End:
502