From: Thomas Walker Lynch Date: Thu, 25 Sep 2025 11:56:49 +0000 (+0000) Subject: duplication bug fix X-Git-Url: https://git.reasoningtechnology.com/style/static/gitweb.css?a=commitdiff_plain;h=bbd8b73e9d85cd398395697d2a11f091e0065c17;p=subu duplication bug fix --- diff --git a/developer/source/mount/masu__map_own_all.sh b/developer/source/mount/masu__map_own_all.sh index 79d035b..8e14329 100755 --- a/developer/source/mount/masu__map_own_all.sh +++ b/developer/source/mount/masu__map_own_all.sh @@ -1,24 +1,27 @@ +# masu__map_own_all.sh #!/bin/bash +set -euo pipefail +masu="${1:?Usage: $0 [--suid=subu1,subu2] }" +suid_list="${2-}" # optional: --suid=a,b,c -# Check if the correct number of arguments is passed -if [ $# -ne 1 ]; then - echo "Usage: $0 " - exit 1 -fi +# Build a set for quick membership checks +want_suid() { + [[ -n "$suid_list" ]] || return 1 + [[ "$suid_list" =~ ^--suid= ]] || return 1 + IFS=',' read -r -a arr <<< "${suid_list#--suid=}" + for n in "${arr[@]}"; do [[ "$n" == "$1" ]] && return 0; done + return 1 +} -user=$1 +subus=$(./masu__subu_dir_list.sh "$masu") +[[ -n "$subus" ]] || { echo "No sub-users found for $masu"; exit 1; } -# Get the list of sub-users by calling the user_list_subu_home.sh script -subu_list=$(./masu__subu_dir_list.sh "$user") - -# Check if we received any sub-users -if [ -z "$subu_list" ]; then - echo "No sub-users found for $user." - exit 1 -fi - -# Loop through the sub-users and call user_open_subu.sh for each -for subu in $subu_list; do - echo "Opening sub-user: $subu" - ./masu_subu__map_own.sh "$user" "$subu" -done +while IFS= read -r s; do + [[ -n "$s" ]] || continue + echo "Opening sub-user: $s" + if want_suid "$s"; then + sudo ./masu_subu__map_own.sh "$masu" "$s" --suid + else + sudo ./masu_subu__map_own.sh "$masu" "$s" + fi +done <<< "$subus" diff --git a/developer/source/mount/masu__subu_dir_list.sh b/developer/source/mount/masu__subu_dir_list.sh index 6b24a53..b05af66 100755 --- a/developer/source/mount/masu__subu_dir_list.sh +++ b/developer/source/mount/masu__subu_dir_list.sh @@ -1,23 +1,15 @@ +# masu__subu_dir_list.sh #!/bin/bash +set -euo pipefail +user="${1:?usage: $0 }" -# Function to list sub-users in /home//subu -subu_list() { - local user=$1 - local subu_dir="/home/$user/subu" +# Prefer the /home//subu view; if empty/nonexistent, fall back to subu_data. +list_from_dir() { local d="$1"; [[ -d "$d" ]] && find "$d" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' || true; } - if [ ! -d "/home/$user" ]; then - echo "Error: /home/$user does not exist!" - return 1 - fi +candidates="$( + list_from_dir "/home/$user/subu" + [[ -d "/home/$user/subu" && -n "$(ls -A /home/$user/subu 2>/dev/null || true)" ]] || list_from_dir "/home/$user/subu_data" +)" - if [ ! -d "$subu_dir" ]; then - echo "Error: $subu_dir does not exist!" - return 1 - fi - - # List all sub-users in the subu directory - find "$subu_dir" -maxdepth 1 -mindepth 1 -type d -exec basename {} \; -} - -# Run the function with the user as an argument -subu_list "$1" +# Unique, stable order +printf '%s\n' "$candidates" | LC_ALL=C sort -u diff --git a/developer/source/mount/masu_subu__map_own.sh b/developer/source/mount/masu_subu__map_own.sh index d6820e5..319437c 100755 --- a/developer/source/mount/masu_subu__map_own.sh +++ b/developer/source/mount/masu_subu__map_own.sh @@ -1,92 +1,62 @@ +# masu_subu__map_own.sh #!/bin/bash -# masu_subu__map_own.sh [--suid] -# -# Examples: -# sudo ./masu_subu__map_own.sh Thomas developer -# sudo ./masu_subu__map_own.sh Thomas developer --suid - +# usage: sudo ./masu_subu__map_own.sh [--suid] set -euo pipefail -need() { command -v "$1" >/dev/null 2>&1 || { echo "missing: $1" >&2; exit 1; }; } - -subu_bind() { - local user="$1" - local subu="$2" - local want_suid="${3-}" # optional third arg - - need bindfs - need findmnt - need mountpoint - - # identities - local master_user_name="$user" - local master_group="$user" - local subu_user_name="${user}-${subu}" - local subu_group="${user}-${subu}" - - id "$master_user_name" &>/dev/null || { echo "Error: user '$master_user_name' not found!" >&2; return 1; } - id "$subu_user_name" &>/dev/null || { echo "Error: sub-user '$subu_user_name' not found!" >&2; return 1; } - - # paths - local subu_data_path="/home/$user/subu_data/$subu" - local subu_mount_point_path="/home/$user/subu/$subu" - - [[ -d "$subu_data_path" ]] || { echo "Error: source dir '$subu_data_path' does not exist!" >&2; return 1; } - mkdir -p "$subu_mount_point_path" - - # desired options - local base_opts="allow_other,default_permissions,exec" - local opts="$base_opts,nosuid" - if [[ "$want_suid" == "--suid" ]]; then - opts="$base_opts,suid" +need(){ command -v "$1" >/dev/null 2>&1 || { echo "missing: $1" >&2; exit 1; }; } + +want_suid=0 +case "${3-}" in + --suid) want_suid=1 ;; + "" ) ;; + * ) echo "unknown option: $3" >&2; exit 2 ;; +esac + +masu="${1:?usage: $0 [--suid] }" +subu="${2:?usage: $0 [--suid] }" + +need bindfs; need findmnt; need mountpoint; id "$masu" >/dev/null +id "${masu}-${subu}" >/dev/null + +src="/home/$masu/subu_data/$subu" +tgt="/home/$masu/subu/$subu" +[[ -d "$src" ]] || { echo "Error: source dir '$src' does not exist" >&2; exit 1; } +mkdir -p "$tgt" + +base_opts="allow_other,default_permissions,exec" +desired_opts="$base_opts,$([[ $want_suid -eq 1 ]] && echo suid || echo nosuid)" +map_opt="--map=${masu}-${subu}/${masu}:@${masu}-${subu}/@${masu}" + +opts_have() { grep -qw "$1"; } + +# Peel off incorrect layers until either: +# - nothing is mounted on $tgt, or +# - the top-most layer is a bindfs of $src with desired opts +while mountpoint -q "$tgt"; do + read -r FSTYPE SOURCE OPTIONS < <(findmnt -T "$tgt" -no FSTYPE,SOURCE,OPTIONS) + if [[ "$FSTYPE" != fuse*bindfs* && "$FSTYPE" != fuse.bindfs && "$FSTYPE" != fuse3.bindfs ]]; then + echo "⚠︎ '$tgt' is a mountpoint but not bindfs (fstype=$FSTYPE); unmounting this layer…" + umount "$tgt" || umount -l "$tgt" || true + continue fi - # map rule - local map_opt="--map=${subu_user_name}/${master_user_name}:@${subu_group}/@${master_group}" - - # check if *this path* is already a mountpoint - if mountpoint -q "$subu_mount_point_path"; then - # only care about a few options, avoid brittle whole-string compare - local current_opts - current_opts="$(findmnt -no OPTIONS -T "$subu_mount_point_path" 2>/dev/null || true)" - - have_exec=$(grep -qw exec <<<"$current_opts" && echo 1 || echo 0) - have_suid=$(grep -qw suid <<<"$current_opts" && echo 1 || echo 0) - have_nosuid=$(grep -qw nosuid <<<"$current_opts" && echo 1 || echo 0) - have_allow=$(grep -qw allow_other <<<"$current_opts" && echo 1 || echo 0) - - want_suid_flag=$([[ "$want_suid" == "--suid" ]] && echo 1 || echo 0) - - needs_change=0 - [[ $have_exec -eq 1 ]] || needs_change=1 - [[ $have_allow -eq 1 ]] || needs_change=1 - if [[ $want_suid_flag -eq 1 ]]; then - [[ $have_suid -eq 1 && $have_nosuid -eq 0 ]] || needs_change=1 - else - [[ $have_nosuid -eq 1 && $have_suid -eq 0 ]] || needs_change=1 - fi - - if [[ $needs_change -eq 1 ]]; then - echo "remounting $subu_mount_point_path with opts: $opts" - umount "$subu_mount_point_path" || { echo "⚠︎ umount failed; trying lazy"; umount -l "$subu_mount_point_path" || true; } - bindfs -o "$opts" $map_opt "$subu_data_path" "$subu_mount_point_path" - else - echo "already mounted with compatible options: $current_opts" - fi - else - echo "mounting $subu_data_path -> $subu_mount_point_path with opts: $opts" - bindfs -o "$opts" $map_opt "$subu_data_path" "$subu_mount_point_path" + # Normalize desired + want_suid_kw=$([[ $want_suid -eq 1 ]] && echo suid || echo nosuid) + # Check source and essential flags without brittle full-string compare + if [[ "$SOURCE" == "$src" ]] \ + && opts_have <<<"$OPTIONS" allow_other \ + && opts_have <<<"$OPTIONS" exec \ + && opts_have <<<"$OPTIONS" "$want_suid_kw" \ + && ! opts_have <<<"$OPTIONS" "$([[ $want_suid -eq 1 ]] && echo nosuid || echo suid)"; then + echo "already mounted OK: $tgt ← $src ($OPTIONS)" + exit 0 fi - # verify - findmnt "$subu_mount_point_path" -o TARGET,FSTYPE,OPTIONS - echo "OK: $subu_data_path -> $subu_mount_point_path" - if [[ "$want_suid" == "--suid" ]]; then - echo "note: suid is ENABLED; setuid binaries (e.g., the gasket) can take effect on this mount." - else - echo "note: nosuid (default) — setuid will NOT take effect on this mount." - fi -} + echo "unmounting incorrect layer on $tgt (src=$SOURCE opts=$OPTIONS)…" + umount "$tgt" || umount -l "$tgt" || true +done -# run (sudo not needed if already root) -subu_bind "${1:-}" "${2:-}" "${3:-}" +echo "mounting $src -> $tgt (opts: $desired_opts)" +bindfs -o "$desired_opts" $map_opt "$src" "$tgt" +findmnt "$tgt" -o TARGET,SOURCE,FSTYPE,OPTIONS +echo "OK"