LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Blogs > Lumak's Guide to Random Things
User Name
Password

Notices

OK I don't really have a good title yet but I figure I can post works in progress and other tips I've come across or other interesting things.
Rate this Entry

USB drive auto mounter script!

Posted 12-01-2008 at 12:35 AM by lumak

Yes that's right! I kid you not! A marvelous bash script to automatically mount a usb flash drive (or at least set it up to mount it by users) it is commented and should be 'easy' to follow. There are probably better ways to do this, but at the time I didn't want to install anything (e.g. pmount) and I didn't feel like using autofs.

what does the script do if it doesn't automatically mount the drive?
- It determines an appropriate mount name from the file system label or defaults to 'flash'.
- It creates a symbolic link in /dev that points to the mountable partition
- It makes the mount point (e.g. /media/flash)
- It auto increments by 1 if the mountpoint is not empty OR the link is already there (e.g. /media/flash1 (it skips 0))

- IT EDITS FSTAB TO MAKE THE PARTITION MOUNTABLE BY ALL USERS. (bold because this is a security risk and I really didn't want to edit fstab either... oh well)
- It attempts to respect fstab rules by not creating any for a partition if they already exist.

Exciting huh?

It cleans it self up after you eject the device. I did not place any unmounts in the removal so if you don't use 'eject /dev/linkname' or at the very least use 'unmount' manually, you may have some issues. I'm tired of the script for now and just wanted to share it.

SO... here is what to do.
create /etc/udev/rules.d/90-local.rules (or whatever is appropriate for your OS) and place the following.
Code:
# This is messy but I'm no expert on the matter and it works
SUBSYSTEMS=="scsi", KERNEL=="sd*", ACTION=="add", GROUP="plugdev", RUN+="flashhandler.sh $env{DEVNAME} start"

ACTION=="remove", SUBSYSTEMS=="scsi", KERNEL=="sd*", RUN+="flashhandler.sh $env{DEVNAME} stop"

create a file and make it executable. from above, I named mine flashhandler.sh and I placed mine in the 'working/script' directory for udev. On my system (slackware) this is /lib/udev. If you place it some other place, the udev rules file should contain a direct path name to flashhandler.sh
Code:
#!/bin/bash
#
# This is in the public domain!
#
# A 'simple' script to create the a set up to allow users to
# mount their usb drives.

DEVICE=$1
COMMAND=$2

# How odd... most of the commands are in /bin and sym linked
# in /usr/bin. execpt for 'find'.  'find' is only in /usr/bin
PATH=/bin:/usr/bin
DEVDIR=/dev
MNTDIR=/media
CFGDIR=/etc

# just to be clear, put this in fstab format not mount format,
# the '0 0' is part of the line later in the script. You could
# move it here if you wish
FSTABOPTIONS="$ID_FS_TYPE noauto,user,rw,sync,dmask=027,fmask=137"

function fh_start () {
  # If the device is not mounted
  if ! grep $DEVICE $CFGDIR/mtab &> $DEVDIR/null; then
    # Find the file system label to name the link and mount point after
    NAME=`echo $ID_FS_LABEL | tr [:upper:] [:lower:]`
    if [ ! $NAME ]; then
      # Fall back to a default value
      NAME="flash"
    fi
    # By default, we want no suffix
    SUFFIX=
    # Loop until we have a safe link/mount point name.  Hopefully
    # this is done on the first try
    MADELINK=0
    while [ $MADELINK -eq 0 ]; do
      # is the mount point empty? is there a dev sym link?
      if [ ! "$(ls -A $MNTDIR/${NAME}${SUFFIX} 2> $DEVDIR/null)" ] && \
         [ ! "$(find $DEVDIR -name ${NAME}${SUFFIX} 2> $DEVDIR/null)" ]; then
        # Make the sym link
        ( cd $DEVDIR; ln -s `basename $DEVICE` ${NAME}${SUFFIX} )
        # Create the mount point
        mkdir -p $MNTDIR/${NAME}${SUFFIX}
        # Write an entry into /etc/fstab so that users can mount
        # the device as long as the device is not already listed.
        if ! grep ^$DEVICE $CFGDIR/fstab &> $DEVDIR/null && \
           ! grep ^$DEVDIR/${NAME}${SUFFIX} $CFGDIR/fstab &> $DEVDIR/null; then
           FSTABENTRY="$DEVDIR/${NAME}${SUFFIX} $MNTDIR/${NAME}${SUFFIX} $FSTABOPTIONS 0 0"
           echo $FSTABENTRY >> $CFGDIR/fstab
        fi
        
	# Do not mount the device here.  It will be owned by
        # root:root. Only mount it here if you specify
        # uid=root,uid=somegroup" along with permissions for the
        # group to do what you want them to.
	# if grep $MNTDIR/${NAME}${SUFFIX} $CFGDIR/fstab &> $DEVDIR/null; then
        #   mount $MNTDIR/${NAME}${SUFFIX}
        # fi

        # Exit the loop
        MADELINK=1
      else
        # To make the sym link and mount point match, we need to
        # increment it and try again.  This is a dirty solution and
        # really should have a better exit stratigy.  Additionally,
        # we do no error checking for people that name their
        # partitions drives after stupid things that already
        # appear in the /dev directory.  e.g. sd, fd, cdrom, etc.
        let SUFFIX++
      fi
    done
  fi
}

function fh_stop () {
  # The device unmounting is handeled by 'eject'.  A safe check
  # should probably be placed here just to make sure it really
  # is unmounted.  Have the script check /etc/mtab.
  # Since there is a possibility of multiple links to the device,
  # we should loop through all the links and undo everything.
  # You should probably do some error checking to make sure the
  # file is there for you to remove it or something of the such
  BASEDEV=`basename $DEVICE`
  for LINKFILE in `find $DEVDIR -lname $BASEDEV 2> $DEVDIR/null`; do
    NAME=`basename $LINKFILE`

    # Remove the sym link and mount point
    rm -f $LINKFILE
    rm -f $MNTDIR/$NAME

    # Remove our exact fstab entry that we put in before.  This is
    # sloppy. We don't actually know if we definitely added a line
    # in or not.  Maybe some sort of log file is needed to check
    # this first.
    FSTABENTRY="$LINKFILE $MNTDIR/$NAME $FSTABOPTIONS 0 0"
    sed -i -e "\@$FSTABENTRY@d" $CFGDIR/fstab
  done
}

# All scsi devices get passed into this script by udev. we are only
# interested in those connected through usb and that are
# filesystems... Hopefully this works when the filesystem is on the
# main device itself and not on a partiton.  e.g. /dev/sda instead of
# /dev/sda1.

# This should actually be placed into the udev rule to avoid
# confusion at the source and avoid running the script in the first
# place.
if [ $ID_BUS == "usb" ] && [ $ID_FS_USAGE == "filesystem" ]; then
  case $COMMAND in
    start)
      fh_start
    ;;
  
    stop)
      fh_stop
    ;;
  
    *)
      echo "This script should be run by udev rules only"
    ;;
  esac
fi

I tested this with my ipod nano (hey it was free) and my flash drive. The ipod was properly set up for sd?2 and the flash drive was properly set up for sd?1. I did not test different methods. bugs, tips, experience with this script would be appreciated; just leave a comment.

Some things I have not tested:
- make a hole flash drive the file system with no partitions (e.g. /dev/sda)
- make a flash drive with multiple partitions of various file system types.
- Test external hard drives (or make the script support it)

Check back later for when I post a blog entry on getting autofs to do something similar.
Views 3077 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 04:12 AM.

Main Menu
Advertisement

Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration