check_integrity.sh 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #!/usr/bin/env bash
  2. # Utility script to check the game sanity
  3. # As of now, this script does not repair files.
  4. #
  5. # Usage: ./check_integrity.sh FILENAME quick
  6. # FILENAME : Checksum file e.g. "pkg_version" of the game or voiceover pack
  7. # "quick" : Skips md5 checks for more speed but is less reliable
  8. set -e
  9. # ======== Functions
  10. fatal() {
  11. echo
  12. for arg in "$@"; do
  13. echo " * $arg" >&2
  14. done
  15. echo
  16. exit 1
  17. }
  18. on_file_mismatch() {
  19. # 1 = Error Msg, 2 = Filepath
  20. >&2 echo "$2"
  21. >&2 echo " * $1"
  22. }
  23. if [[ $(uname) == "Darwin" || $(uname) == *"BSD" ]]; then
  24. STATFLAGS="-f %z"
  25. md5sum() {
  26. md5 -q $@
  27. }
  28. else
  29. STATFLAGS="-c %s"
  30. fi
  31. check_single() {
  32. # 1 = filepath
  33. filepath="$1"
  34. checksum="$2"
  35. filesize="$3"
  36. #echo "Testing: $filepath $checksum $filesize"
  37. if [ ! -e "$filepath" ]; then
  38. on_file_mismatch "Missing" "$filepath"
  39. return
  40. fi
  41. local size=$(stat $STATFLAGS "$filepath")
  42. if [ "$size" -ne "$filesize" ]; then
  43. on_file_mismatch "Size mismatch: $size != $filesize" "$filepath"
  44. return
  45. fi
  46. if [ "$CHECK_MD5" -eq 1 ]; then
  47. sum=($(md5sum "$filepath"))
  48. if [ "$sum" != "$checksum" ]; then
  49. on_file_mismatch "Checksum error: $sum != $checksum" "$filepath"
  50. return
  51. fi
  52. fi
  53. }
  54. # ======== Evaluated variables
  55. MASTER_FILE="$1"
  56. CHECK_MD5=1
  57. JOBS=4
  58. [ ! -e "$MASTER_FILE" ] && fatal \
  59. "Checksum file $MASTER_FILE not found."
  60. if [ "$2" == "quick" ]; then
  61. CHECK_MD5=0
  62. echo "--- Mode: Quick file size checking (fast, less reliable)"
  63. else
  64. echo "--- Mode: Detailed md5 checking (slow, most reliable)"
  65. fi
  66. echo ""
  67. # This is faster than running "jq" on each line
  68. # outputs a string in form of "Direcotry/File.ext|abc123|10001"
  69. per_line_data=$(jq -r "[.remoteName, .md5, .fileSize] | join(\"|\")" "$MASTER_FILE")
  70. i=0
  71. total=$(echo "$per_line_data" | wc -l)
  72. while IFS='|' read -r filepath checksum filesize; do
  73. i=$((i + 1))
  74. while [ $(jobs | wc -l) -gt $JOBS ]; do
  75. sleep 0.1
  76. done
  77. check_single "$filepath" "$checksum" "$filesize" &
  78. # Log file names every now and then
  79. if [ $((i % 500)) == 0 ]; then
  80. percent=$((i * 100 / total))
  81. echo "--- Progress: ${percent}% (${i} / ${total})"
  82. fi
  83. done <<< "$per_line_data"
  84. while [ $(jobs | wc -l) -gt 1 ]; do
  85. sleep 0.1
  86. done
  87. echo ""
  88. echo "==> DONE"
  89. exit 0