175a6cdb3SDavid E. O'Brien#!/bin/sh 275a6cdb3SDavid E. O'Brien# install - install a program, script, or datafile 3*58a0f0d0SEitan Adler 4*58a0f0d0SEitan Adlerscriptversion=2011-11-20.07; # UTC 5*58a0f0d0SEitan Adler 6*58a0f0d0SEitan Adler# This originates from X11R5 (mit/util/scripts/install.sh), which was 7*58a0f0d0SEitan Adler# later released in X11R6 (xc/config/util/install.sh) with the 8*58a0f0d0SEitan Adler# following copyright and license. 9a2e8fb4cSDavid E. O'Brien# 10*58a0f0d0SEitan Adler# Copyright (C) 1994 X Consortium 11a2e8fb4cSDavid E. O'Brien# 12*58a0f0d0SEitan Adler# Permission is hereby granted, free of charge, to any person obtaining a copy 13*58a0f0d0SEitan Adler# of this software and associated documentation files (the "Software"), to 14*58a0f0d0SEitan Adler# deal in the Software without restriction, including without limitation the 15*58a0f0d0SEitan Adler# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16*58a0f0d0SEitan Adler# sell copies of the Software, and to permit persons to whom the Software is 17*58a0f0d0SEitan Adler# furnished to do so, subject to the following conditions: 18*58a0f0d0SEitan Adler# 19*58a0f0d0SEitan Adler# The above copyright notice and this permission notice shall be included in 20*58a0f0d0SEitan Adler# all copies or substantial portions of the Software. 21*58a0f0d0SEitan Adler# 22*58a0f0d0SEitan Adler# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23*58a0f0d0SEitan Adler# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24*58a0f0d0SEitan Adler# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25*58a0f0d0SEitan Adler# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26*58a0f0d0SEitan Adler# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27*58a0f0d0SEitan Adler# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28*58a0f0d0SEitan Adler# 29*58a0f0d0SEitan Adler# Except as contained in this notice, the name of the X Consortium shall not 30*58a0f0d0SEitan Adler# be used in advertising or otherwise to promote the sale, use or other deal- 31*58a0f0d0SEitan Adler# ings in this Software without prior written authorization from the X Consor- 32*58a0f0d0SEitan Adler# tium. 33*58a0f0d0SEitan Adler# 34*58a0f0d0SEitan Adler# 35*58a0f0d0SEitan Adler# FSF changes to this file are in the public domain. 3675a6cdb3SDavid E. O'Brien# 3775a6cdb3SDavid E. O'Brien# Calling this script install-sh is preferred over install.sh, to prevent 38*58a0f0d0SEitan Adler# 'make' implicit rules from creating a file called install from it 3975a6cdb3SDavid E. O'Brien# when there is no Makefile. 4075a6cdb3SDavid E. O'Brien# 4175a6cdb3SDavid E. O'Brien# This script is compatible with the BSD install script, but was written 42974b70c4SDavid E. O'Brien# from scratch. 43974b70c4SDavid E. O'Brien 44*58a0f0d0SEitan Adlernl=' 45*58a0f0d0SEitan Adler' 46*58a0f0d0SEitan AdlerIFS=" "" $nl" 47*58a0f0d0SEitan Adler 4875a6cdb3SDavid E. O'Brien# set DOITPROG to echo to test this script 4975a6cdb3SDavid E. O'Brien 5075a6cdb3SDavid E. O'Brien# Don't use :- since 4.3BSD and earlier shells don't like it. 51*58a0f0d0SEitan Adlerdoit=${DOITPROG-} 52*58a0f0d0SEitan Adlerif test -z "$doit"; then 53*58a0f0d0SEitan Adler doit_exec=exec 54*58a0f0d0SEitan Adlerelse 55*58a0f0d0SEitan Adler doit_exec=$doit 56*58a0f0d0SEitan Adlerfi 5775a6cdb3SDavid E. O'Brien 58*58a0f0d0SEitan Adler# Put in absolute file names if you don't have them in your path; 59*58a0f0d0SEitan Adler# or use environment vars. 6075a6cdb3SDavid E. O'Brien 61*58a0f0d0SEitan Adlerchgrpprog=${CHGRPPROG-chgrp} 62*58a0f0d0SEitan Adlerchmodprog=${CHMODPROG-chmod} 63*58a0f0d0SEitan Adlerchownprog=${CHOWNPROG-chown} 64*58a0f0d0SEitan Adlercmpprog=${CMPPROG-cmp} 65*58a0f0d0SEitan Adlercpprog=${CPPROG-cp} 66*58a0f0d0SEitan Adlermkdirprog=${MKDIRPROG-mkdir} 67*58a0f0d0SEitan Adlermvprog=${MVPROG-mv} 68*58a0f0d0SEitan Adlerrmprog=${RMPROG-rm} 69*58a0f0d0SEitan Adlerstripprog=${STRIPPROG-strip} 7080c86c36SDavid E. O'Brien 71*58a0f0d0SEitan Adlerposix_glob='?' 72*58a0f0d0SEitan Adlerinitialize_posix_glob=' 73*58a0f0d0SEitan Adler test "$posix_glob" != "?" || { 74*58a0f0d0SEitan Adler if (set -f) 2>/dev/null; then 75*58a0f0d0SEitan Adler posix_glob= 76*58a0f0d0SEitan Adler else 77*58a0f0d0SEitan Adler posix_glob=: 78*58a0f0d0SEitan Adler fi 79*58a0f0d0SEitan Adler } 80*58a0f0d0SEitan Adler' 8175a6cdb3SDavid E. O'Brien 82*58a0f0d0SEitan Adlerposix_mkdir= 83*58a0f0d0SEitan Adler 84*58a0f0d0SEitan Adler# Desired mode of installed file. 85*58a0f0d0SEitan Adlermode=0755 86*58a0f0d0SEitan Adler 87*58a0f0d0SEitan Adlerchgrpcmd= 88*58a0f0d0SEitan Adlerchmodcmd=$chmodprog 89*58a0f0d0SEitan Adlerchowncmd= 90*58a0f0d0SEitan Adlermvcmd=$mvprog 9175a6cdb3SDavid E. O'Brienrmcmd="$rmprog -f" 92*58a0f0d0SEitan Adlerstripcmd= 9375a6cdb3SDavid E. O'Brien 94*58a0f0d0SEitan Adlersrc= 95*58a0f0d0SEitan Adlerdst= 96*58a0f0d0SEitan Adlerdir_arg= 97*58a0f0d0SEitan Adlerdst_arg= 98*58a0f0d0SEitan Adler 99*58a0f0d0SEitan Adlercopy_on_change=false 100*58a0f0d0SEitan Adlerno_target_directory= 101*58a0f0d0SEitan Adler 102*58a0f0d0SEitan Adlerusage="\ 103*58a0f0d0SEitan AdlerUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104*58a0f0d0SEitan Adler or: $0 [OPTION]... SRCFILES... DIRECTORY 105*58a0f0d0SEitan Adler or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106*58a0f0d0SEitan Adler or: $0 [OPTION]... -d DIRECTORIES... 107*58a0f0d0SEitan Adler 108*58a0f0d0SEitan AdlerIn the 1st form, copy SRCFILE to DSTFILE. 109*58a0f0d0SEitan AdlerIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110*58a0f0d0SEitan AdlerIn the 4th, create DIRECTORIES. 111*58a0f0d0SEitan Adler 112*58a0f0d0SEitan AdlerOptions: 113*58a0f0d0SEitan Adler --help display this help and exit. 114*58a0f0d0SEitan Adler --version display version info and exit. 115*58a0f0d0SEitan Adler 116*58a0f0d0SEitan Adler -c (ignored) 117*58a0f0d0SEitan Adler -C install only if different (preserve the last data modification time) 118*58a0f0d0SEitan Adler -d create directories instead of installing files. 119*58a0f0d0SEitan Adler -g GROUP $chgrpprog installed files to GROUP. 120*58a0f0d0SEitan Adler -m MODE $chmodprog installed files to MODE. 121*58a0f0d0SEitan Adler -o USER $chownprog installed files to USER. 122*58a0f0d0SEitan Adler -s $stripprog installed files. 123*58a0f0d0SEitan Adler -t DIRECTORY install into DIRECTORY. 124*58a0f0d0SEitan Adler -T report an error if DSTFILE is a directory. 125*58a0f0d0SEitan Adler 126*58a0f0d0SEitan AdlerEnvironment variables override the default commands: 127*58a0f0d0SEitan Adler CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128*58a0f0d0SEitan Adler RMPROG STRIPPROG 129*58a0f0d0SEitan Adler" 130*58a0f0d0SEitan Adler 131*58a0f0d0SEitan Adlerwhile test $# -ne 0; do 13275a6cdb3SDavid E. O'Brien case $1 in 133*58a0f0d0SEitan Adler -c) ;; 13480c86c36SDavid E. O'Brien 135*58a0f0d0SEitan Adler -C) copy_on_change=true;; 13680c86c36SDavid E. O'Brien 137*58a0f0d0SEitan Adler -d) dir_arg=true;; 13880c86c36SDavid E. O'Brien 139d1d50c78SDavid E. O'Brien -g) chgrpcmd="$chgrpprog $2" 140*58a0f0d0SEitan Adler shift;; 141d1d50c78SDavid E. O'Brien 142*58a0f0d0SEitan Adler --help) echo "$usage"; exit $?;; 14375a6cdb3SDavid E. O'Brien 144*58a0f0d0SEitan Adler -m) mode=$2 145*58a0f0d0SEitan Adler case $mode in 146*58a0f0d0SEitan Adler *' '* | *' '* | *' 147*58a0f0d0SEitan Adler'* | *'*'* | *'?'* | *'['*) 148*58a0f0d0SEitan Adler echo "$0: invalid mode: $mode" >&2 149*58a0f0d0SEitan Adler exit 1;; 150974b70c4SDavid E. O'Brien esac 151*58a0f0d0SEitan Adler shift;; 152*58a0f0d0SEitan Adler 153*58a0f0d0SEitan Adler -o) chowncmd="$chownprog $2" 154*58a0f0d0SEitan Adler shift;; 155*58a0f0d0SEitan Adler 156*58a0f0d0SEitan Adler -s) stripcmd=$stripprog;; 157*58a0f0d0SEitan Adler 158*58a0f0d0SEitan Adler -t) dst_arg=$2 159*58a0f0d0SEitan Adler # Protect names problematic for 'test' and other utilities. 160*58a0f0d0SEitan Adler case $dst_arg in 161*58a0f0d0SEitan Adler -* | [=\(\)!]) dst_arg=./$dst_arg;; 162*58a0f0d0SEitan Adler esac 163*58a0f0d0SEitan Adler shift;; 164*58a0f0d0SEitan Adler 165*58a0f0d0SEitan Adler -T) no_target_directory=true;; 166*58a0f0d0SEitan Adler 167*58a0f0d0SEitan Adler --version) echo "$0 $scriptversion"; exit $?;; 168*58a0f0d0SEitan Adler 169*58a0f0d0SEitan Adler --) shift 170*58a0f0d0SEitan Adler break;; 171*58a0f0d0SEitan Adler 172*58a0f0d0SEitan Adler -*) echo "$0: invalid option: $1" >&2 173*58a0f0d0SEitan Adler exit 1;; 174*58a0f0d0SEitan Adler 175*58a0f0d0SEitan Adler *) break;; 176*58a0f0d0SEitan Adler esac 177*58a0f0d0SEitan Adler shift 178974b70c4SDavid E. O'Briendone 179974b70c4SDavid E. O'Brien 180*58a0f0d0SEitan Adlerif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 181*58a0f0d0SEitan Adler # When -d is used, all remaining arguments are directories to create. 182*58a0f0d0SEitan Adler # When -t is used, the destination is already specified. 183*58a0f0d0SEitan Adler # Otherwise, the last argument is the destination. Remove it from $@. 184*58a0f0d0SEitan Adler for arg 185*58a0f0d0SEitan Adler do 186*58a0f0d0SEitan Adler if test -n "$dst_arg"; then 187*58a0f0d0SEitan Adler # $@ is not empty: it contains at least $arg. 188*58a0f0d0SEitan Adler set fnord "$@" "$dst_arg" 189*58a0f0d0SEitan Adler shift # fnord 190*58a0f0d0SEitan Adler fi 191*58a0f0d0SEitan Adler shift # arg 192*58a0f0d0SEitan Adler dst_arg=$arg 193*58a0f0d0SEitan Adler # Protect names problematic for 'test' and other utilities. 194*58a0f0d0SEitan Adler case $dst_arg in 195*58a0f0d0SEitan Adler -* | [=\(\)!]) dst_arg=./$dst_arg;; 196*58a0f0d0SEitan Adler esac 197*58a0f0d0SEitan Adler done 198*58a0f0d0SEitan Adlerfi 199*58a0f0d0SEitan Adler 200*58a0f0d0SEitan Adlerif test $# -eq 0; then 201*58a0f0d0SEitan Adler if test -z "$dir_arg"; then 202*58a0f0d0SEitan Adler echo "$0: no input file specified." >&2 20375a6cdb3SDavid E. O'Brien exit 1 204d1d50c78SDavid E. O'Brien fi 205*58a0f0d0SEitan Adler # It's OK to call 'install-sh -d' without argument. 206*58a0f0d0SEitan Adler # This can happen when creating conditional directories. 207*58a0f0d0SEitan Adler exit 0 20875a6cdb3SDavid E. O'Brienfi 209*58a0f0d0SEitan Adler 210*58a0f0d0SEitan Adlerif test -z "$dir_arg"; then 211*58a0f0d0SEitan Adler do_exit='(exit $ret); exit $ret' 212*58a0f0d0SEitan Adler trap "ret=129; $do_exit" 1 213*58a0f0d0SEitan Adler trap "ret=130; $do_exit" 2 214*58a0f0d0SEitan Adler trap "ret=141; $do_exit" 13 215*58a0f0d0SEitan Adler trap "ret=143; $do_exit" 15 216*58a0f0d0SEitan Adler 217*58a0f0d0SEitan Adler # Set umask so as not to create temps with too-generous modes. 218*58a0f0d0SEitan Adler # However, 'strip' requires both read and write access to temps. 219*58a0f0d0SEitan Adler case $mode in 220*58a0f0d0SEitan Adler # Optimize common cases. 221*58a0f0d0SEitan Adler *644) cp_umask=133;; 222*58a0f0d0SEitan Adler *755) cp_umask=22;; 223*58a0f0d0SEitan Adler 224*58a0f0d0SEitan Adler *[0-7]) 225*58a0f0d0SEitan Adler if test -z "$stripcmd"; then 226*58a0f0d0SEitan Adler u_plus_rw= 227974b70c4SDavid E. O'Brien else 228*58a0f0d0SEitan Adler u_plus_rw='% 200' 229974b70c4SDavid E. O'Brien fi 230*58a0f0d0SEitan Adler cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 231*58a0f0d0SEitan Adler *) 232*58a0f0d0SEitan Adler if test -z "$stripcmd"; then 233*58a0f0d0SEitan Adler u_plus_rw= 234974b70c4SDavid E. O'Brien else 235*58a0f0d0SEitan Adler u_plus_rw=,u+rw 236*58a0f0d0SEitan Adler fi 237*58a0f0d0SEitan Adler cp_umask=$mode$u_plus_rw;; 238*58a0f0d0SEitan Adler esac 239*58a0f0d0SEitan Adlerfi 240974b70c4SDavid E. O'Brien 241*58a0f0d0SEitan Adlerfor src 242*58a0f0d0SEitan Adlerdo 243*58a0f0d0SEitan Adler # Protect names problematic for 'test' and other utilities. 244*58a0f0d0SEitan Adler case $src in 245*58a0f0d0SEitan Adler -* | [=\(\)!]) src=./$src;; 246*58a0f0d0SEitan Adler esac 247*58a0f0d0SEitan Adler 248*58a0f0d0SEitan Adler if test -n "$dir_arg"; then 249*58a0f0d0SEitan Adler dst=$src 250*58a0f0d0SEitan Adler dstdir=$dst 251*58a0f0d0SEitan Adler test -d "$dstdir" 252*58a0f0d0SEitan Adler dstdir_status=$? 253*58a0f0d0SEitan Adler else 254*58a0f0d0SEitan Adler 255*58a0f0d0SEitan Adler # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 25675a6cdb3SDavid E. O'Brien # might cause directories to be created, which would be especially bad 25775a6cdb3SDavid E. O'Brien # if $src (and thus $dsttmp) contains '*'. 258*58a0f0d0SEitan Adler if test ! -f "$src" && test ! -d "$src"; then 259*58a0f0d0SEitan Adler echo "$0: $src does not exist." >&2 26080c86c36SDavid E. O'Brien exit 1 261974b70c4SDavid E. O'Brien fi 26280c86c36SDavid E. O'Brien 263*58a0f0d0SEitan Adler if test -z "$dst_arg"; then 264*58a0f0d0SEitan Adler echo "$0: no destination specified." >&2 265*58a0f0d0SEitan Adler exit 1 266974b70c4SDavid E. O'Brien fi 267*58a0f0d0SEitan Adler dst=$dst_arg 268*58a0f0d0SEitan Adler 269*58a0f0d0SEitan Adler # If destination is a directory, append the input filename; won't work 270*58a0f0d0SEitan Adler # if double slashes aren't ignored. 271*58a0f0d0SEitan Adler if test -d "$dst"; then 272*58a0f0d0SEitan Adler if test -n "$no_target_directory"; then 273*58a0f0d0SEitan Adler echo "$0: $dst_arg: Is a directory" >&2 274*58a0f0d0SEitan Adler exit 1 27580c86c36SDavid E. O'Brien fi 276*58a0f0d0SEitan Adler dstdir=$dst 277*58a0f0d0SEitan Adler dst=$dstdir/`basename "$src"` 278*58a0f0d0SEitan Adler dstdir_status=0 279974b70c4SDavid E. O'Brien else 280*58a0f0d0SEitan Adler # Prefer dirname, but fall back on a substitute if dirname fails. 281*58a0f0d0SEitan Adler dstdir=` 282*58a0f0d0SEitan Adler (dirname "$dst") 2>/dev/null || 283*58a0f0d0SEitan Adler expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 284*58a0f0d0SEitan Adler X"$dst" : 'X\(//\)[^/]' \| \ 285*58a0f0d0SEitan Adler X"$dst" : 'X\(//\)$' \| \ 286*58a0f0d0SEitan Adler X"$dst" : 'X\(/\)' \| . 2>/dev/null || 287*58a0f0d0SEitan Adler echo X"$dst" | 288*58a0f0d0SEitan Adler sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 289*58a0f0d0SEitan Adler s//\1/ 290*58a0f0d0SEitan Adler q 291*58a0f0d0SEitan Adler } 292*58a0f0d0SEitan Adler /^X\(\/\/\)[^/].*/{ 293*58a0f0d0SEitan Adler s//\1/ 294*58a0f0d0SEitan Adler q 295*58a0f0d0SEitan Adler } 296*58a0f0d0SEitan Adler /^X\(\/\/\)$/{ 297*58a0f0d0SEitan Adler s//\1/ 298*58a0f0d0SEitan Adler q 299*58a0f0d0SEitan Adler } 300*58a0f0d0SEitan Adler /^X\(\/\).*/{ 301*58a0f0d0SEitan Adler s//\1/ 302*58a0f0d0SEitan Adler q 303*58a0f0d0SEitan Adler } 304*58a0f0d0SEitan Adler s/.*/./; q' 305*58a0f0d0SEitan Adler ` 306*58a0f0d0SEitan Adler 307*58a0f0d0SEitan Adler test -d "$dstdir" 308*58a0f0d0SEitan Adler dstdir_status=$? 309*58a0f0d0SEitan Adler fi 31075a6cdb3SDavid E. O'Brien fi 31180c86c36SDavid E. O'Brien 312*58a0f0d0SEitan Adler obsolete_mkdir_used=false 31375a6cdb3SDavid E. O'Brien 314*58a0f0d0SEitan Adler if test $dstdir_status != 0; then 315*58a0f0d0SEitan Adler case $posix_mkdir in 316*58a0f0d0SEitan Adler '') 317*58a0f0d0SEitan Adler # Create intermediate dirs using mode 755 as modified by the umask. 318*58a0f0d0SEitan Adler # This is like FreeBSD 'install' as of 1997-10-28. 319*58a0f0d0SEitan Adler umask=`umask` 320*58a0f0d0SEitan Adler case $stripcmd.$umask in 321*58a0f0d0SEitan Adler # Optimize common cases. 322*58a0f0d0SEitan Adler *[2367][2367]) mkdir_umask=$umask;; 323*58a0f0d0SEitan Adler .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 32480c86c36SDavid E. O'Brien 325*58a0f0d0SEitan Adler *[0-7]) 326*58a0f0d0SEitan Adler mkdir_umask=`expr $umask + 22 \ 327*58a0f0d0SEitan Adler - $umask % 100 % 40 + $umask % 20 \ 328*58a0f0d0SEitan Adler - $umask % 10 % 4 + $umask % 2 329*58a0f0d0SEitan Adler `;; 330*58a0f0d0SEitan Adler *) mkdir_umask=$umask,go-w;; 33180c86c36SDavid E. O'Brien esac 33280c86c36SDavid E. O'Brien 333*58a0f0d0SEitan Adler # With -d, create the new directory with the user-specified mode. 334*58a0f0d0SEitan Adler # Otherwise, rely on $mkdir_umask. 335*58a0f0d0SEitan Adler if test -n "$dir_arg"; then 336*58a0f0d0SEitan Adler mkdir_mode=-m$mode 337*58a0f0d0SEitan Adler else 338*58a0f0d0SEitan Adler mkdir_mode= 339*58a0f0d0SEitan Adler fi 34080c86c36SDavid E. O'Brien 341*58a0f0d0SEitan Adler posix_mkdir=false 342*58a0f0d0SEitan Adler case $umask in 343*58a0f0d0SEitan Adler *[123567][0-7][0-7]) 344*58a0f0d0SEitan Adler # POSIX mkdir -p sets u+wx bits regardless of umask, which 345*58a0f0d0SEitan Adler # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 346*58a0f0d0SEitan Adler ;; 347*58a0f0d0SEitan Adler *) 348*58a0f0d0SEitan Adler tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 349*58a0f0d0SEitan Adler trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 35080c86c36SDavid E. O'Brien 351*58a0f0d0SEitan Adler if (umask $mkdir_umask && 352*58a0f0d0SEitan Adler exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 353*58a0f0d0SEitan Adler then 354*58a0f0d0SEitan Adler if test -z "$dir_arg" || { 355*58a0f0d0SEitan Adler # Check for POSIX incompatibilities with -m. 356*58a0f0d0SEitan Adler # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 357*58a0f0d0SEitan Adler # other-writable bit of parent directory when it shouldn't. 358*58a0f0d0SEitan Adler # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 359*58a0f0d0SEitan Adler ls_ld_tmpdir=`ls -ld "$tmpdir"` 360*58a0f0d0SEitan Adler case $ls_ld_tmpdir in 361*58a0f0d0SEitan Adler d????-?r-*) different_mode=700;; 362*58a0f0d0SEitan Adler d????-?--*) different_mode=755;; 363*58a0f0d0SEitan Adler *) false;; 364*58a0f0d0SEitan Adler esac && 365*58a0f0d0SEitan Adler $mkdirprog -m$different_mode -p -- "$tmpdir" && { 366*58a0f0d0SEitan Adler ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 367*58a0f0d0SEitan Adler test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 368*58a0f0d0SEitan Adler } 369*58a0f0d0SEitan Adler } 370*58a0f0d0SEitan Adler then posix_mkdir=: 371*58a0f0d0SEitan Adler fi 372*58a0f0d0SEitan Adler rmdir "$tmpdir/d" "$tmpdir" 373*58a0f0d0SEitan Adler else 374*58a0f0d0SEitan Adler # Remove any dirs left behind by ancient mkdir implementations. 375*58a0f0d0SEitan Adler rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 376*58a0f0d0SEitan Adler fi 377*58a0f0d0SEitan Adler trap '' 0;; 378*58a0f0d0SEitan Adler esac;; 379*58a0f0d0SEitan Adler esac 38080c86c36SDavid E. O'Brien 381*58a0f0d0SEitan Adler if 382*58a0f0d0SEitan Adler $posix_mkdir && ( 383*58a0f0d0SEitan Adler umask $mkdir_umask && 384*58a0f0d0SEitan Adler $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 385*58a0f0d0SEitan Adler ) 386*58a0f0d0SEitan Adler then : 387*58a0f0d0SEitan Adler else 38880c86c36SDavid E. O'Brien 389*58a0f0d0SEitan Adler # The umask is ridiculous, or mkdir does not conform to POSIX, 390*58a0f0d0SEitan Adler # or it failed possibly due to a race condition. Create the 391*58a0f0d0SEitan Adler # directory the slow way, step by step, checking for races as we go. 392*58a0f0d0SEitan Adler 393*58a0f0d0SEitan Adler case $dstdir in 394*58a0f0d0SEitan Adler /*) prefix='/';; 395*58a0f0d0SEitan Adler [-=\(\)!]*) prefix='./';; 396*58a0f0d0SEitan Adler *) prefix='';; 397*58a0f0d0SEitan Adler esac 398*58a0f0d0SEitan Adler 399*58a0f0d0SEitan Adler eval "$initialize_posix_glob" 400*58a0f0d0SEitan Adler 401*58a0f0d0SEitan Adler oIFS=$IFS 402*58a0f0d0SEitan Adler IFS=/ 403*58a0f0d0SEitan Adler $posix_glob set -f 404*58a0f0d0SEitan Adler set fnord $dstdir 405*58a0f0d0SEitan Adler shift 406*58a0f0d0SEitan Adler $posix_glob set +f 407*58a0f0d0SEitan Adler IFS=$oIFS 408*58a0f0d0SEitan Adler 409*58a0f0d0SEitan Adler prefixes= 410*58a0f0d0SEitan Adler 411*58a0f0d0SEitan Adler for d 412*58a0f0d0SEitan Adler do 413*58a0f0d0SEitan Adler test X"$d" = X && continue 414*58a0f0d0SEitan Adler 415*58a0f0d0SEitan Adler prefix=$prefix$d 416*58a0f0d0SEitan Adler if test -d "$prefix"; then 417*58a0f0d0SEitan Adler prefixes= 418*58a0f0d0SEitan Adler else 419*58a0f0d0SEitan Adler if $posix_mkdir; then 420*58a0f0d0SEitan Adler (umask=$mkdir_umask && 421*58a0f0d0SEitan Adler $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 422*58a0f0d0SEitan Adler # Don't fail if two instances are running concurrently. 423*58a0f0d0SEitan Adler test -d "$prefix" || exit 1 424*58a0f0d0SEitan Adler else 425*58a0f0d0SEitan Adler case $prefix in 426*58a0f0d0SEitan Adler *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 427*58a0f0d0SEitan Adler *) qprefix=$prefix;; 428*58a0f0d0SEitan Adler esac 429*58a0f0d0SEitan Adler prefixes="$prefixes '$qprefix'" 430*58a0f0d0SEitan Adler fi 431*58a0f0d0SEitan Adler fi 432*58a0f0d0SEitan Adler prefix=$prefix/ 433*58a0f0d0SEitan Adler done 434*58a0f0d0SEitan Adler 435*58a0f0d0SEitan Adler if test -n "$prefixes"; then 436*58a0f0d0SEitan Adler # Don't fail if two instances are running concurrently. 437*58a0f0d0SEitan Adler (umask $mkdir_umask && 438*58a0f0d0SEitan Adler eval "\$doit_exec \$mkdirprog $prefixes") || 439*58a0f0d0SEitan Adler test -d "$dstdir" || exit 1 440*58a0f0d0SEitan Adler obsolete_mkdir_used=true 441*58a0f0d0SEitan Adler fi 442*58a0f0d0SEitan Adler fi 443*58a0f0d0SEitan Adler fi 444*58a0f0d0SEitan Adler 445*58a0f0d0SEitan Adler if test -n "$dir_arg"; then 446*58a0f0d0SEitan Adler { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 447*58a0f0d0SEitan Adler { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 448*58a0f0d0SEitan Adler { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 449*58a0f0d0SEitan Adler test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 450*58a0f0d0SEitan Adler else 451*58a0f0d0SEitan Adler 452*58a0f0d0SEitan Adler # Make a couple of temp file names in the proper directory. 453*58a0f0d0SEitan Adler dsttmp=$dstdir/_inst.$$_ 454*58a0f0d0SEitan Adler rmtmp=$dstdir/_rm.$$_ 455*58a0f0d0SEitan Adler 456*58a0f0d0SEitan Adler # Trap to clean up those temp files at exit. 457*58a0f0d0SEitan Adler trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 458*58a0f0d0SEitan Adler 459*58a0f0d0SEitan Adler # Copy the file name to the temp name. 460*58a0f0d0SEitan Adler (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 461*58a0f0d0SEitan Adler 462*58a0f0d0SEitan Adler # and set any options; do chmod last to preserve setuid bits. 463*58a0f0d0SEitan Adler # 464d1d50c78SDavid E. O'Brien # If any of these fail, we abort the whole thing. If we want to 465d1d50c78SDavid E. O'Brien # ignore errors from any of these, just make sure not to ignore 466*58a0f0d0SEitan Adler # errors from the above "$doit $cpprog $src $dsttmp" command. 467*58a0f0d0SEitan Adler # 468*58a0f0d0SEitan Adler { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 469*58a0f0d0SEitan Adler { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 470*58a0f0d0SEitan Adler { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 471*58a0f0d0SEitan Adler { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 47280c86c36SDavid E. O'Brien 473*58a0f0d0SEitan Adler # If -C, don't bother to copy if it wouldn't change the file. 474*58a0f0d0SEitan Adler if $copy_on_change && 475*58a0f0d0SEitan Adler old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 476*58a0f0d0SEitan Adler new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 477*58a0f0d0SEitan Adler 478*58a0f0d0SEitan Adler eval "$initialize_posix_glob" && 479*58a0f0d0SEitan Adler $posix_glob set -f && 480*58a0f0d0SEitan Adler set X $old && old=:$2:$4:$5:$6 && 481*58a0f0d0SEitan Adler set X $new && new=:$2:$4:$5:$6 && 482*58a0f0d0SEitan Adler $posix_glob set +f && 483*58a0f0d0SEitan Adler 484*58a0f0d0SEitan Adler test "$old" = "$new" && 485*58a0f0d0SEitan Adler $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 486*58a0f0d0SEitan Adler then 487*58a0f0d0SEitan Adler rm -f "$dsttmp" 488*58a0f0d0SEitan Adler else 489*58a0f0d0SEitan Adler # Rename the file to the real destination. 490*58a0f0d0SEitan Adler $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 491*58a0f0d0SEitan Adler 492*58a0f0d0SEitan Adler # The rename failed, perhaps because mv can't rename something else 493*58a0f0d0SEitan Adler # to itself, or perhaps because mv is so ancient that it does not 494*58a0f0d0SEitan Adler # support -f. 495*58a0f0d0SEitan Adler { 496*58a0f0d0SEitan Adler # Now remove or move aside any old file at destination location. 497*58a0f0d0SEitan Adler # We try this two ways since rm can't unlink itself on some 498*58a0f0d0SEitan Adler # systems and the destination file might be busy for other 499*58a0f0d0SEitan Adler # reasons. In this case, the final cleanup might fail but the new 500*58a0f0d0SEitan Adler # file should still install successfully. 501*58a0f0d0SEitan Adler { 502*58a0f0d0SEitan Adler test ! -f "$dst" || 503*58a0f0d0SEitan Adler $doit $rmcmd -f "$dst" 2>/dev/null || 504*58a0f0d0SEitan Adler { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 505*58a0f0d0SEitan Adler { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 506*58a0f0d0SEitan Adler } || 507*58a0f0d0SEitan Adler { echo "$0: cannot unlink or rename $dst" >&2 508*58a0f0d0SEitan Adler (exit 1); exit 1 509*58a0f0d0SEitan Adler } 510*58a0f0d0SEitan Adler } && 511d1d50c78SDavid E. O'Brien 512d1d50c78SDavid E. O'Brien # Now rename the file to the real destination. 513*58a0f0d0SEitan Adler $doit $mvcmd "$dsttmp" "$dst" 514*58a0f0d0SEitan Adler } 515*58a0f0d0SEitan Adler fi || exit 1 516d1d50c78SDavid E. O'Brien 517*58a0f0d0SEitan Adler trap '' 0 51875a6cdb3SDavid E. O'Brien fi 519*58a0f0d0SEitan Adlerdone 52075a6cdb3SDavid E. O'Brien 521*58a0f0d0SEitan Adler# Local variables: 522*58a0f0d0SEitan Adler# eval: (add-hook 'write-file-hooks 'time-stamp) 523*58a0f0d0SEitan Adler# time-stamp-start: "scriptversion=" 524*58a0f0d0SEitan Adler# time-stamp-format: "%:y-%02m-%02d.%02H" 525*58a0f0d0SEitan Adler# time-stamp-time-zone: "UTC" 526*58a0f0d0SEitan Adler# time-stamp-end: "; # UTC" 527*58a0f0d0SEitan Adler# End: 528