From be2edd19d89ff383e1373d730126aa671232ee66 Mon Sep 17 00:00:00 2001 From: David Kebler Date: Thu, 2 Jan 2025 17:23:00 -0800 Subject: [PATCH] added functions for ini file parsing and conversion to environment vars fixed dir2subv functions add subv_snap fixed is_subv --- modules/filesystem/btrfs/btrfs.mod | 155 +++++++++++++++++------------ modules/scripting/ini.mod | 16 +++ 2 files changed, 107 insertions(+), 64 deletions(-) create mode 100644 modules/scripting/ini.mod diff --git a/modules/filesystem/btrfs/btrfs.mod b/modules/filesystem/btrfs/btrfs.mod index 9fef071..c02384a 100644 --- a/modules/filesystem/btrfs/btrfs.mod +++ b/modules/filesystem/btrfs/btrfs.mod @@ -9,26 +9,40 @@ module_load path is_subv () { if [[ $1 == "-r" ]]; then - if ! btrfs subvolume show "$2" 2> /dev/null | grep readonly &> /dev/null; then return 1; fi - else - return $(btrfs subvolume show "$1" &> /dev/null) + return $(btrfs subvolume show "$2" 2> /dev/null | grep readonly &> /dev/null) + else + return $(btrfs subvolume show "$1" &> /dev/null) + fi + +} + +is_subvv () { + if is_subv "$@"; then + echo is a $([[ $1 == "-r" ]] && echo "read only") subvolume + else + echo is not a $([[ $1 == "-r" ]] && echo "read only") subvolume + return 1 fi } +# TODO: convert these into subcommands -is_subvv () { - if [[ $1 == "-r" ]]; then - if ! btrfs subvolume show "$2" 2> /dev/null | grep readonly &> /dev/null; then - echo not a readonly subvolume - else - echo readonly subvoluem - fi - else - if btrfs subvolume show "$1" &> /dev/null; then - echo subvolume +subv_snap () { + local usesudo; local ro + [[ $1 == "-r" ]] && ro=true && shift + [[ $# -eq 0 ]] && echo no subvolume name passed && return 1 + [[ $# -eq 1 ]] && echo no snapshot path/name passed && return 2 + [[ $EUID -ne 0 ]] && usesudo=sudo + if is_subv "$1"; then + if [[ -v PS1 ]]; then + confirm create snapshot of subvolume $(realpath "$1") to $(realpath "$2") || return 1 + $usesudo "$BTRFS_BIN" subvolume snapshot $ro "$1" "$2" else - echo not a subvolume + $usesudo "$BTRFS_BIN" subvolume snapshot $ro -q "$1" "$2" fi + else + echo $1 not a subvolume, can not make a snapshot + return 3 fi } @@ -89,6 +103,7 @@ subv_del() { + subv_size () { local all; [[ $1 == "-a" ]] && all=true @@ -118,13 +133,14 @@ echo "~ $((subvolumeFolderSize/1024/1024)) GB" } # https://unix.stackexchange.com/questions/93324/how-does-this-find-command-using-find-exec-sh-c-sh-work -find_subvolumes() { - dir=${1:-.} - dep=${2:-1} - sudo /bin/find "$dir" -mindepth 1 -maxdepth "$dep" -type d -exec bash -c ' +subv_find() { + local dir=${1:-.} + local max="-maxdepth ${2:-1}" + [[ "$2" == "max" ]] && max="" + sudo /bin/find "$dir" -mindepth 1 $max -type d -exec sudo -E bash -c ' for d do - subv=$(basename $d) - sudo '"$BTRFS_BIN"' subvolume show "$d" >/dev/null 2>&1 && printf "%s\n" "$subv" + lvl=$(/bin/btrfs subvolume show "$d" 2>/dev/null | grep "Top level ID:") + [[ ${lvl##* } -gt 0 ]] && printf "%s\n" "$d" done' find-sh {} + } @@ -196,27 +212,37 @@ subv_xfer() { $dr sudo "$BTRFS_BIN" sub snap -r "$src" "$tsnap" fi - if [[ $dr ]]; then - echo "sudo $BTRFS_BIN send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | btrfs receive $dest" - echo "sudo mv $dest/$name.tmp $dest/$name$ext" - echo "[[ ""$tsnap"" ]] && sudo $BTRFS_BIN sub del $tsnap" - echo "sudo ""$BTRFS_BIN"" sub snap $dest/$name.tmp $dest/$name$ext" - echo "sudo ""$BTRFS_BIN"" sub del $dest/$name.tmp" - else - # TODO: add mbuffer, show progress - sudo "$BTRFS_BIN" send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | sudo "$BTRFS_BIN" receive "$dest" - # FIXME: take a snapshot of the destination .tmp then remove .tmp, otherwise it will be readonly - # sudo mv "$dest"/"$name".tmp "$dest"/"$name"$ext - if is_subv -r "$dest"/"$name".tmp; then - sudo "$BTRFS_BIN" sub snap "$dest"/"$name".tmp "$dest"/"$name""$ext" - sudo "$BTRFS_BIN" sub del "$dest"/"$name".tmp - echo transfer is complete - fi - [[ "$tsnap" ]] && sudo "$BTRFS_BIN" sub del "$tsnap" - - ls -la "$dest" - ls -la "$dest"/"$name""$ext" - fi +if [[ $dr ]]; then + echo "sudo $BTRFS_BIN send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | btrfs receive $dest" + echo "[[ ""$tsnap"" ]] && sudo $BTRFS_BIN sub del $tsnap" + echo "sudo ""$BTRFS_BIN"" sub snap $dest/$name.tmp $dest/$name$ext" + echo "sudo ""$BTRFS_BIN"" sub del $dest/$name.tmp" + else + # TODO: add mbuffer, show progress + if is_subv "$dest"/"$name".tmp; then + echo destination temporary subvolume "$dest"/"$name".tmp exists. Deleting so xfer can proceed + subv_del "$dest"/"$name".tmp + fi + sudo "$BTRFS_BIN" send $([[ $tsnap ]] && echo "$tsnap" || echo "$src") | sudo "$BTRFS_BIN" receive "$dest" + if is_subv -r "$dest"/"$name".tmp; then + echo transfer of "$name" to "$name""$ext" is complete, deleting source temporary snap "$tsnap" + [[ "$tsnap" ]] && sudo "$BTRFS_BIN" sub del "$tsnap" + if is_subv "$dest"/"$name""$ext"; then + if ! confirm -s destination subvolume "$dest"/"$name""$ext" already exists do you want to overwrite it; then + sudo "$BTRFS_BIN" sub del "$dest"/"$name".tmp + return 1 + fi + fi + sudo "$BTRFS_BIN" sub snap "$dest"/"$name".tmp "$dest"/"$name""$ext" + sudo "$BTRFS_BIN" sub del "$dest"/"$name".tmp + ls -la "$dest" + ls -la "$dest"/"$name""$ext" + else + echo error receiving "$dest"/"$name".tmp, deleting source temporary snap "$tsnap" + [[ "$tsnap" ]] && sudo "$BTRFS_BIN" sub del "$tsnap" + return 1 + fi + fi } @@ -322,22 +348,20 @@ alias btsub="sudo $BTRFS_BIN subvolume" dir2subv () { # Directory to convert into BTRFS subvolume - - -dirPath="$1" + local dirPath; local dirSub; local perms + dirPath="$(realpath "$1")" if [[ ! -d $dirPath ]]; then echo no directory at "$dirPath"; return 1; fi -dirSub="$2" +[[ $2 ]] && dirSub="$(realpath "$2")" perms=/tmp/perms_$(basename "$dirPath") - if is_subv "$dirPath"; then echo "$dirPath" is already a subvolume, exiting; return 0; fi if ! confirm transform "$dirPath" into a subvolume at "${dirSub:-$dirPath}"; then return 1; fi pushd "$dirPath" &> /dev/null || return echo saving permissions at "$PWD" to "$perms" -getfacl -R . | sudo tee "$perms" -cat "$perms" +sudo bash -c 'getfacl -R . > '"$perms"'' +popd &> /dev/null || return 0 if [[ ! $dirSub ]]; then echo moving "$dirPath" to "${dirPath}_temp" @@ -347,34 +371,37 @@ fi echo creating subvolume at "${dirSub:-$dirPath}" sudo "$BTRFS_BIN" subvolume create "${dirSub:-$dirPath}" -# Copy as reflink for speed and save space +echo copying contents to new subvolume if [[ $dirSub ]]; then -echo copying "$dirPath" to "$dirSub" -sudo cp --archive --one-file-system --reflink=always "${dirPath}/." "${dirSub}" -pushd "$dirSub" &> /dev/null || return 1 + # if confirm copying "$dirPath" to "$dirSub"; then + sudo /bin/cp --archive --one-file-system --reflink=always "${dirPath}/." "${dirSub}" + # fi else -echo copying "${dirPath}"_temp back to subvolume at "$dirPath" -sudo cp --archive --one-file-system --reflink=always "${dirPath}_temp/." "${dirPath}" + # if confirm copying "${dirPath}"_temp back to subvolume at "$dirPath"; then + sudo /bin/cp --archive --one-file-system --reflink=always "${dirPath}_temp/." "${dirPath}" + # fi fi -# echo for debugging changing permissions at "$PWD" -# sudo chmod -R 777 . -# sudo chown -R nobody:nobody . -# ls -la . -# echo "---------------------" - -echo restore saved permissions to "$perms" -sudo setfacl --restore="$perms" -sudo rm -f "$perms" +pushd "${dirSub:-$dirPath}" &> /dev/null || return +# cat $perms +echo restoring saved permissions using "$perms" on $PWD +if sudo setfacl --restore="$perms"; then + echo permissions restored, deleting $perms + sudo rm -f "$perms" + else + echo FATAL: permissions were not resorted +fi +popd &> /dev/null || return 0 echo "$dirPath" has been converted into a subvolume at "${dirSub:-$dirPath}" if [[ -d ${dirPath}_temp ]];then + echo $dirPath was converted but now check it is ok before deleting temporary copy if confirm -s do you want to now delete the copy at "${dirPath}"_temp; then sudo rm -rf --one-file-system "${dirPath}_temp" fi fi -popd &> /dev/null || return 0 + } diff --git a/modules/scripting/ini.mod b/modules/scripting/ini.mod new file mode 100644 index 0000000..5967bb4 --- /dev/null +++ b/modules/scripting/ini.mod @@ -0,0 +1,16 @@ +#!/bin/bash +# https://stackoverflow.com/a/61329094 + +parse_ini () { +local ini=$1 +if [[ ! -f $ini ]]; then ini=$1.ini; if [[ ! -f $ini ]]; then echo no file "$ini"; return 1; fi fi +sed -n -E "/^\[.*\]/{s/\[(.*)\]/\1/;h;n;};/^[a-zA-Z]/{s/#.*//;G;s/([^ ]*) *= *(.*)\n(.*)/\3_\1='\2'/;p;}" "$ini" | \ +sed -E 's/^_//'| \ +sed -E 's/^([^=]*)[.]/\1_/' | \ +sed -E 's/^([^=]*)[-]/\1_/' | \ +( [[ $2 ]] && grep "$2" || cat ) +} + +ini2env () { + eval $(parse_ini "$@") +} \ No newline at end of file