bind-dirs.sh 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. }
  45. legacy() {
  46. if [ -d /rw/srv/qubes-whonix ]; then
  47. mv /rw/srv/qubes-whonix /rw/bind-dirs || true
  48. fi
  49. if [ -d /rw/srv/whonix ]; then
  50. mv /rw/srv/whonix /rw/bind-dirs || true
  51. fi
  52. }
  53. bind_dirs() {
  54. ## legend
  55. ## fso: file system object
  56. ## ro: read-only
  57. ## rw: read-write
  58. for fso_ro in ${binds[@]}; do
  59. local symlink_level_counter
  60. symlink_level_counter="0"
  61. while true; do
  62. if [ -h "$fso_ro" ]; then
  63. ## Resolving where there symlink points to, and using the result
  64. ## for bind mount instead.
  65. symlink_level_counter="$(( symlink_level_counter + 1 ))"
  66. true "$fso_ro is a symlink"
  67. fso_real_location="$(realpath "$fso_ro")"
  68. fso_ro="$fso_real_location"
  69. else
  70. true "$fso_ro is not a symlink"
  71. break
  72. fi
  73. if [ "$symlink_level_counter" -ge "$symlink_level_max" ]; then
  74. break
  75. fi
  76. done
  77. true "fso_ro: $fso_ro"
  78. fso_rw="${rw_dest_dir}${fso_ro}"
  79. # Make sure fso_ro is not mounted.
  80. umount "$fso_ro" 2> /dev/null || true
  81. if [ -n "$1" ]; then
  82. true "Umounting $1 only..."
  83. continue
  84. fi
  85. # Initially copy over data directories to /rw if rw directory does not exist.
  86. if [ -d "$fso_ro" ] || [ -f "$fso_ro" ]; then
  87. cp --verbose --no-clobber --archive --recursive --parents "$fso_ro" "$rw_dest_dir"
  88. else
  89. true "$fso_ro is neither a directory nor a file or does not exist, skipping."
  90. continue
  91. fi
  92. # Bind the fso.
  93. mount --bind "$fso_rw" "$fso_ro"
  94. done
  95. }
  96. main() {
  97. prerequisite "$@"
  98. init "$@"
  99. legacy "$@"
  100. bind_dirs "$@"
  101. }
  102. for source_folder in /usr/lib/qubes-bind-dirs.d /etc/qubes-bind-dirs.d /rw/config/qubes-bind-dirs.d ; do
  103. true "source_folder: $source_folder"
  104. if [ ! -d "$source_folder" ]; then
  105. continue
  106. fi
  107. for file_name in "$source_folder/"*".conf" ; do
  108. bash -n "$file_name"
  109. source "$file_name"
  110. done
  111. done
  112. main "$@"