Georg Grabler (STiAT) - blog

Life is like an endlessly recursive fractal of perverse pain and suffering.

Automounting USB-Disks

There are several solutions out there for automounting USB filesystems, though, none of them satisfied me, and most made more problems and were very unreliable, so I went for the “classic” way using udev rules and fstab.

I’ve a home-server running my ownCloud for syncing my contacts/calendar/files when I’m at home (not accessible from the outside world). Though, I’ve an external harddisk at this server which may be plugged, and maybe isn’t when I’m using it somewhere else or when I just don’t use it holding a lot of my files, which is a NTFS partition.

Interestingly mounting directly via udev brought up folder permissions to be d?????????, so an inaccessible directory. Adding the line to fstab and using udev works just perfectly fine though.

Note that I added a very specific rule for the disk, since it always needs the same mountpoint to be accessible via ownCloud (if plugged in :D).

/etc/udev/rules.d/99-WDElements.rules

KERNEL=="sd?1", SUBSYSTEMS=="usb", ATTRS{product}=="Elements 10B8", ATTRS{serial}=="5758363141343453343439
38",ATTRS{manufacturer}=="Western Digital", SYMLINK+="Elements"ACTION=="add", KERNEL=="sd?1", SUBSYSTEMS=="usb", ATTRS{product}=="Elements 10B8", ATTRS{serial}=="5758363
14134345334343938",ATTRS{manufacturer}=="Western Digital", RUN+="/bin/mount /media/Elements"ACTION=="remove", KERNEL=="sd?1", SUBSYSTEMS=="usb", ATTRS{product}=="Elements 10B8", ATTRS{serial}=="5758
36314134345334343938",ATTRS{manufacturer}=="Western Digital", RUN+="/bin/umount /media/Elements"

Now, how I’m getting there? What are the Parameters?
It’s pretty simple, you can identify the parameters you’ll need to identify a harddisk by using udevadm. It’s a simple tool which outputs udev information about the device and it’s parent devices. You can use all parameters from the specified device and one parent device. This is important, because if you use information from more than one parent device, the udev rule will never ever work.
The command to use to identify the parameters is as follows, in my case at the time plugging in the USB device was /dev/sdb1

udevadm info -n /dev/sdb1 --attribute-walk

So, what does it actually do? It identifies the hardware by KERNEL, SUBSYSEMS, ATTRS{product} ATTRS{serial} ATTRS{manufacturer}, and adds a Symlink called “Elements”, which will show up as /dev/Elements. This is an important step to be able to mount it using fstab, because if you have more than one removable device plugged, it may not be sdb1, but sd?1, which is why i have the ? in the KERNEL line, which basically means every character. You could go for KERNEL==”sd[b-z]1″ or similar too, but I didn’t see a reason for that in my configuration.

This means we’re now left with a /dev/Elements node, pointing to /dev/sd?1 which is my partition on the disk. All we need to do is create the directory we want to mount the disk to, in my case a simple “mkdir /media/Elements”. But you can basically mount it everywhere you want in your filesystem.

The ACTION==”add” is what’s being executed for the device (same options to identify the device of course), when it’s plugged in. In our case, we want to mount it, and use the fstab options when mounting.

The ACTION==”remove” is what’s being executed for the device when it’s unplugged. When we unplug it, we want to unmount the filesystem. Will be re-mounted when re-plugged anyway.

/etc/fstab

/dev/Elements   /media/Elements ntfs-3g    gid=100,dmask=002,fmask=113,utf8,flush,rw,noatime,user, noauto        0       0

