changeset 555:2fda9ab57359

Normalize the output of _get_mounts_at_directory() to use TABs as field separators only. This is a precondition for properly handling SPACE chars in datasets and/or mountpoints. BUGS: Handling of spaces not yet done.
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 11 Sep 2024 12:34:32 +0200
parents c8348c707928
children a593dce19f54
files sbin/ftjail share/local-bsdtools/common.subr
diffstat 2 files changed, 28 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/sbin/ftjail	Wed Sep 11 12:11:52 2024 +0200
+++ b/sbin/ftjail	Wed Sep 11 12:34:32 2024 +0200
@@ -965,7 +965,7 @@
     # mountpoint in ZFS.
     # Also check that it is a clone proper.
     #
-    IFS=' '$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _line <<EOF4tHGCSS
+    IFS=$'\t' read -r _root_dataset _root_mountpoint _root_type _root_options _line <<EOF4tHGCSS
 ${_dir_mounts}
 EOF4tHGCSS
     [ "${_root_mountpoint}" != "${_directory}" ] && { echo "ERROR: found root mountpoint does not match given directory" 1>&2; return 1; }
@@ -992,9 +992,15 @@
     _u_tmpdir="$(env TMPDIR=/var/tmp mktemp -d -t ftjail_${_dir_basename})"
     [ -z "${_u_tmpdir}" ] && { echo "ERROR: cannot create unique temp dir" 1>&2; return 1; }
     _dir_fn_fstab="${_u_tmpdir}/fstab"
-    echo -n "${_dir_mounts}" >>"${_dir_fn_fstab}"
+    #
+    # XXX FIXME: handle spaces in device and mountpoint names: replace
+    #            with a literal `\040'. Note that ${_dir_mounts} is
+    #            normalized already: it uses TAB characters as field
+    #            separator exclusively.
+    #
+    printf '%s' "${_dir_mounts}" >>"${_dir_fn_fstab}"
     _dir_fn_tldir="${_u_tmpdir}/tldirs"
-    find "${_directory}" -depth 1 -type d 2>/dev/null | sort >>"${_dir_fn_tldir}"
+    LC_ALL=C /usr/bin/find "${_directory}" -depth 1 -type d 2>/dev/null | LC_ALL=C /usr/bin/sort >>"${_dir_fn_tldir}"
 
     # Unmount in reverse order: unmount can do it for us
     echo "Unmounting all datasets mounted at \`${_directory}'"
--- a/share/local-bsdtools/common.subr	Wed Sep 11 12:11:52 2024 +0200
+++ b/share/local-bsdtools/common.subr	Wed Sep 11 12:34:32 2024 +0200
@@ -369,38 +369,43 @@
 _get_mounts_at_directory() {
     local _directory
 
-    local _fstab
+    local _fstab _mp1 _mp2
 
     _directory=${1-}
     case "${_directory}" in
+        '')
+            # OK this matches at the root directory
+            _mp1='/'
+            _mp2='/'
+            ;;
+        /)
+            # OK this matches at the root directory
+            _mp1='/'
+            _mp2='/'
+            ;;
         */)
-            echo "ERROR: a trailing slash in directory name given" 1>&2;
-            exit 1;
+            fatal 1 "a trailing slash in directory path given"
             ;;
         /*)
-            :
-            ;;
-        '')
-            echo "ERROR: no directory given" 1>&2;
-            exit 1;
+            _mp1="${_directory}"
+            _mp2="${_directory}/"
             ;;
         *)
-            echo "ERROR: directory must be an absolute path" 1>&2;
-            exit 1;
+            fatal 1 "given directory must be an absolute path"
             ;;
     esac
     if [ -x "${JQ}" ]; then
         /sbin/mount -p --libxo=json,no-locale \
         | LC_ALL=C "${JQ}" -r $'.mount.fstab[] | [.device, .mntpoint, .fstype, .opts, .dump, .pass] | @tsv ' \
-        | LC_ALL=C /usr/bin/awk -F $'\\t+' -v OFS=$'\t' -v ds1="${_directory}" -v ds2="${_directory}/" $'{ if (($2 == ds1) || (index($2, ds2) == 1)) { print; } }' \
-        | LC_ALL=C /usr/bin/sort -t $'\t' -k1
+        | LC_ALL=C /usr/bin/awk -F $'\\t+' -v OFS=$'\t' -v mp1="${_mp1}" -v mp2="${_mp2}" $'{ if (($2 == mp1) || (index($2, mp2) == 1)) { print; } }' \
+        | LC_ALL=C /usr/bin/sort --field-separator=$'\t' --key=2
     else
         # Check for unexpected spaces
         if ! check_for_proper_fstab; then
             fatal 1 "Unexpected spaces in fstab. Please install \`${JQ}'."
         fi
-        _fstab="$(/sbin/mount -p | awk -v pa1="^${_directory}\$" -v pa2="^${_directory}/" '($2 ~ pa1) || ($2 ~ pa2 ) { print; }' | sort -k3)"
-        echo "${_fstab}"
+        _fstab="$(/sbin/mount -p | LC_ALL=C awk -v OFS=$'\t' -v mp1="${_mp1}" -v mp2="${_mp2}" $'{ if (($2 == mp1) || (index($2, mp2) == 1)) { print $1, $2, $3, $4, $5, $6; } }' | LC_ALL=C /usr/bin/sort --field-separator=$'\t' --key=2)"
+        printf '%s' "${_fstab}"
     fi
 }