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