check-merged 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env bash
  2. #
  3. # Check if a given custom skeleton or overlay complies to the merged
  4. # requirements:
  5. #
  6. # - for unmerged:
  7. # /bin missing*, or an existing directory; not a symlink
  8. # /lib missing*, or an existing directory; not a symlink
  9. # /sbin missing*, or an existing directory; not a symlink
  10. # /usr/bin/ missing*, or an existing directory; not a symlink
  11. # /usr/lib/ missing*, or an existing directory; not a symlink
  12. # /usr/sbin/ missing*, or an existing directory; not a symlink
  13. #
  14. # *: must be present for skeletons, can be missing for overlays
  15. #
  16. # - for merged-usr: all of the above, except:
  17. # /bin missing, or a relative symlink to usr/bin
  18. # /lib missing, or a relative symlink to usr/lib
  19. # /sbin missing, or a relative symlink to usr/sbin
  20. #
  21. # - for merged-bin: all of the above, except:
  22. # /usr/sbin missing, or a relative symlink to bin (thus points
  23. # to /usr/bin)
  24. #
  25. # Input:
  26. # -t TYPE the type of root to check: 'skeleton' or 'overlay'
  27. # -u check for merged /usr
  28. # -b check for merged /usr/bin
  29. # $*: the root directories (skeleton, overlays) to check
  30. # Output:
  31. # stdout: the list of non-compliant paths (empty if compliant).
  32. # Exit code:
  33. # 0: in case of success (stdout will be empty)
  34. # !0: if any directory to check is improperly merged
  35. #
  36. type=
  37. merged_usr=false
  38. merged_bin=false
  39. while getopts "t:ub" OPT; do
  40. case "${OPT}" in
  41. (t) type="${OPTARG}";;
  42. (u) merged_usr=true;;
  43. (b) merged_bin=true;;
  44. (:) printf "option %s expects a mandatory argument\n" "${OPTARG}"; exit 1;;
  45. (\?) printf "unknown option %s\n" "${OPTARG}"; exit 1;;
  46. esac
  47. done
  48. # Remove the options processed by getopts from $@,
  49. # so that $@ now contains only the root directories to check.
  50. shift $((OPTIND -1))
  51. if [ "${type}" = "skeleton" ]; then
  52. strict=true
  53. else
  54. strict=false
  55. fi
  56. report_error() {
  57. local type="${1}"
  58. local root="${2}"
  59. local fmt="${3}"
  60. shift 3
  61. if ${first}; then
  62. printf "The %s in %s is not properly setup:\n" \
  63. "${type}" "${root}"
  64. fi
  65. first=false
  66. # shellcheck disable=SC2059 # fmt *is* a format string
  67. printf " - ${fmt}" "${@}"
  68. is_success=false
  69. }
  70. test_merged() {
  71. local type="${1}"
  72. local root="${2}"
  73. local base="${3}"
  74. local dir1="${4}"
  75. local dir2="${5}"
  76. if ! test -e "${root}${base}${dir1}"; then
  77. return 0
  78. elif [ "$(readlink "${root}${base}${dir1}")" = "${dir2}" ]; then
  79. return 0
  80. fi
  81. # Otherwise, this directory is not merged
  82. report_error "${type}" "${root}" \
  83. '%s%s should be missing, or be a relative symlink to %s\n' \
  84. "${base}" "${dir1}" "${dir2}"
  85. }
  86. test_dir() {
  87. local type="${1}"
  88. local root="${2}"
  89. local base="${3}"
  90. local dir="${4}"
  91. if ! test -e "${root}${base}${dir}" && ! ${strict}; then
  92. return 0
  93. elif test -d "${root}${base}${dir}" && ! test -L "${root}${base}${dir}"; then
  94. return 0
  95. fi
  96. # Otherwise, this entry is not a proper directory
  97. report_error "${type}" "${root}" \
  98. "%s%s should exist, be a directory, and not be a symlink\n" \
  99. "${base}" "${dir}"
  100. }
  101. is_success=true
  102. for root; do
  103. first=true
  104. test_dir "${type}" "${root}" "/" "usr/bin"
  105. test_dir "${type}" "${root}" "/" "usr/lib"
  106. if ${merged_usr}; then
  107. test_merged "${type}" "${root}" "/" "bin" "usr/bin"
  108. test_merged "${type}" "${root}" "/" "lib" "usr/lib"
  109. test_merged "${type}" "${root}" "/" "sbin" "usr/sbin"
  110. if ${merged_bin}; then
  111. test_merged "${type}" "${root}" "/usr/" "sbin" "bin"
  112. else
  113. test_dir "${type}" "${root}" "/" "usr/sbin"
  114. fi
  115. else
  116. test_dir "${type}" "${root}" "/" "bin"
  117. test_dir "${type}" "${root}" "/" "lib"
  118. test_dir "${type}" "${root}" "/" "sbin"
  119. test_dir "${type}" "${root}" "/" "usr/sbin"
  120. fi
  121. done
  122. ${is_success}