changeset 249:a91e1c5173cc

Also support direct mounting of the RW skeleton subdirs at a mountpoint
author Franz Glasner <fzglas.hg@dom66.de>
date Sun, 11 Sep 2022 13:02:39 +0200
parents 0b5dbf394aa2
children c4d835ccb4ae
files sbin/ftjail
diffstat 1 files changed, 80 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/sbin/ftjail	Sun Sep 11 10:57:00 2022 +0200
+++ b/sbin/ftjail	Sun Sep 11 13:02:39 2022 +0200
@@ -43,6 +43,8 @@
     Canonically mount the RO base and the RW skeleton into MOUNTPOINT and
     MOUNTPOINT/skeleton
 
+    -L        Mount the skeleton into a "skeleton" subdirectory
+    -P        Mount the skeleton directly over the base
     -n        Do not really mount but show what would be mounted where
     -u        Alias of -n
 
@@ -55,10 +57,13 @@
     Create symbolic links between the RO base and the RW skeleton.
     Base and skeleton must be canonically mounted already.
 
-  populate MOUNTPOINT BASETXZ
+  populate [ OPTIONS ] MOUNTPOINT BASETXZ
 
     Populate the directory in MOUNTPOINT with the base system in BASETXZ
 
+    -L        Populate having a "skeleton" subdirectory within the mountpoint
+    -P        Populate directly into the mountpoint
+
 ENVIRONMENT:
 
   All environment variables that affect "zfs" are effective also.
@@ -289,10 +294,29 @@
 command_populate_tmpl() {
     # MOUNTPOINT -- base.txz
     local _mp _basetxz
+    local _opt_symlink
 
-    local _dir
+    local _opt _dir
+
+    _opt_symlink=""
 
-    _ensure_no_options "$@"
+    while getopts "LP" _opt ; do
+        case ${_opt} in
+            L)
+                _opt_symlink="yes"
+                ;;
+            P)
+                _opt_symlink="no"
+                ;;
+            \?)
+                return 2;
+                ;;
+        esac
+    done
+    shift $((OPTIND-1))
+    OPTIND=1
+
+    [ -z "${_opt_symlink}" ] && { echo "ERROR: -L or -P must be given" 1>&2; return 2; }
 
     _mp="${1-}"
     _basetxz="${2-}"
@@ -314,27 +338,35 @@
         return 1
     fi
 
-    echo "Extracting RO base ..."
-    tar -C "${_mp}" --exclude=./etc --exclude=./root --exclude=./tmp --exclude=./usr/local --exclude=./var --no-safe-writes -xJp -f "${_basetxz}" || return
-    # "home" is not part of base
-    for _dir in etc root tmp usr/local var ; do
-        echo "Extracting RW skeleton: ${_dir} ..."
-        tar -C "${_mp}/skeleton" --include="./${_dir}" --exclude=./root/.cshrc --exclude=./root/.profile -xJp -f "${_basetxz}" || return
-    done
-    # In the original archive they are archived as hardlinks: make symlinks here
-    (cd "${_mp}/skeleton/root" && ln -s ../../.profile .profile) || return
-    (cd "${_mp}/skeleton/root" && ln -s ../../.cshrc .cshrc) || return
+    if [ "${_opt_symlink}" = "yes" ]; then
+        echo "Extracting RO base ..."
+        tar -C "${_mp}" --exclude=./etc --exclude=./root --exclude=./tmp --exclude=./usr/local --exclude=./var --no-safe-writes -xJp -f "${_basetxz}" || return
+        # "home" is not part of base
+        for _dir in etc root tmp usr/local var ; do
+            echo "Extracting RW skeleton: ${_dir} ..."
+            tar -C "${_mp}/skeleton" --include="./${_dir}" --exclude=./root/.cshrc --exclude=./root/.profile -xJp -f "${_basetxz}" || return
+        done
+        # In the original archive they are archived as hardlinks: make proper symlinks here
+        (cd "${_mp}/skeleton/root" && ln -s ../../.profile .profile) || return
+        (cd "${_mp}/skeleton/root" && ln -s ../../.cshrc .cshrc) || return
+    else
+        echo "Extracting base ..."
+        tar -C "${_mp}" --exclude=./root/.cshrc --exclude=./root/.profile --no-safe-writes -xJp -f "${_basetxz}" || return
+        # In the original archive they are archived as hardlinks: make proper symlinks here
+        (cd "${_mp}/root" && ln -s ../.profile .profile) || return
+        (cd "${_mp}/root" && ln -s ../.cshrc .cshrc) || return        
+    fi
 
     find "${_mp}/boot" -type f -delete || true
 }
 
 
 #
