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