github的一些开源项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
15 KiB

  1. #!/bin/sh
  2. # install - install a program, script, or datafile
  3. scriptversion=2020-11-14.01; # 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. # Create dirs (including intermediate dirs) using mode 755.
  63. # This is like GNU 'install' as of coreutils 8.32 (2020).
  64. mkdir_umask=22
  65. backupsuffix=
  66. chgrpcmd=
  67. chmodcmd=$chmodprog
  68. chowncmd=
  69. mvcmd=$mvprog
  70. rmcmd="$rmprog -f"
  71. stripcmd=
  72. src=
  73. dst=
  74. dir_arg=
  75. dst_arg=
  76. copy_on_change=false
  77. is_target_a_directory=possibly
  78. usage="\
  79. Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
  80. or: $0 [OPTION]... SRCFILES... DIRECTORY
  81. or: $0 [OPTION]... -t DIRECTORY SRCFILES...
  82. or: $0 [OPTION]... -d DIRECTORIES...
  83. In the 1st form, copy SRCFILE to DSTFILE.
  84. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
  85. In the 4th, create DIRECTORIES.
  86. Options:
  87. --help display this help and exit.
  88. --version display version info and exit.
  89. -c (ignored)
  90. -C install only if different (preserve data modification time)
  91. -d create directories instead of installing files.
  92. -g GROUP $chgrpprog installed files to GROUP.
  93. -m MODE $chmodprog installed files to MODE.
  94. -o USER $chownprog installed files to USER.
  95. -p pass -p to $cpprog.
  96. -s $stripprog installed files.
  97. -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
  98. -t DIRECTORY install into DIRECTORY.
  99. -T report an error if DSTFILE is a directory.
  100. Environment variables override the default commands:
  101. CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
  102. RMPROG STRIPPROG
  103. By default, rm is invoked with -f; when overridden with RMPROG,
  104. it's up to you to specify -f if you want it.
  105. If -S is not specified, no backups are attempted.
  106. Email bug reports to bug-automake@gnu.org.
  107. Automake home page: https://www.gnu.org/software/automake/
  108. "
  109. while test $# -ne 0; do
  110. case $1 in
  111. -c) ;;
  112. -C) copy_on_change=true;;
  113. -d) dir_arg=true;;
  114. -g) chgrpcmd="$chgrpprog $2"
  115. shift;;
  116. --help) echo "$usage"; exit $?;;
  117. -m) mode=$2
  118. case $mode in
  119. *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
  120. echo "$0: invalid mode: $mode" >&2
  121. exit 1;;
  122. esac
  123. shift;;
  124. -o) chowncmd="$chownprog $2"
  125. shift;;
  126. -p) cpprog="$cpprog -p";;
  127. -s) stripcmd=$stripprog;;
  128. -S) backupsuffix="$2"
  129. shift;;
  130. -t)
  131. is_target_a_directory=always
  132. dst_arg=$2
  133. # Protect names problematic for 'test' and other utilities.
  134. case $dst_arg in
  135. -* | [=\(\)!]) dst_arg=./$dst_arg;;
  136. esac
  137. shift;;
  138. -T) is_target_a_directory=never;;
  139. --version) echo "$0 $scriptversion"; exit $?;;
  140. --) shift
  141. break;;
  142. -*) echo "$0: invalid option: $1" >&2
  143. exit 1;;
  144. *) break;;
  145. esac
  146. shift
  147. done
  148. # We allow the use of options -d and -T together, by making -d
  149. # take the precedence; this is for compatibility with GNU install.
  150. if test -n "$dir_arg"; then
  151. if test -n "$dst_arg"; then
  152. echo "$0: target directory not allowed when installing a directory." >&2
  153. exit 1
  154. fi
  155. fi
  156. if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
  157. # When -d is used, all remaining arguments are directories to create.
  158. # When -t is used, the destination is already specified.
  159. # Otherwise, the last argument is the destination. Remove it from $@.
  160. for arg
  161. do
  162. if test -n "$dst_arg"; then
  163. # $@ is not empty: it contains at least $arg.
  164. set fnord "$@" "$dst_arg"
  165. shift # fnord
  166. fi
  167. shift # arg
  168. dst_arg=$arg
  169. # Protect names problematic for 'test' and other utilities.
  170. case $dst_arg in
  171. -* | [=\(\)!]) dst_arg=./$dst_arg;;
  172. esac
  173. done
  174. fi
  175. if test $# -eq 0; then
  176. if test -z "$dir_arg"; then
  177. echo "$0: no input file specified." >&2
  178. exit 1
  179. fi
  180. # It's OK to call 'install-sh -d' without argument.
  181. # This can happen when creating conditional directories.
  182. exit 0
  183. fi
  184. if test -z "$dir_arg"; then
  185. if test $# -gt 1 || test "$is_target_a_directory" = always; then
  186. if test ! -d "$dst_arg"; then
  187. echo "$0: $dst_arg: Is not a directory." >&2
  188. exit 1
  189. fi
  190. fi
  191. fi
  192. if test -z "$dir_arg"; then
  193. do_exit='(exit $ret); exit $ret'
  194. trap "ret=129; $do_exit" 1
  195. trap "ret=130; $do_exit" 2
  196. trap "ret=141; $do_exit" 13
  197. trap "ret=143; $do_exit" 15
  198. # Set umask so as not to create temps with too-generous modes.
  199. # However, 'strip' requires both read and write access to temps.
  200. case $mode in
  201. # Optimize common cases.
  202. *644) cp_umask=133;;
  203. *755) cp_umask=22;;
  204. *[0-7])
  205. if test -z "$stripcmd"; then
  206. u_plus_rw=
  207. else
  208. u_plus_rw='% 200'
  209. fi
  210. cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
  211. *)
  212. if test -z "$stripcmd"; then
  213. u_plus_rw=
  214. else
  215. u_plus_rw=,u+rw
  216. fi
  217. cp_umask=$mode$u_plus_rw;;
  218. esac
  219. fi
  220. for src
  221. do
  222. # Protect names problematic for 'test' and other utilities.
  223. case $src in
  224. -* | [=\(\)!]) src=./$src;;
  225. esac
  226. if test -n "$dir_arg"; then
  227. dst=$src
  228. dstdir=$dst
  229. test -d "$dstdir"
  230. dstdir_status=$?
  231. # Don't chown directories that already exist.
  232. if test $dstdir_status = 0; then
  233. chowncmd=""
  234. fi
  235. else
  236. # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
  237. # might cause directories to be created, which would be especially bad
  238. # if $src (and thus $dsttmp) contains '*'.
  239. if test ! -f "$src" && test ! -d "$src"; then
  240. echo "$0: $src does not exist." >&2
  241. exit 1
  242. fi
  243. if test -z "$dst_arg"; then
  244. echo "$0: no destination specified." >&2
  245. exit 1
  246. fi
  247. dst=$dst_arg
  248. # If destination is a directory, append the input filename.
  249. if test -d "$dst"; then
  250. if test "$is_target_a_directory" = never; then
  251. echo "$0: $dst_arg: Is a directory" >&2
  252. exit 1
  253. fi
  254. dstdir=$dst
  255. dstbase=`basename "$src"`
  256. case $dst in
  257. */) dst=$dst$dstbase;;
  258. *) dst=$dst/$dstbase;;
  259. esac
  260. dstdir_status=0
  261. else
  262. dstdir=`dirname "$dst"`
  263. test -d "$dstdir"
  264. dstdir_status=$?
  265. fi
  266. fi
  267. case $dstdir in
  268. */) dstdirslash=$dstdir;;
  269. *) dstdirslash=$dstdir/;;
  270. esac
  271. obsolete_mkdir_used=false
  272. if test $dstdir_status != 0; then
  273. case $posix_mkdir in
  274. '')
  275. # With -d, create the new directory with the user-specified mode.
  276. # Otherwise, rely on $mkdir_umask.
  277. if test -n "$dir_arg"; then
  278. mkdir_mode=-m$mode
  279. else
  280. mkdir_mode=
  281. fi
  282. posix_mkdir=false
  283. # The $RANDOM variable is not portable (e.g., dash). Use it
  284. # here however when possible just to lower collision chance.
  285. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
  286. trap '
  287. ret=$?
  288. rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
  289. exit $ret
  290. ' 0
  291. # Because "mkdir -p" follows existing symlinks and we likely work
  292. # directly in world-writeable /tmp, make sure that the '$tmpdir'
  293. # directory is successfully created first before we actually test
  294. # 'mkdir -p'.
  295. if (umask $mkdir_umask &&
  296. $mkdirprog $mkdir_mode "$tmpdir" &&
  297. exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
  298. then
  299. if test -z "$dir_arg" || {
  300. # Check for POSIX incompatibilities with -m.
  301. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
  302. # other-writable bit of parent directory when it shouldn't.
  303. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
  304. test_tmpdir="$tmpdir/a"
  305. ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
  306. case $ls_ld_tmpdir in
  307. d????-?r-*) different_mode=700;;
  308. d????-?--*) different_mode=755;;
  309. *) false;;
  310. esac &&
  311. $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
  312. ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
  313. test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
  314. }
  315. }
  316. then posix_mkdir=:
  317. fi
  318. rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
  319. else
  320. # Remove any dirs left behind by ancient mkdir implementations.
  321. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
  322. fi
  323. trap '' 0;;
  324. esac
  325. if
  326. $posix_mkdir && (
  327. umask $mkdir_umask &&
  328. $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
  329. )
  330. then :
  331. else
  332. # mkdir does not conform to POSIX,
  333. # or it failed possibly due to a race condition. Create the
  334. # directory the slow way, step by step, checking for races as we go.
  335. case $dstdir in
  336. /*) prefix='/';;
  337. [-=\(\)!]*) prefix='./';;
  338. *) prefix='';;
  339. esac
  340. oIFS=$IFS
  341. IFS=/
  342. set -f
  343. set fnord $dstdir
  344. shift
  345. set +f
  346. IFS=$oIFS
  347. prefixes=
  348. for d
  349. do
  350. test X"$d" = X && continue
  351. prefix=$prefix$d
  352. if test -d "$prefix"; then
  353. prefixes=
  354. else
  355. if $posix_mkdir; then
  356. (umask $mkdir_umask &&
  357. $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
  358. # Don't fail if two instances are running concurrently.
  359. test -d "$prefix" || exit 1
  360. else
  361. case $prefix in
  362. *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
  363. *) qprefix=$prefix;;
  364. esac
  365. prefixes="$prefixes '$qprefix'"
  366. fi
  367. fi
  368. prefix=$prefix/
  369. done
  370. if test -n "$prefixes"; then
  371. # Don't fail if two instances are running concurrently.
  372. (umask $mkdir_umask &&
  373. eval "\$doit_exec \$mkdirprog $prefixes") ||
  374. test -d "$dstdir" || exit 1
  375. obsolete_mkdir_used=true
  376. fi
  377. fi
  378. fi
  379. if test -n "$dir_arg"; then
  380. { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
  381. { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
  382. { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
  383. test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
  384. else
  385. # Make a couple of temp file names in the proper directory.
  386. dsttmp=${dstdirslash}_inst.$$_
  387. rmtmp=${dstdirslash}_rm.$$_
  388. # Trap to clean up those temp files at exit.
  389. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
  390. # Copy the file name to the temp name.
  391. (umask $cp_umask &&
  392. { test -z "$stripcmd" || {
  393. # Create $dsttmp read-write so that cp doesn't create it read-only,
  394. # which would cause strip to fail.
  395. if test -z "$doit"; then
  396. : >"$dsttmp" # No need to fork-exec 'touch'.
  397. else
  398. $doit touch "$dsttmp"
  399. fi
  400. }
  401. } &&
  402. $doit_exec $cpprog "$src" "$dsttmp") &&
  403. # and set any options; do chmod last to preserve setuid bits.
  404. #
  405. # If any of these fail, we abort the whole thing. If we want to
  406. # ignore errors from any of these, just make sure not to ignore
  407. # errors from the above "$doit $cpprog $src $dsttmp" command.
  408. #
  409. { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
  410. { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
  411. { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
  412. { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
  413. # If -C, don't bother to copy if it wouldn't change the file.
  414. if $copy_on_change &&
  415. old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
  416. new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
  417. set -f &&
  418. set X $old && old=:$2:$4:$5:$6 &&
  419. set X $new && new=:$2:$4:$5:$6 &&
  420. set +f &&
  421. test "$old" = "$new" &&
  422. $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
  423. then
  424. rm -f "$dsttmp"
  425. else
  426. # If $backupsuffix is set, and the file being installed
  427. # already exists, attempt a backup. Don't worry if it fails,
  428. # e.g., if mv doesn't support -f.
  429. if test -n "$backupsuffix" && test -f "$dst"; then
  430. $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
  431. fi
  432. # Rename the file to the real destination.
  433. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
  434. # The rename failed, perhaps because mv can't rename something else
  435. # to itself, or perhaps because mv is so ancient that it does not
  436. # support -f.
  437. {
  438. # Now remove or move aside any old file at destination location.
  439. # We try this two ways since rm can't unlink itself on some
  440. # systems and the destination file might be busy for other
  441. # reasons. In this case, the final cleanup might fail but the new
  442. # file should still install successfully.
  443. {
  444. test ! -f "$dst" ||
  445. $doit $rmcmd "$dst" 2>/dev/null ||
  446. { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
  447. { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
  448. } ||
  449. { echo "$0: cannot unlink or rename $dst" >&2
  450. (exit 1); exit 1
  451. }
  452. } &&
  453. # Now rename the file to the real destination.
  454. $doit $mvcmd "$dsttmp" "$dst"
  455. }
  456. fi || exit 1
  457. trap '' 0
  458. fi
  459. done
  460. # Local variables:
  461. # eval: (add-hook 'before-save-hook 'time-stamp)
  462. # time-stamp-start: "scriptversion="
  463. # time-stamp-format: "%:y-%02m-%02d.%02H"
  464. # time-stamp-time-zone: "UTC0"
  465. # time-stamp-end: "; # UTC"
  466. # End: