Compare commits
6 commits
160a7763b7
...
74ed7582f9
| Author | SHA1 | Date | |
|---|---|---|---|
| 74ed7582f9 | |||
| 10d81b7e5b | |||
| 83324dd0f7 | |||
| 2e31283b61 | |||
| 84f55f82b8 | |||
| eb0aab1613 |
11 changed files with 426 additions and 238 deletions
31
README.md
31
README.md
|
|
@ -36,8 +36,6 @@ lackadaisical` if you so desire.
|
|||
To read this notice again, call the function 'daisy_help'.
|
||||
===============================================================================
|
||||
These are the included binaries and utilities:
|
||||
- calm:
|
||||
Reduce a process 'niceness' to 0.
|
||||
- cdz:
|
||||
This utility extracts an archive to /tmp and changes
|
||||
directory to it in a new shell instance. Upon exit,
|
||||
|
|
@ -47,6 +45,27 @@ These are the included binaries and utilities:
|
|||
NO_ARCHIVEMOUNT=1. The standard script supports zip,
|
||||
tarballs, and rar archives. We recommend relying on
|
||||
archivemount` if you have it installed.
|
||||
Use "--check" to only check if a file is an archive.
|
||||
It returns 0 if it is, 1 otherwise.
|
||||
- squasher:
|
||||
These convenient set of tools allow you to easily create
|
||||
XZ-compressed SquashFS images from existing folders to save
|
||||
disk space. The resulting folder is still writable since it is
|
||||
mounted using an 'overlay' system. You can use 'squasher make'
|
||||
to compresses an existing folder. These folders are automatically
|
||||
mounted when you use 'cd' to navigate to them (via an alias).
|
||||
When using 'make-squash-image' on an already mounted folder, it will
|
||||
instead update the existing image. As of writing, we do not have a
|
||||
SystemD service to auto-mount, however, you cam easily add auto-mount
|
||||
as a cron job. Here is a list of tools, they all take the same
|
||||
folder argument:
|
||||
> squasher make: Converts the folder into a hidden image
|
||||
on the same disk as the folder.
|
||||
> squasher mount: Sets up a mount for the XZ image alongside
|
||||
directories for changes
|
||||
> squasher umount: Self-explanatory.
|
||||
> squasher destroy: Extracts the image and essentially reverts
|
||||
everything. File changes are kept, however.
|
||||
- editx:
|
||||
Uses your standard CLI editor to create/modify a
|
||||
file and make it executable.
|
||||
|
|
@ -64,7 +83,7 @@ These are the included binaries and utilities:
|
|||
Format is <dir> -> .daisy/<dir>/<year>/<month>/<day>.
|
||||
Recommended to run via crontab - automatically cleans
|
||||
up empty folders.
|
||||
A symlink to the base of the folder's tree, ".tree",
|
||||
A symbolic link to the base of the folder's tree, ".tree",
|
||||
is created in the root of the specified directly.
|
||||
Can be used for everything you'd like to sort by date.
|
||||
For example; a diary, browser downloads, backups, code.
|
||||
|
|
@ -92,11 +111,11 @@ These are the included binaries and utilities:
|
|||
This is a tool similar to which and others, the key
|
||||
difference is that it returns partial matches. It can
|
||||
be used to search for binaries.
|
||||
- binbox:
|
||||
- scripbox:
|
||||
This tool can be used to pack bash scripts into one
|
||||
big megascript, much like how `busybox` works.
|
||||
You can also make symlinks to it to invoke a specific
|
||||
script (as of writing, 11/25, symlinks do not work well).
|
||||
script.
|
||||
- bak/unbak:
|
||||
These small utilities make backups of files by making
|
||||
a copy with a .bak suffix. Unbak reverses the process
|
||||
|
|
@ -137,6 +156,8 @@ These are the included binaries and utilities:
|
|||
The variable is stored locally in the shell as "LD_CLIP".
|
||||
- ldrc:
|
||||
Edits daisy.source and re-sources it, similarly to shrc.
|
||||
Append "-e" to edit "extra.src", to add custom functions in the
|
||||
lackadaisical namespace.
|
||||
- daisy_reload:
|
||||
Re-sources daisy.source. Essentially `ldrc` without
|
||||
editing.
|
||||
|
|
|
|||
12
agenda
12
agenda
|
|
@ -28,10 +28,7 @@ root_dir=$(dirname $1)/.daisy/$(basename $1)
|
|||
today_sym=$1
|
||||
|
||||
# Present day
|
||||
today=$(date -I)
|
||||
year=$(echo $today | awk -F"-" '{print $1}')
|
||||
month=$(echo $today | awk -F"-" '{print $2}')
|
||||
day=$(echo $today | awk -F"-" '{print $3}')
|
||||
read year month day < <(date "+%Y %m %d")
|
||||
|
||||
set -e
|
||||
|
||||
|
|
@ -50,11 +47,10 @@ function errorFn
|
|||
trap errorFn ERR
|
||||
|
||||
# First we clear out empty folders, and remove the symlink if it exists
|
||||
test -e "$root_dir" && find "$root_dir" -maxdepth 3 -type d -empty -print | xargs rm -rf
|
||||
test -L "$today_sym" && rm -rf "$today_sym"
|
||||
test -e "$root_dir" && find "$root_dir" -maxdepth 3 -type d -empty -delete
|
||||
|
||||
# Now we can set up today's directory
|
||||
mkdir -p "$root_dir/$year/$month/$day"
|
||||
ln -s "$root_dir/$year/$month/$day" "$today_sym"
|
||||
ln -sf "$root_dir/$year/$month/$day" "$today_sym"
|
||||
ln -s "$root_dir" "$today_sym/.tree"
|
||||
exitcode=@?
|
||||
exitcode=$?
|
||||
|
|
|
|||
41
calm
41
calm
|
|
@ -1,41 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# Calm a process down
|
||||
# NEEDS_WORK: cleanup
|
||||
# calm <pid> == only one process
|
||||
# calm <bin> == all processes that match query
|
||||
# calm * == if used in proc or a folder with just PID files, if not you will get an error
|
||||
# calm <pid> <bin> .... OK
|
||||
# set's NICE value to 0
|
||||
# need sudo
|
||||
|
||||
LD_INTERNAL=1
|
||||
. $(dirname $(realpath $0))/daisy.source
|
||||
|
||||
pids=$@
|
||||
|
||||
errorFn()
|
||||
{
|
||||
echo calm: Invalid operation or no such PID/process \(\"$(echo "$pids" | tr '\n' ' ' | cut -c -20)...\"\)
|
||||
exit
|
||||
}
|
||||
|
||||
for pid in $pids
|
||||
do
|
||||
# Process to PID in elegant way
|
||||
newpids=$(pidof "$pid")
|
||||
if [ "$newpids" ]
|
||||
then
|
||||
binary=$pid
|
||||
pid=$newpids
|
||||
else
|
||||
newbins=$pid
|
||||
binary=$(ps -p "$pid" -o comm= 2>/dev/null )
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
errorFn
|
||||
fi
|
||||
fi
|
||||
|
||||
echo Calming down $pid \("$binary"\)...
|
||||
sudo renice -n 0 -p $pid;
|
||||
done
|
||||
195
cdz
195
cdz
|
|
@ -1,118 +1,151 @@
|
|||
#!/usr/bin/env bash
|
||||
# Usage: cdz [--check] <archive>
|
||||
|
||||
if [[ $LD_INTERNAL -ne 1 ]];
|
||||
if [[ $LD_INTERNAL -ne 1 ]]
|
||||
then
|
||||
LD_INTERNAL=1
|
||||
. $(dirname $(realpath $0))/daisy.source
|
||||
fi
|
||||
|
||||
target=$1
|
||||
is_archive()
|
||||
{
|
||||
local file="$1"
|
||||
local mime_type=$(file --mime-type -b "$file")
|
||||
|
||||
if [[ $mime_type == *"tar"* || $file == *.tar* || $mime_type == "application/zip" || $mime_type == "application/x-rar" ]]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if command -v archivemount >/dev/null 2>&1
|
||||
then
|
||||
local test_dir=$(mktemp -d /tmp/cdz_check.XXXXXXXX)
|
||||
local result=1
|
||||
if archivemount -o readonly "$file" "$test_dir" >/dev/null 2>&1
|
||||
then
|
||||
result=0
|
||||
umount "$test_dir"
|
||||
fi
|
||||
rmdir "$test_dir"
|
||||
return $result
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if file exists
|
||||
if [[ -z "$target" ]];
|
||||
check_mode=0
|
||||
if [[ "$1" == "--check" ]]
|
||||
then
|
||||
echo "No target specified."
|
||||
check_mode=1
|
||||
shift
|
||||
fi
|
||||
|
||||
target=$1
|
||||
if [[ -z "$target" ]]
|
||||
then
|
||||
if [[ $check_mode -eq 0 ]]
|
||||
then
|
||||
echo "No target specified."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! test -f "$target";
|
||||
if [[ ! -f "$target" ]]
|
||||
then
|
||||
echo "File not found: \"$target\""
|
||||
if [[ $check_mode -eq 0 ]]
|
||||
then
|
||||
echo "File not found: \"$target\""
|
||||
fi
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Check if archivemount is present
|
||||
which archivemount 1>/dev/null 2>/dev/null
|
||||
hasmounter=$?
|
||||
target_abs=$(realpath "$target")
|
||||
name=$(basename "$target")
|
||||
|
||||
file "$target" 1>/dev/null
|
||||
exitcode=$?
|
||||
report=$(file "$target")
|
||||
name=$(echo $@ | sed 's/:.*//' | sed 's|.*/||')
|
||||
if is_archive "$target_abs"
|
||||
then
|
||||
if [[ $check_mode -eq 1 ]]
|
||||
then
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
if [[ $check_mode -eq 1 ]]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
mime_type=$(file --mime-type -b "$target_abs")
|
||||
echo "Unsupported archive type: $mime_type"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for archive type, supported types are zip/tar/rar
|
||||
# Proceed with extraction
|
||||
has_archivemount=$(command -v archivemount >/dev/null 2>&1; echo $?)
|
||||
|
||||
if [[ $has_archivemount -eq 0 && $NO_ARCHIVEMOUNT -ne 1 ]]
|
||||
then
|
||||
use_mounter=1
|
||||
else
|
||||
use_mounter=0
|
||||
fi
|
||||
|
||||
mime_type=$(file --mime-type -b "$target_abs")
|
||||
comm1=(:)
|
||||
comm2=(echo "Unsupported archive type$add: \"$target\"")
|
||||
comm2=(echo "Unsupported archive type: $mime_type")
|
||||
comm3=(:)
|
||||
comm4=(:)
|
||||
comm5=(:)
|
||||
|
||||
echo $report | grep "tar archive" 1>/dev/null
|
||||
istar=$?
|
||||
echo $report | grep "Zip archive" 1>/dev/null
|
||||
iszip=$?
|
||||
echo $report | grep "Android" 1>/dev/null
|
||||
iszip=$?
|
||||
echo $report | grep "RAR archive" 1>/dev/null
|
||||
israr=$?
|
||||
|
||||
# TAR archives come in many forms, if none of our tests say it's tar
|
||||
# ...but it looks like tar and barks like tar, let's take the shot.
|
||||
# Seems to work fairly well for the record.
|
||||
res=$(echo "$target" | grep ".tar")
|
||||
if [[ $res != "" ]];
|
||||
if [[ $use_mounter -eq 1 ]]
|
||||
then
|
||||
istar=0
|
||||
echo "Using archivemount..."
|
||||
comm2=(archivemount -o allow_root,use_ino "$target_abs")
|
||||
comm4=(cd ..)
|
||||
comm5=(umount)
|
||||
elif [[ $mime_type == *"tar"* || $target_abs == *.tar* ]]
|
||||
then
|
||||
comm2=(tar xvf "$target_abs" -C)
|
||||
elif [[ $mime_type == "application/zip" ]]
|
||||
then
|
||||
if command -v unzip >/dev/null 2>&1
|
||||
then
|
||||
comm2=(unzip -q "$target_abs" -d)
|
||||
else
|
||||
comm1=(echo "unzip is missing")
|
||||
comm3=(exit 1)
|
||||
fi
|
||||
elif [[ $mime_type == "application/x-rar" ]]
|
||||
then
|
||||
if command -v unrar >/dev/null 2>&1
|
||||
then
|
||||
# unrar needs the directory as the last argument
|
||||
comm2=(unrar x -idq "$target_abs")
|
||||
else
|
||||
comm1=(echo "unrar is missing")
|
||||
comm3=(exit 1)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $NO_ARCHIVEMOUNT -eq 1 ]]; then
|
||||
hasmounter=1
|
||||
fi
|
||||
|
||||
if (( $hasmounter == 0 )); then
|
||||
echo "We have \`archivemount\`, so we'll use that!"
|
||||
echo "If you'd prefer we not use it, please specify NO_ARCHIVEMOUNT=1"
|
||||
istar=1
|
||||
iszip=1
|
||||
israr=1
|
||||
fi
|
||||
|
||||
# Now we set the right command
|
||||
if (( $istar == 0 )); then
|
||||
comm2=(tar xvf "$target" -C)
|
||||
elif (( $iszip == 0 )); then
|
||||
which unzip 1>/dev/null
|
||||
exitcode=$?
|
||||
if (( $exitcode == 0 )); then
|
||||
comm2=(unzip -q "$target" -d)
|
||||
else
|
||||
comm1=(echo "The utility 'unzip' is missing, please install it")
|
||||
comm3=(exit 1)
|
||||
fi
|
||||
elif (( $israr == 0 )); then
|
||||
which unrar 1>/dev/null
|
||||
exitcode=$?
|
||||
if (( exitcode == 0 )); then
|
||||
comm2=(unrar -i nul "$target")
|
||||
else
|
||||
comm1=(echo "The utility 'unrar' is missing, please install it")
|
||||
comm3=(exit 1)
|
||||
fi
|
||||
elif (( $hasmounter == 0 )); then
|
||||
comm2=(archivemount -o allow_root -o use_ino "$target")
|
||||
comm4=(cd ..)
|
||||
comm5=(umount)
|
||||
fi
|
||||
|
||||
# Create the temp dir, usually
|
||||
dir=$(mktemp -d /tmp/extracted.XXXXXXXX)
|
||||
|
||||
# And the rest of the commands
|
||||
"${comm1[@]}"
|
||||
"${comm2[@]}" $dir
|
||||
if [[ ${comm2[0]} == "unrar" ]]
|
||||
then
|
||||
"${comm2[@]}" "$dir"
|
||||
else
|
||||
"${comm2[@]}" "$dir"
|
||||
fi
|
||||
"${comm3[@]}"
|
||||
|
||||
currentpath=$(pwd)
|
||||
sym="$currentpath/$name.tmp"
|
||||
ln -f -s "$dir" "$sym"
|
||||
sym="$(pwd)/$name.tmp"
|
||||
ln -sf "$dir" "$sym"
|
||||
cd "$sym"
|
||||
|
||||
echo "A symlink has been made under the name \"$sym\"."
|
||||
echo "This symlink points to the data directory \"$dir\"."
|
||||
echo "Extracted to $dir (linked via $sym)"
|
||||
echo "Type exit to finish."
|
||||
|
||||
echo "Type 'exit' to exit the extracted archive's folder and auto-delete it."
|
||||
eval $SHELL
|
||||
|
||||
"${comm4[@]}"
|
||||
"${comm5[@]}" $dir
|
||||
rm -rf $dir
|
||||
"${comm5[@]}" "$dir"
|
||||
rm -rf "$dir"
|
||||
rm "$sym"
|
||||
|
|
|
|||
61
daisy.source
61
daisy.source
|
|
@ -24,7 +24,6 @@ function ld_dbg
|
|||
then
|
||||
$@
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
# Variables for use in other utilities
|
||||
|
|
@ -38,10 +37,11 @@ fi
|
|||
# Check for dependencies
|
||||
function _daisy_dependency_check
|
||||
{
|
||||
BIN=$(command -v $1 2>/dev/null)
|
||||
res=$?
|
||||
|
||||
echo $(($res ^ 1))
|
||||
if command -v "$1" >/dev/null 2>&1; then
|
||||
echo 1
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
LD_HAS_fzf=$(_daisy_dependency_check fzf)
|
||||
|
|
@ -77,20 +77,22 @@ fi
|
|||
# [LEA.TODO] Turn these into arrays
|
||||
LD_ALIASFILE="$LD_CONFIG_FOLDER/aliases.src"
|
||||
LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src"
|
||||
LD_ESOURCEFILE="$LD_CONFIG_FOLDER/extra.src"
|
||||
touch $LD_ALIASFILE
|
||||
touch $LD_EDITORFILE
|
||||
touch $LD_ESOURCEFILE
|
||||
|
||||
ld_dbg echo "Sourced config contents:"
|
||||
ld_dbg cat $LD_ALIASFILE
|
||||
ld_dbg cat $LD_EDITORFILE
|
||||
ld_dbg cat $LD_ESOURCEFILE
|
||||
|
||||
# Source everything in the config folder
|
||||
function _daisy_source_configs
|
||||
{
|
||||
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
|
||||
do
|
||||
source "$f"
|
||||
done
|
||||
while IFS= read -r -d '' f; do
|
||||
source "$f"
|
||||
done < <(find "$LD_CONFIG_FOLDER" -name "*.src" -type f -print0)
|
||||
}
|
||||
|
||||
# Installation into PATH
|
||||
|
|
@ -123,7 +125,7 @@ function daisy_wait_for_editor
|
|||
|
||||
while true;
|
||||
do
|
||||
alive=$(ps aux | grep $fname | grep $pname)
|
||||
alive=$(pgrep -f "$pname.*$fname")
|
||||
if [[ $alive == "" ]]
|
||||
then
|
||||
break
|
||||
|
|
@ -132,12 +134,37 @@ function daisy_wait_for_editor
|
|||
done
|
||||
}
|
||||
|
||||
function multicd
|
||||
{
|
||||
cdpath="$@"
|
||||
if [[ $cdpath == '' ]]
|
||||
then
|
||||
\cd
|
||||
return
|
||||
fi
|
||||
|
||||
if cdz --check "$cdpath" >/dev/null 2>&1
|
||||
then
|
||||
cdz "$cdpath"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -f "$cdpath/.needs_mount" ]]
|
||||
then
|
||||
squasher mount "$cdpath"
|
||||
fi
|
||||
\cd "$cdpath"
|
||||
}
|
||||
|
||||
alias cd=multicd
|
||||
|
||||
# Undocumented but internally used
|
||||
function daisy_editor
|
||||
{
|
||||
editor=${LD_EDITOR:-$EDITOR};
|
||||
ld_dbg echo Opening $editor to edit file: $1
|
||||
$editor "$1"
|
||||
$editor "$1"
|
||||
sleep 1
|
||||
daisy_wait_for_editor $editor "$1"
|
||||
}
|
||||
|
||||
|
|
@ -248,7 +275,7 @@ function ched
|
|||
for editor in "${editors[@]}";
|
||||
do
|
||||
editor_real=$(command -v "$editor")
|
||||
if command -v "$editor_rmeal" >/dev/null 2>&1;
|
||||
if command -v "$editor_real" >/dev/null 2>&1;
|
||||
then
|
||||
if [[ $(realpath "$EDITOR") == "$editor_real" ]];
|
||||
then
|
||||
|
|
@ -299,8 +326,12 @@ function daisy_reload
|
|||
|
||||
function ldrc
|
||||
{
|
||||
daisy_editor "$LD_SOURCE_FILE"
|
||||
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
|
||||
ARG=$1
|
||||
SOURCE="$LD_SOURCE_FILE"
|
||||
[[ "$ARG" == "-e" ]] && SOURCE="$LD_ESOURCEFILE"
|
||||
|
||||
daisy_editor "$SOURCE"
|
||||
LD_INTERNAL=0 source "$SOURCE"
|
||||
}
|
||||
|
||||
enc_is_folder=0
|
||||
|
|
@ -483,7 +514,7 @@ function daisy_unalias
|
|||
|
||||
# Remove from aliases list
|
||||
newdata=$(cat "$LD_ALIASFILE" | grep -v "alias $unalias_param")
|
||||
bak "$LD_ALIASFILE" 1>/dev/null
|
||||
[[ NO_BAK -lt 1 ]] && bak "$LD_ALIASFILE" 1>/dev/null
|
||||
echo -e $newdata > "$LD_ALIASFILE"
|
||||
}
|
||||
|
||||
|
|
|
|||
13
editx
13
editx
|
|
@ -16,15 +16,12 @@ then
|
|||
ched "EDITOR env variable not set! You will have to set it yourself in the next screen."
|
||||
fi
|
||||
|
||||
exists=$(file "$1" >/dev/null && echo $?)
|
||||
[[ -e "$1" ]] && existed=1 || existed=0
|
||||
|
||||
touch "$1"
|
||||
chmod +x "$1"
|
||||
$EDITOR "$1"
|
||||
wait $!
|
||||
size=$(du "$1" | cut -f 1)
|
||||
chmod +x "$1"
|
||||
daisy_editor "$1"
|
||||
|
||||
if [[ $size -eq 0 && $exists -ne 0 ]];
|
||||
then
|
||||
rm -rf "$1"
|
||||
if [[ ! -s "$1" && $existed -eq 0 ]]; then
|
||||
rm -f "$1"
|
||||
fi
|
||||
|
|
|
|||
18
own
18
own
|
|
@ -5,13 +5,19 @@
|
|||
LD_INTERNAL=1
|
||||
. $(dirname $(realpath $0))/daisy.source
|
||||
|
||||
if [[ $@ == '' ]];
|
||||
then
|
||||
echo "$LD_BIN: Used to quickly take ownership of files/folders."
|
||||
echo "Requires sudo. If sudo is not installed, this tool will fai."
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "$LD_BIN: Quickly take ownership of files/folders."
|
||||
echo "Usage: $LD_BIN <folders or files>"
|
||||
echo "Means: chown -R <youruser>:<youruser> <folders or files>"
|
||||
echo "Requires sudo. If sudo is not installed, this tool will fail."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
sudo chown -R $(whoami):$(whoami) $@
|
||||
# Ensure all arguments exist before attempting chown
|
||||
for target in "$@"; do
|
||||
if [[ ! -e "$target" ]]; then
|
||||
echo "Error: \"$target\" does not exist."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
sudo chown -R "$(whoami):$(whoami)" "$@"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env bash
|
||||
# binbox: Creates a multi-binary script that self-contains the input scripts.
|
||||
# scriptbox: Creates a multi-binary script that self-contains the input scripts.
|
||||
# Symlinking to the resulting binary with the name of one of the original scripts will trigger
|
||||
# said script. The idea is similar to `busybox`.
|
||||
|
||||
179
squasher
Executable file
179
squasher
Executable file
|
|
@ -0,0 +1,179 @@
|
|||
#!/bin/bash
|
||||
# Lackadaisical squashfs tools - Squasher
|
||||
# Combined utility for make, mount, umount, and destroy operations.
|
||||
|
||||
BIN_DIR=$(dirname "$(readlink -f "$0")")
|
||||
COMMAND="$1"
|
||||
DIR="$2"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {make|mount|umount|destroy} <directory>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -z "$COMMAND" || -z "$DIR" ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
DIR=$(readlink -f "$DIR")
|
||||
DIR_SHORT=$(basename "$DIR")
|
||||
OVERLAY_ROOT="$(dirname "$DIR")/.squashfs/$DIR_SHORT"
|
||||
OVERLAY_UPPER="$OVERLAY_ROOT/upper"
|
||||
OVERLAY_LOWER="$OVERLAY_ROOT/lower"
|
||||
OVERLAY_WORK="$OVERLAY_ROOT/work"
|
||||
OVERLAY_TARG="$DIR"
|
||||
|
||||
case "$COMMAND" in
|
||||
make)
|
||||
if [[ ! -d "$DIR" ]]; then
|
||||
echo "Error: Directory \"$DIR\" does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..."
|
||||
for fs in fuse squashfs overlay; do
|
||||
if ! grep -q "$fs" /proc/filesystems; then
|
||||
echo "Attempting to load $fs module..."
|
||||
sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; }
|
||||
fi
|
||||
done
|
||||
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=false
|
||||
mkdir -p "$OVERLAY_ROOT"
|
||||
|
||||
if [[ -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Existing image found, updating..."
|
||||
"$0" mount "$DIR"
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=true
|
||||
fi
|
||||
|
||||
echo "Compressing \"$DIR\"..."
|
||||
sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1
|
||||
|
||||
if [[ "$RECREATE" == "true" ]]; then
|
||||
echo "Cleaning up old layers..."
|
||||
"$0" umount "$DIR"
|
||||
if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then
|
||||
sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK"
|
||||
rm -f "${OVERLAY_ROOT}.img"
|
||||
fi
|
||||
fi
|
||||
|
||||
mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img"
|
||||
mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG"
|
||||
|
||||
sudo rm -rf "$DIR"
|
||||
mkdir -p "$DIR"
|
||||
touch "$DIR/.needs_mount"
|
||||
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Storage Stats:"
|
||||
echo " Original size: $DIRSIZE"
|
||||
echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
|
||||
SERVICE_CONTENT="[Unit]
|
||||
Description=SquashFS Mount for %I
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=${BIN_DIR}/squasher mount %I
|
||||
ExecStop=${BIN_DIR}/squasher umount %I
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target"
|
||||
|
||||
echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
|
||||
read -p "Enable auto-mount service ($SERVICE_NAME)? [y/N] " yn
|
||||
|
||||
if [[ "$yn" =~ ^[Yy]$ ]]; then
|
||||
sudo systemctl enable --now "$SERVICE_NAME"
|
||||
sudo systemctl stop "$SERVICE_NAME"
|
||||
sudo systemctl start "$SERVICE_NAME"
|
||||
else
|
||||
echo "Manual mount command: sudo systemctl start $SERVICE_NAME"
|
||||
fi
|
||||
;;
|
||||
|
||||
mount)
|
||||
if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$0" umount "$DIR" 2>/dev/null
|
||||
mkdir -p "$OVERLAY_LOWER"
|
||||
sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount squashfs image." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo mount -t overlay none "$OVERLAY_TARG" \
|
||||
-o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount overlay." >&2
|
||||
sudo umount "$OVERLAY_LOWER" 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SquashFS filesystem is mounted and ready."
|
||||
;;
|
||||
|
||||
umount)
|
||||
sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null
|
||||
sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null
|
||||
|
||||
if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then
|
||||
echo "Warning: Filesystem is still mounted. Check for open processes."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SquashFS filesystem has been unmounted."
|
||||
;;
|
||||
|
||||
destroy)
|
||||
if [[ ! -f "$DIR/.needs_mount" ]]; then
|
||||
if ! mountpoint -q "$DIR"; then
|
||||
echo "Error: $DIR is not a SquashFS directory."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
|
||||
echo "Disabling service ($SERVICE_NAME)..."
|
||||
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null
|
||||
sudo systemctl disable "$SERVICE_NAME" 2>/dev/null
|
||||
|
||||
echo "Ensuring image is mounted to preserve data..."
|
||||
"$0" mount "$DIR" 1>/dev/null 2>/dev/null
|
||||
|
||||
echo "Destroying image and restoring data..."
|
||||
TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX)
|
||||
sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; }
|
||||
|
||||
"$0" umount "$DIR"
|
||||
sudo rm -rf "$DIR"
|
||||
sudo mv "$TEMP_DIR" "$DIR"
|
||||
sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img"
|
||||
|
||||
echo "Success: SquashFS image destroyed and data restored to \"$DIR\"."
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
101
sshp
101
sshp
|
|
@ -1,95 +1,58 @@
|
|||
#!/usr/bin/env bash
|
||||
# sshp ("SSH PLUS") from lackadaisical
|
||||
|
||||
mounts=()
|
||||
ssh_args=()
|
||||
remote_port=$((10000 + RANDOM % 10000))
|
||||
local_user=$(whoami)
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "sshp (\"SSH PLUS\") from lackadaisical."
|
||||
echo "Accepts all standard SSH options (see man ssh)."
|
||||
echo "Additionally, supports SSHFS mounts using a Docker-style syntax (-m)."
|
||||
echo "Usage: sshp -m <local>:<remote> [user@]host [ssh_options]"
|
||||
echo "Example: sshp -m /home/juli:/home/juli juli@juli.pyon"
|
||||
exit 1
|
||||
usage() {
|
||||
echo "Usage: sshp -m <local>:<remote> [user@]host [ssh_options]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-m)
|
||||
if [[ -z "$2" ]]
|
||||
then
|
||||
echo "Error: -m requires argument"
|
||||
exit 1
|
||||
fi
|
||||
mounts+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
ssh_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
case "$1" in
|
||||
-m)
|
||||
if [[ -z "$2" ]]; then echo "Error: -m requires argument"; exit 1; fi
|
||||
mounts+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
ssh_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ${#ssh_args[@]} -eq 0 ]]
|
||||
then
|
||||
usage
|
||||
fi
|
||||
[[ ${#ssh_args[@]} -eq 0 ]] && usage
|
||||
|
||||
mount_logic=""
|
||||
unmount_logic=""
|
||||
|
||||
for map in "${mounts[@]}"; do
|
||||
local_path="${map%%:*}"
|
||||
remote_path="${map##*:}"
|
||||
local_path="${map%%:*}"
|
||||
remote_path="${map##*:}"
|
||||
[[ "$local_path" != /* ]] && local_path="$PWD/$local_path"
|
||||
|
||||
if [[ "$local_path" != /* ]]
|
||||
then
|
||||
local_path="$PWD/$local_path"
|
||||
fi
|
||||
mount_logic+="
|
||||
echo '>> Preparing mount: ${remote_path}';
|
||||
mkdir -p \"${remote_path}\" 2>/dev/null || sudo mkdir -p \"${remote_path}\"
|
||||
|
||||
mount_logic+="
|
||||
echo '>> Preparing mount: ${remote_path}';
|
||||
if ! mkdir -p \"${remote_path}\" 2>/dev/null
|
||||
then
|
||||
sudo mkdir -p \"${remote_path}\"
|
||||
fi
|
||||
|
||||
if ! sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user ${local_user}@localhost:\"${local_path}\" \"${remote_path}\" 2>/dev/null
|
||||
then
|
||||
echo ' (User mount failed, attempting escalation...)';
|
||||
if ! sudo sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user,allow_other ${local_user}@localhost:\"${local_path}\" \"${remote_path}\"
|
||||
then
|
||||
echo ' ! Mount failed completely. Check permissions or keys.';
|
||||
fi
|
||||
else
|
||||
echo ' > Mounted successfully.';
|
||||
fi
|
||||
"
|
||||
|
||||
unmount_logic+="
|
||||
fusermount -u -z \"${remote_path}\" 2>/dev/null || sudo fusermount -u -z \"${remote_path}\" 2>/dev/null;
|
||||
"
|
||||
sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user ${local_user}@localhost:\"${local_path}\" \"${remote_path}\" 2>/dev/null || \
|
||||
sudo sshfs -p ${remote_port} -o StrictHostKeyChecking=no,idmap=user,allow_other ${local_user}@localhost:\"${local_path}\" \"${remote_path}\"
|
||||
"
|
||||
unmount_logic+="fusermount -u -z \"${remote_path}\" 2>/dev/null || sudo fusermount -u -z \"${remote_path}\" 2>/dev/null;"
|
||||
done
|
||||
|
||||
remote_script="
|
||||
if ! command -v sshfs >/dev/null 2>&1
|
||||
then
|
||||
echo 'WARNING: \"sshfs\" not found on remote host.'
|
||||
echo '>> Skipping mounts, proceeding with shell only...';
|
||||
echo '----------------------------------------------';
|
||||
else
|
||||
${mount_logic}
|
||||
fi
|
||||
|
||||
${SHELL:-bash};
|
||||
|
||||
if command -v sshfs >/dev/null 2>&1
|
||||
then
|
||||
if ! command -v sshfs >/dev/null 2>&1; then
|
||||
echo 'WARNING: \"sshfs\" not found on remote host.'
|
||||
else
|
||||
${mount_logic}
|
||||
fi
|
||||
\${SHELL:-bash};
|
||||
${unmount_logic}
|
||||
fi
|
||||
"
|
||||
|
||||
ssh -t -R ${remote_port}:localhost:22 "${ssh_args[@]}" "$remote_script"
|
||||
|
|
|
|||
11
what
11
what
|
|
@ -26,7 +26,10 @@
|
|||
LD_INTERNAL=1
|
||||
. $(dirname $(realpath $0))/daisy.source
|
||||
|
||||
pwd=/
|
||||
all_bins=$(cd / && echo $PATH | sed 's/[:]/ /g' | xargs ls -A | grep -v ":" | sort | uniq)
|
||||
output=$(printf '%s\n' "-n" $all_bins | grep -i "$1")
|
||||
echo "$output"
|
||||
all_bins=$(compgen -c | sort -u)
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
echo "$all_bins" | grep -i "$1"
|
||||
else
|
||||
echo "$all_bins"
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue