14edb46e9SPaul Traina#!/bin/sh 24edb46e9SPaul Traina# install - install a program, script, or datafile 3*0a7e5f1fSJoseph Mingrone 4*0a7e5f1fSJoseph Mingronescriptversion=2020-11-14.01; # UTC 5*0a7e5f1fSJoseph Mingrone 6*0a7e5f1fSJoseph Mingrone# This originates from X11R5 (mit/util/scripts/install.sh), which was 7*0a7e5f1fSJoseph Mingrone# later released in X11R6 (xc/config/util/install.sh) with the 8*0a7e5f1fSJoseph Mingrone# following copyright and license. 94de76e31SBill Fenner# 10*0a7e5f1fSJoseph Mingrone# Copyright (C) 1994 X Consortium 114de76e31SBill Fenner# 12*0a7e5f1fSJoseph Mingrone# Permission is hereby granted, free of charge, to any person obtaining a copy 13*0a7e5f1fSJoseph Mingrone# of this software and associated documentation files (the "Software"), to 14*0a7e5f1fSJoseph Mingrone# deal in the Software without restriction, including without limitation the 15*0a7e5f1fSJoseph Mingrone# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16*0a7e5f1fSJoseph Mingrone# sell copies of the Software, and to permit persons to whom the Software is 17*0a7e5f1fSJoseph Mingrone# furnished to do so, subject to the following conditions: 18*0a7e5f1fSJoseph Mingrone# 19*0a7e5f1fSJoseph Mingrone# The above copyright notice and this permission notice shall be included in 20*0a7e5f1fSJoseph Mingrone# all copies or substantial portions of the Software. 21*0a7e5f1fSJoseph Mingrone# 22*0a7e5f1fSJoseph Mingrone# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23*0a7e5f1fSJoseph Mingrone# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24*0a7e5f1fSJoseph Mingrone# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25*0a7e5f1fSJoseph Mingrone# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26*0a7e5f1fSJoseph Mingrone# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27*0a7e5f1fSJoseph Mingrone# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28*0a7e5f1fSJoseph Mingrone# 29*0a7e5f1fSJoseph Mingrone# Except as contained in this notice, the name of the X Consortium shall not 30*0a7e5f1fSJoseph Mingrone# be used in advertising or otherwise to promote the sale, use or other deal- 31*0a7e5f1fSJoseph Mingrone# ings in this Software without prior written authorization from the X Consor- 32*0a7e5f1fSJoseph Mingrone# tium. 33*0a7e5f1fSJoseph Mingrone# 34*0a7e5f1fSJoseph Mingrone# 35*0a7e5f1fSJoseph Mingrone# FSF changes to this file are in the public domain. 364edb46e9SPaul Traina# 374edb46e9SPaul Traina# Calling this script install-sh is preferred over install.sh, to prevent 38*0a7e5f1fSJoseph Mingrone# 'make' implicit rules from creating a file called install from it 394edb46e9SPaul Traina# when there is no Makefile. 404edb46e9SPaul Traina# 414edb46e9SPaul Traina# This script is compatible with the BSD install script, but was written 42*0a7e5f1fSJoseph Mingrone# from scratch. 434edb46e9SPaul Traina 44*0a7e5f1fSJoseph Mingronetab=' ' 45*0a7e5f1fSJoseph Mingronenl=' 46*0a7e5f1fSJoseph Mingrone' 47*0a7e5f1fSJoseph MingroneIFS=" $tab$nl" 484edb46e9SPaul Traina 49*0a7e5f1fSJoseph Mingrone# Set DOITPROG to "echo" to test this script. 504edb46e9SPaul Traina 51*0a7e5f1fSJoseph Mingronedoit=${DOITPROG-} 52*0a7e5f1fSJoseph Mingronedoit_exec=${doit:-exec} 534edb46e9SPaul Traina 54*0a7e5f1fSJoseph Mingrone# Put in absolute file names if you don't have them in your path; 55*0a7e5f1fSJoseph Mingrone# or use environment vars. 564edb46e9SPaul Traina 57*0a7e5f1fSJoseph Mingronechgrpprog=${CHGRPPROG-chgrp} 58*0a7e5f1fSJoseph Mingronechmodprog=${CHMODPROG-chmod} 59*0a7e5f1fSJoseph Mingronechownprog=${CHOWNPROG-chown} 60*0a7e5f1fSJoseph Mingronecmpprog=${CMPPROG-cmp} 61*0a7e5f1fSJoseph Mingronecpprog=${CPPROG-cp} 62*0a7e5f1fSJoseph Mingronemkdirprog=${MKDIRPROG-mkdir} 63*0a7e5f1fSJoseph Mingronemvprog=${MVPROG-mv} 64*0a7e5f1fSJoseph Mingronermprog=${RMPROG-rm} 65*0a7e5f1fSJoseph Mingronestripprog=${STRIPPROG-strip} 664edb46e9SPaul Traina 67*0a7e5f1fSJoseph Mingroneposix_mkdir= 684edb46e9SPaul Traina 69*0a7e5f1fSJoseph Mingrone# Desired mode of installed file. 70*0a7e5f1fSJoseph Mingronemode=0755 71*0a7e5f1fSJoseph Mingrone 72*0a7e5f1fSJoseph Mingrone# Create dirs (including intermediate dirs) using mode 755. 73*0a7e5f1fSJoseph Mingrone# This is like GNU 'install' as of coreutils 8.32 (2020). 74*0a7e5f1fSJoseph Mingronemkdir_umask=22 75*0a7e5f1fSJoseph Mingrone 76*0a7e5f1fSJoseph Mingronebackupsuffix= 77*0a7e5f1fSJoseph Mingronechgrpcmd= 78*0a7e5f1fSJoseph Mingronechmodcmd=$chmodprog 79*0a7e5f1fSJoseph Mingronechowncmd= 80*0a7e5f1fSJoseph Mingronemvcmd=$mvprog 814edb46e9SPaul Trainarmcmd="$rmprog -f" 82*0a7e5f1fSJoseph Mingronestripcmd= 834edb46e9SPaul Traina 84*0a7e5f1fSJoseph Mingronesrc= 85*0a7e5f1fSJoseph Mingronedst= 86*0a7e5f1fSJoseph Mingronedir_arg= 87*0a7e5f1fSJoseph Mingronedst_arg= 88*0a7e5f1fSJoseph Mingrone 89*0a7e5f1fSJoseph Mingronecopy_on_change=false 90*0a7e5f1fSJoseph Mingroneis_target_a_directory=possibly 91*0a7e5f1fSJoseph Mingrone 92*0a7e5f1fSJoseph Mingroneusage="\ 93*0a7e5f1fSJoseph MingroneUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 94*0a7e5f1fSJoseph Mingrone or: $0 [OPTION]... SRCFILES... DIRECTORY 95*0a7e5f1fSJoseph Mingrone or: $0 [OPTION]... -t DIRECTORY SRCFILES... 96*0a7e5f1fSJoseph Mingrone or: $0 [OPTION]... -d DIRECTORIES... 97*0a7e5f1fSJoseph Mingrone 98*0a7e5f1fSJoseph MingroneIn the 1st form, copy SRCFILE to DSTFILE. 99*0a7e5f1fSJoseph MingroneIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 100*0a7e5f1fSJoseph MingroneIn the 4th, create DIRECTORIES. 101*0a7e5f1fSJoseph Mingrone 102*0a7e5f1fSJoseph MingroneOptions: 103*0a7e5f1fSJoseph Mingrone --help display this help and exit. 104*0a7e5f1fSJoseph Mingrone --version display version info and exit. 105*0a7e5f1fSJoseph Mingrone 106*0a7e5f1fSJoseph Mingrone -c (ignored) 107*0a7e5f1fSJoseph Mingrone -C install only if different (preserve data modification time) 108*0a7e5f1fSJoseph Mingrone -d create directories instead of installing files. 109*0a7e5f1fSJoseph Mingrone -g GROUP $chgrpprog installed files to GROUP. 110*0a7e5f1fSJoseph Mingrone -m MODE $chmodprog installed files to MODE. 111*0a7e5f1fSJoseph Mingrone -o USER $chownprog installed files to USER. 112*0a7e5f1fSJoseph Mingrone -p pass -p to $cpprog. 113*0a7e5f1fSJoseph Mingrone -s $stripprog installed files. 114*0a7e5f1fSJoseph Mingrone -S SUFFIX attempt to back up existing files, with suffix SUFFIX. 115*0a7e5f1fSJoseph Mingrone -t DIRECTORY install into DIRECTORY. 116*0a7e5f1fSJoseph Mingrone -T report an error if DSTFILE is a directory. 117*0a7e5f1fSJoseph Mingrone 118*0a7e5f1fSJoseph MingroneEnvironment variables override the default commands: 119*0a7e5f1fSJoseph Mingrone CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 120*0a7e5f1fSJoseph Mingrone RMPROG STRIPPROG 121*0a7e5f1fSJoseph Mingrone 122*0a7e5f1fSJoseph MingroneBy default, rm is invoked with -f; when overridden with RMPROG, 123*0a7e5f1fSJoseph Mingroneit's up to you to specify -f if you want it. 124*0a7e5f1fSJoseph Mingrone 125*0a7e5f1fSJoseph MingroneIf -S is not specified, no backups are attempted. 126*0a7e5f1fSJoseph Mingrone 127*0a7e5f1fSJoseph MingroneEmail bug reports to bug-automake@gnu.org. 128*0a7e5f1fSJoseph MingroneAutomake home page: https://www.gnu.org/software/automake/ 129*0a7e5f1fSJoseph Mingrone" 130*0a7e5f1fSJoseph Mingrone 131*0a7e5f1fSJoseph Mingronewhile test $# -ne 0; do 1324edb46e9SPaul Traina case $1 in 133*0a7e5f1fSJoseph Mingrone -c) ;; 1344edb46e9SPaul Traina 135*0a7e5f1fSJoseph Mingrone -C) copy_on_change=true;; 1364edb46e9SPaul Traina 137*0a7e5f1fSJoseph Mingrone -d) dir_arg=true;; 1384edb46e9SPaul Traina 1394edb46e9SPaul Traina -g) chgrpcmd="$chgrpprog $2" 140*0a7e5f1fSJoseph Mingrone shift;; 1414edb46e9SPaul Traina 142*0a7e5f1fSJoseph Mingrone --help) echo "$usage"; exit $?;; 1434edb46e9SPaul Traina 144*0a7e5f1fSJoseph Mingrone -m) mode=$2 145*0a7e5f1fSJoseph Mingrone case $mode in 146*0a7e5f1fSJoseph Mingrone *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) 147*0a7e5f1fSJoseph Mingrone echo "$0: invalid mode: $mode" >&2 148*0a7e5f1fSJoseph Mingrone exit 1;; 149*0a7e5f1fSJoseph Mingrone esac 150*0a7e5f1fSJoseph Mingrone shift;; 1514edb46e9SPaul Traina 152*0a7e5f1fSJoseph Mingrone -o) chowncmd="$chownprog $2" 153*0a7e5f1fSJoseph Mingrone shift;; 1544edb46e9SPaul Traina 155*0a7e5f1fSJoseph Mingrone -p) cpprog="$cpprog -p";; 156*0a7e5f1fSJoseph Mingrone 157*0a7e5f1fSJoseph Mingrone -s) stripcmd=$stripprog;; 158*0a7e5f1fSJoseph Mingrone 159*0a7e5f1fSJoseph Mingrone -S) backupsuffix="$2" 160*0a7e5f1fSJoseph Mingrone shift;; 161*0a7e5f1fSJoseph Mingrone 162*0a7e5f1fSJoseph Mingrone -t) 163*0a7e5f1fSJoseph Mingrone is_target_a_directory=always 164*0a7e5f1fSJoseph Mingrone dst_arg=$2 165*0a7e5f1fSJoseph Mingrone # Protect names problematic for 'test' and other utilities. 166*0a7e5f1fSJoseph Mingrone case $dst_arg in 167*0a7e5f1fSJoseph Mingrone -* | [=\(\)!]) dst_arg=./$dst_arg;; 168*0a7e5f1fSJoseph Mingrone esac 169*0a7e5f1fSJoseph Mingrone shift;; 170*0a7e5f1fSJoseph Mingrone 171*0a7e5f1fSJoseph Mingrone -T) is_target_a_directory=never;; 172*0a7e5f1fSJoseph Mingrone 173*0a7e5f1fSJoseph Mingrone --version) echo "$0 $scriptversion"; exit $?;; 174*0a7e5f1fSJoseph Mingrone 175*0a7e5f1fSJoseph Mingrone --) shift 176*0a7e5f1fSJoseph Mingrone break;; 177*0a7e5f1fSJoseph Mingrone 178*0a7e5f1fSJoseph Mingrone -*) echo "$0: invalid option: $1" >&2 179*0a7e5f1fSJoseph Mingrone exit 1;; 180*0a7e5f1fSJoseph Mingrone 181*0a7e5f1fSJoseph Mingrone *) break;; 182*0a7e5f1fSJoseph Mingrone esac 183*0a7e5f1fSJoseph Mingrone shift 184*0a7e5f1fSJoseph Mingronedone 185*0a7e5f1fSJoseph Mingrone 186*0a7e5f1fSJoseph Mingrone# We allow the use of options -d and -T together, by making -d 187*0a7e5f1fSJoseph Mingrone# take the precedence; this is for compatibility with GNU install. 188*0a7e5f1fSJoseph Mingrone 189*0a7e5f1fSJoseph Mingroneif test -n "$dir_arg"; then 190*0a7e5f1fSJoseph Mingrone if test -n "$dst_arg"; then 191*0a7e5f1fSJoseph Mingrone echo "$0: target directory not allowed when installing a directory." >&2 192*0a7e5f1fSJoseph Mingrone exit 1 1934edb46e9SPaul Traina fi 194*0a7e5f1fSJoseph Mingronefi 195*0a7e5f1fSJoseph Mingrone 196*0a7e5f1fSJoseph Mingroneif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 197*0a7e5f1fSJoseph Mingrone # When -d is used, all remaining arguments are directories to create. 198*0a7e5f1fSJoseph Mingrone # When -t is used, the destination is already specified. 199*0a7e5f1fSJoseph Mingrone # Otherwise, the last argument is the destination. Remove it from $@. 200*0a7e5f1fSJoseph Mingrone for arg 201*0a7e5f1fSJoseph Mingrone do 202*0a7e5f1fSJoseph Mingrone if test -n "$dst_arg"; then 203*0a7e5f1fSJoseph Mingrone # $@ is not empty: it contains at least $arg. 204*0a7e5f1fSJoseph Mingrone set fnord "$@" "$dst_arg" 205*0a7e5f1fSJoseph Mingrone shift # fnord 206*0a7e5f1fSJoseph Mingrone fi 207*0a7e5f1fSJoseph Mingrone shift # arg 208*0a7e5f1fSJoseph Mingrone dst_arg=$arg 209*0a7e5f1fSJoseph Mingrone # Protect names problematic for 'test' and other utilities. 210*0a7e5f1fSJoseph Mingrone case $dst_arg in 211*0a7e5f1fSJoseph Mingrone -* | [=\(\)!]) dst_arg=./$dst_arg;; 2124edb46e9SPaul Traina esac 2134edb46e9SPaul Traina done 214*0a7e5f1fSJoseph Mingronefi 2154edb46e9SPaul Traina 216*0a7e5f1fSJoseph Mingroneif test $# -eq 0; then 217*0a7e5f1fSJoseph Mingrone if test -z "$dir_arg"; then 218*0a7e5f1fSJoseph Mingrone echo "$0: no input file specified." >&2 2194edb46e9SPaul Traina exit 1 220*0a7e5f1fSJoseph Mingrone fi 221*0a7e5f1fSJoseph Mingrone # It's OK to call 'install-sh -d' without argument. 222*0a7e5f1fSJoseph Mingrone # This can happen when creating conditional directories. 223*0a7e5f1fSJoseph Mingrone exit 0 2244edb46e9SPaul Trainafi 2254edb46e9SPaul Traina 226*0a7e5f1fSJoseph Mingroneif test -z "$dir_arg"; then 227*0a7e5f1fSJoseph Mingrone if test $# -gt 1 || test "$is_target_a_directory" = always; then 228*0a7e5f1fSJoseph Mingrone if test ! -d "$dst_arg"; then 229*0a7e5f1fSJoseph Mingrone echo "$0: $dst_arg: Is not a directory." >&2 230*0a7e5f1fSJoseph Mingrone exit 1 231*0a7e5f1fSJoseph Mingrone fi 232*0a7e5f1fSJoseph Mingrone fi 233*0a7e5f1fSJoseph Mingronefi 234*0a7e5f1fSJoseph Mingrone 235*0a7e5f1fSJoseph Mingroneif test -z "$dir_arg"; then 236*0a7e5f1fSJoseph Mingrone do_exit='(exit $ret); exit $ret' 237*0a7e5f1fSJoseph Mingrone trap "ret=129; $do_exit" 1 238*0a7e5f1fSJoseph Mingrone trap "ret=130; $do_exit" 2 239*0a7e5f1fSJoseph Mingrone trap "ret=141; $do_exit" 13 240*0a7e5f1fSJoseph Mingrone trap "ret=143; $do_exit" 15 241*0a7e5f1fSJoseph Mingrone 242*0a7e5f1fSJoseph Mingrone # Set umask so as not to create temps with too-generous modes. 243*0a7e5f1fSJoseph Mingrone # However, 'strip' requires both read and write access to temps. 244*0a7e5f1fSJoseph Mingrone case $mode in 245*0a7e5f1fSJoseph Mingrone # Optimize common cases. 246*0a7e5f1fSJoseph Mingrone *644) cp_umask=133;; 247*0a7e5f1fSJoseph Mingrone *755) cp_umask=22;; 248*0a7e5f1fSJoseph Mingrone 249*0a7e5f1fSJoseph Mingrone *[0-7]) 250*0a7e5f1fSJoseph Mingrone if test -z "$stripcmd"; then 251*0a7e5f1fSJoseph Mingrone u_plus_rw= 252*0a7e5f1fSJoseph Mingrone else 253*0a7e5f1fSJoseph Mingrone u_plus_rw='% 200' 254*0a7e5f1fSJoseph Mingrone fi 255*0a7e5f1fSJoseph Mingrone cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 256*0a7e5f1fSJoseph Mingrone *) 257*0a7e5f1fSJoseph Mingrone if test -z "$stripcmd"; then 258*0a7e5f1fSJoseph Mingrone u_plus_rw= 259*0a7e5f1fSJoseph Mingrone else 260*0a7e5f1fSJoseph Mingrone u_plus_rw=,u+rw 261*0a7e5f1fSJoseph Mingrone fi 262*0a7e5f1fSJoseph Mingrone cp_umask=$mode$u_plus_rw;; 263*0a7e5f1fSJoseph Mingrone esac 264*0a7e5f1fSJoseph Mingronefi 265*0a7e5f1fSJoseph Mingrone 266*0a7e5f1fSJoseph Mingronefor src 267*0a7e5f1fSJoseph Mingronedo 268*0a7e5f1fSJoseph Mingrone # Protect names problematic for 'test' and other utilities. 269*0a7e5f1fSJoseph Mingrone case $src in 270*0a7e5f1fSJoseph Mingrone -* | [=\(\)!]) src=./$src;; 271*0a7e5f1fSJoseph Mingrone esac 272*0a7e5f1fSJoseph Mingrone 273*0a7e5f1fSJoseph Mingrone if test -n "$dir_arg"; then 2744edb46e9SPaul Traina dst=$src 275*0a7e5f1fSJoseph Mingrone dstdir=$dst 276*0a7e5f1fSJoseph Mingrone test -d "$dstdir" 277*0a7e5f1fSJoseph Mingrone dstdir_status=$? 278*0a7e5f1fSJoseph Mingrone # Don't chown directories that already exist. 279*0a7e5f1fSJoseph Mingrone if test $dstdir_status = 0; then 280*0a7e5f1fSJoseph Mingrone chowncmd="" 2814edb46e9SPaul Traina fi 2824edb46e9SPaul Traina else 2834edb46e9SPaul Traina 284*0a7e5f1fSJoseph Mingrone # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 2854edb46e9SPaul Traina # might cause directories to be created, which would be especially bad 2864edb46e9SPaul Traina # if $src (and thus $dsttmp) contains '*'. 287*0a7e5f1fSJoseph Mingrone if test ! -f "$src" && test ! -d "$src"; then 288*0a7e5f1fSJoseph Mingrone echo "$0: $src does not exist." >&2 2894edb46e9SPaul Traina exit 1 2904edb46e9SPaul Traina fi 2914edb46e9SPaul Traina 292*0a7e5f1fSJoseph Mingrone if test -z "$dst_arg"; then 293*0a7e5f1fSJoseph Mingrone echo "$0: no destination specified." >&2 2944edb46e9SPaul Traina exit 1 295*0a7e5f1fSJoseph Mingrone fi 296*0a7e5f1fSJoseph Mingrone dst=$dst_arg 297*0a7e5f1fSJoseph Mingrone 298*0a7e5f1fSJoseph Mingrone # If destination is a directory, append the input filename. 299*0a7e5f1fSJoseph Mingrone if test -d "$dst"; then 300*0a7e5f1fSJoseph Mingrone if test "$is_target_a_directory" = never; then 301*0a7e5f1fSJoseph Mingrone echo "$0: $dst_arg: Is a directory" >&2 302*0a7e5f1fSJoseph Mingrone exit 1 303*0a7e5f1fSJoseph Mingrone fi 304*0a7e5f1fSJoseph Mingrone dstdir=$dst 305*0a7e5f1fSJoseph Mingrone dstbase=`basename "$src"` 306*0a7e5f1fSJoseph Mingrone case $dst in 307*0a7e5f1fSJoseph Mingrone */) dst=$dst$dstbase;; 308*0a7e5f1fSJoseph Mingrone *) dst=$dst/$dstbase;; 309*0a7e5f1fSJoseph Mingrone esac 310*0a7e5f1fSJoseph Mingrone dstdir_status=0 3114edb46e9SPaul Traina else 312*0a7e5f1fSJoseph Mingrone dstdir=`dirname "$dst"` 313*0a7e5f1fSJoseph Mingrone test -d "$dstdir" 314*0a7e5f1fSJoseph Mingrone dstdir_status=$? 315*0a7e5f1fSJoseph Mingrone fi 3164edb46e9SPaul Traina fi 3174edb46e9SPaul Traina 318*0a7e5f1fSJoseph Mingrone case $dstdir in 319*0a7e5f1fSJoseph Mingrone */) dstdirslash=$dstdir;; 320*0a7e5f1fSJoseph Mingrone *) dstdirslash=$dstdir/;; 321*0a7e5f1fSJoseph Mingrone esac 3224edb46e9SPaul Traina 323*0a7e5f1fSJoseph Mingrone obsolete_mkdir_used=false 324*0a7e5f1fSJoseph Mingrone 325*0a7e5f1fSJoseph Mingrone if test $dstdir_status != 0; then 326*0a7e5f1fSJoseph Mingrone case $posix_mkdir in 327*0a7e5f1fSJoseph Mingrone '') 328*0a7e5f1fSJoseph Mingrone # With -d, create the new directory with the user-specified mode. 329*0a7e5f1fSJoseph Mingrone # Otherwise, rely on $mkdir_umask. 330*0a7e5f1fSJoseph Mingrone if test -n "$dir_arg"; then 331*0a7e5f1fSJoseph Mingrone mkdir_mode=-m$mode 332*0a7e5f1fSJoseph Mingrone else 333*0a7e5f1fSJoseph Mingrone mkdir_mode= 334*0a7e5f1fSJoseph Mingrone fi 335*0a7e5f1fSJoseph Mingrone 336*0a7e5f1fSJoseph Mingrone posix_mkdir=false 337*0a7e5f1fSJoseph Mingrone # The $RANDOM variable is not portable (e.g., dash). Use it 338*0a7e5f1fSJoseph Mingrone # here however when possible just to lower collision chance. 339*0a7e5f1fSJoseph Mingrone tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 340*0a7e5f1fSJoseph Mingrone 341*0a7e5f1fSJoseph Mingrone trap ' 342*0a7e5f1fSJoseph Mingrone ret=$? 343*0a7e5f1fSJoseph Mingrone rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null 344*0a7e5f1fSJoseph Mingrone exit $ret 345*0a7e5f1fSJoseph Mingrone ' 0 346*0a7e5f1fSJoseph Mingrone 347*0a7e5f1fSJoseph Mingrone # Because "mkdir -p" follows existing symlinks and we likely work 348*0a7e5f1fSJoseph Mingrone # directly in world-writeable /tmp, make sure that the '$tmpdir' 349*0a7e5f1fSJoseph Mingrone # directory is successfully created first before we actually test 350*0a7e5f1fSJoseph Mingrone # 'mkdir -p'. 351*0a7e5f1fSJoseph Mingrone if (umask $mkdir_umask && 352*0a7e5f1fSJoseph Mingrone $mkdirprog $mkdir_mode "$tmpdir" && 353*0a7e5f1fSJoseph Mingrone exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 3544edb46e9SPaul Traina then 355*0a7e5f1fSJoseph Mingrone if test -z "$dir_arg" || { 356*0a7e5f1fSJoseph Mingrone # Check for POSIX incompatibilities with -m. 357*0a7e5f1fSJoseph Mingrone # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 358*0a7e5f1fSJoseph Mingrone # other-writable bit of parent directory when it shouldn't. 359*0a7e5f1fSJoseph Mingrone # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 360*0a7e5f1fSJoseph Mingrone test_tmpdir="$tmpdir/a" 361*0a7e5f1fSJoseph Mingrone ls_ld_tmpdir=`ls -ld "$test_tmpdir"` 362*0a7e5f1fSJoseph Mingrone case $ls_ld_tmpdir in 363*0a7e5f1fSJoseph Mingrone d????-?r-*) different_mode=700;; 364*0a7e5f1fSJoseph Mingrone d????-?--*) different_mode=755;; 365*0a7e5f1fSJoseph Mingrone *) false;; 366*0a7e5f1fSJoseph Mingrone esac && 367*0a7e5f1fSJoseph Mingrone $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { 368*0a7e5f1fSJoseph Mingrone ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` 369*0a7e5f1fSJoseph Mingrone test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 370*0a7e5f1fSJoseph Mingrone } 371*0a7e5f1fSJoseph Mingrone } 372*0a7e5f1fSJoseph Mingrone then posix_mkdir=: 373*0a7e5f1fSJoseph Mingrone fi 374*0a7e5f1fSJoseph Mingrone rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 3754edb46e9SPaul Traina else 376*0a7e5f1fSJoseph Mingrone # Remove any dirs left behind by ancient mkdir implementations. 377*0a7e5f1fSJoseph Mingrone rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null 3784edb46e9SPaul Traina fi 379*0a7e5f1fSJoseph Mingrone trap '' 0;; 380*0a7e5f1fSJoseph Mingrone esac 3814edb46e9SPaul Traina 382*0a7e5f1fSJoseph Mingrone if 383*0a7e5f1fSJoseph Mingrone $posix_mkdir && ( 384*0a7e5f1fSJoseph Mingrone umask $mkdir_umask && 385*0a7e5f1fSJoseph Mingrone $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 386*0a7e5f1fSJoseph Mingrone ) 387*0a7e5f1fSJoseph Mingrone then : 388*0a7e5f1fSJoseph Mingrone else 3894edb46e9SPaul Traina 390*0a7e5f1fSJoseph Mingrone # mkdir does not conform to POSIX, 391*0a7e5f1fSJoseph Mingrone # or it failed possibly due to a race condition. Create the 392*0a7e5f1fSJoseph Mingrone # directory the slow way, step by step, checking for races as we go. 3934edb46e9SPaul Traina 394*0a7e5f1fSJoseph Mingrone case $dstdir in 395*0a7e5f1fSJoseph Mingrone /*) prefix='/';; 396*0a7e5f1fSJoseph Mingrone [-=\(\)!]*) prefix='./';; 397*0a7e5f1fSJoseph Mingrone *) prefix='';; 398*0a7e5f1fSJoseph Mingrone esac 3994edb46e9SPaul Traina 400*0a7e5f1fSJoseph Mingrone oIFS=$IFS 401*0a7e5f1fSJoseph Mingrone IFS=/ 402*0a7e5f1fSJoseph Mingrone set -f 403*0a7e5f1fSJoseph Mingrone set fnord $dstdir 4044edb46e9SPaul Traina shift 405*0a7e5f1fSJoseph Mingrone set +f 406*0a7e5f1fSJoseph Mingrone IFS=$oIFS 4074edb46e9SPaul Traina 408*0a7e5f1fSJoseph Mingrone prefixes= 409*0a7e5f1fSJoseph Mingrone 410*0a7e5f1fSJoseph Mingrone for d 411*0a7e5f1fSJoseph Mingrone do 412*0a7e5f1fSJoseph Mingrone test X"$d" = X && continue 413*0a7e5f1fSJoseph Mingrone 414*0a7e5f1fSJoseph Mingrone prefix=$prefix$d 415*0a7e5f1fSJoseph Mingrone if test -d "$prefix"; then 416*0a7e5f1fSJoseph Mingrone prefixes= 4174edb46e9SPaul Traina else 418*0a7e5f1fSJoseph Mingrone if $posix_mkdir; then 419*0a7e5f1fSJoseph Mingrone (umask $mkdir_umask && 420*0a7e5f1fSJoseph Mingrone $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 421*0a7e5f1fSJoseph Mingrone # Don't fail if two instances are running concurrently. 422*0a7e5f1fSJoseph Mingrone test -d "$prefix" || exit 1 423*0a7e5f1fSJoseph Mingrone else 424*0a7e5f1fSJoseph Mingrone case $prefix in 425*0a7e5f1fSJoseph Mingrone *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 426*0a7e5f1fSJoseph Mingrone *) qprefix=$prefix;; 427*0a7e5f1fSJoseph Mingrone esac 428*0a7e5f1fSJoseph Mingrone prefixes="$prefixes '$qprefix'" 4294edb46e9SPaul Traina fi 430*0a7e5f1fSJoseph Mingrone fi 431*0a7e5f1fSJoseph Mingrone prefix=$prefix/ 4324edb46e9SPaul Traina done 433*0a7e5f1fSJoseph Mingrone 434*0a7e5f1fSJoseph Mingrone if test -n "$prefixes"; then 435*0a7e5f1fSJoseph Mingrone # Don't fail if two instances are running concurrently. 436*0a7e5f1fSJoseph Mingrone (umask $mkdir_umask && 437*0a7e5f1fSJoseph Mingrone eval "\$doit_exec \$mkdirprog $prefixes") || 438*0a7e5f1fSJoseph Mingrone test -d "$dstdir" || exit 1 439*0a7e5f1fSJoseph Mingrone obsolete_mkdir_used=true 440*0a7e5f1fSJoseph Mingrone fi 441*0a7e5f1fSJoseph Mingrone fi 4424edb46e9SPaul Traina fi 4434edb46e9SPaul Traina 444*0a7e5f1fSJoseph Mingrone if test -n "$dir_arg"; then 445*0a7e5f1fSJoseph Mingrone { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 446*0a7e5f1fSJoseph Mingrone { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 447*0a7e5f1fSJoseph Mingrone { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 448*0a7e5f1fSJoseph Mingrone test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 4494edb46e9SPaul Traina else 4504edb46e9SPaul Traina 451*0a7e5f1fSJoseph Mingrone # Make a couple of temp file names in the proper directory. 452*0a7e5f1fSJoseph Mingrone dsttmp=${dstdirslash}_inst.$$_ 453*0a7e5f1fSJoseph Mingrone rmtmp=${dstdirslash}_rm.$$_ 4544edb46e9SPaul Traina 455*0a7e5f1fSJoseph Mingrone # Trap to clean up those temp files at exit. 456*0a7e5f1fSJoseph Mingrone trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 457*0a7e5f1fSJoseph Mingrone 458*0a7e5f1fSJoseph Mingrone # Copy the file name to the temp name. 459*0a7e5f1fSJoseph Mingrone (umask $cp_umask && 460*0a7e5f1fSJoseph Mingrone { test -z "$stripcmd" || { 461*0a7e5f1fSJoseph Mingrone # Create $dsttmp read-write so that cp doesn't create it read-only, 462*0a7e5f1fSJoseph Mingrone # which would cause strip to fail. 463*0a7e5f1fSJoseph Mingrone if test -z "$doit"; then 464*0a7e5f1fSJoseph Mingrone : >"$dsttmp" # No need to fork-exec 'touch'. 4654edb46e9SPaul Traina else 466*0a7e5f1fSJoseph Mingrone $doit touch "$dsttmp" 4674edb46e9SPaul Traina fi 468*0a7e5f1fSJoseph Mingrone } 469*0a7e5f1fSJoseph Mingrone } && 470*0a7e5f1fSJoseph Mingrone $doit_exec $cpprog "$src" "$dsttmp") && 4714edb46e9SPaul Traina 472*0a7e5f1fSJoseph Mingrone # and set any options; do chmod last to preserve setuid bits. 473*0a7e5f1fSJoseph Mingrone # 4744edb46e9SPaul Traina # If any of these fail, we abort the whole thing. If we want to 4754edb46e9SPaul Traina # ignore errors from any of these, just make sure not to ignore 476*0a7e5f1fSJoseph Mingrone # errors from the above "$doit $cpprog $src $dsttmp" command. 477*0a7e5f1fSJoseph Mingrone # 478*0a7e5f1fSJoseph Mingrone { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 479*0a7e5f1fSJoseph Mingrone { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 480*0a7e5f1fSJoseph Mingrone { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 481*0a7e5f1fSJoseph Mingrone { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 4824edb46e9SPaul Traina 483*0a7e5f1fSJoseph Mingrone # If -C, don't bother to copy if it wouldn't change the file. 484*0a7e5f1fSJoseph Mingrone if $copy_on_change && 485*0a7e5f1fSJoseph Mingrone old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 486*0a7e5f1fSJoseph Mingrone new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 487*0a7e5f1fSJoseph Mingrone set -f && 488*0a7e5f1fSJoseph Mingrone set X $old && old=:$2:$4:$5:$6 && 489*0a7e5f1fSJoseph Mingrone set X $new && new=:$2:$4:$5:$6 && 490*0a7e5f1fSJoseph Mingrone set +f && 491*0a7e5f1fSJoseph Mingrone test "$old" = "$new" && 492*0a7e5f1fSJoseph Mingrone $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 493*0a7e5f1fSJoseph Mingrone then 494*0a7e5f1fSJoseph Mingrone rm -f "$dsttmp" 495*0a7e5f1fSJoseph Mingrone else 496*0a7e5f1fSJoseph Mingrone # If $backupsuffix is set, and the file being installed 497*0a7e5f1fSJoseph Mingrone # already exists, attempt a backup. Don't worry if it fails, 498*0a7e5f1fSJoseph Mingrone # e.g., if mv doesn't support -f. 499*0a7e5f1fSJoseph Mingrone if test -n "$backupsuffix" && test -f "$dst"; then 500*0a7e5f1fSJoseph Mingrone $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null 501*0a7e5f1fSJoseph Mingrone fi 502*0a7e5f1fSJoseph Mingrone 503*0a7e5f1fSJoseph Mingrone # Rename the file to the real destination. 504*0a7e5f1fSJoseph Mingrone $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 505*0a7e5f1fSJoseph Mingrone 506*0a7e5f1fSJoseph Mingrone # The rename failed, perhaps because mv can't rename something else 507*0a7e5f1fSJoseph Mingrone # to itself, or perhaps because mv is so ancient that it does not 508*0a7e5f1fSJoseph Mingrone # support -f. 509*0a7e5f1fSJoseph Mingrone { 510*0a7e5f1fSJoseph Mingrone # Now remove or move aside any old file at destination location. 511*0a7e5f1fSJoseph Mingrone # We try this two ways since rm can't unlink itself on some 512*0a7e5f1fSJoseph Mingrone # systems and the destination file might be busy for other 513*0a7e5f1fSJoseph Mingrone # reasons. In this case, the final cleanup might fail but the new 514*0a7e5f1fSJoseph Mingrone # file should still install successfully. 515*0a7e5f1fSJoseph Mingrone { 516*0a7e5f1fSJoseph Mingrone test ! -f "$dst" || 517*0a7e5f1fSJoseph Mingrone $doit $rmcmd "$dst" 2>/dev/null || 518*0a7e5f1fSJoseph Mingrone { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 519*0a7e5f1fSJoseph Mingrone { $doit $rmcmd "$rmtmp" 2>/dev/null; :; } 520*0a7e5f1fSJoseph Mingrone } || 521*0a7e5f1fSJoseph Mingrone { echo "$0: cannot unlink or rename $dst" >&2 522*0a7e5f1fSJoseph Mingrone (exit 1); exit 1 523*0a7e5f1fSJoseph Mingrone } 524*0a7e5f1fSJoseph Mingrone } && 5254edb46e9SPaul Traina 5264edb46e9SPaul Traina # Now rename the file to the real destination. 527*0a7e5f1fSJoseph Mingrone $doit $mvcmd "$dsttmp" "$dst" 528*0a7e5f1fSJoseph Mingrone } 529*0a7e5f1fSJoseph Mingrone fi || exit 1 5304edb46e9SPaul Traina 531*0a7e5f1fSJoseph Mingrone trap '' 0 532*0a7e5f1fSJoseph Mingrone fi 533*0a7e5f1fSJoseph Mingronedone 5344edb46e9SPaul Traina 535*0a7e5f1fSJoseph Mingrone# Local variables: 536*0a7e5f1fSJoseph Mingrone# eval: (add-hook 'before-save-hook 'time-stamp) 537*0a7e5f1fSJoseph Mingrone# time-stamp-start: "scriptversion=" 538*0a7e5f1fSJoseph Mingrone# time-stamp-format: "%:y-%02m-%02d.%02H" 539*0a7e5f1fSJoseph Mingrone# time-stamp-time-zone: "UTC0" 540*0a7e5f1fSJoseph Mingrone# time-stamp-end: "; # UTC" 541*0a7e5f1fSJoseph Mingrone# End: 542