penguin/utils

my env utils

commit a0d3e81faa92e8b53fc5ca7f75b5e05c2694b77f

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-07-20T15:13:56Z
subjectAdded kstore download
commit a0d3e81faa92e8b53fc5ca7f75b5e05c2694b77f
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-07-20T15:13:56Z

    Added kstore download
---
 bash/dist/rbashrc        |   2 +-
 bash/dist/rbashrc.asc    |  10 ++--
 bash/dist/sources.list   |   2 +-
 bash/sources/16_keystore | 117 +++++++++++++++++++++++++++++++++++++++--------
 4 files changed, 105 insertions(+), 26 deletions(-)

diff --git a/bash/dist/rbashrc b/bash/dist/rbashrc
index b0b2c6a..25dee4e 100755
--- a/bash/dist/rbashrc
+++ b/bash/dist/rbashrc
@@ -18,7 +18,7 @@ RBASH_CONFIG="$RBASH_HOME/config"
 RBASH_ENV="$RBASH_HOME/env"
 RBASH_MERGED="$RBASH_CACHE_DIR/merged"
 RBASH_BIN="$RBASH_HOME/bin"
-RBASH_SOURCES_SUM="35fcb5b8248bd42d7b723b59fced636d08e183db39157753f331d6312d497f26"
+RBASH_SOURCES_SUM="27af738aaf2cc06e37c7a50f19982c3cac8b9444414997c67738ad5911d5f502"
 
 
 # ---- rbash: bash/core/00_env.bash ----
diff --git a/bash/dist/rbashrc.asc b/bash/dist/rbashrc.asc
index a32eb0d..a7535a2 100644
--- a/bash/dist/rbashrc.asc
+++ b/bash/dist/rbashrc.asc
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNATURE-----
 
-iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCal4xjxsUgAAAAAAEAA5t
-YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8MS8AEAsBsn7/OguDTuudMHR2zj
-qhucXMmwPNog4hWUEZkVJ+gBAOqJ8S/RzrHyZUCaZCytQqgI9aeex6BxxT1jplBH
-bbsM
-=UzMm
+iJEEABYKADkWIQR8HpSNhBJUxWnt+97Vz1+xz60nwwUCal47IhsUgAAAAAAEAA5t
+YW51MiwyLjUrMS4xMiwwLDMACgkQ1c9fsc+tJ8M5AQD+NsWRcjhbw6Wz3Qzt0UqE
+bP7n30ypjOdxdsP33DOcS8MA/j2WUY8PUlJ0jn2V+Wtcuvey0AzidOex8e4iKvID
+IFQN
+=IJtH
 -----END PGP SIGNATURE-----
diff --git a/bash/dist/sources.list b/bash/dist/sources.list
index 8324fc4..779bf52 100644
--- a/bash/dist/sources.list
+++ b/bash/dist/sources.list
@@ -3,7 +3,7 @@ e50644286373408263ce5a6f455bf967585a767cce055e67423bd33fdafeab9f  sources/12_sho
 043a103f7602304732b37c8219ba4f74bc8af37278fc6d2f63d642ef9a29a6fe  sources/13_shortcuts_macos
 3340cf44a97771e6839e03443e8276c25804e0918c0415b1ffe0112d060cee2d  sources/14_shortcuts_greps
 a0d62f10f39fa988d8ff8ce13a1751488e6bad1662c3b97ab8ef3fa09c702666  sources/15_gpg-agent
-4b3c7bdc57fbc94e072e74399cd800c3693ff635fa9064f9e5d05c1ac92e255c  sources/16_keystore
+b7fd79447cef0353c54501c23022f1a45fc9377f5826694a67710e06332073e9  sources/16_keystore
 570a67928ad4eb2ae343ebc3eee39413989087388fe35e0cd675573add6730b0  sources/17_kcontext
 f45e3d068475a40b838336f675948d07b544967d03fbf491abd70e131db38fb0  sources/18_kotp
 7ce7ab97af4aa3f6681981d0d2f687b3eb9b7e7beda5e3b74b651210f7c6fac9  sources/19_k8s_funcs