Parameter explaination

  • /dev/Elements
    The SYMLINK we create by the udev rule, which represents our physical device.
  • /media/Elements
    The folder you created, and want the filesystem mounted to
  • ntfs
    The corresponding file system
  • gid=100
    The group-id you want to mount the device with. The group “100” represents “users” in my case, which every user I have is in (as www-data, so ownCloud can write there too). You certainly could even set a uid if you want to, but for my configuration it’s not necessary
  • dmask=002
    This is the permission for the “folders”, means who can open, read and write folders. This is a fat/ntfs specific option, which are used on the whole filesystem. You can not set permissions on a folder basis as it’s in ext4 or other UNIX filesystems.
    The options “00” represent “read, write, execute” (rwx) for the owner (root) and the group (users).
    The option “2” is for “everyone”, which is the read and execute permission. So “everyone” may not create, write or delte in the filesystem, but they can open and read it (r-x). The table explaining the options you have in dmask and fmask is below this list.
  • dmask=113
    This is the permission for “files”, means who can read or write files. This as well is a fat/ntfs specific option, which are used on the whole filesystem. You can not set file permissions on a file basis as you can on ext4 and other unix filesystems.
    The options “11” represent the permission of the owner (root), and the group (users), and represent the read and write permission. (rw-)
    The option “3” represents the permission for “everyone”, and represents read only permission (r–).
  • utf8
    This simply specifies that utf8 characters may be used on this filesystem, which basically is a standard today.
  • flush
    This specifies that the system should use the flush data option more often on this filesystem, and as a result copy, move, delete dialogs stay up until the data is actually on the disk, otherwhise it can happen that your data is actually not on the disk when the copy is finished.
  • rw
    Specifies that the system should mount the system in rw mode, so you can read and write files from/to disk (other option would be “ro”, where nobody would be able to write the filesystem, despite the dmask and umask options)
  • noatime
    Defines that inode access times may not be updated on this filesystem. Improves performance for  FAT/NTFS filesystemss.
  • user
    Specifies that only the user mounting the filesystem (and root) can unmount it again. Since I want dbus to handle it, that option makes sense, so no other user may unmount the filesystem. The other option would be “users”, where users with the proper permission in /etc/group could mount or unmount the filesystem, which I don’t want.
  • noauto
    Specifies that the file system is not mounted by fstab, but another way. In our case, it’s udev mounting and unmounting the filesystem for us.

fmask/dmask permission option table

    0   1   2   3   4   5   6   7
r   +   +   +   +   -   -   -   -
w   +   +   -   -   +   +   -   -
x   +   -   +   -   +   -   +   -

That’s basically all you need to know for automounting specific USB devices. You can adopt adding more RUN+= options to automount all file systems being plugged in, reducing the parameters to check for which harddisk exactly was plugged in. I didn’t go for that, since it’s a very specific use-case. Tools like “autofs” claim to do that for you, but in fact – they didn’t for me, I ended up with a hell of devices and folders. A more generic UDEV rule would be the following (it does not use FSTAB):

# Don't do anything if it isn't a device
KERNEL!="sd[b-z]*", GOTO="exit"
# Don't do anything if it's not added by blkid, another check for filesystem
ACTION=="add", PROGRAM!="/sbin/blkid %N", GOTO="exit"

# Import filesystem variables as ID_FS_LABEL and ID_FS_TYPE
IMPORT{program}="/sbin/blkid -o udev -p %N

#make sure we're adding/removing a filesystem here
ACTION=="add", ENV{ID_FS_USAGE}!="filesystem", GOTO="exit"
ACTION=="remove", ENV{ID_FS_USAGE}!="filesystem", GOTO="exit"

# if we have a filesystem label, we want to use it for the mountpoint
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="%k"

# mount options - for all the same
ACTION=="add", ENV{mount_options}="gid=100,dmask=000,fmask=111,utf8,flush,rw,noatime,users"

# ntfs mount, we need to specify ntfs as file system
ACTION=="add", ENV{ID_FS_TYPE}=="ntfs", RUN+="/bin/mkdir -p '/media/%E{dir_name}'", RUN+="/bin/mount -t ntfs-3g -o %E{mount_options} /dev/%k '/media/%E{dir_name}'"

# all others we just can use "auto" type
ACTION=="add", ENV{ID_FS_TYPE}!="ntfs",RUN+="/bin/mkdir -p '/media/%E{dir_name}'", RUN+="/bin/mount -t auto -o %E{mount_options} /dev/%k '/media/%E{dir_name}'"

# on unplugging, we unmount and delete the mountpoint again
ACTION=="remove", RUN+="/bin/umount '/media/%E{dir_name}'", RUN+="/bin/rmdir '/media/%E{dir_name}"

# the exit point, we need this so we can GOTO here if it's not a filesystem
LABEL="exit"

There are no comments

Leave a Reply

Your email address will not be published. Required fields are marked *