install-sh revision 301ea0f4
1301ea0f4Smrg#!/bin/sh 2301ea0f4Smrg# install - install a program, script, or datafile 3301ea0f4Smrg 4301ea0f4Smrgscriptversion=2005-05-14.22 5301ea0f4Smrg 6301ea0f4Smrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7301ea0f4Smrg# later released in X11R6 (xc/config/util/install.sh) with the 8301ea0f4Smrg# following copyright and license. 9301ea0f4Smrg# 10301ea0f4Smrg# Copyright (C) 1994 X Consortium 11301ea0f4Smrg# 12301ea0f4Smrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13301ea0f4Smrg# of this software and associated documentation files (the "Software"), to 14301ea0f4Smrg# deal in the Software without restriction, including without limitation the 15301ea0f4Smrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16301ea0f4Smrg# sell copies of the Software, and to permit persons to whom the Software is 17301ea0f4Smrg# furnished to do so, subject to the following conditions: 18301ea0f4Smrg# 19301ea0f4Smrg# The above copyright notice and this permission notice shall be included in 20301ea0f4Smrg# all copies or substantial portions of the Software. 21301ea0f4Smrg# 22301ea0f4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23301ea0f4Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24301ea0f4Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25301ea0f4Smrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26301ea0f4Smrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27301ea0f4Smrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28301ea0f4Smrg# 29301ea0f4Smrg# Except as contained in this notice, the name of the X Consortium shall not 30301ea0f4Smrg# be used in advertising or otherwise to promote the sale, use or other deal- 31301ea0f4Smrg# ings in this Software without prior written authorization from the X Consor- 32301ea0f4Smrg# tium. 33301ea0f4Smrg# 34301ea0f4Smrg# 35301ea0f4Smrg# FSF changes to this file are in the public domain. 36301ea0f4Smrg# 37301ea0f4Smrg# Calling this script install-sh is preferred over install.sh, to prevent 38301ea0f4Smrg# `make' implicit rules from creating a file called install from it 39301ea0f4Smrg# when there is no Makefile. 40301ea0f4Smrg# 41301ea0f4Smrg# This script is compatible with the BSD install script, but was written 42301ea0f4Smrg# from scratch. It can only install one file at a time, a restriction 43301ea0f4Smrg# shared with many OS's install programs. 44301ea0f4Smrg 45301ea0f4Smrg# set DOITPROG to echo to test this script 46301ea0f4Smrg 47301ea0f4Smrg# Don't use :- since 4.3BSD and earlier shells don't like it. 48301ea0f4Smrgdoit="${DOITPROG-}" 49301ea0f4Smrg 50301ea0f4Smrg# put in absolute paths if you don't have them in your path; or use env. vars. 51301ea0f4Smrg 52301ea0f4Smrgmvprog="${MVPROG-mv}" 53301ea0f4Smrgcpprog="${CPPROG-cp}" 54301ea0f4Smrgchmodprog="${CHMODPROG-chmod}" 55301ea0f4Smrgchownprog="${CHOWNPROG-chown}" 56301ea0f4Smrgchgrpprog="${CHGRPPROG-chgrp}" 57301ea0f4Smrgstripprog="${STRIPPROG-strip}" 58301ea0f4Smrgrmprog="${RMPROG-rm}" 59301ea0f4Smrgmkdirprog="${MKDIRPROG-mkdir}" 60301ea0f4Smrg 61301ea0f4Smrgchmodcmd="$chmodprog 0755" 62301ea0f4Smrgchowncmd= 63301ea0f4Smrgchgrpcmd= 64301ea0f4Smrgstripcmd= 65301ea0f4Smrgrmcmd="$rmprog -f" 66301ea0f4Smrgmvcmd="$mvprog" 67301ea0f4Smrgsrc= 68301ea0f4Smrgdst= 69301ea0f4Smrgdir_arg= 70301ea0f4Smrgdstarg= 71301ea0f4Smrgno_target_directory= 72301ea0f4Smrg 73301ea0f4Smrgusage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 74301ea0f4Smrg or: $0 [OPTION]... SRCFILES... DIRECTORY 75301ea0f4Smrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 76301ea0f4Smrg or: $0 [OPTION]... -d DIRECTORIES... 77301ea0f4Smrg 78301ea0f4SmrgIn the 1st form, copy SRCFILE to DSTFILE. 79301ea0f4SmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 80301ea0f4SmrgIn the 4th, create DIRECTORIES. 81301ea0f4Smrg 82301ea0f4SmrgOptions: 83301ea0f4Smrg-c (ignored) 84301ea0f4Smrg-d create directories instead of installing files. 85301ea0f4Smrg-g GROUP $chgrpprog installed files to GROUP. 86301ea0f4Smrg-m MODE $chmodprog installed files to MODE. 87301ea0f4Smrg-o USER $chownprog installed files to USER. 88301ea0f4Smrg-s $stripprog installed files. 89301ea0f4Smrg-t DIRECTORY install into DIRECTORY. 90301ea0f4Smrg-T report an error if DSTFILE is a directory. 91301ea0f4Smrg--help display this help and exit. 92301ea0f4Smrg--version display version info and exit. 93301ea0f4Smrg 94301ea0f4SmrgEnvironment variables override the default commands: 95301ea0f4Smrg CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 96301ea0f4Smrg" 97301ea0f4Smrg 98301ea0f4Smrgwhile test -n "$1"; do 99301ea0f4Smrg case $1 in 100301ea0f4Smrg -c) shift 101301ea0f4Smrg continue;; 102301ea0f4Smrg 103301ea0f4Smrg -d) dir_arg=true 104301ea0f4Smrg shift 105301ea0f4Smrg continue;; 106301ea0f4Smrg 107301ea0f4Smrg -g) chgrpcmd="$chgrpprog $2" 108301ea0f4Smrg shift 109301ea0f4Smrg shift 110301ea0f4Smrg continue;; 111301ea0f4Smrg 112301ea0f4Smrg --help) echo "$usage"; exit $?;; 113301ea0f4Smrg 114301ea0f4Smrg -m) chmodcmd="$chmodprog $2" 115301ea0f4Smrg shift 116301ea0f4Smrg shift 117301ea0f4Smrg continue;; 118301ea0f4Smrg 119301ea0f4Smrg -o) chowncmd="$chownprog $2" 120301ea0f4Smrg shift 121301ea0f4Smrg shift 122301ea0f4Smrg continue;; 123301ea0f4Smrg 124301ea0f4Smrg -s) stripcmd=$stripprog 125301ea0f4Smrg shift 126301ea0f4Smrg continue;; 127301ea0f4Smrg 128301ea0f4Smrg -t) dstarg=$2 129301ea0f4Smrg shift 130301ea0f4Smrg shift 131301ea0f4Smrg continue;; 132301ea0f4Smrg 133301ea0f4Smrg -T) no_target_directory=true 134301ea0f4Smrg shift 135301ea0f4Smrg continue;; 136301ea0f4Smrg 137301ea0f4Smrg --version) echo "$0 $scriptversion"; exit $?;; 138301ea0f4Smrg 139301ea0f4Smrg *) # When -d is used, all remaining arguments are directories to create. 140301ea0f4Smrg # When -t is used, the destination is already specified. 141301ea0f4Smrg test -n "$dir_arg$dstarg" && break 142301ea0f4Smrg # Otherwise, the last argument is the destination. Remove it from $@. 143301ea0f4Smrg for arg 144301ea0f4Smrg do 145301ea0f4Smrg if test -n "$dstarg"; then 146301ea0f4Smrg # $@ is not empty: it contains at least $arg. 147301ea0f4Smrg set fnord "$@" "$dstarg" 148301ea0f4Smrg shift # fnord 149301ea0f4Smrg fi 150301ea0f4Smrg shift # arg 151301ea0f4Smrg dstarg=$arg 152301ea0f4Smrg done 153301ea0f4Smrg break;; 154301ea0f4Smrg esac 155301ea0f4Smrgdone 156301ea0f4Smrg 157301ea0f4Smrgif test -z "$1"; then 158301ea0f4Smrg if test -z "$dir_arg"; then 159301ea0f4Smrg echo "$0: no input file specified." >&2 160301ea0f4Smrg exit 1 161301ea0f4Smrg fi 162301ea0f4Smrg # It's OK to call `install-sh -d' without argument. 163301ea0f4Smrg # This can happen when creating conditional directories. 164301ea0f4Smrg exit 0 165301ea0f4Smrgfi 166301ea0f4Smrg 167301ea0f4Smrgfor src 168301ea0f4Smrgdo 169301ea0f4Smrg # Protect names starting with `-'. 170301ea0f4Smrg case $src in 171301ea0f4Smrg -*) src=./$src ;; 172301ea0f4Smrg esac 173301ea0f4Smrg 174301ea0f4Smrg if test -n "$dir_arg"; then 175301ea0f4Smrg dst=$src 176301ea0f4Smrg src= 177301ea0f4Smrg 178301ea0f4Smrg if test -d "$dst"; then 179301ea0f4Smrg mkdircmd=: 180301ea0f4Smrg chmodcmd= 181301ea0f4Smrg else 182301ea0f4Smrg mkdircmd=$mkdirprog 183301ea0f4Smrg fi 184301ea0f4Smrg else 185301ea0f4Smrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 186301ea0f4Smrg # might cause directories to be created, which would be especially bad 187301ea0f4Smrg # if $src (and thus $dsttmp) contains '*'. 188301ea0f4Smrg if test ! -f "$src" && test ! -d "$src"; then 189301ea0f4Smrg echo "$0: $src does not exist." >&2 190301ea0f4Smrg exit 1 191301ea0f4Smrg fi 192301ea0f4Smrg 193301ea0f4Smrg if test -z "$dstarg"; then 194301ea0f4Smrg echo "$0: no destination specified." >&2 195301ea0f4Smrg exit 1 196301ea0f4Smrg fi 197301ea0f4Smrg 198301ea0f4Smrg dst=$dstarg 199301ea0f4Smrg # Protect names starting with `-'. 200301ea0f4Smrg case $dst in 201301ea0f4Smrg -*) dst=./$dst ;; 202301ea0f4Smrg esac 203301ea0f4Smrg 204301ea0f4Smrg # If destination is a directory, append the input filename; won't work 205301ea0f4Smrg # if double slashes aren't ignored. 206301ea0f4Smrg if test -d "$dst"; then 207301ea0f4Smrg if test -n "$no_target_directory"; then 208301ea0f4Smrg echo "$0: $dstarg: Is a directory" >&2 209301ea0f4Smrg exit 1 210301ea0f4Smrg fi 211301ea0f4Smrg dst=$dst/`basename "$src"` 212301ea0f4Smrg fi 213301ea0f4Smrg fi 214301ea0f4Smrg 215301ea0f4Smrg # This sed command emulates the dirname command. 216301ea0f4Smrg dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` 217301ea0f4Smrg 218301ea0f4Smrg # Make sure that the destination directory exists. 219301ea0f4Smrg 220301ea0f4Smrg # Skip lots of stat calls in the usual case. 221301ea0f4Smrg if test ! -d "$dstdir"; then 222301ea0f4Smrg defaultIFS=' 223301ea0f4Smrg ' 224301ea0f4Smrg IFS="${IFS-$defaultIFS}" 225301ea0f4Smrg 226301ea0f4Smrg oIFS=$IFS 227301ea0f4Smrg # Some sh's can't handle IFS=/ for some reason. 228301ea0f4Smrg IFS='%' 229301ea0f4Smrg set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` 230301ea0f4Smrg shift 231301ea0f4Smrg IFS=$oIFS 232301ea0f4Smrg 233301ea0f4Smrg pathcomp= 234301ea0f4Smrg 235301ea0f4Smrg while test $# -ne 0 ; do 236301ea0f4Smrg pathcomp=$pathcomp$1 237301ea0f4Smrg shift 238301ea0f4Smrg if test ! -d "$pathcomp"; then 239301ea0f4Smrg $mkdirprog "$pathcomp" 240301ea0f4Smrg # mkdir can fail with a `File exist' error in case several 241301ea0f4Smrg # install-sh are creating the directory concurrently. This 242301ea0f4Smrg # is OK. 243301ea0f4Smrg test -d "$pathcomp" || exit 244301ea0f4Smrg fi 245301ea0f4Smrg pathcomp=$pathcomp/ 246301ea0f4Smrg done 247301ea0f4Smrg fi 248301ea0f4Smrg 249301ea0f4Smrg if test -n "$dir_arg"; then 250301ea0f4Smrg $doit $mkdircmd "$dst" \ 251301ea0f4Smrg && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ 252301ea0f4Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ 253301ea0f4Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ 254301ea0f4Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } 255301ea0f4Smrg 256301ea0f4Smrg else 257301ea0f4Smrg dstfile=`basename "$dst"` 258301ea0f4Smrg 259301ea0f4Smrg # Make a couple of temp file names in the proper directory. 260301ea0f4Smrg dsttmp=$dstdir/_inst.$$_ 261301ea0f4Smrg rmtmp=$dstdir/_rm.$$_ 262301ea0f4Smrg 263301ea0f4Smrg # Trap to clean up those temp files at exit. 264301ea0f4Smrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 265301ea0f4Smrg trap '(exit $?); exit' 1 2 13 15 266301ea0f4Smrg 267301ea0f4Smrg # Copy the file name to the temp name. 268301ea0f4Smrg $doit $cpprog "$src" "$dsttmp" && 269301ea0f4Smrg 270301ea0f4Smrg # and set any options; do chmod last to preserve setuid bits. 271301ea0f4Smrg # 272301ea0f4Smrg # If any of these fail, we abort the whole thing. If we want to 273301ea0f4Smrg # ignore errors from any of these, just make sure not to ignore 274301ea0f4Smrg # errors from the above "$doit $cpprog $src $dsttmp" command. 275301ea0f4Smrg # 276301ea0f4Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 277301ea0f4Smrg && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 278301ea0f4Smrg && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 279301ea0f4Smrg && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && 280301ea0f4Smrg 281301ea0f4Smrg # Now rename the file to the real destination. 282301ea0f4Smrg { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ 283301ea0f4Smrg || { 284301ea0f4Smrg # The rename failed, perhaps because mv can't rename something else 285301ea0f4Smrg # to itself, or perhaps because mv is so ancient that it does not 286301ea0f4Smrg # support -f. 287301ea0f4Smrg 288301ea0f4Smrg # Now remove or move aside any old file at destination location. 289301ea0f4Smrg # We try this two ways since rm can't unlink itself on some 290301ea0f4Smrg # systems and the destination file might be busy for other 291301ea0f4Smrg # reasons. In this case, the final cleanup might fail but the new 292301ea0f4Smrg # file should still install successfully. 293301ea0f4Smrg { 294301ea0f4Smrg if test -f "$dstdir/$dstfile"; then 295301ea0f4Smrg $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ 296301ea0f4Smrg || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ 297301ea0f4Smrg || { 298301ea0f4Smrg echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 299301ea0f4Smrg (exit 1); exit 1 300301ea0f4Smrg } 301301ea0f4Smrg else 302301ea0f4Smrg : 303301ea0f4Smrg fi 304301ea0f4Smrg } && 305301ea0f4Smrg 306301ea0f4Smrg # Now rename the file to the real destination. 307301ea0f4Smrg $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" 308301ea0f4Smrg } 309301ea0f4Smrg } 310301ea0f4Smrg fi || { (exit 1); exit 1; } 311301ea0f4Smrgdone 312301ea0f4Smrg 313301ea0f4Smrg# The final little trick to "correctly" pass the exit status to the exit trap. 314301ea0f4Smrg{ 315301ea0f4Smrg (exit 0); exit 0 316301ea0f4Smrg} 317301ea0f4Smrg 318301ea0f4Smrg# Local variables: 319301ea0f4Smrg# eval: (add-hook 'write-file-hooks 'time-stamp) 320301ea0f4Smrg# time-stamp-start: "scriptversion=" 321301ea0f4Smrg# time-stamp-format: "%:y-%02m-%02d.%02H" 322301ea0f4Smrg# time-stamp-end: "$" 323301ea0f4Smrg# End: 324