diff --git a/bash/sources/16_keystore b/bash/sources/16_keystore
index 050f7f0..e4a9e5a 100644
--- a/bash/sources/16_keystore
+++ b/bash/sources/16_keystore
@@ -2,14 +2,14 @@
 
 _SQLITE=$( which sqlite3 2>&1 )
 if [ $? -ne 0 ]; then
-    echo "sqlite3 is missing" >&2
-    return 1
+	echo "sqlite3 is missing" >&2
+	return 1
 fi
 
 echo "test" | openssl enc -e -aes-256-cbc -pbkdf2 -k test 2>/dev/null > /dev/null
 if [ $? -ne 0 ]; then
-    echo "openssl does not exists nor support pbkdf2" >&2
-    return 1
+	echo "openssl does not exists nor support pbkdf2" >&2
+	return 1
 fi
 
 _AUTH_DB=$RBASH_HOME/keystore.db
@@ -32,6 +32,7 @@ function kstore {
 		search) shift; _kstoresearch $@ ;;
 		secret) shift; _kstoresecret $@ ;;
 		upload) shift; _kstoreupload $@ ;;
+		download) shift; _kstoredownload $@ ;;
 		*)
 			__func_head "add [key] [value|file|-] [prop, default: $_KSTORE_DEF_PROP]"
 			__func_help "update [key] [value|file|-] [prop, default: $_KSTORE_DEF_PROP]"
