install-sh revision 228692
1117610Sdes#!/bin/sh 2117610Sdes# install - install a program, script, or datafile 3141098Sdes 4228692Sdesscriptversion=2009-04-28.21; # UTC 5141098Sdes 6141098Sdes# This originates from X11R5 (mit/util/scripts/install.sh), which was 7141098Sdes# later released in X11R6 (xc/config/util/install.sh) with the 8141098Sdes# following copyright and license. 9117610Sdes# 10141098Sdes# Copyright (C) 1994 X Consortium 11117610Sdes# 12141098Sdes# Permission is hereby granted, free of charge, to any person obtaining a copy 13141098Sdes# of this software and associated documentation files (the "Software"), to 14141098Sdes# deal in the Software without restriction, including without limitation the 15141098Sdes# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16141098Sdes# sell copies of the Software, and to permit persons to whom the Software is 17141098Sdes# furnished to do so, subject to the following conditions: 18117610Sdes# 19141098Sdes# The above copyright notice and this permission notice shall be included in 20141098Sdes# all copies or substantial portions of the Software. 21141098Sdes# 22141098Sdes# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23141098Sdes# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24141098Sdes# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25141098Sdes# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26141098Sdes# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27141098Sdes# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28141098Sdes# 29141098Sdes# Except as contained in this notice, the name of the X Consortium shall not 30141098Sdes# be used in advertising or otherwise to promote the sale, use or other deal- 31141098Sdes# ings in this Software without prior written authorization from the X Consor- 32141098Sdes# tium. 33141098Sdes# 34141098Sdes# 35141098Sdes# FSF changes to this file are in the public domain. 36141098Sdes# 37117610Sdes# Calling this script install-sh is preferred over install.sh, to prevent 38117610Sdes# `make' implicit rules from creating a file called install from it 39117610Sdes# when there is no Makefile. 40117610Sdes# 41117610Sdes# This script is compatible with the BSD install script, but was written 42228692Sdes# from scratch. 43117610Sdes 44228692Sdesnl=' 45228692Sdes' 46228692SdesIFS=" "" $nl" 47228692Sdes 48117610Sdes# set DOITPROG to echo to test this script 49117610Sdes 50117610Sdes# Don't use :- since 4.3BSD and earlier shells don't like it. 51228692Sdesdoit=${DOITPROG-} 52228692Sdesif test -z "$doit"; then 53228692Sdes doit_exec=exec 54228692Sdeselse 55228692Sdes doit_exec=$doit 56228692Sdesfi 57117610Sdes 58228692Sdes# Put in absolute file names if you don't have them in your path; 59228692Sdes# or use environment vars. 60117610Sdes 61228692Sdeschgrpprog=${CHGRPPROG-chgrp} 62228692Sdeschmodprog=${CHMODPROG-chmod} 63228692Sdeschownprog=${CHOWNPROG-chown} 64228692Sdescmpprog=${CMPPROG-cmp} 65228692Sdescpprog=${CPPROG-cp} 66228692Sdesmkdirprog=${MKDIRPROG-mkdir} 67228692Sdesmvprog=${MVPROG-mv} 68228692Sdesrmprog=${RMPROG-rm} 69228692Sdesstripprog=${STRIPPROG-strip} 70117610Sdes 71228692Sdesposix_glob='?' 72228692Sdesinitialize_posix_glob=' 73228692Sdes test "$posix_glob" != "?" || { 74228692Sdes if (set -f) 2>/dev/null; then 75228692Sdes posix_glob= 76228692Sdes else 77228692Sdes posix_glob=: 78228692Sdes fi 79228692Sdes } 80228692Sdes' 81228692Sdes 82228692Sdesposix_mkdir= 83228692Sdes 84228692Sdes# Desired mode of installed file. 85228692Sdesmode=0755 86228692Sdes 87228692Sdeschgrpcmd= 88228692Sdeschmodcmd=$chmodprog 89141098Sdeschowncmd= 90228692Sdesmvcmd=$mvprog 91228692Sdesrmcmd="$rmprog -f" 92141098Sdesstripcmd= 93228692Sdes 94141098Sdessrc= 95141098Sdesdst= 96141098Sdesdir_arg= 97228692Sdesdst_arg= 98228692Sdes 99228692Sdescopy_on_change=false 100174832Sdesno_target_directory= 101117610Sdes 102228692Sdesusage="\ 103228692SdesUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104141098Sdes or: $0 [OPTION]... SRCFILES... DIRECTORY 105174832Sdes or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106174832Sdes or: $0 [OPTION]... -d DIRECTORIES... 107117610Sdes 108174832SdesIn the 1st form, copy SRCFILE to DSTFILE. 109174832SdesIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110174832SdesIn the 4th, create DIRECTORIES. 111117610Sdes 112141098SdesOptions: 113228692Sdes --help display this help and exit. 114228692Sdes --version display version info and exit. 115117610Sdes 116228692Sdes -c (ignored) 117228692Sdes -C install only if different (preserve the last data modification time) 118228692Sdes -d create directories instead of installing files. 119228692Sdes -g GROUP $chgrpprog installed files to GROUP. 120228692Sdes -m MODE $chmodprog installed files to MODE. 121228692Sdes -o USER $chownprog installed files to USER. 122228692Sdes -s $stripprog installed files. 123228692Sdes -t DIRECTORY install into DIRECTORY. 124228692Sdes -T report an error if DSTFILE is a directory. 125228692Sdes 126141098SdesEnvironment variables override the default commands: 127228692Sdes CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128228692Sdes RMPROG STRIPPROG 129141098Sdes" 130117610Sdes 131228692Sdeswhile test $# -ne 0; do 132141098Sdes case $1 in 133228692Sdes -c) ;; 134117610Sdes 135228692Sdes -C) copy_on_change=true;; 136117610Sdes 137228692Sdes -d) dir_arg=true;; 138228692Sdes 139141098Sdes -g) chgrpcmd="$chgrpprog $2" 140228692Sdes shift;; 141117610Sdes 142174832Sdes --help) echo "$usage"; exit $?;; 143117610Sdes 144228692Sdes -m) mode=$2 145228692Sdes case $mode in 146228692Sdes *' '* | *' '* | *' 147228692Sdes'* | *'*'* | *'?'* | *'['*) 148228692Sdes echo "$0: invalid mode: $mode" >&2 149228692Sdes exit 1;; 150228692Sdes esac 151228692Sdes shift;; 152117610Sdes 153141098Sdes -o) chowncmd="$chownprog $2" 154228692Sdes shift;; 155117610Sdes 156228692Sdes -s) stripcmd=$stripprog;; 157117610Sdes 158228692Sdes -t) dst_arg=$2 159228692Sdes shift;; 160117610Sdes 161228692Sdes -T) no_target_directory=true;; 162117610Sdes 163174832Sdes --version) echo "$0 $scriptversion"; exit $?;; 164174832Sdes 165228692Sdes --) shift 166141098Sdes break;; 167228692Sdes 168228692Sdes -*) echo "$0: invalid option: $1" >&2 169228692Sdes exit 1;; 170228692Sdes 171228692Sdes *) break;; 172141098Sdes esac 173228692Sdes shift 174141098Sdesdone 175141098Sdes 176228692Sdesif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 177228692Sdes # When -d is used, all remaining arguments are directories to create. 178228692Sdes # When -t is used, the destination is already specified. 179228692Sdes # Otherwise, the last argument is the destination. Remove it from $@. 180228692Sdes for arg 181228692Sdes do 182228692Sdes if test -n "$dst_arg"; then 183228692Sdes # $@ is not empty: it contains at least $arg. 184228692Sdes set fnord "$@" "$dst_arg" 185228692Sdes shift # fnord 186228692Sdes fi 187228692Sdes shift # arg 188228692Sdes dst_arg=$arg 189228692Sdes done 190228692Sdesfi 191228692Sdes 192228692Sdesif test $# -eq 0; then 193141098Sdes if test -z "$dir_arg"; then 194141098Sdes echo "$0: no input file specified." >&2 195141098Sdes exit 1 196141098Sdes fi 197141098Sdes # It's OK to call `install-sh -d' without argument. 198141098Sdes # This can happen when creating conditional directories. 199141098Sdes exit 0 200117610Sdesfi 201117610Sdes 202228692Sdesif test -z "$dir_arg"; then 203228692Sdes trap '(exit $?); exit' 1 2 13 15 204228692Sdes 205228692Sdes # Set umask so as not to create temps with too-generous modes. 206228692Sdes # However, 'strip' requires both read and write access to temps. 207228692Sdes case $mode in 208228692Sdes # Optimize common cases. 209228692Sdes *644) cp_umask=133;; 210228692Sdes *755) cp_umask=22;; 211228692Sdes 212228692Sdes *[0-7]) 213228692Sdes if test -z "$stripcmd"; then 214228692Sdes u_plus_rw= 215228692Sdes else 216228692Sdes u_plus_rw='% 200' 217228692Sdes fi 218228692Sdes cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 219228692Sdes *) 220228692Sdes if test -z "$stripcmd"; then 221228692Sdes u_plus_rw= 222228692Sdes else 223228692Sdes u_plus_rw=,u+rw 224228692Sdes fi 225228692Sdes cp_umask=$mode$u_plus_rw;; 226228692Sdes esac 227228692Sdesfi 228228692Sdes 229141098Sdesfor src 230141098Sdesdo 231141098Sdes # Protect names starting with `-'. 232141098Sdes case $src in 233228692Sdes -*) src=./$src;; 234141098Sdes esac 235117610Sdes 236141098Sdes if test -n "$dir_arg"; then 237141098Sdes dst=$src 238228692Sdes dstdir=$dst 239228692Sdes test -d "$dstdir" 240228692Sdes dstdir_status=$? 241228692Sdes else 242117610Sdes 243174832Sdes # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 244141098Sdes # might cause directories to be created, which would be especially bad 245141098Sdes # if $src (and thus $dsttmp) contains '*'. 246141098Sdes if test ! -f "$src" && test ! -d "$src"; then 247141098Sdes echo "$0: $src does not exist." >&2 248141098Sdes exit 1 249141098Sdes fi 250117610Sdes 251228692Sdes if test -z "$dst_arg"; then 252141098Sdes echo "$0: no destination specified." >&2 253141098Sdes exit 1 254141098Sdes fi 255117610Sdes 256228692Sdes dst=$dst_arg 257141098Sdes # Protect names starting with `-'. 258141098Sdes case $dst in 259228692Sdes -*) dst=./$dst;; 260141098Sdes esac 261117610Sdes 262141098Sdes # If destination is a directory, append the input filename; won't work 263141098Sdes # if double slashes aren't ignored. 264141098Sdes if test -d "$dst"; then 265174832Sdes if test -n "$no_target_directory"; then 266228692Sdes echo "$0: $dst_arg: Is a directory" >&2 267174832Sdes exit 1 268174832Sdes fi 269228692Sdes dstdir=$dst 270228692Sdes dst=$dstdir/`basename "$src"` 271228692Sdes dstdir_status=0 272228692Sdes else 273228692Sdes # Prefer dirname, but fall back on a substitute if dirname fails. 274228692Sdes dstdir=` 275228692Sdes (dirname "$dst") 2>/dev/null || 276228692Sdes expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 277228692Sdes X"$dst" : 'X\(//\)[^/]' \| \ 278228692Sdes X"$dst" : 'X\(//\)$' \| \ 279228692Sdes X"$dst" : 'X\(/\)' \| . 2>/dev/null || 280228692Sdes echo X"$dst" | 281228692Sdes sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 282228692Sdes s//\1/ 283228692Sdes q 284228692Sdes } 285228692Sdes /^X\(\/\/\)[^/].*/{ 286228692Sdes s//\1/ 287228692Sdes q 288228692Sdes } 289228692Sdes /^X\(\/\/\)$/{ 290228692Sdes s//\1/ 291228692Sdes q 292228692Sdes } 293228692Sdes /^X\(\/\).*/{ 294228692Sdes s//\1/ 295228692Sdes q 296228692Sdes } 297228692Sdes s/.*/./; q' 298228692Sdes ` 299228692Sdes 300228692Sdes test -d "$dstdir" 301228692Sdes dstdir_status=$? 302141098Sdes fi 303141098Sdes fi 304117610Sdes 305228692Sdes obsolete_mkdir_used=false 306117610Sdes 307228692Sdes if test $dstdir_status != 0; then 308228692Sdes case $posix_mkdir in 309228692Sdes '') 310228692Sdes # Create intermediate dirs using mode 755 as modified by the umask. 311228692Sdes # This is like FreeBSD 'install' as of 1997-10-28. 312228692Sdes umask=`umask` 313228692Sdes case $stripcmd.$umask in 314228692Sdes # Optimize common cases. 315228692Sdes *[2367][2367]) mkdir_umask=$umask;; 316228692Sdes .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 317117610Sdes 318228692Sdes *[0-7]) 319228692Sdes mkdir_umask=`expr $umask + 22 \ 320228692Sdes - $umask % 100 % 40 + $umask % 20 \ 321228692Sdes - $umask % 10 % 4 + $umask % 2 322228692Sdes `;; 323228692Sdes *) mkdir_umask=$umask,go-w;; 324228692Sdes esac 325117610Sdes 326228692Sdes # With -d, create the new directory with the user-specified mode. 327228692Sdes # Otherwise, rely on $mkdir_umask. 328228692Sdes if test -n "$dir_arg"; then 329228692Sdes mkdir_mode=-m$mode 330228692Sdes else 331228692Sdes mkdir_mode= 332228692Sdes fi 333117610Sdes 334228692Sdes posix_mkdir=false 335228692Sdes case $umask in 336228692Sdes *[123567][0-7][0-7]) 337228692Sdes # POSIX mkdir -p sets u+wx bits regardless of umask, which 338228692Sdes # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 339228692Sdes ;; 340228692Sdes *) 341228692Sdes tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 342228692Sdes trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 343117610Sdes 344228692Sdes if (umask $mkdir_umask && 345228692Sdes exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 346228692Sdes then 347228692Sdes if test -z "$dir_arg" || { 348228692Sdes # Check for POSIX incompatibilities with -m. 349228692Sdes # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 350228692Sdes # other-writeable bit of parent directory when it shouldn't. 351228692Sdes # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 352228692Sdes ls_ld_tmpdir=`ls -ld "$tmpdir"` 353228692Sdes case $ls_ld_tmpdir in 354228692Sdes d????-?r-*) different_mode=700;; 355228692Sdes d????-?--*) different_mode=755;; 356228692Sdes *) false;; 357228692Sdes esac && 358228692Sdes $mkdirprog -m$different_mode -p -- "$tmpdir" && { 359228692Sdes ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 360228692Sdes test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 361228692Sdes } 362228692Sdes } 363228692Sdes then posix_mkdir=: 364228692Sdes fi 365228692Sdes rmdir "$tmpdir/d" "$tmpdir" 366228692Sdes else 367228692Sdes # Remove any dirs left behind by ancient mkdir implementations. 368228692Sdes rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 369228692Sdes fi 370228692Sdes trap '' 0;; 371228692Sdes esac;; 372228692Sdes esac 373228692Sdes 374228692Sdes if 375228692Sdes $posix_mkdir && ( 376228692Sdes umask $mkdir_umask && 377228692Sdes $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 378228692Sdes ) 379228692Sdes then : 380228692Sdes else 381228692Sdes 382228692Sdes # The umask is ridiculous, or mkdir does not conform to POSIX, 383228692Sdes # or it failed possibly due to a race condition. Create the 384228692Sdes # directory the slow way, step by step, checking for races as we go. 385228692Sdes 386228692Sdes case $dstdir in 387228692Sdes /*) prefix='/';; 388228692Sdes -*) prefix='./';; 389228692Sdes *) prefix='';; 390228692Sdes esac 391228692Sdes 392228692Sdes eval "$initialize_posix_glob" 393228692Sdes 394228692Sdes oIFS=$IFS 395228692Sdes IFS=/ 396228692Sdes $posix_glob set -f 397228692Sdes set fnord $dstdir 398141098Sdes shift 399228692Sdes $posix_glob set +f 400228692Sdes IFS=$oIFS 401228692Sdes 402228692Sdes prefixes= 403228692Sdes 404228692Sdes for d 405228692Sdes do 406228692Sdes test -z "$d" && continue 407228692Sdes 408228692Sdes prefix=$prefix$d 409228692Sdes if test -d "$prefix"; then 410228692Sdes prefixes= 411228692Sdes else 412228692Sdes if $posix_mkdir; then 413228692Sdes (umask=$mkdir_umask && 414228692Sdes $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 415228692Sdes # Don't fail if two instances are running concurrently. 416228692Sdes test -d "$prefix" || exit 1 417228692Sdes else 418228692Sdes case $prefix in 419228692Sdes *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 420228692Sdes *) qprefix=$prefix;; 421228692Sdes esac 422228692Sdes prefixes="$prefixes '$qprefix'" 423228692Sdes fi 424228692Sdes fi 425228692Sdes prefix=$prefix/ 426228692Sdes done 427228692Sdes 428228692Sdes if test -n "$prefixes"; then 429228692Sdes # Don't fail if two instances are running concurrently. 430228692Sdes (umask $mkdir_umask && 431228692Sdes eval "\$doit_exec \$mkdirprog $prefixes") || 432228692Sdes test -d "$dstdir" || exit 1 433228692Sdes obsolete_mkdir_used=true 434141098Sdes fi 435228692Sdes fi 436141098Sdes fi 437117610Sdes 438141098Sdes if test -n "$dir_arg"; then 439228692Sdes { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 440228692Sdes { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 441228692Sdes { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 442228692Sdes test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 443141098Sdes else 444117610Sdes 445141098Sdes # Make a couple of temp file names in the proper directory. 446141098Sdes dsttmp=$dstdir/_inst.$$_ 447141098Sdes rmtmp=$dstdir/_rm.$$_ 448117610Sdes 449141098Sdes # Trap to clean up those temp files at exit. 450174832Sdes trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 451117610Sdes 452174832Sdes # Copy the file name to the temp name. 453228692Sdes (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 454117610Sdes 455141098Sdes # and set any options; do chmod last to preserve setuid bits. 456141098Sdes # 457141098Sdes # If any of these fail, we abort the whole thing. If we want to 458141098Sdes # ignore errors from any of these, just make sure not to ignore 459174832Sdes # errors from the above "$doit $cpprog $src $dsttmp" command. 460141098Sdes # 461228692Sdes { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 462228692Sdes { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 463228692Sdes { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 464228692Sdes { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 465117610Sdes 466228692Sdes # If -C, don't bother to copy if it wouldn't change the file. 467228692Sdes if $copy_on_change && 468228692Sdes old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 469228692Sdes new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 470117610Sdes 471228692Sdes eval "$initialize_posix_glob" && 472228692Sdes $posix_glob set -f && 473228692Sdes set X $old && old=:$2:$4:$5:$6 && 474228692Sdes set X $new && new=:$2:$4:$5:$6 && 475228692Sdes $posix_glob set +f && 476117610Sdes 477228692Sdes test "$old" = "$new" && 478228692Sdes $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 479228692Sdes then 480228692Sdes rm -f "$dsttmp" 481228692Sdes else 482228692Sdes # Rename the file to the real destination. 483228692Sdes $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 484228692Sdes 485228692Sdes # The rename failed, perhaps because mv can't rename something else 486228692Sdes # to itself, or perhaps because mv is so ancient that it does not 487228692Sdes # support -f. 488228692Sdes { 489228692Sdes # Now remove or move aside any old file at destination location. 490228692Sdes # We try this two ways since rm can't unlink itself on some 491228692Sdes # systems and the destination file might be busy for other 492228692Sdes # reasons. In this case, the final cleanup might fail but the new 493228692Sdes # file should still install successfully. 494228692Sdes { 495228692Sdes test ! -f "$dst" || 496228692Sdes $doit $rmcmd -f "$dst" 2>/dev/null || 497228692Sdes { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 498228692Sdes { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 499228692Sdes } || 500228692Sdes { echo "$0: cannot unlink or rename $dst" >&2 501228692Sdes (exit 1); exit 1 502228692Sdes } 503228692Sdes } && 504228692Sdes 505228692Sdes # Now rename the file to the real destination. 506228692Sdes $doit $mvcmd "$dsttmp" "$dst" 507228692Sdes } 508228692Sdes fi || exit 1 509228692Sdes 510228692Sdes trap '' 0 511228692Sdes fi 512141098Sdesdone 513117610Sdes 514141098Sdes# Local variables: 515141098Sdes# eval: (add-hook 'write-file-hooks 'time-stamp) 516141098Sdes# time-stamp-start: "scriptversion=" 517141098Sdes# time-stamp-format: "%:y-%02m-%02d.%02H" 518228692Sdes# time-stamp-time-zone: "UTC" 519228692Sdes# time-stamp-end: "; # UTC" 520141098Sdes# End: 521