1*4882a593Smuzhiyun#!/bin/sh 2*4882a593Smuzhiyun# install - install a program, script, or datafile 3*4882a593Smuzhiyun 4*4882a593Smuzhiyunscriptversion=2018-03-11.20; # UTC 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun# This originates from X11R5 (mit/util/scripts/install.sh), which was 7*4882a593Smuzhiyun# later released in X11R6 (xc/config/util/install.sh) with the 8*4882a593Smuzhiyun# following copyright and license. 9*4882a593Smuzhiyun# 10*4882a593Smuzhiyun# Copyright (C) 1994 X Consortium 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun# Permission is hereby granted, free of charge, to any person obtaining a copy 13*4882a593Smuzhiyun# of this software and associated documentation files (the "Software"), to 14*4882a593Smuzhiyun# deal in the Software without restriction, including without limitation the 15*4882a593Smuzhiyun# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16*4882a593Smuzhiyun# sell copies of the Software, and to permit persons to whom the Software is 17*4882a593Smuzhiyun# furnished to do so, subject to the following conditions: 18*4882a593Smuzhiyun# 19*4882a593Smuzhiyun# The above copyright notice and this permission notice shall be included in 20*4882a593Smuzhiyun# all copies or substantial portions of the Software. 21*4882a593Smuzhiyun# 22*4882a593Smuzhiyun# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23*4882a593Smuzhiyun# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24*4882a593Smuzhiyun# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25*4882a593Smuzhiyun# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26*4882a593Smuzhiyun# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27*4882a593Smuzhiyun# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28*4882a593Smuzhiyun# 29*4882a593Smuzhiyun# Except as contained in this notice, the name of the X Consortium shall not 30*4882a593Smuzhiyun# be used in advertising or otherwise to promote the sale, use or other deal- 31*4882a593Smuzhiyun# ings in this Software without prior written authorization from the X Consor- 32*4882a593Smuzhiyun# tium. 33*4882a593Smuzhiyun# 34*4882a593Smuzhiyun# 35*4882a593Smuzhiyun# FSF changes to this file are in the public domain. 36*4882a593Smuzhiyun# 37*4882a593Smuzhiyun# Calling this script install-sh is preferred over install.sh, to prevent 38*4882a593Smuzhiyun# 'make' implicit rules from creating a file called install from it 39*4882a593Smuzhiyun# when there is no Makefile. 40*4882a593Smuzhiyun# 41*4882a593Smuzhiyun# This script is compatible with the BSD install script, but was written 42*4882a593Smuzhiyun# from scratch. 43*4882a593Smuzhiyun 44*4882a593Smuzhiyuntab=' ' 45*4882a593Smuzhiyunnl=' 46*4882a593Smuzhiyun' 47*4882a593SmuzhiyunIFS=" $tab$nl" 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun# Set DOITPROG to "echo" to test this script. 50*4882a593Smuzhiyun 51*4882a593Smuzhiyundoit=${DOITPROG-} 52*4882a593Smuzhiyundoit_exec=${doit:-exec} 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun# Put in absolute file names if you don't have them in your path; 55*4882a593Smuzhiyun# or use environment vars. 56*4882a593Smuzhiyun 57*4882a593Smuzhiyunchgrpprog=${CHGRPPROG-chgrp} 58*4882a593Smuzhiyunchmodprog=${CHMODPROG-chmod} 59*4882a593Smuzhiyunchownprog=${CHOWNPROG-chown} 60*4882a593Smuzhiyuncmpprog=${CMPPROG-cmp} 61*4882a593Smuzhiyuncpprog=${CPPROG-cp} 62*4882a593Smuzhiyunmkdirprog=${MKDIRPROG-mkdir} 63*4882a593Smuzhiyunmvprog=${MVPROG-mv} 64*4882a593Smuzhiyunrmprog=${RMPROG-rm} 65*4882a593Smuzhiyunstripprog=${STRIPPROG-strip} 66*4882a593Smuzhiyun 67*4882a593Smuzhiyunposix_mkdir= 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun# Desired mode of installed file. 70*4882a593Smuzhiyunmode=0755 71*4882a593Smuzhiyun 72*4882a593Smuzhiyunchgrpcmd= 73*4882a593Smuzhiyunchmodcmd=$chmodprog 74*4882a593Smuzhiyunchowncmd= 75*4882a593Smuzhiyunmvcmd=$mvprog 76*4882a593Smuzhiyunrmcmd="$rmprog -f" 77*4882a593Smuzhiyunstripcmd= 78*4882a593Smuzhiyun 79*4882a593Smuzhiyunsrc= 80*4882a593Smuzhiyundst= 81*4882a593Smuzhiyundir_arg= 82*4882a593Smuzhiyundst_arg= 83*4882a593Smuzhiyun 84*4882a593Smuzhiyuncopy_on_change=false 85*4882a593Smuzhiyunis_target_a_directory=possibly 86*4882a593Smuzhiyun 87*4882a593Smuzhiyunusage="\ 88*4882a593SmuzhiyunUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89*4882a593Smuzhiyun or: $0 [OPTION]... SRCFILES... DIRECTORY 90*4882a593Smuzhiyun or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91*4882a593Smuzhiyun or: $0 [OPTION]... -d DIRECTORIES... 92*4882a593Smuzhiyun 93*4882a593SmuzhiyunIn the 1st form, copy SRCFILE to DSTFILE. 94*4882a593SmuzhiyunIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95*4882a593SmuzhiyunIn the 4th, create DIRECTORIES. 96*4882a593Smuzhiyun 97*4882a593SmuzhiyunOptions: 98*4882a593Smuzhiyun --help display this help and exit. 99*4882a593Smuzhiyun --version display version info and exit. 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun -c (ignored) 102*4882a593Smuzhiyun -C install only if different (preserve the last data modification time) 103*4882a593Smuzhiyun -d create directories instead of installing files. 104*4882a593Smuzhiyun -g GROUP $chgrpprog installed files to GROUP. 105*4882a593Smuzhiyun -m MODE $chmodprog installed files to MODE. 106*4882a593Smuzhiyun -o USER $chownprog installed files to USER. 107*4882a593Smuzhiyun -s $stripprog installed files. 108*4882a593Smuzhiyun -t DIRECTORY install into DIRECTORY. 109*4882a593Smuzhiyun -T report an error if DSTFILE is a directory. 110*4882a593Smuzhiyun 111*4882a593SmuzhiyunEnvironment variables override the default commands: 112*4882a593Smuzhiyun CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 113*4882a593Smuzhiyun RMPROG STRIPPROG 114*4882a593Smuzhiyun" 115*4882a593Smuzhiyun 116*4882a593Smuzhiyunwhile test $# -ne 0; do 117*4882a593Smuzhiyun case $1 in 118*4882a593Smuzhiyun -c) ;; 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun -C) copy_on_change=true;; 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun -d) dir_arg=true;; 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun -g) chgrpcmd="$chgrpprog $2" 125*4882a593Smuzhiyun shift;; 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun --help) echo "$usage"; exit $?;; 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun -m) mode=$2 130*4882a593Smuzhiyun case $mode in 131*4882a593Smuzhiyun *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 132*4882a593Smuzhiyun echo "$0: invalid mode: $mode" >&2 133*4882a593Smuzhiyun exit 1;; 134*4882a593Smuzhiyun esac 135*4882a593Smuzhiyun shift;; 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun -o) chowncmd="$chownprog $2" 138*4882a593Smuzhiyun shift;; 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun -s) stripcmd=$stripprog;; 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun -t) 143*4882a593Smuzhiyun is_target_a_directory=always 144*4882a593Smuzhiyun dst_arg=$2 145*4882a593Smuzhiyun # Protect names problematic for 'test' and other utilities. 146*4882a593Smuzhiyun case $dst_arg in 147*4882a593Smuzhiyun -* | [=\(\)!]) dst_arg=./$dst_arg;; 148*4882a593Smuzhiyun esac 149*4882a593Smuzhiyun shift;; 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun -T) is_target_a_directory=never;; 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun --version) echo "$0 $scriptversion"; exit $?;; 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun --) shift 156*4882a593Smuzhiyun break;; 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun -*) echo "$0: invalid option: $1" >&2 159*4882a593Smuzhiyun exit 1;; 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun *) break;; 162*4882a593Smuzhiyun esac 163*4882a593Smuzhiyun shift 164*4882a593Smuzhiyundone 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun# We allow the use of options -d and -T together, by making -d 167*4882a593Smuzhiyun# take the precedence; this is for compatibility with GNU install. 168*4882a593Smuzhiyun 169*4882a593Smuzhiyunif test -n "$dir_arg"; then 170*4882a593Smuzhiyun if test -n "$dst_arg"; then 171*4882a593Smuzhiyun echo "$0: target directory not allowed when installing a directory." >&2 172*4882a593Smuzhiyun exit 1 173*4882a593Smuzhiyun fi 174*4882a593Smuzhiyunfi 175*4882a593Smuzhiyun 176*4882a593Smuzhiyunif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177*4882a593Smuzhiyun # When -d is used, all remaining arguments are directories to create. 178*4882a593Smuzhiyun # When -t is used, the destination is already specified. 179*4882a593Smuzhiyun # Otherwise, the last argument is the destination. Remove it from $@. 180*4882a593Smuzhiyun for arg 181*4882a593Smuzhiyun do 182*4882a593Smuzhiyun if test -n "$dst_arg"; then 183*4882a593Smuzhiyun # $@ is not empty: it contains at least $arg. 184*4882a593Smuzhiyun set fnord "$@" "$dst_arg" 185*4882a593Smuzhiyun shift # fnord 186*4882a593Smuzhiyun fi 187*4882a593Smuzhiyun shift # arg 188*4882a593Smuzhiyun dst_arg=$arg 189*4882a593Smuzhiyun # Protect names problematic for 'test' and other utilities. 190*4882a593Smuzhiyun case $dst_arg in 191*4882a593Smuzhiyun -* | [=\(\)!]) dst_arg=./$dst_arg;; 192*4882a593Smuzhiyun esac 193*4882a593Smuzhiyun done 194*4882a593Smuzhiyunfi 195*4882a593Smuzhiyun 196*4882a593Smuzhiyunif test $# -eq 0; then 197*4882a593Smuzhiyun if test -z "$dir_arg"; then 198*4882a593Smuzhiyun echo "$0: no input file specified." >&2 199*4882a593Smuzhiyun exit 1 200*4882a593Smuzhiyun fi 201*4882a593Smuzhiyun # It's OK to call 'install-sh -d' without argument. 202*4882a593Smuzhiyun # This can happen when creating conditional directories. 203*4882a593Smuzhiyun exit 0 204*4882a593Smuzhiyunfi 205*4882a593Smuzhiyun 206*4882a593Smuzhiyunif test -z "$dir_arg"; then 207*4882a593Smuzhiyun if test $# -gt 1 || test "$is_target_a_directory" = always; then 208*4882a593Smuzhiyun if test ! -d "$dst_arg"; then 209*4882a593Smuzhiyun echo "$0: $dst_arg: Is not a directory." >&2 210*4882a593Smuzhiyun exit 1 211*4882a593Smuzhiyun fi 212*4882a593Smuzhiyun fi 213*4882a593Smuzhiyunfi 214*4882a593Smuzhiyun 215*4882a593Smuzhiyunif test -z "$dir_arg"; then 216*4882a593Smuzhiyun do_exit='(exit $ret); exit $ret' 217*4882a593Smuzhiyun trap "ret=129; $do_exit" 1 218*4882a593Smuzhiyun trap "ret=130; $do_exit" 2 219*4882a593Smuzhiyun trap "ret=141; $do_exit" 13 220*4882a593Smuzhiyun trap "ret=143; $do_exit" 15 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun # Set umask so as not to create temps with too-generous modes. 223*4882a593Smuzhiyun # However, 'strip' requires both read and write access to temps. 224*4882a593Smuzhiyun case $mode in 225*4882a593Smuzhiyun # Optimize common cases. 226*4882a593Smuzhiyun *644) cp_umask=133;; 227*4882a593Smuzhiyun *755) cp_umask=22;; 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun *[0-7]) 230*4882a593Smuzhiyun if test -z "$stripcmd"; then 231*4882a593Smuzhiyun u_plus_rw= 232*4882a593Smuzhiyun else 233*4882a593Smuzhiyun u_plus_rw='% 200' 234*4882a593Smuzhiyun fi 235*4882a593Smuzhiyun cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 236*4882a593Smuzhiyun *) 237*4882a593Smuzhiyun if test -z "$stripcmd"; then 238*4882a593Smuzhiyun u_plus_rw= 239*4882a593Smuzhiyun else 240*4882a593Smuzhiyun u_plus_rw=,u+rw 241*4882a593Smuzhiyun fi 242*4882a593Smuzhiyun cp_umask=$mode$u_plus_rw;; 243*4882a593Smuzhiyun esac 244*4882a593Smuzhiyunfi 245*4882a593Smuzhiyun 246*4882a593Smuzhiyunfor src 247*4882a593Smuzhiyundo 248*4882a593Smuzhiyun # Protect names problematic for 'test' and other utilities. 249*4882a593Smuzhiyun case $src in 250*4882a593Smuzhiyun -* | [=\(\)!]) src=./$src;; 251*4882a593Smuzhiyun esac 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun if test -n "$dir_arg"; then 254*4882a593Smuzhiyun dst=$src 255*4882a593Smuzhiyun dstdir=$dst 256*4882a593Smuzhiyun test -d "$dstdir" 257*4882a593Smuzhiyun dstdir_status=$? 258*4882a593Smuzhiyun else 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 261*4882a593Smuzhiyun # might cause directories to be created, which would be especially bad 262*4882a593Smuzhiyun # if $src (and thus $dsttmp) contains '*'. 263*4882a593Smuzhiyun if test ! -f "$src" && test ! -d "$src"; then 264*4882a593Smuzhiyun echo "$0: $src does not exist." >&2 265*4882a593Smuzhiyun exit 1 266*4882a593Smuzhiyun fi 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun if test -z "$dst_arg"; then 269*4882a593Smuzhiyun echo "$0: no destination specified." >&2 270*4882a593Smuzhiyun exit 1 271*4882a593Smuzhiyun fi 272*4882a593Smuzhiyun dst=$dst_arg 273*4882a593Smuzhiyun 274*4882a593Smuzhiyun # If destination is a directory, append the input filename. 275*4882a593Smuzhiyun if test -d "$dst"; then 276*4882a593Smuzhiyun if test "$is_target_a_directory" = never; then 277*4882a593Smuzhiyun echo "$0: $dst_arg: Is a directory" >&2 278*4882a593Smuzhiyun exit 1 279*4882a593Smuzhiyun fi 280*4882a593Smuzhiyun dstdir=$dst 281*4882a593Smuzhiyun dstbase=`basename "$src"` 282*4882a593Smuzhiyun case $dst in 283*4882a593Smuzhiyun */) dst=$dst$dstbase;; 284*4882a593Smuzhiyun *) dst=$dst/$dstbase;; 285*4882a593Smuzhiyun esac 286*4882a593Smuzhiyun dstdir_status=0 287*4882a593Smuzhiyun else 288*4882a593Smuzhiyun dstdir=`dirname "$dst"` 289*4882a593Smuzhiyun test -d "$dstdir" 290*4882a593Smuzhiyun dstdir_status=$? 291*4882a593Smuzhiyun fi 292*4882a593Smuzhiyun fi 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun case $dstdir in 295*4882a593Smuzhiyun */) dstdirslash=$dstdir;; 296*4882a593Smuzhiyun *) dstdirslash=$dstdir/;; 297*4882a593Smuzhiyun esac 298*4882a593Smuzhiyun 299*4882a593Smuzhiyun obsolete_mkdir_used=false 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun if test $dstdir_status != 0; then 302*4882a593Smuzhiyun case $posix_mkdir in 303*4882a593Smuzhiyun '') 304*4882a593Smuzhiyun # Create intermediate dirs using mode 755 as modified by the umask. 305*4882a593Smuzhiyun # This is like FreeBSD 'install' as of 1997-10-28. 306*4882a593Smuzhiyun umask=`umask` 307*4882a593Smuzhiyun case $stripcmd.$umask in 308*4882a593Smuzhiyun # Optimize common cases. 309*4882a593Smuzhiyun *[2367][2367]) mkdir_umask=$umask;; 310*4882a593Smuzhiyun .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun *[0-7]) 313*4882a593Smuzhiyun mkdir_umask=`expr $umask + 22 \ 314*4882a593Smuzhiyun - $umask % 100 % 40 + $umask % 20 \ 315*4882a593Smuzhiyun - $umask % 10 % 4 + $umask % 2 316*4882a593Smuzhiyun `;; 317*4882a593Smuzhiyun *) mkdir_umask=$umask,go-w;; 318*4882a593Smuzhiyun esac 319*4882a593Smuzhiyun 320*4882a593Smuzhiyun # With -d, create the new directory with the user-specified mode. 321*4882a593Smuzhiyun # Otherwise, rely on $mkdir_umask. 322*4882a593Smuzhiyun if test -n "$dir_arg"; then 323*4882a593Smuzhiyun mkdir_mode=-m$mode 324*4882a593Smuzhiyun else 325*4882a593Smuzhiyun mkdir_mode= 326*4882a593Smuzhiyun fi 327*4882a593Smuzhiyun 328*4882a593Smuzhiyun posix_mkdir=false 329*4882a593Smuzhiyun case $umask in 330*4882a593Smuzhiyun *[123567][0-7][0-7]) 331*4882a593Smuzhiyun # POSIX mkdir -p sets u+wx bits regardless of umask, which 332*4882a593Smuzhiyun # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 333*4882a593Smuzhiyun ;; 334*4882a593Smuzhiyun *) 335*4882a593Smuzhiyun # Note that $RANDOM variable is not portable (e.g. dash); Use it 336*4882a593Smuzhiyun # here however when possible just to lower collision chance. 337*4882a593Smuzhiyun tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 338*4882a593Smuzhiyun 339*4882a593Smuzhiyun trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 340*4882a593Smuzhiyun 341*4882a593Smuzhiyun # Because "mkdir -p" follows existing symlinks and we likely work 342*4882a593Smuzhiyun # directly in world-writeable /tmp, make sure that the '$tmpdir' 343*4882a593Smuzhiyun # directory is successfully created first before we actually test 344*4882a593Smuzhiyun # 'mkdir -p' feature. 345*4882a593Smuzhiyun if (umask $mkdir_umask && 346*4882a593Smuzhiyun $mkdirprog $mkdir_mode "$tmpdir" && 347*4882a593Smuzhiyun exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 348*4882a593Smuzhiyun then 349*4882a593Smuzhiyun if test -z "$dir_arg" || { 350*4882a593Smuzhiyun # Check for POSIX incompatibilities with -m. 351*4882a593Smuzhiyun # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 352*4882a593Smuzhiyun # other-writable bit of parent directory when it shouldn't. 353*4882a593Smuzhiyun # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 354*4882a593Smuzhiyun test_tmpdir="$tmpdir/a" 355*4882a593Smuzhiyun ls_ld_tmpdir=`ls -ld "$test_tmpdir"` 356*4882a593Smuzhiyun case $ls_ld_tmpdir in 357*4882a593Smuzhiyun d????-?r-*) different_mode=700;; 358*4882a593Smuzhiyun d????-?--*) different_mode=755;; 359*4882a593Smuzhiyun *) false;; 360*4882a593Smuzhiyun esac && 361*4882a593Smuzhiyun $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { 362*4882a593Smuzhiyun ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` 363*4882a593Smuzhiyun test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 364*4882a593Smuzhiyun } 365*4882a593Smuzhiyun } 366*4882a593Smuzhiyun then posix_mkdir=: 367*4882a593Smuzhiyun fi 368*4882a593Smuzhiyun rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 369*4882a593Smuzhiyun else 370*4882a593Smuzhiyun # Remove any dirs left behind by ancient mkdir implementations. 371*4882a593Smuzhiyun rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null 372*4882a593Smuzhiyun fi 373*4882a593Smuzhiyun trap '' 0;; 374*4882a593Smuzhiyun esac;; 375*4882a593Smuzhiyun esac 376*4882a593Smuzhiyun 377*4882a593Smuzhiyun if 378*4882a593Smuzhiyun $posix_mkdir && ( 379*4882a593Smuzhiyun umask $mkdir_umask && 380*4882a593Smuzhiyun $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 381*4882a593Smuzhiyun ) 382*4882a593Smuzhiyun then : 383*4882a593Smuzhiyun else 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun # The umask is ridiculous, or mkdir does not conform to POSIX, 386*4882a593Smuzhiyun # or it failed possibly due to a race condition. Create the 387*4882a593Smuzhiyun # directory the slow way, step by step, checking for races as we go. 388*4882a593Smuzhiyun 389*4882a593Smuzhiyun case $dstdir in 390*4882a593Smuzhiyun /*) prefix='/';; 391*4882a593Smuzhiyun [-=\(\)!]*) prefix='./';; 392*4882a593Smuzhiyun *) prefix='';; 393*4882a593Smuzhiyun esac 394*4882a593Smuzhiyun 395*4882a593Smuzhiyun oIFS=$IFS 396*4882a593Smuzhiyun IFS=/ 397*4882a593Smuzhiyun set -f 398*4882a593Smuzhiyun set fnord $dstdir 399*4882a593Smuzhiyun shift 400*4882a593Smuzhiyun set +f 401*4882a593Smuzhiyun IFS=$oIFS 402*4882a593Smuzhiyun 403*4882a593Smuzhiyun prefixes= 404*4882a593Smuzhiyun 405*4882a593Smuzhiyun for d 406*4882a593Smuzhiyun do 407*4882a593Smuzhiyun test X"$d" = X && continue 408*4882a593Smuzhiyun 409*4882a593Smuzhiyun prefix=$prefix$d 410*4882a593Smuzhiyun if test -d "$prefix"; then 411*4882a593Smuzhiyun prefixes= 412*4882a593Smuzhiyun else 413*4882a593Smuzhiyun if $posix_mkdir; then 414*4882a593Smuzhiyun (umask=$mkdir_umask && 415*4882a593Smuzhiyun $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 416*4882a593Smuzhiyun # Don't fail if two instances are running concurrently. 417*4882a593Smuzhiyun test -d "$prefix" || exit 1 418*4882a593Smuzhiyun else 419*4882a593Smuzhiyun case $prefix in 420*4882a593Smuzhiyun *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 421*4882a593Smuzhiyun *) qprefix=$prefix;; 422*4882a593Smuzhiyun esac 423*4882a593Smuzhiyun prefixes="$prefixes '$qprefix'" 424*4882a593Smuzhiyun fi 425*4882a593Smuzhiyun fi 426*4882a593Smuzhiyun prefix=$prefix/ 427*4882a593Smuzhiyun done 428*4882a593Smuzhiyun 429*4882a593Smuzhiyun if test -n "$prefixes"; then 430*4882a593Smuzhiyun # Don't fail if two instances are running concurrently. 431*4882a593Smuzhiyun (umask $mkdir_umask && 432*4882a593Smuzhiyun eval "\$doit_exec \$mkdirprog $prefixes") || 433*4882a593Smuzhiyun test -d "$dstdir" || exit 1 434*4882a593Smuzhiyun obsolete_mkdir_used=true 435*4882a593Smuzhiyun fi 436*4882a593Smuzhiyun fi 437*4882a593Smuzhiyun fi 438*4882a593Smuzhiyun 439*4882a593Smuzhiyun if test -n "$dir_arg"; then 440*4882a593Smuzhiyun { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 441*4882a593Smuzhiyun { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 442*4882a593Smuzhiyun { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 443*4882a593Smuzhiyun test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 444*4882a593Smuzhiyun else 445*4882a593Smuzhiyun 446*4882a593Smuzhiyun # Make a couple of temp file names in the proper directory. 447*4882a593Smuzhiyun dsttmp=${dstdirslash}_inst.$$_ 448*4882a593Smuzhiyun rmtmp=${dstdirslash}_rm.$$_ 449*4882a593Smuzhiyun 450*4882a593Smuzhiyun # Trap to clean up those temp files at exit. 451*4882a593Smuzhiyun trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 452*4882a593Smuzhiyun 453*4882a593Smuzhiyun # Copy the file name to the temp name. 454*4882a593Smuzhiyun (umask $cp_umask && 455*4882a593Smuzhiyun { test -z "$stripcmd" || { 456*4882a593Smuzhiyun # Create $dsttmp read-write so that cp doesn't create it read-only, 457*4882a593Smuzhiyun # which would cause strip to fail. 458*4882a593Smuzhiyun if test -z "$doit"; then 459*4882a593Smuzhiyun : >"$dsttmp" # No need to fork-exec 'touch'. 460*4882a593Smuzhiyun else 461*4882a593Smuzhiyun $doit touch "$dsttmp" 462*4882a593Smuzhiyun fi 463*4882a593Smuzhiyun } 464*4882a593Smuzhiyun } && 465*4882a593Smuzhiyun $doit_exec $cpprog "$src" "$dsttmp") && 466*4882a593Smuzhiyun 467*4882a593Smuzhiyun # and set any options; do chmod last to preserve setuid bits. 468*4882a593Smuzhiyun # 469*4882a593Smuzhiyun # If any of these fail, we abort the whole thing. If we want to 470*4882a593Smuzhiyun # ignore errors from any of these, just make sure not to ignore 471*4882a593Smuzhiyun # errors from the above "$doit $cpprog $src $dsttmp" command. 472*4882a593Smuzhiyun # 473*4882a593Smuzhiyun { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 474*4882a593Smuzhiyun { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 475*4882a593Smuzhiyun { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 476*4882a593Smuzhiyun { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 477*4882a593Smuzhiyun 478*4882a593Smuzhiyun # If -C, don't bother to copy if it wouldn't change the file. 479*4882a593Smuzhiyun if $copy_on_change && 480*4882a593Smuzhiyun old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 481*4882a593Smuzhiyun new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 482*4882a593Smuzhiyun set -f && 483*4882a593Smuzhiyun set X $old && old=:$2:$4:$5:$6 && 484*4882a593Smuzhiyun set X $new && new=:$2:$4:$5:$6 && 485*4882a593Smuzhiyun set +f && 486*4882a593Smuzhiyun test "$old" = "$new" && 487*4882a593Smuzhiyun $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 488*4882a593Smuzhiyun then 489*4882a593Smuzhiyun rm -f "$dsttmp" 490*4882a593Smuzhiyun else 491*4882a593Smuzhiyun # Rename the file to the real destination. 492*4882a593Smuzhiyun $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 493*4882a593Smuzhiyun 494*4882a593Smuzhiyun # The rename failed, perhaps because mv can't rename something else 495*4882a593Smuzhiyun # to itself, or perhaps because mv is so ancient that it does not 496*4882a593Smuzhiyun # support -f. 497*4882a593Smuzhiyun { 498*4882a593Smuzhiyun # Now remove or move aside any old file at destination location. 499*4882a593Smuzhiyun # We try this two ways since rm can't unlink itself on some 500*4882a593Smuzhiyun # systems and the destination file might be busy for other 501*4882a593Smuzhiyun # reasons. In this case, the final cleanup might fail but the new 502*4882a593Smuzhiyun # file should still install successfully. 503*4882a593Smuzhiyun { 504*4882a593Smuzhiyun test ! -f "$dst" || 505*4882a593Smuzhiyun $doit $rmcmd -f "$dst" 2>/dev/null || 506*4882a593Smuzhiyun { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 507*4882a593Smuzhiyun { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 508*4882a593Smuzhiyun } || 509*4882a593Smuzhiyun { echo "$0: cannot unlink or rename $dst" >&2 510*4882a593Smuzhiyun (exit 1); exit 1 511*4882a593Smuzhiyun } 512*4882a593Smuzhiyun } && 513*4882a593Smuzhiyun 514*4882a593Smuzhiyun # Now rename the file to the real destination. 515*4882a593Smuzhiyun $doit $mvcmd "$dsttmp" "$dst" 516*4882a593Smuzhiyun } 517*4882a593Smuzhiyun fi || exit 1 518*4882a593Smuzhiyun 519*4882a593Smuzhiyun trap '' 0 520*4882a593Smuzhiyun fi 521*4882a593Smuzhiyundone 522*4882a593Smuzhiyun 523*4882a593Smuzhiyun# Local variables: 524*4882a593Smuzhiyun# eval: (add-hook 'before-save-hook 'time-stamp) 525*4882a593Smuzhiyun# time-stamp-start: "scriptversion=" 526*4882a593Smuzhiyun# time-stamp-format: "%:y-%02m-%02d.%02H" 527*4882a593Smuzhiyun# time-stamp-time-zone: "UTC0" 528*4882a593Smuzhiyun# time-stamp-end: "; # UTC" 529*4882a593Smuzhiyun# End: 530