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