Thanks to udev and HAL the usage of external volumes such as USB pens or external hard-disks has become quite easy on modern Linux distributions. But if you own an external hard-disk, which is encrypted, things aren't as comfortable because the aforementioned systems are neither able to detect the type of encryption nor if the device is encrypted at all. They just fail to mount it while telling you something like “unknown partition table” and the like
.
So in order to get such a disk mounted you usually have to fire up a terminal and type something like:
% sudo truecrypt /dev/sdb /mnt/disk Enter Password:
Well, these are quite a few steps and the more often I had to type it the more I wished it would be as easy as with my camera.
So, I wondered if there could be a way to get a similar behaviour. My idea was to use a custom udev rule, which triggers a script whenever I plug in my hard-disk, combined with a tiny but tremendously useful tool called zenity, which allows you to integrate simple GTK dialogs in shell scripts.
One thing you need, in order to be able to assemble the udev rule, is some information about the external disk in question. udev provides a tool called udevinfo, which does exactly that, namely querying udev device informations. A simple:
% sudo tail -f /var/log/messages.log
before plugging in the hard-disk obtains the device to query.
Nov 7 00:33:22 tatooine scsi3 : SCSI emulation for USB Mass Storage devices Nov 7 00:33:27 tatooine scsi 3:0:0:0: Direct-Access SAMSUNG HD300LD 0000 PQ: 0 ANSI: 0 Nov 7 00:33:27 tatooine sd 3:0:0:0: [sdb] 586072368 512-byte hardware sectors (300069 MB) Nov 7 00:33:27 tatooine sd 3:0:0:0: [sdb] Write Protect is off Nov 7 00:33:27 tatooine sd 3:0:0:0: [sdb] 586072368 512-byte hardware sectors (300069 MB) Nov 7 00:33:27 tatooine sd 3:0:0:0: [sdb] Write Protect is off Nov 7 00:33:27 tatooine sdb: unknown partition table Nov 7 00:33:27 tatooine sd 3:0:0:0: [sdb] Attached SCSI disk Nov 7 00:33:27 tatooine sd 3:0:0:0: Attached scsi generic sg2 type 0
Which in this case is obviously /dev/sdb. With this information you are able to find out the corresponding node in the /sys directory by using udevinfo.
% udevinfo --query path --name=/dev/sdb /block/sdb
Knowing that you can finally obtain the information needed for the udev rule. The following command will output a rather lengthy list of information about the device, so I just snip out the relevant stuff.
% udevinfo --attribute-walk --path=/block/sdb
--- snip ---
looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':
KERNELS=="6:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{modalias}=="scsi:t-0x00"
ATTRS{ioerr_cnt}=="0x0"
ATTRS{iodone_cnt}=="0x17"
ATTRS{iorequest_cnt}=="0x17"
ATTRS{iocounterbits}=="32"
ATTRS{timeout}=="60"
ATTRS{state}=="running"
ATTRS{rev}=="0000"
ATTRS{model}=="HD300LD "
ATTRS{vendor}=="SAMSUNG "
ATTRS{scsi_level}=="0"
ATTRS{type}=="0"
ATTRS{queue_type}=="none"
ATTRS{queue_depth}=="1"
ATTRS{device_blocked}=="0"
ATTRS{max_sectors}=="240"
--- snap ---
Off course you can combine both of these commands to one single line and use the short options instead:
% udevinfo -a -p $(udevinfo -q path -n /dev/sdb)
From the above output, the most interesting informations are ATTRS{model} and ATTRS{vendor}. If you don't happen to have 2 of those disks, this is enough to assemble a custom udev rule. It's good practice to put your own rules into a separate rules file. On Arch Linux the rules are located under /etc/udev/rules.d1).
ACTION=="add", KERNEL=="sd[a-z]", ATRRS{vendor}=="SAMSUNG", ATTRS{model}=="HD300LD", RUN="/home/user/bin/truemount.sh /dev/%k /home/chi/mnt/coruscant"
As you can see, the RUN part of this rule triggers a script. This script finally does all the magic. It takes two options the first is the device node and the second is the mount point the device should be mounted at. However, there's a little problem now. The script which gets triggered by udev does not know anything about our graphical environment - and even worse it is run as root. It took me while to figure out a workaround (some ideas on the Arch forums finally brought me on the right track).
The idea of this script is to generate a little GTK pop-up window which asks the user for the password for the attached hard-disk. If the mount fails, it tries again and again until the mount was successful. If the user chooses to cancel the mount it stops. The trick however is, to call zenity as the user who runs the graphical environment and to export the DISPLAY environment variable so that zenity is able to connect to it.
#!/bin/sh # @author Michael Klier <chi@chimeric.de> SRC=$1 DEST=$2 OK= while [ "$OK" != "0" ]; do PASS=$(su user -c 'export DISPLAY=:0.0; zenity --entry --title="truemount" --text="enter password for '$SRC'" --hide-text') # catch "cancel" [[ "$?" == "1" ]] && exit 0 /usr/bin/truecrypt -p $PASS $SRC $DEST OK=$? done
That's finally it
! Whenever you attach the encrypted hard-disk, you get a little pop-up asking for the password and the disk is mounted at your desired mountpoint.
You can target the script for other hard-disks as well - all you have to do is find out and change the ATTRS{vendor} and ATTRS{model} values. If you have to pass certain mount options to truecrypt the script will need some adjustments of course.
Tried your Gutsy-Script. On plug-in, nothing happens. When I execute the truemount.sh manually with the correct parameters, i get:
.bin/truemount.sh: 20: [[: not found
My scripting skills are rather limited and I would be grateful if one could point me in the right direction. Thanks.
2007/11/30 10:46@sebs: Hmm I wonder what causes this. The usage of [[ is encouraged in http://www.tldp.org/LDP/abs/html/testconstructs.html and on my system the script is working very well. You could try single Brackets though.
2008/02/23 11:56
OK, after a bit of fiddling I got it to work.
Here is how i did this on Ubuntu Gusty:
# # truecrypt mount rules # # use the following to get vendor information: # udevinfo -a -p $(udevinfo -q path -n /dev/sdb) # ACTION=="add", KERNEL=="sd[a-z][0-9]", ATRRS{vendor}=="WDC WD32", ATTRS{model}=="00JB-00KFA0 ", RUN="/home/sb/bin/truemount.sh sb /dev/%k /home/sb/Daten"Note the new KERNEL-Regex, whitch also matches on truecrypt partitions rather than the “raw” sdx device. I also added the username as a parameter to truemount.sh to simplify it's setup