bind-dirs.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #!/bin/bash -e
  2. # vim: set ts=4 sw=4 sts=4 et :
  3. #
  4. # bind-dirs
  5. # Binds directories which allows changes in TemplateBasedVM to persist.
  6. #
  7. # To umount all bind-dirs, just pass any arg in $1, like umount
  8. #
  9. # Copyright (C) 2014 - 2015 Jason Mehring <nrgaway@gmail.com>
  10. # Copyright (C) 2014 - 2015 Patrick Schleizer <adrelanos@riseup.net>
  11. # License: GPL-2+
  12. #
  13. # This program is free software; you can redistribute it and/or
  14. # modify it under the terms of the GNU General Public License
  15. # as published by the Free Software Foundation; either version 2
  16. # of the License, or (at your option) any later version.
  17. #
  18. # This program is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. set -x
  26. prerequisite() {
  27. qubes_vm_persistence="$(qubesdb-read /qubes-vm-persistence)"
  28. if [ ! "$qubes_vm_persistence" = "rw-only" ]; then
  29. true "No TemplateBasedVM detected. Exiting."
  30. exit 0
  31. fi
  32. if [ -f "/var/run/qubes-service/qubes-dvm" ]; then
  33. # https://github.com/QubesOS/qubes-issues/issues/1328#issuecomment-169483029
  34. # Do none of the following in a DispVM.
  35. # During DispVM savefile generation, 'qubesdb-read /qubes-vm-persistence'
  36. # outputs 'rw'.
  37. exit 0
  38. fi
  39. }
  40. init() {
  41. [ -n "$rw_dest_dir" ] || rw_dest_dir="/rw/bind-dirs"
  42. [ -n "$symlink_level_max" ] || symlink_level_max="10"
  43. mkdir --parents "$rw_dest_dir"
  44. shopt -s nullglob
  45. shopt -s dotglob
  46. }
  47. legacy() {
  48. local item
  49. for item in /rw/srv/qubes-whonix/* /rw/srv/whonix/*; do
  50. mv "$item" /rw/bind-dirs/ || true
  51. done
  52. for item in /rw/srv/qubes-whonix /rw/srv/whonix; do
  53. if [ -d "$item" ]; then
  54. rmdir "$item" || true
  55. fi
  56. done
  57. }
  58. bind_dirs() {
  59. ## legend
  60. ## fso: file system object
  61. ## ro: read-only
  62. ## rw: read-write
  63. for fso_ro in ${binds[@]}; do
  64. local symlink_level_counter
  65. symlink_level_counter="0"
  66. while true; do
  67. if [ -h "$fso_ro" ]; then
  68. ## Resolving where there symlink points to, and using the result
  69. ## for bind mount instead.
  70. symlink_level_counter="$(( symlink_level_counter + 1 ))"
  71. true "$fso_ro is a symlink"
  72. fso_real_location="$(realpath "$fso_ro")"
  73. fso_ro="$fso_real_location"
  74. else
  75. true "$fso_ro is not a symlink"
  76. break
  77. fi
  78. if [ "$symlink_level_counter" -ge "$symlink_level_max" ]; then
  79. break
  80. fi
  81. done
  82. true "fso_ro: $fso_ro"
  83. fso_rw="${rw_dest_dir}${fso_ro}"
  84. # Make sure fso_ro is not mounted.
  85. umount "$fso_ro" 2> /dev/null || true
  86. if [ -n "$1" ]; then
  87. true "Umounting $1 only..."
  88. continue
  89. fi
  90. # Initially copy over data directories to /rw if rw directory does not exist.
  91. if [ -d "$fso_ro" ] || [ -f "$fso_ro" ]; then
  92. cp --verbose --no-clobber --archive --recursive --parents "$fso_ro" "$rw_dest_dir"
  93. else
  94. true "$fso_ro is neither a directory nor a file or does not exist, skipping."
  95. continue
  96. fi
  97. # Bind the fso.
  98. mount --bind "$fso_rw" "$fso_ro"
  99. done
  100. }
  101. main() {
  102. prerequisite "$@"
  103. init "$@"
  104. legacy "$@"
  105. bind_dirs "$@"
  106. }
  107. for source_folder in /usr/lib/qubes-bind-dirs.d /etc/qubes-bind-dirs.d /rw/config/qubes-bind-dirs.d ; do
  108. true "source_folder: $source_folder"
  109. if [ ! -d "$source_folder" ]; then
  110. continue
  111. fi
  112. for file_name in "$source_folder/"*".conf" ; do
  113. bash -n "$file_name"
  114. source "$file_name"
  115. done
  116. done
  117. main "$@"