#!/bin/sh # # Automount hotplugged block devices, by Wout Mertens (wmertens@gentoo.org) # # Linux v2.6 version # This script is released under version 2 of the GPL. # To install this, either make it /sbin/hotplug, or, if you have # linux-hotplug installed, make it /etc/hotplug.d/block/automount.hotplug . # It needs to be executable. I tested it with busybox's ash. # # The devices will be mounted for the console user if applicable. # # To work, this needs: # - v2.6 kernel support: # - hotplugging, /proc mounted, /sys mounted # - filesystems that will be mounted, like vfat # - sh, echo, sed, stat or ls, getent or grep passwd, # mount, umount, mkdir, rmdir. logger is used if there. # # Possible improvements: # - Call a notifier script when mounting/unmounting. This could create the # desktop entry by itself. # - Edit fstab instead, and give the "user" option. This depends more on # the user/desktop knowing what he/it is doing. # Changelog: # # - 2005-03-26 Mark Burazin (mark@burazin.net) # - Multiple partitions are now correctly created as separate icons # # - 2005-03-20 Mark Burazin (mark@burazin.net) # - Creation of desktop entry under /home/(current user)/Desktop # - use supermount and subfs successfuly. # - Solve bug where sometimes the icons were not deleted (problem was in spaces # which were in some names eg. "JUMPDRIVE " -> "JUMPDRIVE") # - Another issue of the delete bug is when the usb is quicker and we don't # know the device name. There is a solution, but You must uncomment the "usbbug" line # - allow a definition for using diffrent icons for diffrent drives check the # PRODUCTS_* variables. # Debugging # set -xv # exec > /tmp/hotplug.$$ 2>&1 # Configuration ICON_PATH=/usr/kde/3.3/share/icons/default.kde/scalable/devices PATH="/bin:/sbin:/usr/bin:/usr/sbin" export PATH # We only handle block device messages [ "$1" != "block" ] && exit 0 # Proclaim stuff to the world mesg () { logger -t $0 "$*" } # Is path already mounted? is_path_mounted () { while read dev path rest do if [ "$path" = "$1" ] then return 0 fi done < /proc/self/mounts return 1 } # Get mounted path for a device get_mounted_path () { while read dev path rest do if [ "$dev" = "$1" ] then echo "$path" return 0 fi done < /proc/self/mounts return 1 } get_product_info () { # Here You can setup which are the default # icons ICON_HDD=hdd_mount.svgz ICON_USBPENDRIVE=usbpendrive_mount.svgz ICON_DEFAULT=$ICON_USBPENDRIVE # And which icons to assign to which product id's, joust remove # spaces from the name eg. "SOME USB DRIVE" -> "SOMEUSBDRIVE" # and leave it surrounded by ":" PRODUCTS_USBPENDRIVE=":JUMPDRIVE:" PRODUCTS_HDD=":B200P0:24320:USBMSReader:USBCFReader:" # Find the name PRODUCT=`cat /sys/$1/$2/device/model` if [ -z "$PRODUCT" ] then PRODUCT=generic else PRODUCT=`echo $PRODUCT | sed 's/ //g'` fi # Find the vendor VENDOR=`cat /sys/$1/$2/device/vendor` if [ -z "$VENDOR" ] then VENDOR=vendor else VENDOR=`echo $VENDOR | sed 's/ //g'` VENDOR=`echo $VENDOR | sed 's/-//g'` fi # Find out who we are going to mount it as CONSOLEUSER=`stat -c%U /dev/console 2>/dev/null` if [ -z "$CONSOLEUSER" ] then set `ls -l /dev/console` CONSOLEUSER=$3 fi [ -n "$CONSOLEUSER" ] || CONSOLEUSER=root PASSWD=`getent passwd $CONSOLEUSER 2>/dev/null` if [ -z "$PASSWD" ] then PASSWD=`grep "$CONSOLEUSER" /etc/passwd||grep root /etc/passwd` fi if [ -z "$PASSWD" ] then mesg "Could not get password entry for $CONSOLEUSER" exit 1 fi set `echo $PASSWD | sed 's/:/ /g'` if [ $# -lt 4 ] then mesg "Bad password entry for $CONSOLEUSER" exit 1 fi USERID=$3 USERGID=$4 # if we have a quick usb unplug (can't determine product) # then we need to find the icons by device and delete them. if [ "$ACTION" = "remove" && $PRODUCT = "generic" ] then set `grep -l -e"$DEVICE" /home/$CONSOLEUSER/Desktop/*.desktop` if [ $# -lt 1 ] then # this solves the usbbug, uncomment to allow this feature, but be careful mesg "Deleting stale icon...$#" rm /home/$CONSOLEUSER/Desktop/$#.desktop fi fi #uncomment this so You can see the name for PRODUCTS_* variables #mesg "Searching for product: ->$PRODUCT<-" # Find the icon type if [ ! -z `echo $PRODUCTS_USBPENDRIVE | grep -e:$PRODUCT:` ] then ICON_USE=$ICON_USBPENDRIVE elif [ ! -z `echo $PRODUCTS_HDD | grep -e:$PRODUCT:` ] then ICON_USE=$ICON_HDD else ICON_USE=$ICON_DEFAULT fi } # Wait for a file to appear wait_for () { local count=0 while [ $count -lt 10 ] && [ ! -e "$1" ] do sleep 1 done [ $count -eq 10 ] && return 1 return 0 } # Remove strange characters from a filename clean_filename () { # Note the lack of quotes around $1, this strips off spaces. echo $1 | sed 's/[ /?*\"<>]/_/g' } # Figure out the device to mount set `echo $DEVPATH | sed 's/\// /g'` [ $# -ne 3 ] && exit 0 DEVICE=/dev/$3 if [ "$ACTION" = "remove" ] then # Is it ours? dir=`get_mounted_path $DEVICE` echo "$dir" | grep -q ^/mnt/usb || exit 0 get_product_info $1 $2 $ACTION $DEVICE # Unmount it [ -d "$dir" ] || exit 1 umount -lf "$dir" rmdir "$dir" # remove the desktop icon mesg Unmounting $DEVICE, $dir $PRODUCT for user $CONSOLEUSER SDEV=`echo $DEVICE | sed 's/\///g'` rm "/home/$CONSOLEUSER/Desktop/$SDEV.desktop" exit 1 fi if [ "$ACTION" = "add" ] then # Is it a usb device? Exit if not. ls -l /sys/$1/$2/device | sed 's/^.* -> //g' | grep -q usb || exit 0 # Mount it # Make sure we have support for vfat modprobe -q vfat wait_for /sys/$1/$2/device/vendor || exit 1 get_product_info $1 $2 $ACTION # Find out where we mount it MOUNTPATH=/mnt/usb/`clean_filename "$PRODUCT"` if is_path_mounted "$MOUNTPATH" then count=1 while is_path_mounted "${MOUNTPATH}_${count}" do count=$(( $count + 1 )) done MOUNTPATH="${MOUNTPATH}_${count}" PRODUCT="${PRODUCT}_${count}" fi # Make sure it's a directory if [ -e "$MOUNTPATH" ] then if [ ! -d "$MOUNTPATH" ] then mesg "$MOUNTPATH exists but is not a directory" exit 1 fi else mkdir -p "$MOUNTPATH" if [ $? -ne 0 ] then mesg "Could not create mountpoint $MOUNTPATH" exit 1 fi fi # These options should prevent abuse and make it writeable for the # console user. if grep -q subfs /proc/filesystems then MOUNTOPTS="-s -t subfs -o fs=vfat:ext3:ext2:reiserfs,noatime,nosuid,umask=077,uid=$USERID,gid=$USERGID" elif grep -q supermount /proc/filesystems then MOUNTOPTS="-s -t supermount -onoatime,nosuid,umask=077,uid=$USERID,gid=$USERGID" else #MOUNTOPTS="-s -onoatime,sync,dirsync,nosuid,umask=077,uid=$3,gid=$4" MOUNTOPTS="-s -onoatime,sync,user,exec,umask=0000" fi mesg Mounting $DEVICE on $MOUNTPATH, options $MOUNTOPTS $ICON_USE mount $MOUNTOPTS $DEVICE $MOUNTPATH # Everything was mounted fine, create a Desktop icon SDEV=`echo $DEVICE | sed 's/\///g'` OUTPUTFILE="/home/$CONSOLEUSER/Desktop/$SDEV.desktop" echo "[Desktop Entry]" > $OUTPUTFILE echo "Version=1.0" >> $OUTPUTFILE echo "Name=$VENDOR $PRODUCT" >> $OUTPUTFILE echo "Encoding=UTF-8" >> $OUTPUTFILE echo "Type=Link" >> $OUTPUTFILE echo "URL=$MOUNTPATH" >> $OUTPUTFILE echo "Dev=$DEVICE" >> $OUTPUTFILE echo "Icon=$ICON_PATH/$ICON_USE" >> $OUTPUTFILE chmod 777 $OUTPUTFILE chown $CONSOLEUSER $OUTPUTFILE chgrp users $OUTPUTFILE fi exit