-
-
Notifications
You must be signed in to change notification settings - Fork 804
Expand file tree
/
Copy pathnmount
More file actions
executable file
·139 lines (133 loc) · 5.96 KB
/
nmount
File metadata and controls
executable file
·139 lines (133 loc) · 5.96 KB
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
133
134
135
136
137
138
139
#!/usr/bin/env sh
# Description: Toggle mount status of a device using pmount
# If the device is not mounted, it will be mounted.
# If the device is mounted, it will be unmounted and powered down.
#
# Dependencies: lsblk, pmount (optional), udisks2
#
# Usage: Runs `lsblk` on 'l', unmounts all USB HDDs on 'u', exits on 'Return`.
#
# Notes:
# - The script uses Linux-specific lsblk to list block devices. Alternatives:
# macOS: "diskutil list"
# BSD: "geom disk list"
# - The script uses udisksctl (from udisks2) to power down devices. This is also Linux-specific.
# Users on non-Linux platforms can comment it and use an alternative to power-down disks.
#
# Shell: POSIX compliant
# Author: Arun Prakash Jana
prompt="device name [e.g. sdXn] ('l'ist, 'u'nmount all USB, 'q'uit): "
lsblk
printf "\nEnsure you aren't still in the mounted device.\n"
printf "%s" "$prompt"
read -r dev
while [ -n "$dev" ]; do
if [ "$dev" = "l" ]; then
lsblk
elif [ "$dev" = "q" ]; then
exit
elif [ "$dev" = "u" ]; then
usb_devs=$(lsblk -ndo NAME,TRAN | awk '$2=="usb"{print $1}')
if [ -z "$usb_devs" ]; then
echo "No USB block devices found."
else
for disk in $usb_devs; do
# Get only real partitions (e.g. sda1), skip device-mapper entries like luks-*
parts=$(lsblk -nlpo NAME,TYPE "/dev/$disk" | awk '$2=="part"{print $1}')
if [ -z "$parts" ]; then
echo "/dev/$disk has no partitions, skipping."
continue
fi
mounted=0
for part in $parts; do
mnt=$(lsblk -n "$part" -o MOUNTPOINT | sed '/^$/d')
# Check if this partition or any child (e.g. LUKS) is mounted
child_mnt=$(lsblk -nro MOUNTPOINT "$part" | sed '/^$/d')
if [ -z "$mnt" ] && [ -z "$child_mnt" ]; then
continue
fi
mounted=1
if type pumount >/dev/null 2>&1; then
sync "$child_mnt"
pumount "$part"
prc=$?
elif lsblk -n "$part" -o FSTYPE | grep -q "crypto_LUKS"; then
dev_map=$(udisksctl info -b "$part" | grep "CleartextDevice" | grep -o "dm_2d[[:digit:]]*" | sed "s/_2d/-/")
sync "$child_mnt"
udisksctl unmount -b "/dev/$dev_map" --no-user-interaction >/dev/null
prc=$?
udisksctl lock -b "$part" --no-user-interaction >/dev/null
else
sync "$mnt"
udisksctl unmount -b "$part" --no-user-interaction >/dev/null
prc=$?
fi
if [ $prc -eq 0 ]; then
echo "$part unmounted."
else
echo "Failed to unmount $part."
fi
done
if [ $mounted -eq 0 ]; then
echo "/dev/$disk has no mounted partitions, skipping."
continue
fi
if udisksctl power-off -b "/dev/$disk" --no-user-interaction 2>/dev/null; then
echo "/dev/$disk ejected."
fi
done
fi
else
# LUKS volumes mounted with udisksctl appear differently than with pmount
if grep -qs "$dev " /proc/mounts || [ -n "$(lsblk -n "/dev/$dev" -o MOUNTPOINT)" ]; then
sync "$(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")"
if type pumount >/dev/null 2>&1; then
pumount "/dev/$dev"
exit_code="$?"
else
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
# We need to manually get the unlocked device, unmount it, and then lock the volume
if lsblk -n "/dev/$dev" -o FSTYPE | grep "crypto_LUKS" >/dev/null; then
dev_map="$(udisksctl info -b /dev/"$dev" | grep "CleartextDevice" | grep -o "dm_2d[[:digit:]]*" | sed "s/_2d/-/")"
udisksctl unmount -b "/dev/$dev_map" --no-user-interaction >/dev/null
exit_code="$?"
udisksctl lock -b "/dev/$dev" --no-user-interaction >/dev/null
else
udisksctl unmount -b "/dev/$dev" --no-user-interaction >/dev/null
exit_code="$?"
fi
fi
if [ $exit_code -eq 0 ]; then
echo "/dev/$dev unmounted."
if udisksctl power-off -b "/dev/$dev" --no-user-interaction; then
echo "/dev/$dev ejected."
fi
fi
elif [ -b "/dev/$dev" ]; then
if type pmount >/dev/null 2>&1; then
pmount "/dev/$dev"
exit_code="$?"
else
# Unlike pmount, udisksctl does not transparently handle LUKS volumes
# We need to manually get the unlocked device and mount that instead of the volume itself
if [ "$(lsblk "/dev/$dev" -n -o FSTYPE)" = "crypto_LUKS" ]; then
dev_map=$(udisksctl unlock -b "/dev/$dev" --no-user-interaction | grep -o "dm-[[:digit:]]*")
udisksctl mount -b "/dev/$dev_map" --no-user-interaction >/dev/null
exit_code="$?"
else
udisksctl mount -b "/dev/$dev" --no-user-interaction >/dev/null
exit_code="$?"
fi
fi
if [ $exit_code -eq 0 ]; then
sleep 1
echo "/dev/$dev mounted to $(lsblk -n "/dev/$dev" -o MOUNTPOINT | sed "/^$/d")."
fi
else
echo "/dev/$dev does not exist or is not a block device."
fi
fi
echo
printf "%s" "$prompt"
read -r dev
done