install-sh revision af9a7ee5
1caade7ccSmrg#!/bin/sh 2caade7ccSmrg# install - install a program, script, or datafile 3caade7ccSmrg 4af9a7ee5Smrgscriptversion=2011-11-20.07; # UTC 5caade7ccSmrg 6caade7ccSmrg# This originates from X11R5 (mit/util/scripts/install.sh), which was 7caade7ccSmrg# later released in X11R6 (xc/config/util/install.sh) with the 8caade7ccSmrg# following copyright and license. 9caade7ccSmrg# 10caade7ccSmrg# Copyright (C) 1994 X Consortium 11caade7ccSmrg# 12caade7ccSmrg# Permission is hereby granted, free of charge, to any person obtaining a copy 13caade7ccSmrg# of this software and associated documentation files (the "Software"), to 14caade7ccSmrg# deal in the Software without restriction, including without limitation the 15caade7ccSmrg# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16caade7ccSmrg# sell copies of the Software, and to permit persons to whom the Software is 17caade7ccSmrg# furnished to do so, subject to the following conditions: 18caade7ccSmrg# 19caade7ccSmrg# The above copyright notice and this permission notice shall be included in 20caade7ccSmrg# all copies or substantial portions of the Software. 21caade7ccSmrg# 22caade7ccSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23caade7ccSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24caade7ccSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25caade7ccSmrg# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26caade7ccSmrg# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27caade7ccSmrg# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28caade7ccSmrg# 29caade7ccSmrg# Except as contained in this notice, the name of the X Consortium shall not 30caade7ccSmrg# be used in advertising or otherwise to promote the sale, use or other deal- 31caade7ccSmrg# ings in this Software without prior written authorization from the X Consor- 32caade7ccSmrg# tium. 33caade7ccSmrg# 34caade7ccSmrg# 35caade7ccSmrg# FSF changes to this file are in the public domain. 36caade7ccSmrg# 37caade7ccSmrg# Calling this script install-sh is preferred over install.sh, to prevent 38af9a7ee5Smrg# 'make' implicit rules from creating a file called install from it 39caade7ccSmrg# when there is no Makefile. 40caade7ccSmrg# 41caade7ccSmrg# This script is compatible with the BSD install script, but was written 42caade7ccSmrg# from scratch. 43caade7ccSmrg 44caade7ccSmrgnl=' 45caade7ccSmrg' 46caade7ccSmrgIFS=" "" $nl" 47caade7ccSmrg 48caade7ccSmrg# set DOITPROG to echo to test this script 49caade7ccSmrg 50caade7ccSmrg# Don't use :- since 4.3BSD and earlier shells don't like it. 51485f0483Smrgdoit=${DOITPROG-} 52caade7ccSmrgif test -z "$doit"; then 53caade7ccSmrg doit_exec=exec 54caade7ccSmrgelse 55caade7ccSmrg doit_exec=$doit 56caade7ccSmrgfi 57caade7ccSmrg 58caade7ccSmrg# Put in absolute file names if you don't have them in your path; 59caade7ccSmrg# or use environment vars. 60caade7ccSmrg 61485f0483Smrgchgrpprog=${CHGRPPROG-chgrp} 62485f0483Smrgchmodprog=${CHMODPROG-chmod} 63485f0483Smrgchownprog=${CHOWNPROG-chown} 64485f0483Smrgcmpprog=${CMPPROG-cmp} 65485f0483Smrgcpprog=${CPPROG-cp} 66485f0483Smrgmkdirprog=${MKDIRPROG-mkdir} 67485f0483Smrgmvprog=${MVPROG-mv} 68485f0483Smrgrmprog=${RMPROG-rm} 69485f0483Smrgstripprog=${STRIPPROG-strip} 70485f0483Smrg 71485f0483Smrgposix_glob='?' 72485f0483Smrginitialize_posix_glob=' 73485f0483Smrg test "$posix_glob" != "?" || { 74485f0483Smrg if (set -f) 2>/dev/null; then 75485f0483Smrg posix_glob= 76485f0483Smrg else 77485f0483Smrg posix_glob=: 78485f0483Smrg fi 79485f0483Smrg } 80485f0483Smrg' 81caade7ccSmrg 82caade7ccSmrgposix_mkdir= 83caade7ccSmrg 84caade7ccSmrg# Desired mode of installed file. 85caade7ccSmrgmode=0755 86caade7ccSmrg 87485f0483Smrgchgrpcmd= 88caade7ccSmrgchmodcmd=$chmodprog 89caade7ccSmrgchowncmd= 90485f0483Smrgmvcmd=$mvprog 91caade7ccSmrgrmcmd="$rmprog -f" 92485f0483Smrgstripcmd= 93485f0483Smrg 94caade7ccSmrgsrc= 95caade7ccSmrgdst= 96caade7ccSmrgdir_arg= 97485f0483Smrgdst_arg= 98485f0483Smrg 99485f0483Smrgcopy_on_change=false 100caade7ccSmrgno_target_directory= 101caade7ccSmrg 102485f0483Smrgusage="\ 103485f0483SmrgUsage: $0 [OPTION]... [-T] SRCFILE DSTFILE 104caade7ccSmrg or: $0 [OPTION]... SRCFILES... DIRECTORY 105caade7ccSmrg or: $0 [OPTION]... -t DIRECTORY SRCFILES... 106caade7ccSmrg or: $0 [OPTION]... -d DIRECTORIES... 107caade7ccSmrg 108caade7ccSmrgIn the 1st form, copy SRCFILE to DSTFILE. 109caade7ccSmrgIn the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 110caade7ccSmrgIn the 4th, create DIRECTORIES. 111caade7ccSmrg 112caade7ccSmrgOptions: 113485f0483Smrg --help display this help and exit. 114485f0483Smrg --version display version info and exit. 115485f0483Smrg 116485f0483Smrg -c (ignored) 117485f0483Smrg -C install only if different (preserve the last data modification time) 118485f0483Smrg -d create directories instead of installing files. 119485f0483Smrg -g GROUP $chgrpprog installed files to GROUP. 120485f0483Smrg -m MODE $chmodprog installed files to MODE. 121485f0483Smrg -o USER $chownprog installed files to USER. 122485f0483Smrg -s $stripprog installed files. 123485f0483Smrg -t DIRECTORY install into DIRECTORY. 124485f0483Smrg -T report an error if DSTFILE is a directory. 125caade7ccSmrg 126caade7ccSmrgEnvironment variables override the default commands: 127485f0483Smrg CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG 128485f0483Smrg RMPROG STRIPPROG 129caade7ccSmrg" 130caade7ccSmrg 131caade7ccSmrgwhile test $# -ne 0; do 132caade7ccSmrg case $1 in 133485f0483Smrg -c) ;; 134485f0483Smrg 135485f0483Smrg -C) copy_on_change=true;; 136caade7ccSmrg 137485f0483Smrg -d) dir_arg=true;; 138caade7ccSmrg 139caade7ccSmrg -g) chgrpcmd="$chgrpprog $2" 140485f0483Smrg shift;; 141caade7ccSmrg 142caade7ccSmrg --help) echo "$usage"; exit $?;; 143caade7ccSmrg 144caade7ccSmrg -m) mode=$2 145caade7ccSmrg case $mode in 146caade7ccSmrg *' '* | *' '* | *' 147caade7ccSmrg'* | *'*'* | *'?'* | *'['*) 148caade7ccSmrg echo "$0: invalid mode: $mode" >&2 149caade7ccSmrg exit 1;; 150caade7ccSmrg esac 151485f0483Smrg shift;; 152caade7ccSmrg 153caade7ccSmrg -o) chowncmd="$chownprog $2" 154485f0483Smrg shift;; 155caade7ccSmrg 156485f0483Smrg -s) stripcmd=$stripprog;; 157caade7ccSmrg 158485f0483Smrg -t) dst_arg=$2 159af9a7ee5Smrg # Protect names problematic for 'test' and other utilities. 160af9a7ee5Smrg case $dst_arg in 161af9a7ee5Smrg -* | [=\(\)!]) dst_arg=./$dst_arg;; 162af9a7ee5Smrg esac 163485f0483Smrg shift;; 164caade7ccSmrg 165485f0483Smrg -T) no_target_directory=true;; 166caade7ccSmrg 167caade7ccSmrg --version) echo "$0 $scriptversion"; exit $?;; 168caade7ccSmrg 169caade7ccSmrg --) shift 170caade7ccSmrg break;; 171caade7ccSmrg 172caade7ccSmrg -*) echo "$0: invalid option: $1" >&2 173caade7ccSmrg exit 1;; 174caade7ccSmrg 175caade7ccSmrg *) break;; 176caade7ccSmrg esac 177485f0483Smrg shift 178caade7ccSmrgdone 179caade7ccSmrg 180485f0483Smrgif test $# -ne 0 && test -z "$dir_arg$dst_arg"; then 181caade7ccSmrg # When -d is used, all remaining arguments are directories to create. 182caade7ccSmrg # When -t is used, the destination is already specified. 183caade7ccSmrg # Otherwise, the last argument is the destination. Remove it from $@. 184caade7ccSmrg for arg 185caade7ccSmrg do 186485f0483Smrg if test -n "$dst_arg"; then 187caade7ccSmrg # $@ is not empty: it contains at least $arg. 188485f0483Smrg set fnord "$@" "$dst_arg" 189caade7ccSmrg shift # fnord 190caade7ccSmrg fi 191caade7ccSmrg shift # arg 192485f0483Smrg dst_arg=$arg 193af9a7ee5Smrg # Protect names problematic for 'test' and other utilities. 194af9a7ee5Smrg case $dst_arg in 195af9a7ee5Smrg -* | [=\(\)!]) dst_arg=./$dst_arg;; 196af9a7ee5Smrg esac 197caade7ccSmrg done 198caade7ccSmrgfi 199caade7ccSmrg 200caade7ccSmrgif test $# -eq 0; then 201caade7ccSmrg if test -z "$dir_arg"; then 202caade7ccSmrg echo "$0: no input file specified." >&2 203caade7ccSmrg exit 1 204caade7ccSmrg fi 205af9a7ee5Smrg # It's OK to call 'install-sh -d' without argument. 206caade7ccSmrg # This can happen when creating conditional directories. 207caade7ccSmrg exit 0 208caade7ccSmrgfi 209caade7ccSmrg 210caade7ccSmrgif test -z "$dir_arg"; then 211af9a7ee5Smrg do_exit='(exit $ret); exit $ret' 212af9a7ee5Smrg trap "ret=129; $do_exit" 1 213af9a7ee5Smrg trap "ret=130; $do_exit" 2 214af9a7ee5Smrg trap "ret=141; $do_exit" 13 215af9a7ee5Smrg trap "ret=143; $do_exit" 15 216caade7ccSmrg 217caade7ccSmrg # Set umask so as not to create temps with too-generous modes. 218caade7ccSmrg # However, 'strip' requires both read and write access to temps. 219caade7ccSmrg case $mode in 220caade7ccSmrg # Optimize common cases. 221caade7ccSmrg *644) cp_umask=133;; 222caade7ccSmrg *755) cp_umask=22;; 223caade7ccSmrg 224caade7ccSmrg *[0-7]) 225caade7ccSmrg if test -z "$stripcmd"; then 226caade7ccSmrg u_plus_rw= 227caade7ccSmrg else 228caade7ccSmrg u_plus_rw='% 200' 229caade7ccSmrg fi 230caade7ccSmrg cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 231caade7ccSmrg *) 232caade7ccSmrg if test -z "$stripcmd"; then 233caade7ccSmrg u_plus_rw= 234caade7ccSmrg else 235caade7ccSmrg u_plus_rw=,u+rw 236caade7ccSmrg fi 237caade7ccSmrg cp_umask=$mode$u_plus_rw;; 238caade7ccSmrg esac 239caade7ccSmrgfi 240caade7ccSmrg 241caade7ccSmrgfor src 242caade7ccSmrgdo 243af9a7ee5Smrg # Protect names problematic for 'test' and other utilities. 244caade7ccSmrg case $src in 245af9a7ee5Smrg -* | [=\(\)!]) src=./$src;; 246caade7ccSmrg esac 247caade7ccSmrg 248caade7ccSmrg if test -n "$dir_arg"; then 249caade7ccSmrg dst=$src 250caade7ccSmrg dstdir=$dst 251caade7ccSmrg test -d "$dstdir" 252caade7ccSmrg dstdir_status=$? 253caade7ccSmrg else 254caade7ccSmrg 255caade7ccSmrg # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 256caade7ccSmrg # might cause directories to be created, which would be especially bad 257caade7ccSmrg # if $src (and thus $dsttmp) contains '*'. 258caade7ccSmrg if test ! -f "$src" && test ! -d "$src"; then 259caade7ccSmrg echo "$0: $src does not exist." >&2 260caade7ccSmrg exit 1 261caade7ccSmrg fi 262caade7ccSmrg 263485f0483Smrg if test -z "$dst_arg"; then 264caade7ccSmrg echo "$0: no destination specified." >&2 265caade7ccSmrg exit 1 266caade7ccSmrg fi 267485f0483Smrg dst=$dst_arg 268caade7ccSmrg 269caade7ccSmrg # If destination is a directory, append the input filename; won't work 270caade7ccSmrg # if double slashes aren't ignored. 271caade7ccSmrg if test -d "$dst"; then 272caade7ccSmrg if test -n "$no_target_directory"; then 273485f0483Smrg echo "$0: $dst_arg: Is a directory" >&2 274caade7ccSmrg exit 1 275caade7ccSmrg fi 276caade7ccSmrg dstdir=$dst 277caade7ccSmrg dst=$dstdir/`basename "$src"` 278caade7ccSmrg dstdir_status=0 279caade7ccSmrg else 280caade7ccSmrg # Prefer dirname, but fall back on a substitute if dirname fails. 281caade7ccSmrg dstdir=` 282caade7ccSmrg (dirname "$dst") 2>/dev/null || 283caade7ccSmrg expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 284caade7ccSmrg X"$dst" : 'X\(//\)[^/]' \| \ 285caade7ccSmrg X"$dst" : 'X\(//\)$' \| \ 286caade7ccSmrg X"$dst" : 'X\(/\)' \| . 2>/dev/null || 287caade7ccSmrg echo X"$dst" | 288caade7ccSmrg sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 289caade7ccSmrg s//\1/ 290caade7ccSmrg q 291caade7ccSmrg } 292caade7ccSmrg /^X\(\/\/\)[^/].*/{ 293caade7ccSmrg s//\1/ 294caade7ccSmrg q 295caade7ccSmrg } 296caade7ccSmrg /^X\(\/\/\)$/{ 297caade7ccSmrg s//\1/ 298caade7ccSmrg q 299caade7ccSmrg } 300caade7ccSmrg /^X\(\/\).*/{ 301caade7ccSmrg s//\1/ 302caade7ccSmrg q 303caade7ccSmrg } 304caade7ccSmrg s/.*/./; q' 305caade7ccSmrg ` 306caade7ccSmrg 307caade7ccSmrg test -d "$dstdir" 308caade7ccSmrg dstdir_status=$? 309caade7ccSmrg fi 310caade7ccSmrg fi 311caade7ccSmrg 312caade7ccSmrg obsolete_mkdir_used=false 313caade7ccSmrg 314caade7ccSmrg if test $dstdir_status != 0; then 315caade7ccSmrg case $posix_mkdir in 316caade7ccSmrg '') 317caade7ccSmrg # Create intermediate dirs using mode 755 as modified by the umask. 318caade7ccSmrg # This is like FreeBSD 'install' as of 1997-10-28. 319caade7ccSmrg umask=`umask` 320caade7ccSmrg case $stripcmd.$umask in 321caade7ccSmrg # Optimize common cases. 322caade7ccSmrg *[2367][2367]) mkdir_umask=$umask;; 323caade7ccSmrg .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 324caade7ccSmrg 325caade7ccSmrg *[0-7]) 326caade7ccSmrg mkdir_umask=`expr $umask + 22 \ 327caade7ccSmrg - $umask % 100 % 40 + $umask % 20 \ 328caade7ccSmrg - $umask % 10 % 4 + $umask % 2 329caade7ccSmrg `;; 330caade7ccSmrg *) mkdir_umask=$umask,go-w;; 331caade7ccSmrg esac 332caade7ccSmrg 333caade7ccSmrg # With -d, create the new directory with the user-specified mode. 334caade7ccSmrg # Otherwise, rely on $mkdir_umask. 335caade7ccSmrg if test -n "$dir_arg"; then 336caade7ccSmrg mkdir_mode=-m$mode 337caade7ccSmrg else 338caade7ccSmrg mkdir_mode= 339caade7ccSmrg fi 340caade7ccSmrg 341caade7ccSmrg posix_mkdir=false 342caade7ccSmrg case $umask in 343caade7ccSmrg *[123567][0-7][0-7]) 344caade7ccSmrg # POSIX mkdir -p sets u+wx bits regardless of umask, which 345caade7ccSmrg # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 346caade7ccSmrg ;; 347caade7ccSmrg *) 348caade7ccSmrg tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 349caade7ccSmrg trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 350caade7ccSmrg 351caade7ccSmrg if (umask $mkdir_umask && 352caade7ccSmrg exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 353caade7ccSmrg then 354caade7ccSmrg if test -z "$dir_arg" || { 355caade7ccSmrg # Check for POSIX incompatibilities with -m. 356caade7ccSmrg # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 357af9a7ee5Smrg # other-writable bit of parent directory when it shouldn't. 358caade7ccSmrg # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 359caade7ccSmrg ls_ld_tmpdir=`ls -ld "$tmpdir"` 360caade7ccSmrg case $ls_ld_tmpdir in 361caade7ccSmrg d????-?r-*) different_mode=700;; 362caade7ccSmrg d????-?--*) different_mode=755;; 363caade7ccSmrg *) false;; 364caade7ccSmrg esac && 365caade7ccSmrg $mkdirprog -m$different_mode -p -- "$tmpdir" && { 366caade7ccSmrg ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 367caade7ccSmrg test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 368caade7ccSmrg } 369caade7ccSmrg } 370caade7ccSmrg then posix_mkdir=: 371caade7ccSmrg fi 372caade7ccSmrg rmdir "$tmpdir/d" "$tmpdir" 373caade7ccSmrg else 374caade7ccSmrg # Remove any dirs left behind by ancient mkdir implementations. 375caade7ccSmrg rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 376caade7ccSmrg fi 377caade7ccSmrg trap '' 0;; 378caade7ccSmrg esac;; 379caade7ccSmrg esac 380caade7ccSmrg 381caade7ccSmrg if 382caade7ccSmrg $posix_mkdir && ( 383caade7ccSmrg umask $mkdir_umask && 384caade7ccSmrg $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 385caade7ccSmrg ) 386caade7ccSmrg then : 387caade7ccSmrg else 388caade7ccSmrg 389caade7ccSmrg # The umask is ridiculous, or mkdir does not conform to POSIX, 390caade7ccSmrg # or it failed possibly due to a race condition. Create the 391caade7ccSmrg # directory the slow way, step by step, checking for races as we go. 392caade7ccSmrg 393caade7ccSmrg case $dstdir in 394485f0483Smrg /*) prefix='/';; 395af9a7ee5Smrg [-=\(\)!]*) prefix='./';; 396485f0483Smrg *) prefix='';; 397caade7ccSmrg esac 398caade7ccSmrg 399485f0483Smrg eval "$initialize_posix_glob" 400caade7ccSmrg 401caade7ccSmrg oIFS=$IFS 402caade7ccSmrg IFS=/ 403485f0483Smrg $posix_glob set -f 404caade7ccSmrg set fnord $dstdir 405caade7ccSmrg shift 406485f0483Smrg $posix_glob set +f 407caade7ccSmrg IFS=$oIFS 408caade7ccSmrg 409caade7ccSmrg prefixes= 410caade7ccSmrg 411caade7ccSmrg for d 412caade7ccSmrg do 413af9a7ee5Smrg test X"$d" = X && continue 414caade7ccSmrg 415caade7ccSmrg prefix=$prefix$d 416caade7ccSmrg if test -d "$prefix"; then 417caade7ccSmrg prefixes= 418caade7ccSmrg else 419caade7ccSmrg if $posix_mkdir; then 420caade7ccSmrg (umask=$mkdir_umask && 421caade7ccSmrg $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 422caade7ccSmrg # Don't fail if two instances are running concurrently. 423caade7ccSmrg test -d "$prefix" || exit 1 424caade7ccSmrg else 425caade7ccSmrg case $prefix in 426caade7ccSmrg *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 427caade7ccSmrg *) qprefix=$prefix;; 428caade7ccSmrg esac 429caade7ccSmrg prefixes="$prefixes '$qprefix'" 430caade7ccSmrg fi 431caade7ccSmrg fi 432caade7ccSmrg prefix=$prefix/ 433caade7ccSmrg done 434caade7ccSmrg 435caade7ccSmrg if test -n "$prefixes"; then 436caade7ccSmrg # Don't fail if two instances are running concurrently. 437caade7ccSmrg (umask $mkdir_umask && 438caade7ccSmrg eval "\$doit_exec \$mkdirprog $prefixes") || 439caade7ccSmrg test -d "$dstdir" || exit 1 440caade7ccSmrg obsolete_mkdir_used=true 441caade7ccSmrg fi 442caade7ccSmrg fi 443caade7ccSmrg fi 444caade7ccSmrg 445caade7ccSmrg if test -n "$dir_arg"; then 446caade7ccSmrg { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 447caade7ccSmrg { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 448caade7ccSmrg { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 449caade7ccSmrg test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 450caade7ccSmrg else 451caade7ccSmrg 452caade7ccSmrg # Make a couple of temp file names in the proper directory. 453caade7ccSmrg dsttmp=$dstdir/_inst.$$_ 454caade7ccSmrg rmtmp=$dstdir/_rm.$$_ 455caade7ccSmrg 456caade7ccSmrg # Trap to clean up those temp files at exit. 457caade7ccSmrg trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 458caade7ccSmrg 459caade7ccSmrg # Copy the file name to the temp name. 460caade7ccSmrg (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 461caade7ccSmrg 462caade7ccSmrg # and set any options; do chmod last to preserve setuid bits. 463caade7ccSmrg # 464caade7ccSmrg # If any of these fail, we abort the whole thing. If we want to 465caade7ccSmrg # ignore errors from any of these, just make sure not to ignore 466caade7ccSmrg # errors from the above "$doit $cpprog $src $dsttmp" command. 467caade7ccSmrg # 468485f0483Smrg { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && 469485f0483Smrg { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && 470485f0483Smrg { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && 471485f0483Smrg { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 472485f0483Smrg 473485f0483Smrg # If -C, don't bother to copy if it wouldn't change the file. 474485f0483Smrg if $copy_on_change && 475485f0483Smrg old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && 476485f0483Smrg new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && 477485f0483Smrg 478485f0483Smrg eval "$initialize_posix_glob" && 479485f0483Smrg $posix_glob set -f && 480485f0483Smrg set X $old && old=:$2:$4:$5:$6 && 481485f0483Smrg set X $new && new=:$2:$4:$5:$6 && 482485f0483Smrg $posix_glob set +f && 483485f0483Smrg 484485f0483Smrg test "$old" = "$new" && 485485f0483Smrg $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 486485f0483Smrg then 487485f0483Smrg rm -f "$dsttmp" 488485f0483Smrg else 489485f0483Smrg # Rename the file to the real destination. 490485f0483Smrg $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || 491485f0483Smrg 492485f0483Smrg # The rename failed, perhaps because mv can't rename something else 493485f0483Smrg # to itself, or perhaps because mv is so ancient that it does not 494485f0483Smrg # support -f. 495485f0483Smrg { 496485f0483Smrg # Now remove or move aside any old file at destination location. 497485f0483Smrg # We try this two ways since rm can't unlink itself on some 498485f0483Smrg # systems and the destination file might be busy for other 499485f0483Smrg # reasons. In this case, the final cleanup might fail but the new 500485f0483Smrg # file should still install successfully. 501485f0483Smrg { 502485f0483Smrg test ! -f "$dst" || 503485f0483Smrg $doit $rmcmd -f "$dst" 2>/dev/null || 504485f0483Smrg { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && 505485f0483Smrg { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } 506485f0483Smrg } || 507485f0483Smrg { echo "$0: cannot unlink or rename $dst" >&2 508485f0483Smrg (exit 1); exit 1 509485f0483Smrg } 510485f0483Smrg } && 511485f0483Smrg 512485f0483Smrg # Now rename the file to the real destination. 513485f0483Smrg $doit $mvcmd "$dsttmp" "$dst" 514485f0483Smrg } 515485f0483Smrg fi || exit 1 516caade7ccSmrg 517caade7ccSmrg trap '' 0 518caade7ccSmrg fi 519caade7ccSmrgdone 520caade7ccSmrg 521caade7ccSmrg# Local variables: 522caade7ccSmrg# eval: (add-hook 'write-file-hooks 'time-stamp) 523caade7ccSmrg# time-stamp-start: "scriptversion=" 524caade7ccSmrg# time-stamp-format: "%:y-%02m-%02d.%02H" 525485f0483Smrg# time-stamp-time-zone: "UTC" 526485f0483Smrg# time-stamp-end: "; # UTC" 527caade7ccSmrg# End: 528