aboutsummaryrefslogtreecommitdiff
path: root/usb-mount
blob: e9833601715c8b7089ee2e0d4ed2ee83fd895cfb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env bash
set -euo pipefail

UUID="bdd2a016-b6db-493d-ad0a-e8dd8a93dfbd"
NAME="usb_safe"
MNT="/mnt/usb_safe"

DEV_BY_UUID="/dev/disk/by-uuid/${UUID}"
MAPPER="/dev/mapper/${NAME}"

die() { echo "Error: $*" >&2; exit 1; }

need_cmd() {
  command -v "$1" >/dev/null 2>&1 || die "Missing command: $1"
}

resolve_blockdev() {
  local target
  target="$(readlink -f "$DEV_BY_UUID")" || return 1
  [[ -b "$target" ]] || return 1
  echo "$target"
}

is_mapped() { [[ -e "$MAPPER" ]]; }
is_mounted() { mountpoint -q "$MNT"; }

show_busy() {
  echo "Mount appears busy. Processes using $MNT:"
  if command -v lsof >/dev/null 2>&1; then
    sudo lsof +f -- "$MNT" || true
  else
    echo "(Install lsof: sudo apt install lsof)"
    sudo fuser -vm "$MNT" || true
  fi
}

do_open() {
  need_cmd cryptsetup
  need_cmd mount
  need_cmd mountpoint
  need_cmd readlink

  [[ -e "$DEV_BY_UUID" ]] || die "UUID device not found: $DEV_BY_UUID (is the drive plugged in?)"

  local dev
  dev="$(resolve_blockdev)" || die "Could not resolve block device for UUID: $UUID"

  if is_mapped; then
    echo "Mapper already exists: $MAPPER"
  else
    sudo cryptsetup open "$dev" "$NAME"
  fi

  if [[ ! -d "$MNT" ]]; then
    sudo mkdir -p "$MNT"
  fi

  if is_mounted; then
    echo "Already mounted: $MNT"
  else
    sudo mount "$MAPPER" "$MNT"
  fi

  sudo sync
  echo "OK: unlocked and mounted at $MNT"
}

do_close() {
  need_cmd cryptsetup
  need_cmd umount
  need_cmd mountpoint
  need_cmd readlink

  if is_mounted; then
    sudo sync
    if ! sudo umount "$MNT"; then
      show_busy
      die "Unmount failed"
    fi
  fi

  if is_mapped; then
    sudo cryptsetup close "$NAME"
  fi

  if [[ -e "$DEV_BY_UUID" ]]; then
    local dev
    dev="$(resolve_blockdev)" || true
    if [[ -n "${dev:-}" ]] && command -v udisksctl >/dev/null 2>&1; then
      sudo udisksctl power-off -b "$dev" || true
    fi
  fi

  echo "OK: unmounted, closed, and powered off (if supported)"
}

do_status() {
  echo "UUID device: $DEV_BY_UUID"
  if [[ -e "$DEV_BY_UUID" ]]; then
    echo "Resolved:   $(readlink -f "$DEV_BY_UUID")"
  else
    echo "Resolved:   (not present)"
  fi

  echo -n "Mapper:     "
  if is_mapped; then echo "OPEN ($MAPPER)"; else echo "CLOSED"; fi

  echo -n "Mount:      "
  if is_mounted; then echo "MOUNTED ($MNT)"; else echo "NOT MOUNTED"; fi
}

usage() {
  cat <<EOF
Usage: $0 {open|close|status}

open   - unlock LUKS by UUID and mount to $MNT
close  - sync, unmount, close mapper, power-off block device (best-effort)
status - show current state
EOF
}

main() {
  case "${1:-}" in
    open)   do_open ;;
    close)  do_close ;;
    status) do_status ;;
    *) usage; exit 2 ;;
  esac
}

main "$@"