Hi, I have finally made some effort on writing flexible yet very simple automounter for FreeBSD desktop. Feel free to submit me BUG reports ;) It currently supports these file formats: -- NTFS(rw) requires [port]sysutils/fusefs-ntfs[/port] -- FAT/FAT32 -- exFAT requires [port]sysutils/fusefs-exfat[/port] -- EXT2 -- EXT3 -- EXT4 requires [port]sysutils/fusefs-ext4fuse[/port] -- UFS (DOH!) It keeps state of the mounted devices at /var/run/automount.state and logs all activities to /var/log/automount.log file. The place for the script is at /usr/local/sbin/automount.sh executable. The only additional configuration it requires are those lines at the end of /etc/devd.conf file along with restarting /etc/rc.d/devd daemon. notify 200 { match "system" "DEVFS"; match "type" "CREATE"; match "cdev" "(da|mmcsd)[0-9]+"; action "/usr/local/sbin/automount.sh $cdev attach"; }; notify 200 { match "system" "DEVFS"; match "type" "DESTROY"; match "cdev" "(da|mmcsd)[0-9]+"; action "/usr/local/sbin/automount.sh $cdev detach"; }; The /usr/local/sbin/automount.sh executable is here: #! /bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin LOG="/var/log/automount.log" STATE="/var/run/automount.state" DATEFMT="%Y-%m-%d %H:%M:%S" __create_mount_point() { # /* 1=DEV */ MNT="/mnt/$( basename ${1} )" mkdir -p ${MNT} } __state_lock() { while [ -f ${STATE}.lock ]; do sleep 0.5; done :> ${STATE}.lock } __state_unlock() { rm ${STATE}.lock } __state_add() { # /* 1=DEV 2=PROVIDER 3=MNT */ __state_lock echo "${1} ${2} ${3}" >> ${STATE} __state_unlock } __state_remove() { # /* 1=MNT 2=STATE 3=LINE */ LINE=$( grep -n -E "${1}$" ${2} | cut -d : -f 1 ) sed -i '' ${3}d ${2} } __log() { # /* @=MESSAGE */ echo $( date +"${DATEFMT}" ) ${@} >> ${LOG} } case ${2} in (attach) for I in /dev/${1}* do case $( file -L -s ${I} ) in (*NTFS*) __create_mount_point ${I} ntfs-3g ${I} ${MNT} # /* sysutils/fusefs-ntfs */ __log "${I}:mount (ntfs)" ;; (*FAT*) __create_mount_point ${I} fsck_msdosfs -y ${I} mount_msdosfs -o large -o longnames -l -L pl_PL.ISO8859-2 -D cp852 ${I} ${MNT} __log "${I}:mount (fat)" ;; (*ext2*) __create_mount_point ${I} fsck.ext2 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext2)" ;; (*ext3*) __create_mount_point ${I} fsck.ext3 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext3)" ;; (*ext4*) __create_mount_point ${I} fsck.ext4 -y ${I} ext4fuse ${I} ${MNT} # /* sysutils/fusefs-ext4fuse */ __log "${I}:mount (ext4)" ;; (*Unix\ Fast\ File*) __create_mount_point ${I} fsck_ufs -y ${I} mount ${I} ${MNT} __log "${I}:mount (ufs)" ;; (*) case $( dd < ${O} count=1 | strings | head -1 ) in (EXFAT) __create_mount_point ${I} mount.exfat ${I} ${MNT} # /* sysutils/fusefs-exfat */ __log "${I}:mount (ufs)" ;; (*) continue ;; esac ;; esac __state_add ${I} $( mount | grep " ${MNT} " | awk '{printf $1}' ) ${MNT} done ;; (detach) MOUNTED=$( mount ) __state_lock while read DEV PROVIDER MNT do TARGET=$( echo "${MOUNTED}" | grep -E "^${PROVIDER} " | awk '{print $3}' ) [ -z ${TARGET} ] && { __state_remove ${MNT} ${STATE} ${LINE} continue } umount -f ${TARGET} & unset TARGET __state_remove ${MNT} ${STATE} ${LINE} __log "${DEV}:umount" done < ${STATE} __state_unlock __log "/dev/${1}:detach" ;; esac PS. Below are links for 'mirror' threads. http://forums.freebsd.org/showthread.php?t=29895 http://daemonforums.org/showthread.php?t=6838 Regards, vermaden ---
I already made some changes for the 'better' ... Here is the latest version: #! /bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin LOG="/var/log/automount.log" STATE="/var/run/automount.state" DATEFMT="%Y-%m-%d %H:%M:%S" __create_mount_point() { # /* 1=DEV */ MNT="/mnt/$( basename ${1} )" mkdir -p ${MNT} } __state_lock() { while [ -f ${STATE}.lock ]; do sleep 0.5; done :> ${STATE}.lock } __state_unlock() { rm ${STATE}.lock } __state_add() { # /* 1=DEV 2=PROVIDER 3=MNT */ __state_lock grep -E "${3}$" ${STATE} 1> /dev/null 2> /dev/null && { __log "${1}:duplicated '${STATE}'" return 1 } echo "${1} ${2} ${3}" >> ${STATE} __state_unlock } __state_remove() { # /* 1=MNT 2=STATE 3=LINE */ BSMNT=$( echo ${1} | sed 's/\//\\\//g' ) sed -i '' "/${BSMNT}\$/d" ${2} } __log() { # /* @=MESSAGE */ echo $( date +"${DATEFMT}" ) ${@} >> ${LOG} } case ${2} in (attach) for I in /dev/${1}* do case $( file -L -s ${I} ) in (*NTFS*) __create_mount_point ${I} ntfs-3g ${I} ${MNT} # /* sysutils/fusefs-ntfs */ __log "${I}:mount (ntfs)" ;; (*FAT*) __create_mount_point ${I} fsck_msdosfs -y ${I} mount_msdosfs -o large -o longnames -l -L pl_PL.ISO8859-2 -D cp852 ${I} ${MNT} __log "${I}:mount (fat)" ;; (*ext2*) __create_mount_point ${I} fsck.ext2 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext2)" ;; (*ext3*) __create_mount_point ${I} fsck.ext3 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext3)" ;; (*ext4*) __create_mount_point ${I} fsck.ext4 -y ${I} ext4fuse ${I} ${MNT} # /* sysutils/fusefs-ext4fuse */ __log "${I}:mount (ext4)" ;; (*Unix\ Fast\ File*) __create_mount_point ${I} fsck_ufs -y ${I} mount ${I} ${MNT} __log "${I}:mount (ufs)" ;; (*) case $( dd < ${O} count=1 | strings | head -1 ) in (EXFAT) __create_mount_point ${I} mount.exfat ${I} ${MNT} # /* sysutils/fusefs-exfat */ __log "${I}:mount (ufs)" ;; (*) continue ;; esac ;; esac __state_add ${I} $( mount | grep " ${MNT} " | awk '{printf $1}' ) ${MNT} || continue done ;; (detach) __state_lock grep ${1} ${STATE} \ | while read DEV PROVIDER MNT do TARGET=$( mount | grep -E "^${PROVIDER} " | awk '{print $3}' ) [ -z ${TARGET} ] && { __state_remove ${MNT} ${STATE} ${LINE} continue } umount -f ${TARGET} & unset TARGET __state_remove ${MNT} ${STATE} ${LINE} __log "${DEV}:umount" done __state_unlock __log "/dev/${1}:detach" ;; esac I have made tests with 3 different USB drives, with different and same failesystems, connecting them all at once, disconnecting all at once, random connect, disconnect etc. Currently it seems to work ok but suggestions are very welcome.> Some things to consider/test: > > How do I set custom flags, like nosuid,noatime,nodev,noexec,async (or > sync) for mounts?Currently You can add these options to filesystem specific mount command, but its definitely possible.> What if make a usb drive with an illegal name, existing name or other dangerous values?The filesystem label is not used at all, I just use device names, which are reported by FreeBSD, so quite bulletproof here and then create appreciate /mnt/da0s1 directories.> Can I use the automounter to either mount over another mount to > impersonate it, or can I overwrite arbitrary files or directories?I have done everything to check that and to omit that, if not, then submit a BUG ;) Thanks for suggestions Matt. Regards, vermaden -- ...
... even newer version, seems to have all 'problems' fixed now ;) #! /bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin LOG="/var/log/automount.log" STATE="/var/run/automount.state" DATEFMT="%Y-%m-%d %H:%M:%S" __create_mount_point() { # /* 1=DEV */ MNT="/mnt/$( basename ${1} )" mkdir -p ${MNT} } __state_lock() { while [ -f ${STATE}.lock ]; do sleep 0.5; done :> ${STATE}.lock } __state_unlock() { rm ${STATE}.lock } __state_add() { # /* 1=DEV 2=PROVIDER 3=MNT */ __state_lock grep -E "${3}" ${STATE} 1> /dev/null 2> /dev/null && { __log "${1}:duplicated '${STATE}'" return 1 } echo "${1} ${2} ${3}" >> ${STATE} __state_unlock } __state_remove() { # /* 1=MNT 2=STATE 3=LINE */ BSMNT=$( echo ${1} | sed 's/\//\\\//g' ) sed -i '' "/${BSMNT}\$/d" ${2} } __log() { # /* @=MESSAGE */ echo $( date +"${DATEFMT}" ) ${@} >> ${LOG} } case ${2} in (attach) for I in /dev/${1}* do case $( file -L -s ${I} ) in (*NTFS*) __create_mount_point ${I} ntfs-3g ${I} ${MNT} # /* sysutils/fusefs-ntfs */ __log "${I}:mount (ntfs)" ;; (*FAT*) __create_mount_point ${I} fsck_msdosfs -y ${I} mount_msdosfs -o large -l -L pl_PL.ISO8859-2 -D cp852 ${I} ${MNT} __log "${I}:mount (fat)" ;; (*ext2*) __create_mount_point ${I} fsck.ext2 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext2)" ;; (*ext3*) __create_mount_point ${I} fsck.ext3 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext3)" ;; (*ext4*) __create_mount_point ${I} fsck.ext4 -y ${I} ext4fuse ${I} ${MNT} # /* sysutils/fusefs-ext4fuse */ __log "${I}:mount (ext4)" ;; (*Unix\ Fast\ File*) __create_mount_point ${I} fsck_ufs -y ${I} mount ${I} ${MNT} __log "${I}:mount (ufs)" ;; (*) case $( dd < ${O} count=1 | strings | head -1 ) in (EXFAT) __create_mount_point ${I} mount.exfat ${I} ${MNT} # /* sysutils/fusefs-exfat */ __log "${I}:mount (ufs)" ;; (*) continue ;; esac ;; esac __state_add ${I} $( mount | grep -m 1 " ${MNT} " | awk '{printf $1}' ) \ ${MNT} || continue done ;; (detach) MOUNT=$( mount ) __state_lock grep ${1} ${STATE} \ | while read DEV PROVIDER MNT do TARGET=$( echo "${MOUNT}" | grep -E "^${PROVIDER} " | awk '{print $3}' ) [ -z ${TARGET} ] && { __state_remove ${MNT} ${STATE} ${LINE} continue } umount -f ${TARGET} & unset TARGET __state_remove ${MNT} ${STATE} ${LINE} __log "${DEV}:umount" done __state_unlock __log "/dev/${1}:detach" ;; esac
Latest version with additional checks for NTFS and FAT32, to be precise, for NTFS filesystem with label "FAT" and for FAT filesystem with label "NTFS" ;) #! /bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin LOG="/var/log/automount.log" STATE="/var/run/automount.state" DATEFMT="%Y-%m-%d %H:%M:%S" __create_mount_point() { # /* 1=DEV */ MNT="/mnt/$( basename ${1} )" mkdir -p ${MNT} } __state_lock() { while [ -f ${STATE}.lock ]; do sleep 0.5; done :> ${STATE}.lock } __state_unlock() { rm ${STATE}.lock } __state_add() { # /* 1=DEV 2=PROVIDER 3=MNT */ __state_lock grep -E "${3}" ${STATE} 1> /dev/null 2> /dev/null && { __log "${1}:duplicated '${STATE}'" return 1 } echo "${1} ${2} ${3}" >> ${STATE} __state_unlock } __state_remove() { # /* 1=MNT 2=STATE 3=LINE */ BSMNT=$( echo ${1} | sed 's/\//\\\//g' ) sed -i '' "/${BSMNT}\$/d" ${2} } __log() { # /* @=MESSAGE */ echo $( date +"${DATEFMT}" ) ${@} >> ${LOG} } case ${2} in (attach) for I in /dev/${1}* do case $( file -L -s ${I} | sed -E 's/label:\ \".*\"//g' ) in (*NTFS*) dd < ${I} count=1 2> /dev/null \ | strings \ | head -1 \ | grep -q "NTFS" && { __create_mount_point ${I} ntfs-3g ${I} ${MNT} # /* sysutils/fusefs-ntfs */ __log "${I}:mount (ntfs)" } ;; (*FAT*) dd < ${I} count=1 2> /dev/null \ | strings \ | grep -q "FAT32" && { __create_mount_point ${I} fsck_msdosfs -y ${I} mount_msdosfs -o large -l -L pl_PL.ISO8859-2 -D cp852 ${I} ${MNT} __log "${I}:mount (fat)" } ;; (*ext2*) __create_mount_point ${I} fsck.ext2 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext2)" ;; (*ext3*) __create_mount_point ${I} fsck.ext3 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext3)" ;; (*ext4*) __create_mount_point ${I} fsck.ext4 -y ${I} ext4fuse ${I} ${MNT} # /* sysutils/fusefs-ext4fuse */ __log "${I}:mount (ext4)" ;; (*Unix\ Fast\ File*) __create_mount_point ${I} fsck_ufs -y ${I} mount ${I} ${MNT} __log "${I}:mount (ufs)" ;; (*) case $( dd < ${I} count=1 2> /dev/null | strings | head -1 ) in (EXFAT) __create_mount_point ${I} mount.exfat ${I} ${MNT} # /* sysutils/fusefs-exfat */ __log "${I}:mount (ufs)" ;; (*) continue ;; esac ;; esac __state_add ${I} $( mount | grep -m 1 " ${MNT} " | awk '{printf $1}' ) \ ${MNT} || continue done ;; (detach) MOUNT=$( mount ) __state_lock grep ${1} ${STATE} \ | while read DEV PROVIDER MNT do TARGET=$( echo "${MOUNT}" | grep -E "^${PROVIDER} " | awk '{print $3}' ) [ -z ${TARGET} ] && { __state_remove ${MNT} ${STATE} ${LINE} continue } umount -f ${TARGET} & unset TARGET __state_remove ${MNT} ${STATE} ${LINE} __log "${DEV}:umount" done __state_unlock __log "/dev/${1}:detach" ;; esac
Added a check if ntfs-3g is available, if not then mount_ntfs is used instead. Added deleting of empty directories at ${MNTPREFIX}. Added ${MNTPREFIX} to be set to /mnt or /media according to preference #! /bin/sh PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin MNTPREFIX="/media" LOG="/var/log/automount.log" STATE="/var/run/automount.state" DATEFMT="%Y-%m-%d %H:%M:%S" __create_mount_point() { # /* 1=DEV */ MNT="${MNTPREFIX}/$( basename ${1} )" mkdir -p ${MNT} } __state_lock() { while [ -f ${STATE}.lock ]; do sleep 0.5; done :> ${STATE}.lock } __state_unlock() { rm ${STATE}.lock } __state_add() { # /* 1=DEV 2=PROVIDER 3=MNT */ __state_lock grep -E "${3}" ${STATE} 1> /dev/null 2> /dev/null && { __log "${1}:duplicated '${STATE}'" return 1 } echo "${1} ${2} ${3}" >> ${STATE} __state_unlock } __state_remove() { # /* 1=MNT 2=STATE 3=LINE */ BSMNT=$( echo ${1} | sed 's/\//\\\//g' ) sed -i '' "/${BSMNT}\$/d" ${2} } __log() { # /* @=MESSAGE */ echo $( date +"${DATEFMT}" ) ${@} >> ${LOG} } case ${2} in (attach) for I in /dev/${1}* do case $( file -L -s ${I} | sed -E 's/label:\ \".*\"//g' ) in (*NTFS*) dd < ${I} count=1 2> /dev/null \ | strings \ | head -1 \ | grep -q "NTFS" && { __create_mount_point ${I} which ntfs-3g 1> /dev/null 2> /dev/null && { ntfs-3g ${I} ${MNT} # /* sysutils/fusefs-ntfs */ } || { mount_ntfs ${I} ${MNT} } __log "${I}:mount (ntfs)" } ;; (*FAT*) dd < ${I} count=1 2> /dev/null \ | strings \ | grep -q "FAT32" && { __create_mount_point ${I} fsck_msdosfs -y ${I} mount_msdosfs -o large -l -L pl_PL.ISO8859-2 -D cp852 ${I} ${MNT} __log "${I}:mount (fat)" } ;; (*ext2*) __create_mount_point ${I} fsck.ext2 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext2)" ;; (*ext3*) __create_mount_point ${I} fsck.ext3 -y ${I} mount -t ext2fs ${I} ${MNT} __log "${I}:mount (ext3)" ;; (*ext4*) __create_mount_point ${I} fsck.ext4 -y ${I} ext4fuse ${I} ${MNT} # /* sysutils/fusefs-ext4fuse */ __log "${I}:mount (ext4)" ;; (*Unix\ Fast\ File*) __create_mount_point ${I} fsck_ufs -y ${I} mount ${I} ${MNT} __log "${I}:mount (ufs)" ;; (*) case $( dd < ${I} count=1 2> /dev/null | strings | head -1 ) in (EXFAT) __create_mount_point ${I} mount.exfat ${I} ${MNT} # /* sysutils/fusefs-exfat */ __log "${I}:mount (ufs)" ;; (*) continue ;; esac ;; esac __state_add ${I} $( mount | grep -m 1 " ${MNT} " | awk '{printf $1}' ) \ ${MNT} || continue done ;; (detach) MOUNT=$( mount ) __state_lock grep ${1} ${STATE} \ | while read DEV PROVIDER MNT do TARGET=$( echo "${MOUNT}" | grep -E "^${PROVIDER} " | awk '{print $3}' ) [ -z ${TARGET} ] && { __state_remove ${MNT} ${STATE} ${LINE} continue } umount -f ${TARGET} & unset TARGET __state_remove ${MNT} ${STATE} ${LINE} __log "${DEV}:umount" done __state_unlock __log "/dev/${1}:detach" find ${MNTPREFIX} -type d -empty -delete ;; esac> Not sure if you've looked at disktype in sysutils > but it may be useful to you.I will get look into that, thanks ;)> Neat scripts! > MattThanks mate. Regards, vermaden -- ...
Hi, I removed the state_lock and stat_unlock mechanisms as they appeared to be not needed, I have shufled with 3 drives all the time and the 'integrity' has not been lost, at it was a lot faster, because the lock always had to wait for the 'slowest' drive (in term of initializing the device, like USB hard drive). I simplified the 'attach' section a lot, now each filesystem contains only check/fsck (if possible), mount and log info. I also simplified and improved the 'detach' section a little. I have added an option to automatically launch the set-up in config file manager (Yes, like in Windows ;p). These are options that I currently successfully use for NAUTILUS file manager, You need to set-up all three of them to make it work. | POPUP=YES | FM="nautilus --browser --no-desktop" | USER=vermaden My whole config looks like that now: | USERUMOUNT=YES | POPUP=YES | FM="nautilus --browser --no-desktop" | USER=vermaden | ENCODING=pl_PL.ISO8859-2 | CODEPAGE=cp852 All latest updates are available at GITHUB: https://github.com/vermaden/automount written by Freddie Cash ...> Konqueror (KDE 3.x and 4.x) and Dolphin (KDE 4.x mainly, but I > believe there's a KDE 3.x version) also show automatically > mounted and removable media in the sidebar. Works nicely > with HAL. Haven't tested your script yet, but am intrigued by it. > Will see if I can test it sometime this week. > > Native solutions are so much nicer than ported ones. :)Thanks, looking forward to hear some more input about it from You ;) written by Fernando Apestegu?a ...> What a nice piece of work.Thanks mate.> I just downloaded it and try it on a FreeBSD 9.0-RELEASE with > custom kernel. It works like a charm. I tried three different > USB devices without noticing any problems (and I was very > impolite when I unplugged them). > > Thanks for this script.Good to know, try the latest new version from repo, should be even better ;) Regards, vermaden
"Andriy Gapon" <avg@FreeBSD.org> said:> on 28/02/2012 17:26 Alexander Leidinger said the following: > > The kernel does not poll for CD changes, and the people guarding the relevant CD > > code where against something like this in the kernel everytime this came up in > > the past. So no devd event for this. > > My impression was that lately people were asking for it (and nobody actually > "guarded" the code), but there is no good design on how to do it.The mentioned earlier sysctl OID changes whenever CD is in the drive or not, something changes that ... so adding appreciate events like "MEDIA INSERTED" and "MEDIA REMOVED" to cd* class should be enought to handle them and mount/umount the medium with script like mine with appreciate devd(8) config. Regards, vermaden ...
"Ivan Klymenko" <fidaj@ukr.net> pisze:> > > > Note also that the above entry for cd0 does NOT change after > > inserting various different data CDs, all different sizes, nor after > > mounting one, so that 534181888 entry is from some time before, > > perhaps the first CD inserted after boot, not sure? Also the sizes > > are bytes, regardless of sector size (DVD above, while ad0s4 is a > > 32GiB slice on a 120GB disk). > > > > Doesn't look like this one is going to fly. > > I talked about this, that current version be non-working. but if you > make some changes in the cam/scsi|ata/atapi - it will work ...I would love to, but I have absolutely no idea how to do that ;) Regards, vermaden ...
Hi, after some 'fun' with MP3 players I have made some modifications and fixes. Here is a list of whats changed: Fixed bug about inproper exFAT detection, now mounts fine. Fixed bug about creating mount dirs for all attached devices no matter if needed or not. Revised 'detach' section, now removes only directory that is unmounted (if enabled of course). Simplified FAT/NTFS sections, removed additional check as it break some MP3 players default filesystems automount. The latest 1.3 version can be found here as usual: https://github.com/vermaden/automount/ Regards, vermaden