USB FAT Semi-Auto-Mount

Rationale

This is one of those little scripts you write to make life a bit more convenient. It somewhat replicates the behaviour of the Mac OS X automounter where your USB disks simply appear on your desktop when you plug them in. I use it to get similar behaviour on my Linux box, mounting disks to a mount point by their disk label. The only real difference: we run it manually, instead of waiting for it to trigger whenever the OS feels like it.

The script

 #!/usr/local/bin/tclsh
 set mountdirroot "/multimedia"
 set userid pc
 set groupid users

 proc get_mounted {} {
  set tmp [split [exec /bin/mount] "\n"]
  set ::mountdevices [list]
  set ::mountpoints  [list]
  foreach t $tmp { lappend ::mountdevices [lindex [split $t " "] 0] }
  foreach t $tmp { lappend ::mountpoints [lindex [split $t " "] 2] }
  }

 get_mounted

 # Mount any devices present
 set pause 0
 foreach device {
  sda1 sda2 sda3 sda4 sdb1 sdb2 sdb3 sdb4 sdc1 sdc2 sdc3 sdc4
  sdd1 sdd2 sdd3 sdd4 sde1 sde2 sde3 sde4 sdf1 sdf2 sdf3 sdf4
  sdg1 sdg2 sdg3 sdg4 sdh1 sdh2 sdh3 sdh4 sdi1 sdi2 sdi3 sdi4
  } {
  if {[catch { exec /usr/bin/mlabel -i /dev/$device -s :: } tmp ]} { continue }
  set devlabel [lindex $tmp 3]
  puts -nonewline "Found $::mountdirroot/$devlabel at /dev/$device "
  if {[lsearch -exact $mountdevices /dev/$device] > -1} {
   puts "and it is already mounted."
   continue
   } else {
   puts "and will mount it now."
   }
  catch { file mkdir /multimedia/$devlabel } ;# We don't care if it exists.
  if {![catch { exec mount -o rw,noexec,nodev,sync,noatime,uid=$userid,gid=$groupid,shortname=mixed /dev/$device $mountdirroot/$devlabel }]} {
   exec touch [file join $mountdirroot $devlabel .DS_Store] ;# Create a dummy .DS_Store if none exists.
   }
  }

 get_mounted

 # Remove any directories present where nothing is mounted.
 set mountdirs [glob -tails -directory $::mountdirroot *]
 foreach d $mountdirs {
  if {[lsearch -exact $mountpoints $mountdirroot/$d] < 0} {
   puts -nonewline "Found surplus mount point $d and will remove it: "
   if {[catch {file delete $mountdirroot/$d} err]} { puts "$err" } else { puts "done." }
   set ::did(rm) 1
   }
  }

 get_mounted

 # Remove directories where the disk device has been pulled out without unmounting.
 set mountdirs [glob -tails -directory $::mountdirroot *]
 foreach d $mountdirs {
  if {![file exists $mountdirroot/$d/.DS_Store]} {
   puts -nonewline "Mount point $d presumed disconnected and will remove it: "
   if {[catch {exec umount $mountdirroot/$d} err]} { puts "$err" } else { puts -nonewline "unmounted, " }
   after 1000 ;# Give umount some time to unmount the device, etc.
   if {[catch {file delete $mountdirroot/$d} err]} { puts "$err" } else { puts "done." }
   set ::did(rm) 1
   }
  }

 if {![info exists ::did(rm)]} { puts "No surplus mount points found." }

Example output

 emu:~# ./mount-usb-fat.sh
 Found /multimedia/TWO at /dev/sda1 and it is already mounted.
 Found /multimedia/ONE at /dev/sdb1 and will mount it now.
 Found /multimedia/THREE at /dev/sdc1 and it is already mounted.
 Found surplus mount point TEST and will remove it: done.

Recent changes

This script now has support for when a USB drive has been pulled out without being properly unmounted first. This situation can happen intentionally but is most likely due to an accident (cable kicked or pulled out or drive becomes unresponsive due to cable interference data errors). We track this by testing to see if a .DS_Store file exists in the root directory. Drives connected to by Macs will already have such a file, on other systems a harmless 0 byte file will be created.

Added some extra device names, just in case.

Config and other things of note

This automount script requires that mtools [L1 ] is installed on your system to read the disk label information. mtools includes FAT support up to FAT32. You may need to add "mtools_skip_check=1" to your /etc/mtools.conf to ensure your random USB disks don't fall foul of mtools dreaded "total number of sectors not a multiple of sectors per track" error. This error seems to crop up fairly regularly with larger FAT32 partitions.

The main configurables are mountdirroot (in this case, /multimedia), userid and groupid (username and group you want given to the mounts).

Unlabelled disks and labels with spaces will probably cause this script some grief but not really cause anything serious to happen. Replace spaces with underscores or dashes in your disk labels.

Double-check what devices your harddrives are and remove them from the devices list if they conflict. Better safe than sorry, eh. If you're really keen, I guess you could populate this list by running a glob on your /dev tree, but, I've never had a USB use any device not in that list (so far!).

Other filesystems (NTFS, ext2/3/4, ReiserFS, ISO9660, etc) won't be recognised by mtools and therefore this script won't attempt to mount them.


Spot for comments and questions