install-sh 15 KB

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