#!/usr/bin/env bash
#
# crypt — montera gocryptfs-valvet på USB-stickan till ~/crypt
#
# Hittar själv den krypterade katalogen (den som innehåller gocryptfs.conf)
# på inkopplade USB-diskar. gocryptfs frågar efter lösenordet själv, så
# ingen hemlighet passerar det här scriptet.
#
# Användning: crypt montera (default)
# crypt umount avmontera
# crypt status visa läge
# crypt toggle montera om avmonterat, annars avmontera
#
# Miljövariabler:
# CRYPT_MOUNT monteringspunkt (default: ~/crypt)
# CRYPT_CIPHERDIR krypterad katalog (default: autodetekteras)
set -euo pipefail
MOUNT="${CRYPT_MOUNT:-$HOME/crypt}"
die() { printf '✗ %s\n' "$*" >&2; exit 1; }
info() { printf '%s\n' "$*"; }
command -v gocryptfs >/dev/null 2>&1 || die "gocryptfs saknas (sudo apt install gocryptfs fuse3)"
FUSERMOUNT=$(command -v fusermount3 || command -v fusermount || true)
[ -n "$FUSERMOUNT" ] || die "fusermount saknas (sudo apt install fuse3)"
is_mounted() { mountpoint -q "$MOUNT" 2>/dev/null; }
# Skriver ut alla kataloger under monterade USB-diskar som ser ut som ett
# gocryptfs-valv (innehåller gocryptfs.conf).
find_cipherdirs() {
local base conf
for base in "/media/$USER" "/run/media/$USER"; do
[ -d "$base" ] || continue
while IFS= read -r conf; do
dirname "$conf"
done < <(find "$base" -maxdepth 3 -name gocryptfs.conf 2>/dev/null)
done
}
# Monterar omonterade USB-partitioner via udisks om inget valv hittades.
automount_removable() {
command -v udisksctl >/dev/null 2>&1 || return 1
local name
while read -r name; do
[ -n "$name" ] && udisksctl mount -b "/dev/$name" >/dev/null 2>&1 || true
done < <(lsblk -rno NAME,TYPE,RM,FSTYPE,MOUNTPOINT \
| awk '$2=="part" && $3=="1" && $4!="" && $5=="" {print $1}')
}
pick_cipherdir() {
if [ -n "${CRYPT_CIPHERDIR:-}" ]; then
[ -f "$CRYPT_CIPHERDIR/gocryptfs.conf" ] || die "ingen gocryptfs.conf i $CRYPT_CIPHERDIR"
printf '%s\n' "$CRYPT_CIPHERDIR"
return
fi
local dirs=()
mapfile -t dirs < <(find_cipherdirs)
if [ "${#dirs[@]}" -eq 0 ] && automount_removable; then
sleep 1
mapfile -t dirs < <(find_cipherdirs)
fi
case "${#dirs[@]}" in
0) die "hittade inget gocryptfs-valv — sitter USB-stickan i? (eller sätt CRYPT_CIPHERDIR)" ;;
1) printf '%s\n' "${dirs[0]}" ;;
*) local d
PS3="Välj valv: "
select d in "${dirs[@]}"; do
[ -n "${d:-}" ] && { printf '%s\n' "$d"; break; }
done >&2 < /dev/tty ;;
esac
}
do_mount() {
if is_mounted; then
info "● redan monterat på $MOUNT"
return 0
fi
local cipher
cipher=$(pick_cipherdir)
mkdir -p "$MOUNT"
# Monteringspunkten måste vara tom, annars nekar gocryptfs.
if [ -n "$(ls -A "$MOUNT" 2>/dev/null)" ]; then
die "$MOUNT är inte tom och inget är monterat där"
fi
info "Monterar $cipher → $MOUNT"
gocryptfs "$cipher" "$MOUNT"
info "● monterat på $MOUNT"
}
do_umount() {
if ! is_mounted; then
info "○ inget monterat på $MOUNT"
return 0
fi
"$FUSERMOUNT" -u "$MOUNT" || die "kunde inte avmontera $MOUNT (används den? prova: fuser -vm $MOUNT)"
info "○ avmonterat $MOUNT"
}
do_status() {
if is_mounted; then
info "● monterat på $MOUNT"
else
info "○ inte monterat ($MOUNT)"
fi
local d
while IFS= read -r d; do info " valv: $d"; done < <(find_cipherdirs)
}
case "${1:-mount}" in
mount|m) do_mount ;;
umount|unmount|u) do_umount ;;
status|s) do_status ;;
toggle|t) if is_mounted; then do_umount; else do_mount; fi ;;
-h|--help|help) sed -n '3,17p' "$0" | sed 's/^# \{0,1\}//' ;;
*) die "okänt kommando: $1 (mount|umount|status|toggle)" ;;
esac