mktar: Use `wc` instead of `du` in summary message
[sunny256-utils.git] / mdisk
blobb83effd81cb95d5fc3f776767a1d41cf618d8c54
1 #!/bin/sh
3 #==============================================================================
4 # mdisk
5 # File ID: 0548a2d2-ea04-11ed-b5e0-83850402c3ce
7 # Mount a LUKS-encrypted disk under /media/
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #==============================================================================
13 progname=mdisk
14 VERSION=0.2.4
16 opt_help=0
17 opt_quiet=0
18 opt_umount=0
19 opt_verbose=0
20 while test -n "$1"; do
21 case "$1" in
22 -a|--all) opt_all=1; shift ;;
23 -h|--help) opt_help=1; shift ;;
24 -q|--quiet) opt_quiet=$(($opt_quiet + 1)); shift ;;
25 -u|--umount) opt_umount=1; shift ;;
26 -v|--verbose) opt_verbose=$(($opt_verbose + 1)); shift ;;
27 --version) echo $progname $VERSION; exit 0 ;;
28 --) shift; break ;;
30 if printf '%s\n' "$1" | grep -q ^-; then
31 echo "$progname: $1: Unknown option" >&2
32 exit 1
33 else
34 break
36 break ;;
37 esac
38 done
39 opt_verbose=$(($opt_verbose - $opt_quiet))
41 [ -e "$HOME/.mdiskrc" ] && . "$HOME/.mdiskrc"
43 T_BOLD=$(tput bold)
44 T_GREEN=$(tput setaf 2)
45 T_RED=$(tput setaf 1)
46 T_RESET=$(tput sgr0)
48 if test "$opt_help" = "1"; then
49 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
50 cat <<END
52 Mount a LUKS-encrypted disk under /media/.
54 Usage: $progname [options] DISKNAME
56 Options:
58 -a, --all
59 Loop through all directory names under /media/ and mount or unmount
60 all corresponding disks.
61 -h, --help
62 Show this help.
63 -q, --quiet
64 Be more quiet. Can be repeated to increase silence.
65 -v, --verbose
66 Increase level of verbosity. Can be repeated.
67 -u, --umount
68 Unmount the disk.
69 --version
70 Print version information.
72 Environment variables
74 MDISK_KEY_FILE
75 Full path to text file with passphrase for encrypted drives.
77 Files and directories
79 \$HOME/.mdiskrc
80 Init file. A regular shell script that can be used to initialize
81 environment variables and run commands before normal program
82 execution.
83 .dontsleep/
84 If this directory exists at the top of the disk, the disk is
85 prevented from sleeping. When a disk with this directory is mounted,
86 a background process is started that writes 512 random bytes to a
87 file in this directory every two minutes. The current user must have
88 write permission in this directory, otherwise sleeping is not
89 prevented. When the disk is unmounted with -u/--umount, the process
90 is killed.
92 END
93 exit 0
96 msg() {
97 test $1 -gt $opt_verbose && return;
98 shift
99 echo "$progname: $*" >&2
102 err() {
103 echo "$progname: $T_BOLD$T_RED$*$T_RESET" >&2
104 exit 1
107 is_active() {
108 sudo cryptsetup status $disk | grep -q "/dev/mapper/$disk is active"
111 is_in_blkid() {
112 sudo blkid | grep -q "LABEL=\"$1\"" && return 0
113 return 1
116 is_mounted() {
117 df | grep -q "/media/$disk\$" && return 0
118 return 1
121 strip_diskname() {
122 echo $(echo "$1" | sed 's.^/media/..; s./$..')
125 create_ds_script() {
126 echo >$ds_script || err $ds_dir/: Cannot write to directory, \
127 disk sleep is not prevented
128 cat <<'END' >$ds_script
129 #!/bin/sh
131 T_BOLD=$(tput bold)
132 T_RED=$(tput setaf 1)
133 T_RESET=$(tput sgr0)
134 outfile=.dontsleep.bin
136 rm -f $outfile
137 echo $$ >pid || {
138 echo -n "$T_BOLD$T_RED$0: Cannot write pid file to $ds_dir," >&2
139 echo " unable to prevent sleep$T_RESET" >&2
140 exit 1
142 while :; do
143 head -c 512 /dev/urandom >>$outfile
144 (cd; sleep 120)
145 done
149 prevent_sleep() {
150 local disk=$1
152 msg 0 Preventing $disk from sleeping
153 cd "$ds_dir" || err $ds_dir: chdir error
154 (create_ds_script && sh $ds_script $disk) &
157 kill_prevent() {
158 local disk=$1
160 pidfile="$ds_dir/pid"
161 if [ ! -f "$pidfile" ]; then
162 echo $progname: PID file $pidfile not found >&2
163 return
165 kill $(cat $pidfile)
166 rm $pidfile
169 if [ "$opt_all" = "1" ]; then
170 for f in /media/*; do
171 is_in_blkid $(strip_diskname $f) || continue
172 if [ "$opt_umount" = "1" ]; then
173 $0 -u $f
174 else
175 $0 $f
177 done
178 exit
181 disk=$(strip_diskname $1)
182 [ -z "$disk" ] && err No disk specified
184 is_in_blkid $disk || err $disk: Disk not found in blkid
186 ds_dir="/media/$disk/.dontsleep"
187 ds_script=dontsleep
189 if [ "$opt_umount" != "1" ]; then
190 is_mounted $disk && {
191 msg 0 $disk: Already mounted
192 exit 0
194 device=$(blkid -L $disk)
195 msg 1 device = \"$device\"
196 [ -z "$device" ] && err Cannot get device for $disk
197 echo "$device" | grep -q ^/dev/ || err $device: Malformed device name
198 is_active $disk \
199 || sudo cryptsetup luksOpen \
200 $([ -n "$MDISK_KEY_FILE" ] && echo "--key-file $MDISK_KEY_FILE") \
201 $device $disk && mount /media/$disk
202 is_mounted $disk \
203 && msg 0 $T_BOLD$T_GREEN$disk mounted on /media/$disk$T_RESET \
204 || err $disk: mount failed
205 [ -d "$ds_dir" ] && prevent_sleep $disk
206 else
207 [ -d "$ds_dir" ] && kill_prevent $disk
208 is_mounted $disk && umount /media/$disk
209 [ -d "$ds_dir" ] && prevent_sleep $disk
210 is_mounted $disk && err /media/$disk: umount failed
211 sudo cryptsetup luksClose $disk
212 sync
213 is_active $disk && err $disk is still active
214 msg 0 $T_BOLD$T_GREEN$disk is unmounted and closed$T_RESET
217 # vim: set ts=8 sw=8 sts=8 noet fo+=w tw=79 fenc=UTF-8 :