-# _do_mount dataset mountpoint dry-run mount-natural
+# _do_mount dataset mountpoint dry-run mount-natural childs-only
 #
 _do_mount() {
-    local _dsname _mountpoint _dry_run _mount_natural
-    
+    local _dsname _mountpoint _dry_run _mount_natural _childs_only
+
     local _name _mp _canmount _mounted
     local _rootds_mountpoint _relative_mp _real_mp
 
@@ -342,6 +374,7 @@
     _mountpoint="${2}"
     _dry_run="${3}"
     _mount_natural="${4}"
+    _childs_only="${5}"
 
     if [ -z "${_dsname}" ]; then
         echo "ERROR: no dataset given" >&2
@@ -408,13 +441,17 @@
                         fi
                     fi
 
-                    if [ "${_dry_run}" = "yes" ]; then
-                        echo "Would mount ${_name} on ${_real_mp}"
+                    if [ \( "${_childs_only}" = "yes" \) -a \( "${_name}" = "${_dsname}" \) ]; then
+                        echo "Skipping ${_name} because mounting childs only" 1>&2
                     else
-                        mkdir -p "${_real_mp}" 1> /dev/null 2> /dev/null || \
-                            { echo "ERROR: cannot create mountpoint ${_real_mp}" >&2; return 1; }
-                        echo "Mounting ${_name} on ${_real_mp}"
-                        mount -t zfs "${_name}" "${_real_mp}" || return 1
+                        if [ "${_dry_run}" = "yes" ]; then
+                            echo "Would mount ${_name} on ${_real_mp}"
+                        else
+                            mkdir -p "${_real_mp}" 1> /dev/null 2> /dev/null || \
+                                { echo "ERROR: cannot create mountpoint ${_real_mp}" 1>&2; return 1; }
+                            echo "Mounting ${_name} on ${_real_mp}"
+                            mount -t zfs "${_name}" "${_real_mp}" || return 1
+                        fi
                     fi
                     ;;
                 *)
@@ -435,14 +472,21 @@
 #
 command_mount_tmpl() {
     local _ds_base _ds_skel _mountpoint
-    local _opt_dry_run
+    local _opt_dry_run _opt_symlink
 
     local _opt
 
     _opt_dry_run=""
+    _opt_symlink=""
 
-    while getopts "nu" _opt ; do
+    while getopts "LPnu" _opt ; do
         case ${_opt} in
+            L)
+                _opt_symlink="yes"
+                ;;
+            P)
+                _opt_symlink="no"
+                ;;
             n|u)
                 _opt_dry_run="yes"
                 ;;
@@ -454,17 +498,23 @@
     shift $((OPTIND-1))
     OPTIND=1
 
+    [ -z "${_opt_symlink}" ] && { echo "ERROR: -L or -P must be given" 1>&2; return 2; }
+
     _ds_base="${1-}"
     _ds_skel="${2-}"
     _mountpoint="${3-}"
 
-    _do_mount "${_ds_base}" "${_mountpoint}" "${_opt_dry_run}" "" || return
-    if [ "${_opt_dry_run}" != "yes" ]; then
-        if [ ! -d "${_mountpoint}/skeleton" ]; then
-            mkdir "${_mountpoint}/skeleton" || return
+    _do_mount "${_ds_base}" "${_mountpoint}" "${_opt_dry_run}" "" "" || return
+    if [ "${_opt_symlink}" = "yes" ]; then
+        if [ "${_opt_dry_run}" != "yes" ]; then
+            if [ ! -d "${_mountpoint}/skeleton" ]; then
+                mkdir "${_mountpoint}/skeleton" || return
+            fi
         fi
+        _do_mount "${_ds_skel}" "${_mountpoint}/skeleton" "${_opt_dry_run}" "" "" || return
+    else
+        _do_mount "${_ds_skel}" "${_mountpoint}" "${_opt_dry_run}" "" "yes" || return
     fi
-    _do_mount "${_ds_skel}" "${_mountpoint}/skeleton" "${_opt_dry_run}" "" || return
 
     return 0
 }
@@ -475,7 +525,7 @@
 #
 _do_umount() {
     local _dsname
-    
+
     local _name _mp _rest
     local _rootds_mountpoint