command_fastdl.sh 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. #!/bin/bash
  2. # LinuxGSM command_fastdl.sh module
  3. # Author: Daniel Gibbs
  4. # Contributors: https://linuxgsm.com/contrib
  5. # Website: https://linuxgsm.com
  6. # Description: Creates a Fastdl directory.
  7. commandname="FASTDL"
  8. commandaction="Fastdl"
  9. moduleselfname="$(basename "$(readlink -f "${BASH_SOURCE[0]}")")"
  10. fn_firstcommand_set
  11. # Directories.
  12. if [ -z "${webdir}" ]; then
  13. webdir="${rootdir}/public_html"
  14. fi
  15. fastdldir="${webdir}/fastdl"
  16. addonsdir="${systemdir}/addons"
  17. # Server lua autorun dir, used to autorun lua on client connect to the server.
  18. luasvautorundir="${systemdir}/lua/autorun/server"
  19. luafastdlfile="lgsm_cl_force_fastdl.lua"
  20. luafastdlfullpath="${luasvautorundir}/${luafastdlfile}"
  21. # File lists.
  22. fastdlfilelist="${tmpdir}/fastdl_files.txt"
  23. fastdlduplicatelist="${tmpdir}/fastdl_files_duplicate.txt"
  24. fastdlnewrecord="${tmpdir}/fastdl_record.txt"
  25. fastdlrecord="${datadir}/${selfname}-fastdl.txt"
  26. fastdlclientlist="${tmpdir}/fastdl_files_client.txt"
  27. fastdlupdatelist="${tmpdir}/fastdl_files_to_update.txt"
  28. fastdlremovelist="${tmpdir}/fastdl_files_to_remove.txt"
  29. fastdlcompresslist="${tmpdir}/fastdl_files_to_compress.txt"
  30. fastdlmaxcompresssize="157286400"
  31. # Header
  32. fn_print_header
  33. fn_print_nl "More info: ${italic}https://docs.linuxgsm.com/commands/fastdl"
  34. fn_print_nl ""
  35. # Prompts user for Fastdl creation settings.
  36. fn_print_nl "${bold}${lightyellow}${commandaction} Setup"
  37. fn_messages_separator
  38. # Prompt for a full rebuild if directory was already here.
  39. fastdlrebuild="off"
  40. if [ -d "${fastdldir}" ]; then
  41. fn_print_info_nl "Fastdl directory already exists, only changed files will be updated."
  42. fn_print_nl "${fastdldir}"
  43. fn_print_nl ""
  44. if fn_prompt_yn "Rebuild Fastdl directory from scratch? This deletes everything in it." N; then
  45. fastdlrebuild="on"
  46. fn_script_log_info "Rebuild Fastdl directory from scratch: YES"
  47. else
  48. fn_script_log_info "Rebuild Fastdl directory from scratch: NO"
  49. fi
  50. fi
  51. # Garry's Mod Specific.
  52. if [ "${shortname}" == "gmod" ]; then
  53. # Prompt for download enforcer, which is using a .lua addfile resource generator.
  54. if fn_prompt_yn "Force clients to download files?" Y; then
  55. luaresource="on"
  56. fn_script_log_info "Force clients to download files: YES"
  57. else
  58. luaresource="off"
  59. fn_script_log_info "Force clients to download files: NO"
  60. fi
  61. fi
  62. # Clears any fastdl directory content.
  63. fn_clear_old_fastdl() {
  64. # Clearing old Fastdl.
  65. if [ -d "${fastdldir}" ]; then
  66. fn_print "clearing existing Fastdl directory ${fastdldir}"
  67. rm -rf "${fastdldir:?}"
  68. exitcode=$?
  69. if [ "${exitcode}" -ne 0 ]; then
  70. fn_print_fail_eol_nl
  71. fn_script_log_fail "Clearing existing Fastdl directory ${fastdldir}"
  72. core_exit.sh
  73. else
  74. fn_print_ok_eol_nl
  75. fn_script_log_pass "Clearing existing Fastdl directory ${fastdldir}"
  76. fi
  77. fi
  78. }
  79. fn_fastdl_dirs() {
  80. # Check and create directories.
  81. if [ ! -d "${webdir}" ]; then
  82. fn_print "creating web directory ${webdir}"
  83. mkdir -p "${webdir}"
  84. exitcode=$?
  85. if [ "${exitcode}" -ne 0 ]; then
  86. fn_print_fail_eol_nl
  87. fn_script_log_fail "Creating web directory ${webdir}"
  88. core_exit.sh
  89. else
  90. fn_print_ok_eol_nl
  91. fn_script_log_pass "Creating web directory ${webdir}"
  92. fi
  93. fi
  94. if [ ! -d "${fastdldir}" ]; then
  95. fn_print "creating fastdl directory ${fastdldir}"
  96. mkdir -p "${fastdldir}"
  97. exitcode=$?
  98. if [ "${exitcode}" -ne 0 ]; then
  99. fn_print_fail_eol_nl
  100. fn_script_log_fail "Creating fastdl directory ${fastdldir}"
  101. core_exit.sh
  102. else
  103. fn_print_ok_eol_nl
  104. fn_script_log_pass "Creating fastdl directory ${fastdldir}"
  105. fi
  106. fi
  107. }
  108. # Using this gist https://gist.github.com/agunnerson-ibm/efca449565a3e7356906
  109. fn_human_readable_file_size() {
  110. local abbrevs=(
  111. "1152921504606846976:ZB"
  112. "1125899906842624:EB"
  113. "1099511627776:TB"
  114. "1073741824:GB"
  115. "1048576:MB"
  116. "1024:KB"
  117. "1:bytes"
  118. )
  119. local bytes="${1}"
  120. local precision="${2}"
  121. if [[ "${bytes}" == "1" ]]; then
  122. fn_print_nl "1 byte"
  123. else
  124. for item in "${abbrevs[@]}"; do
  125. local factor="${item%:*}"
  126. local abbrev="${item#*:}"
  127. if [[ "${bytes}" -ge "${factor}" ]]; then
  128. size=$(bc -l <<< "${bytes} / ${factor}")
  129. printf "%.*f %s\n" "${precision}" "${size}" "${abbrev}"
  130. break
  131. fi
  132. done
  133. fi
  134. }
  135. # Sets the GoldSrc file types to include for the current directory.
  136. fn_fastdl_goldsrc_extensions() {
  137. fastdl_find_maxdepth=()
  138. if [ "${directory}" == "." ]; then
  139. allowed_extentions_array=("*.wad")
  140. fastdl_find_maxdepth=("-maxdepth" "1")
  141. elif [ "${directory}" == "maps" ]; then
  142. allowed_extentions_array=("*.bsp" "*.res" "*.txt")
  143. elif [ "${directory}" == "models" ]; then
  144. allowed_extentions_array=("*.mdl")
  145. elif [ "${directory}" == "sound" ]; then
  146. allowed_extentions_array=("*.wav")
  147. elif [ "${directory}" == "sprites" ]; then
  148. allowed_extentions_array=("*.spr" "*.txt")
  149. elif [ "${directory}" == "gfx" ]; then
  150. allowed_extentions_array=("*.tga" "*.bmp")
  151. elif [ "${directory}" == "overviews" ]; then
  152. allowed_extentions_array=("*.bmp" "*.tga" "*.txt")
  153. fi
  154. }
  155. # Sets the Source file types to include for the current directory.
  156. fn_fastdl_source_extensions() {
  157. fastdl_find_maxdepth=()
  158. if [ "${directory}" == "maps" ]; then
  159. allowed_extentions_array=("*.bsp" "*.ain" "*.nav" "*.jpg" "*.txt")
  160. elif [ "${directory}" == "materials" ]; then
  161. allowed_extentions_array=("*.vtf" "*.vmt" "*.vbf" "*.png" "*.svg")
  162. elif [ "${directory}" == "models" ]; then
  163. allowed_extentions_array=("*.vtx" "*.vvd" "*.mdl" "*.phy" "*.jpg" "*.png" "*.vmt" "*.vtf")
  164. elif [ "${directory}" == "particles" ]; then
  165. allowed_extentions_array=("*.pcf")
  166. elif [ "${directory}" == "sound" ]; then
  167. allowed_extentions_array=("*.wav" "*.mp3" "*.ogg")
  168. elif [ "${directory}" == "resource" ]; then
  169. allowed_extentions_array=("*")
  170. fi
  171. }
  172. # Adds the allowed files in a content directory to the file list.
  173. fn_fastdl_gather() {
  174. local basedir="${1}"
  175. local priority="${2}"
  176. local label="${directory}"
  177. if [ "${basedir}" != "${systemdir}" ]; then
  178. label="${basedir#"${systemdir}/"}/${directory}"
  179. fi
  180. for allowed_extention in "${allowed_extentions_array[@]}"; do
  181. fileswc=0
  182. if [ -z "${plainoutput}" ]; then
  183. tput sc
  184. fi
  185. while IFS=$'\t' read -r filesize filemtime fastdlfile; do
  186. ((fileswc++))
  187. if [ -z "${plainoutput}" ]; then
  188. tput rc
  189. tput el
  190. fn_print "gathering ${label} ${allowed_extention} : ${fileswc}"
  191. fi
  192. fastdlrelpath="${fastdlfile#"${basedir}/"}"
  193. printf '%s\t%s\t%s\t%s\t%s\n' "${priority}" "${fastdlrelpath#./}" "${filesize}" "${filemtime}" "${fastdlfile}" >> "${fastdlfilelist}"
  194. done < <(find "${basedir}/${directory}" "${fastdl_find_maxdepth[@]}" -type f -iname "${allowed_extention}" -printf '%s\t%T@\t%p\n')
  195. if [ -z "${plainoutput}" ]; then
  196. tput rc
  197. tput el
  198. fi
  199. fn_print "gathering ${label} ${allowed_extention} : ${fileswc}"
  200. if [ ${fileswc} != 0 ]; then
  201. fn_print_ok_eol_nl
  202. else
  203. fn_print_info_eol_nl
  204. fi
  205. done
  206. }
  207. # Adds Garry's Mod files to the file list.
  208. fn_fastdl_gather_gmod() {
  209. cd "${systemdir}" || exit
  210. allowed_extentions_array=("*.ain" "*.bsp" "*.mdl" "*.mp3" "*.ogg" "*.otf" "*.pcf" "*.phy" "*.png" "*.svg" "*.vtf" "*.vmt" "*.vtx" "*.vvd" "*.ttf" "*.wav")
  211. for allowed_extention in "${allowed_extentions_array[@]}"; do
  212. fileswc=0
  213. if [ -z "${plainoutput}" ]; then
  214. tput sc
  215. fi
  216. while IFS=$'\t' read -r filesize filemtime fastdlfile; do
  217. ((fileswc++))
  218. if [ -z "${plainoutput}" ]; then
  219. tput rc
  220. tput el
  221. fn_print "gathering ${allowed_extention} : ${fileswc}"
  222. fi
  223. fastdlrelpath="${fastdlfile#./}"
  224. priority="2"
  225. if [[ "${fastdlrelpath}" == addons/* ]]; then
  226. addonname="${fastdlrelpath#addons/}"
  227. addonname="${addonname%%/*}"
  228. if [ "addons/${addonname}" == "${fastdlrelpath}" ]; then
  229. continue
  230. fi
  231. priority="1:${addonname}"
  232. fastdlrelpath="${fastdlrelpath#addons/"${addonname}"/}"
  233. fi
  234. printf '%s\t%s\t%s\t%s\t%s\n' "${priority}" "${fastdlrelpath}" "${filesize}" "${filemtime}" "${systemdir}/${fastdlfile#./}" >> "${fastdlfilelist}"
  235. if [[ "${fastdlrelpath}" == lua/* ]]; then
  236. printf '%s\t%s\t%s\t%s\t%s\n' "0" "${fastdlrelpath#lua/}" "${filesize}" "${filemtime}" "${systemdir}/${fastdlfile#./}" >> "${fastdlfilelist}"
  237. fi
  238. done < <(find . -type f -iname "${allowed_extention}" -printf '%s\t%T@\t%p\n')
  239. if [ -z "${plainoutput}" ]; then
  240. tput rc
  241. tput el
  242. fi
  243. fn_print "gathering ${allowed_extention} : ${fileswc}"
  244. if [ ${fileswc} != 0 ]; then
  245. fn_print_ok_eol_nl
  246. else
  247. fn_print_skip_eol_nl
  248. fi
  249. done
  250. }
  251. # Works out which files need to be copied, compressed or removed.
  252. fn_fastdl_plan() {
  253. LC_ALL=C sort -t $'\t' -k2,2 -k1,1 "${fastdlfilelist}" | awk -F '\t' -v dupes="${fastdlduplicatelist}" 'seen[$2]++ { print $5 " > " $2 > dupes; next } { print }' > "${fastdlfilelist}.sorted"
  254. mv -f "${fastdlfilelist}.sorted" "${fastdlfilelist}"
  255. if [ -f "${fastdlduplicatelist}" ]; then
  256. duplicatefiles=$(wc -l < "${fastdlduplicatelist}")
  257. while read -r duplicatefile; do
  258. fn_script_log_info "Skipping ${duplicatefile}, already provided by a higher priority path"
  259. done < "${fastdlduplicatelist}"
  260. fi
  261. declare -A fastdlrecordsource=()
  262. declare -A fastdlexpected=()
  263. if [ "${fastdlrebuild}" != "on" ] && [ -f "${fastdlrecord}" ] && [ "$(head -n 1 "${fastdlrecord}")" == "${fastdldir}" ]; then
  264. while IFS=$'\t' read -r fastdltarget recordsource; do
  265. [ -n "${fastdltarget}" ] && fastdlrecordsource["${fastdltarget}"]="${recordsource}"
  266. done < <(tail -n +2 "${fastdlrecord}")
  267. fi
  268. echo "${fastdldir}" > "${fastdlnewrecord}"
  269. read -ra fastdlexcludearray <<< "${fastdlexclude}"
  270. while IFS=$'\t' read -r priority fastdlrelpath filesize filemtime fastdlfile; do
  271. for excludepath in "${fastdlexcludearray[@]}"; do
  272. # shellcheck disable=SC2254
  273. case "${fastdlrelpath}" in
  274. ${excludepath#/}*)
  275. ((excludedfiles++))
  276. continue 2
  277. ;;
  278. esac
  279. done
  280. if [ "${engine}" == "goldsrc" ] || [ "${filesize}" -gt "${fastdlmaxcompresssize}" ]; then
  281. fastdlmode="copy"
  282. fastdltarget="${fastdlrelpath}"
  283. if [ "${engine}" != "goldsrc" ]; then
  284. ((largefiles++))
  285. fi
  286. else
  287. fastdlmode="compress"
  288. fastdltarget="${fastdlrelpath}.bz2"
  289. fi
  290. fastdlsource="${fastdlfile}"$'\t'"${filesize}"$'\t'"${filemtime}"
  291. fastdlexpected["${fastdltarget}"]="on"
  292. printf '%s\t%s\n' "${fastdltarget}" "${fastdlsource}" >> "${fastdlnewrecord}"
  293. echo "${fastdlrelpath}" >> "${fastdlclientlist}"
  294. if [ ! -f "${fastdldir}/${fastdltarget}" ] || [ "${fastdlrecordsource["${fastdltarget}"]}" != "${fastdlsource}" ]; then
  295. printf '%s\t%s\t%s\n' "${fastdlmode}" "${fastdlrelpath}" "${fastdlfile}" >> "${fastdlupdatelist}"
  296. ((updatefiles++))
  297. filesizetotal=$((filesizetotal + filesize))
  298. if [ "${fastdlmode}" == "compress" ]; then
  299. ((compressfiles++))
  300. fi
  301. else
  302. ((unchangedfiles++))
  303. fi
  304. done < "${fastdlfilelist}"
  305. for fastdltarget in "${!fastdlrecordsource[@]}"; do
  306. if [ -z "${fastdlexpected["${fastdltarget}"]}" ] && [ -f "${fastdldir}/${fastdltarget}" ]; then
  307. echo "${fastdltarget}" >> "${fastdlremovelist}"
  308. ((removefiles++))
  309. fi
  310. done
  311. if [ -d "${fastdldir}" ] && [ "${fastdlrebuild}" != "on" ]; then
  312. while read -r fastdltarget; do
  313. if [ -z "${fastdlexpected["${fastdltarget}"]}" ] && [ -z "${fastdlrecordsource["${fastdltarget}"]}" ]; then
  314. ((untrackedfiles++))
  315. fi
  316. done < <(find "${fastdldir}" -type f -printf '%P\n')
  317. fi
  318. }
  319. # Provides info about the fastdl directory content and prompts for confirmation.
  320. fn_fastdl_preview() {
  321. # Remove any file list.
  322. rm -f "${fastdlfilelist:?}" "${fastdlduplicatelist:?}" "${fastdlnewrecord:?}" "${fastdlclientlist:?}" "${fastdlupdatelist:?}" "${fastdlremovelist:?}" "${fastdlcompresslist:?}"
  323. touch "${fastdlclientlist}"
  324. totalfiles=0
  325. untrackedfiles=0
  326. duplicatefiles=0
  327. excludedfiles=0
  328. largefiles=0
  329. updatefiles=0
  330. compressfiles=0
  331. unchangedfiles=0
  332. removefiles=0
  333. filesizetotal=0
  334. fn_print_nl "analysing required files"
  335. fn_script_log_info "Analysing required files"
  336. # Garry's Mod
  337. if [ "${shortname}" == "gmod" ]; then
  338. fn_fastdl_gather_gmod
  339. # Source and GoldSrc engines
  340. else
  341. if [ "${engine}" == "goldsrc" ]; then
  342. fastdl_directories_array=("." "maps" "models" "sound" "sprites" "gfx" "overviews")
  343. else
  344. fastdl_directories_array=("maps" "materials" "models" "particles" "sound" "resource")
  345. fi
  346. fastdl_custom_array=()
  347. if [ "${engine}" == "source" ] && [ -d "${systemdir}/custom" ]; then
  348. while IFS= read -r -d '' customdir; do
  349. fastdl_custom_array+=("${customdir}")
  350. done < <(find "${systemdir}/custom" -mindepth 1 -maxdepth 1 -type d -print0 | LC_ALL=C sort -z)
  351. fi
  352. for directory in "${fastdl_directories_array[@]}"; do
  353. if [ "${engine}" == "goldsrc" ]; then
  354. fn_fastdl_goldsrc_extensions
  355. else
  356. fn_fastdl_source_extensions
  357. fi
  358. for customdir in "${fastdl_custom_array[@]}"; do
  359. if [ -d "${customdir}/${directory}" ]; then
  360. fn_fastdl_gather "${customdir}" "0:${customdir##*/}"
  361. fi
  362. done
  363. if [ -d "${systemdir}/${directory}" ]; then
  364. fn_fastdl_gather "${systemdir}" "1"
  365. fi
  366. done
  367. fi
  368. if [ -f "${fastdlfilelist}" ]; then
  369. fn_print_nl "calculating changes"
  370. fn_sleep_time_1
  371. totalfiles=$(wc -l < "${fastdlfilelist}")
  372. fn_fastdl_plan
  373. else
  374. fn_print_fail_eol_nl "generating file list"
  375. fn_script_log_fail "Generating file list."
  376. core_exit.sh
  377. fi
  378. echo -e "found ${totalfiles} files: ${unchangedfiles} unchanged, ${excludedfiles} excluded, ${duplicatefiles} duplicate"
  379. if [ "${updatefiles}" -gt 0 ]; then
  380. if [ "${engine}" == "source" ]; then
  381. echo -e "about to update ${updatefiles} files, ${compressfiles} to compress, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  382. elif [ "${engine}" == "goldsrc" ]; then
  383. echo -e "about to copy ${updatefiles} files, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  384. fi
  385. fi
  386. if [ "${largefiles}" -gt 0 ]; then
  387. echo -e "${largefiles} files over 150 MB will be copied without compression"
  388. fi
  389. if [ "${removefiles}" -gt 0 ]; then
  390. echo -e "about to remove ${removefiles} files no longer on the server"
  391. fi
  392. if [ "${untrackedfiles}" -gt 0 ]; then
  393. echo -e "${untrackedfiles} files in the Fastdl directory were not added by ${selfname} and will be left alone"
  394. fi
  395. if [ "${updatefiles}" -eq 0 ] && [ "${removefiles}" -eq 0 ]; then
  396. echo -e "Fastdl directory is up to date"
  397. fi
  398. fn_script_log_info "${totalfiles} files, ${updatefiles} to update, ${unchangedfiles} unchanged, ${excludedfiles} excluded, ${removefiles} to remove, total size $(fn_human_readable_file_size "${filesizetotal}" 0)"
  399. if ! fn_prompt_yn "Continue?" Y; then
  400. exitcode=0
  401. core_exit.sh
  402. fi
  403. }
  404. # Removes files from the fastdl directory that are no longer on the server.
  405. fn_fastdl_remove() {
  406. if [ -s "${fastdlremovelist}" ]; then
  407. fn_print "removing ${removefiles} files no longer on the server"
  408. while read -r fastdlstalefile; do
  409. rm -f "${fastdldir:?}/${fastdlstalefile}"
  410. exitcode=$?
  411. if [ "${exitcode}" -ne 0 ]; then
  412. fn_print_fail_eol_nl
  413. fn_script_log_fail "Removing ${fastdldir}/${fastdlstalefile}"
  414. core_exit.sh
  415. else
  416. fn_script_log_pass "Removing ${fastdldir}/${fastdlstalefile}"
  417. fi
  418. done < "${fastdlremovelist}"
  419. find "${fastdldir:?}" -mindepth 1 -type d -empty -delete
  420. fn_print_ok_eol_nl
  421. fi
  422. }
  423. # Copies new and changed files to the fastdl directory.
  424. fn_fastdl_copy() {
  425. if [ -s "${fastdlupdatelist}" ]; then
  426. fileswc=0
  427. if [ -z "${plainoutput}" ]; then
  428. tput sc
  429. fi
  430. while IFS=$'\t' read -r fastdlmode fastdlrelpath fastdlfile; do
  431. ((fileswc++))
  432. if [ -z "${plainoutput}" ]; then
  433. tput rc
  434. tput el
  435. fn_print "copying files : ${fileswc}/${updatefiles}"
  436. fi
  437. fastdltarget="${fastdldir}/${fastdlrelpath}"
  438. mkdir -p "${fastdltarget%/*}" && cp -p "${fastdlfile}" "${fastdltarget}"
  439. exitcode=$?
  440. if [ "${exitcode}" -ne 0 ]; then
  441. fn_print_fail_eol_nl
  442. fn_script_log_fail "Copying ${fastdlfile} > ${fastdltarget}"
  443. core_exit.sh
  444. else
  445. fn_script_log_pass "Copying ${fastdlfile} > ${fastdltarget}"
  446. fi
  447. if [ "${fastdlmode}" == "compress" ]; then
  448. printf '%s\0' "${fastdltarget}" >> "${fastdlcompresslist}"
  449. fi
  450. done < "${fastdlupdatelist}"
  451. if [ -n "${plainoutput}" ]; then
  452. fn_print "copying files : ${fileswc}/${updatefiles}"
  453. fi
  454. fn_print_ok_eol_nl
  455. fi
  456. }
  457. # Builds the fastdl directory content.
  458. fn_fastdl_build() {
  459. # Copy all needed files for Fastdl.
  460. fn_print_nl "updating files in ${fastdldir}"
  461. fn_script_log_info "Updating files in ${fastdldir}"
  462. fn_fastdl_remove
  463. fn_fastdl_copy
  464. if [ "${shortname}" == "gmod" ]; then
  465. fn_fastdl_gmod_dl_enforcer
  466. fi
  467. }
  468. # Generate lua file that will force download any file into the Fastdl directory.
  469. fn_fastdl_gmod_dl_enforcer() {
  470. # Clear old lua file.
  471. if [ -f "${luafastdlfullpath}" ]; then
  472. fn_print "removing existing download enforcer: ${luafastdlfile}"
  473. rm -f "${luafastdlfullpath:?}"
  474. exitcode=$?
  475. if [ "${exitcode}" -ne 0 ]; then
  476. fn_print_fail_eol_nl
  477. fn_script_log_fail "Removing existing download enforcer ${luafastdlfullpath}"
  478. core_exit.sh
  479. else
  480. fn_print_ok_eol_nl
  481. fn_script_log_pass "Removing existing download enforcer ${luafastdlfullpath}"
  482. fi
  483. fi
  484. # Generate new one if user said yes.
  485. if [ "${luaresource}" == "on" ]; then
  486. fn_print "creating new download enforcer: ${luafastdlfile}"
  487. touch "${luafastdlfullpath}"
  488. # Read all filenames and put them into a lua file at the right path.
  489. while read -r line; do
  490. echo -e "resource.AddFile( \"${line}\" )" >> "${luafastdlfullpath}"
  491. done < "${fastdlclientlist}"
  492. exitcode=$?
  493. if [ "${exitcode}" -ne 0 ]; then
  494. fn_print_fail_eol_nl
  495. fn_script_log_fail "Creating new download enforcer ${luafastdlfullpath}"
  496. core_exit.sh
  497. else
  498. fn_print_ok_eol_nl
  499. fn_script_log_pass "Creating new download enforcer ${luafastdlfullpath}"
  500. fi
  501. fi
  502. }
  503. # Compresses Fastdl files using bzip2.
  504. fn_fastdl_bzip2() {
  505. if [ -s "${fastdlcompresslist}" ]; then
  506. fastdlthreads="$(nproc)"
  507. fn_print "compressing ${compressfiles} files using ${fastdlthreads} threads"
  508. xargs -0 -r -n 1 -P "${fastdlthreads}" bzip2 -f < "${fastdlcompresslist}"
  509. compressexitcode=$?
  510. while IFS=$'\t' read -r fastdlmode fastdlrelpath fastdlfile; do
  511. if [ "${fastdlmode}" == "compress" ]; then
  512. filetocompress="${fastdldir}/${fastdlrelpath}"
  513. if [ -f "${filetocompress}.bz2" ] && [ ! -f "${filetocompress}" ]; then
  514. fn_script_log_pass "Compressing ${filetocompress}"
  515. else
  516. fn_script_log_fail "Compressing ${filetocompress}"
  517. fi
  518. fi
  519. done < "${fastdlupdatelist}"
  520. if [ "${compressexitcode}" -ne 0 ]; then
  521. fn_print_fail_eol_nl
  522. fn_script_log_fail "Compressing files"
  523. exitcode=1
  524. core_exit.sh
  525. else
  526. fn_print_ok_eol_nl
  527. fn_script_log_pass "Compressing files"
  528. fi
  529. fi
  530. }
  531. # Saves the list of files written to the fastdl directory.
  532. fn_fastdl_record() {
  533. fn_print "saving Fastdl file record ${fastdlrecord}"
  534. mkdir -p "${datadir}" && mv -f "${fastdlnewrecord}" "${fastdlrecord}"
  535. exitcode=$?
  536. if [ "${exitcode}" -ne 0 ]; then
  537. fn_print_fail_eol_nl
  538. fn_script_log_fail "Saving Fastdl file record ${fastdlrecord}"
  539. core_exit.sh
  540. else
  541. fn_print_ok_eol_nl
  542. fn_script_log_pass "Saving Fastdl file record ${fastdlrecord}"
  543. fi
  544. }
  545. check.sh
  546. # Run functions.
  547. fn_fastdl_preview
  548. if [ "${fastdlrebuild}" == "on" ]; then
  549. fn_clear_old_fastdl
  550. fi
  551. fn_fastdl_dirs
  552. fn_fastdl_build
  553. if [ "${engine}" == "source" ]; then
  554. fn_fastdl_bzip2
  555. fi
  556. fn_fastdl_record
  557. rm -f "${fastdlfilelist:?}" "${fastdlduplicatelist:?}" "${fastdlnewrecord:?}" "${fastdlclientlist:?}" "${fastdlupdatelist:?}" "${fastdlremovelist:?}" "${fastdlcompresslist:?}"
  558. # Finished message.
  559. fn_print_nl "Fastdl files are located in:"
  560. fn_print_nl "${fastdldir}"
  561. fn_print_nl "Fastdl completed"
  562. fn_script_log_info "Fastdl completed"
  563. core_exit.sh