#!/bin/bash
# Filename:      scripts/grml-udev-rebuildfstab
# Purpose:       udev script to update /etc/fstab
# Authors:       grml-team (grml.org)
# Bug-Reports:   see http://grml.org/bugs/
# License:       This file is licensed under the GPL v2+.
################################################################################

PATH="/bin:/sbin:/usr/bin:/usr/sbin"
TMP=$(mktemp 2>/dev/null)
TMPFILE=$(mktemp 2>/dev/null)
ADDEDBYGRML="# Added by GRML"
MOUNTPOINT_PREFIX=/media
MNTFILE="$MOUNTPOINT_PREFIX/.grml-auto-created_do-not-delete-this-file"


logit() {
  if [ -x /usr/bin/logger ] ; then
     /usr/bin/logger -i -t rebuildfstab "$*"
  fi
}

bailout() {
   [ -n "$1" ] && EXITCODE="$1" || EXITCODE=1
   rm -f $TMP $TMPFILE /var/run/rebuildfstab.pid
   exit $EXITCODE
}

echo "$$" > /var/run/rebuildfstab.pid


umask 022


[ -e /etc/grml/autconfig ] && . /etc/grml/autoconfig

if ! [ -w "$(dirname $MNTFILE)" ] ; then
   echo "$0: can not write to $MNTFILE">&2
   logit "can not write to $MNTFILE"
   bailout 10
fi

if [ -z "$TMP" -o -z "$TMPFILE" ] ; then
   echo "$0: could not create tmpfile (is / mounted read-only?), exiting" >&2
   logit 'fatal - could not create tmpfile (is / mounted read-only?), exiting'
   bailout 3
fi

# trap "rm -f $TMP $TMPFILE" 2 3 11


if grep -q " nofstab" /proc/cmdline ; then
   bailout 0
fi

grep -q 'nolabel' /proc/cmdline && NOLABEL='TRUE' || LABEL='TRUE'



if [ "$CONFIG_FSTAB" = "no" ] ; then
    bailout 0
fi


if grep -q ' $MOUNTPOINT_PREFIX ' /proc/mounts ; then
   logit '$MOUNTPOINT_PREFIX is a mounted directory, exiting.'
   bailout 1
fi

# default directories {{{
if [ -d "$MOUNTPOINT_PREFIX" ] ; then
   [ -d "$MOUNTPOINT_PREFIX/floppy" ] || mkdir "$MOUNTPOINT_PREFIX/floppy"
   [ -d "$MOUNTPOINT_PREFIX/cdrom" ]  || mkdir "$MOUNTPOINT_PREFIX/cdrom"
   [ -d "$MOUNTPOINT_PREFIX/test" ]   || mkdir "$MOUNTPOINT_PREFIX/test"
fi
# }}}

# make sure we have the $MNTFILE before reading/writing into it
if [ -z "$NO_AUTO_FILE" ] ; then
   [ -r $MNTFILE ] || touch $MNTFILE
fi


# make sure we have a /etc/fstab at all
(
    flock -x 200
if ! [ -f /etc/fstab ] ; then
  cat > /etc/fstab << EOF
# /etc/fstab - static file system information
# <filesystem> <mountpoint>   <type> <options>                             <dump> <pass>
proc           /proc          proc   rw,nosuid,nodev,noexec                 0      0
none           /proc/bus/usb  usbfs  defaults,noauto                        0      0
sysfs          /sys           sysfs  rw,nosuid,nodev,noexec                 0      0
devpts         /dev/pts       devpts noauto,mode=0622                       0      0
/dev/external  ${MOUNTPOINT_PREFIX}/external  auto   user,noauto,exec,rw,uid=grml,gid=grml  0      0
/dev/external1 ${MOUNTPOINT_PREFIX}/external1 auto   user,noauto,exec,rw,uid=grml,gid=grml  0      0
/dev/cdrom     ${MOUNTPOINT_PREFIX}/cdrom     auto   user,noauto,exec,ro                    0      0
/dev/dvd       ${MOUNTPOINT_PREFIX}/dvd       auto   user,noauto,exec,ro                    0      0
# some other examples:
# /dev/sda1      /Grml         ext3    dev,suid,user,noauto 0  2
# //1.2.3.4/pub  /smb/pub      smbfs   defaults,user,noauto,uid=grml,gid=grml 0 0
# linux:/pub     /beer         nfs     defaults             0  0
# tmpfs          /tmp          tmpfs   size=300M            0  0
# none           /proc/bus/usb usbfs   defaults,nodev,noexec,nosuid,noauto,devgid=1001,devmode=664 0 0
# 192.168.1.101:/backups ${MOUNTPOINT_PREFIX}/nfs nfs  defaults,user,wsize=8192,rsize=8192 0 0
#
# Warning! Please do *not* change any lines below because they are auto-generated.
# If you want to disable rebuildfstab set CONFIG_FSTAB='no' in /etc/grml/autoconfig!
# See 'man grml-udev-rebuildfstab' for more details about the following entries.
EOF
fi
) 200>/var/run/rebuildfstab.lock

[ ! -w /etc/fstab ] && {
  logit "fatal - /etc/fstab not writeable, exiting"
  bailout 0
}