@@ -41,7 +42,8 @@ function kstore {
 			__func_help "list"
 			__func_help "search [key] [prop]"
 			__func_help "secret ..."
-			__func_help "upload s3-compatible-provider-name"
+			__func_help "upload NAME files..."
+			__func_help "download NAME"
 			__func_help "query SQL"
 			return 1
 			;;
@@ -50,7 +52,7 @@ function kstore {
 }
 
 function _kstore {
-    local CUR=${COMP_WORDS[COMP_CWORD]}
+	local CUR=${COMP_WORDS[COMP_CWORD]}
 	local SCOPE=${COMP_WORDS[COMP_CWORD-1]}
 	local t
 
@@ -58,7 +60,7 @@ function _kstore {
 
 	case "$SCOPE" in
 		kstore)
-			COMPREPLY=( $(compgen -W "add del get list query update upload search secret" -- $CUR) )
+			COMPREPLY=( $(compgen -W "add del download get list query update upload search secret" -- $CUR) )
 			return
 			;;
 		get|update)
@@ -526,7 +528,7 @@ function _kstoresecret-change {
 
 function _kstoreupload {
 	if [ -z "$1" ]; then
-		__func_head "[DIR]"
+		__func_head "NAME files..."
 		return 1
 	fi
 
@@ -540,16 +542,11 @@ function _kstoreupload {
 	local _TARGET _FNAME _TEMP
 
 	_TARGET="$1"
+	shift
 
-	if [ ! -r "$_TARGET" ]; then
-		echo "\"$_TARGET\" is not readable"
-		return 1
-	fi
+	_TEMP="$(mktemp -t kstoreupload)" || return 1
 
-	_FNAME=$( basename "$_TARGET" )
-	_TEMP="$( mktemp ).tar.gz"
-
-	tar zcf "$_TEMP" "$_TARGET"
+	tar zcf "$_TEMP" $@
 	_kstoreenc "$_TEMP" > "${_TEMP}.enc"
 
 	echo "Size: $(du -sh "${_TEMP}.enc")"
@@ -560,6 +557,88 @@ function _kstoreupload {
 	rm "${_TEMP}.enc"
 }
 
+function _kstoredownload {
+	if [ -z "$1" ]; then
+		__func_head "NAME"
+		return 1
+	fi
+
+	_kstoreinit || return 1
+
+	if ! command -v arch-download-aws4 >/dev/null 2>&1; then
+		_kstoreinit-s3au || return 1
+	fi
+
+	local _TARGET _TMP _OLD_PIPEFAIL
+	local _ENTRY
+	local -a _EXISTING=()
+
+	_TARGET="$1"
+	_TMP="$(mktemp -t kstoredownload).tar.gz" || return 1
+
+	_OLD_PIPEFAIL="$(set +o | grep pipefail)"
+	set -o pipefail
+
+	if ! arch-download-aws4 "uploads/$_TARGET.enc" |
+		_kstoredec > "$_TMP"
+	then
+		eval "$_OLD_PIPEFAIL"
+		rm -f "$_TMP"
+		echo "Download/decrypt failed. Incorrect bucket? ($ARCH_S3_BUCKET_URL)" >&2
+		return 1
+	fi
+
+	eval "$_OLD_PIPEFAIL"
+
+	if ! tar tzf "$_TMP" >/dev/null; then
+		rm -f "$_TMP"
+		echo "Downloaded data is not a valid tar.gz archive." >&2
+		return 1
+	fi
+
+	# Reject absolute paths and path traversal before extracting.
+	while IFS= read -r _ENTRY; do
+		case "$_ENTRY" in
+			/*|../*|*/../*|*/..)
+				rm -f "$_TMP"
+				echo "Unsafe archive path: $_ENTRY" >&2
+				return 1
+				;;
+		esac
+
+		# Ignore directory collisions; existing directories are expected.
+		if [[ "$_ENTRY" != */ && -e "$_ENTRY" ]]; then
+			_EXISTING+=("$_ENTRY")
+		fi
+	done < <(tar tzf "$_TMP")
+
+	if ((${#_EXISTING[@]})); then
+		echo "The following files already exist:"
+		printf '  %s\n' "${_EXISTING[@]}"
+
+		local _ANSWER
+		read -r -p "Replace these files? [y/N] " _ANSWER
+
+		case "$_ANSWER" in
+			[yY]|[yY][eE][sS])
+				;;
+			*)
+				rm -f "$_TMP"
+				echo "Extraction cancelled."
+				return 1
+				;;
+		esac
+	fi
+
+	if ! tar xzf "$_TMP"; then
+		rm -f "$_TMP"
+		echo "Archive extraction failed." >&2
+		return 1
+	fi
+
+	rm -f "$_TMP"
+}
+
 function _kstoresecret-clear {
 	unset _AUTH_SECRET
 	_kstoresecret-auto del
@@ -591,7 +670,7 @@ function _kstoreadd {
 	_val=`_kstoreenc "$2"`
 	_val=`_kstorequote "$_val"`
 	_prop=`_kstorequote "${3:-$_KSTORE_DEF_PROP}"`
-    $_SQLITE "$_AUTH_DB" \
+	$_SQLITE "$_AUTH_DB" \
 		"INSERT INTO $_KSTORE_TABLE ( key, prop, data )
 			VALUES( '$_key', '$_prop', '$_val' );"
 }
@@ -607,7 +686,7 @@ function _kstoreget {
 	_prop=`_kstorequote "${2:-$_KSTORE_DEF_PROP}"`
 	_cond="key = '$_key' AND prop = '$_prop'"
 
-    $_SQLITE "$_AUTH_DB" "SELECT 1111 FROM $_KSTORE_TABLE WHERE $_cond;" | grep -q 1111
+	$_SQLITE "$_AUTH_DB" "SELECT 1111 FROM $_KSTORE_TABLE WHERE $_cond;" | grep -q 1111
 	if [ $? -eq 0 ]; then
 		$_SQLITE -list "$_AUTH_DB" "SELECT ( data ) FROM $_KSTORE_TABLE WHERE $_cond;" | _kstoredec
 	else
@@ -628,7 +707,7 @@ function _kstoredel {
 	_prop=`_kstorequote "${2:-$_KSTORE_DEF_PROP}"`
 	_cond="key = '$_key' AND prop = '$_prop'"
 
-    $_SQLITE "$_AUTH_DB" "SELECT 1111 FROM $_KSTORE_TABLE WHERE $_cond;" | grep -q 1111
+	$_SQLITE "$_AUTH_DB" "SELECT 1111 FROM $_KSTORE_TABLE WHERE $_cond;" | grep -q 1111
 	if [ $? -eq 0 ]; then
 		$_SQLITE "$_AUTH_DB" "SELECT * FROM $_KSTORE_TABLE WHERE $_cond;"
 		echo