# Simple shell grep, searches for lines STARTING with string
stringinfile () {
  while read line ;do
    case "$line" in
            ($1*) return 0 ;;
    esac
  done < "$2"
  return 1
}

# Remove comment line $1 and the following line from file $2
# sed '/^# Added by GRML/{N;d;}'
removeentries () {
	entry="$1"
	entry=$(echo $1 |  sed "s#/#\\\/#g")
	(
		flock -x 200
		sed -i -e "/$entry/{N;d}" /etc/fstab
	) 200>/var/run/rebuildfstab.lock
}


get_device_name() {
case $ID_FS_TYPE in
# dont use labels for some filesystem
iso9660)
break;
;;
*)
if [ -n "$LABEL" ]  && [ -n "$ID_FS_LABEL_ENC" ] ; then
  # see check_for_label() in scanpartitions for details
  case $ID_FS_LABEL_ENC in
    *\x*)
      addinfo=" # special char in label ($ID_FS_LABEL_ENC) not supported"
      break ;;
    *)
      echo "LABEL=$ID_FS_LABEL_ENC"
      return
      break;
  esac
fi
;;
esac
[ -n "$DM_NAME" ] && echo /dev/mapper/$DM_NAME && return

NAME="$DEVNAME"
for name in $DEVLINKS ; do
    case $name in
        *usb-sd*|*cdrom*|*dvd*)
            NAME="$name"
	    break;
        ;;
esac
done
echo "$NAME"
}

get_mount_point() {
    device="$1"
    mountpoint="${device##*/}"
    mountpoint="${mountpoint#*=}"
    echo "$MOUNTPOINT_PREFIX/$mountpoint"
}

append_fstab() {
	(
		flock -x 200
		echo $ADDEDBYGRML $1 >> /etc/fstab
		echo "$2" >> /etc/fstab
	) 200>/var/run/rebuildfstab.lock

}


if [ -n "$CONFIG_FSTAB_USER" ] ; then
    user="$CONFIG_FSTAB_USER"
else
    user='1000' # take default
fi
if [ -n "$CONFIG_FSTAB_GROUP" ] ; then
    group="$CONFIG_FSTAB_GROUP"
else
    group='users' # take default
fi

if [ -z "$ACTION" ] ; then
    logit "Seems that $0 is not run in a udev environment, exiting." >&2
    bailout 1
fi

# ignore loop devices for now.
case $DEVNAME in
/dev/loop*)
	bailout 0
	;;
esac

removeentries "$ADDEDBYGRML $DEVNAME" /etc/fstab

device=$(get_device_name)
mountpoint=$(get_mount_point $device)

# if entry is already present in /etc/fstab ignore the current event
(
    flock -x 200
    grep -v '^#' /etc/fstab > $TMPFILE
) 200>/var/run/rebuildfstab.lock

for devicelink in $DEVLINKS ; do
    # ignore external
    case "$devicelink" in *external*) continue ;; esac
    stringinfile $devicelink $TMPFILE && bailout 0
done

# if entry is already present ignore it
stringinfile $device $TMPFILE && bailout 0

if [ "$ID_FS_USAGE" != "filesystem" -a "$ID_FS_TYPE" != "swap" ]; then
    # blockdevice in question won't be mountable in this case
    bailout 0
fi

options=noauto,user,dev,suid,exec
case $ID_FS_TYPE in
ntfs)
        options=$options,ro,umask=000
        ;;
vfat|msdos)
        options=$options,umask=000
        ;;
ufs)
        options=$options,ro
        ;;
swap)
        options=defaults
        ;;
esac
case $ID_FS_TYPE in
ntfs|vfat|msdos)
        test -n "$user" && options=$options,uid=$user
        test -n "$group" && options=$options,gid=$group
        ;;
esac

case $ACTION in
add|change)
(
    flock -x 200
    echo "$ADDEDBYGRML $DEVNAME" >> /etc/fstab
    echo "$device $mountpoint $ID_FS_TYPE $options 0 0 $addinfo # $DEVNAME" >> /etc/fstab
) 200>/var/run/rebuildfstab.lock


;;
esac

# Clean $MOUNTPOINT_PREFIX according to info $MNTFILE
if [ -r "$MNTFILE" ] ; then
   for directory in $(cat $MNTFILE) ; do
     rmdir $directory 2>/dev/null && sed -i "s#$directory##" $MNTFILE
   done
   grep '^/.*$' $MNTFILE | sort -u > $TMPFILE
   cat $TMPFILE > $MNTFILE
fi

# Make sure we have all directories in $MOUNTPOINT_PREFIX
while read p m f relax; do
  case "$m" in *none*|*proc*|*sys*|'') continue ;; esac
  if ! grep -q "$m" /proc/mounts ; then
     if ! [ -d "$m" ] ; then
        if mkdir -m 755 -p "$m" ; then
          [ -r "$MNTFILE" ] && grep -q "$m" $MNTFILE || echo "$m" >> $MNTFILE
        fi
     fi
  fi
done <<EOT
$(cat /etc/fstab | grep -v '^#')
EOT

# sort the file again...
if [ -r "$MNTFILE" ] ; then
   grep '^/.*$' $MNTFILE | sort -u > $TMPFILE
   cat $TMPFILE > $MNTFILE
fi

bailout 0

## END OF FILE #################################################################
