#!/bin/sh

### BEGIN INIT INFO
# Provides:          shush-toram
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# X-Start-Before:    $syslog
# X-Stop-After:      $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Silence the hard disk by using tmpfs for /var/log and other directories
# X-Interactive:   yes
### END INIT INFO

# Based on
# http://www.debian-administration.org/article/661/A_transient_/var/log
# and debian tmpfs for /var/run and /var/lock
# but also any other directories

NAME=shush-toram
DESC="hard disk silencer"
RAMNAME=tmpfs
RAMDIRS=/var/log
MINSIZE=52428800
ISON=0

# Include defaults if available
if [ -f /etc/default/$NAME ] ; then
    . /etc/default/$NAME
fi

# Return
#   0 been started or already running
#   1 failure

# Load rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

do_start()
{
    # not root? fail
    [ `id -u` -eq 0 ] || return 2

    # set default return value to success
    RETURN=0
    
    # proceed for each directory
    for RAMDIR in $RAMDIRS; do
	# RAMDIR non-existant? odd. silent fail
	[ -d $RAMDIR ] || continue
		
	# there is a fishy lock, fail with warning
	RAMLOCK=/var/lock/shush-`echo $RAMDIR | sed s@/@@g`.lock
	[ -h $RAMLOCK ] && RETURN=1 && continue # symlink

	# keep ownership and mode
	DIRMODE=`stat -c "%a" $RAMDIR`
	DIRUID=`stat -c "%u" $RAMDIR`
	DIRGID=`stat -c "%g" $RAMDIR`
	
	# make sure ORIGINALDIR exists, with proper modes and ownership
	ORIGINALDIR=`dirname $RAMDIR`/.`basename $RAMDIR`-orig
	[ -d $ORIGINALDIR ] || mkdir $ORIGINALDIR
	chmod $DIRMODE $ORIGINALDIR
	chown $DIRUID:$DIRGID $ORIGINALDIR
    
	# bind the original directory before putting up the ramdisk
	# (unless there's a lock already - handling restart)
	[ ! -f $RAMLOCK ] && mount --bind $RAMDIR $ORIGINALDIR

 	# find out the directory size to set a sensible ramdisk size
	# (we can be generous as tmpfs partitions do not consume any
	# memory until it is actually needed)
	DIRSIZE=`du --summarize --bytes $RAMDIR | cut -f 1`
	DIRSIZE=$(($DIRSIZE * 6))
	[ $DIRSIZE -lt $MINSIZE ] && DIRSIZE=$MINSIZE
	
	# bring up the ramdisk
	if [ ! -f $RAMLOCK ]; then
	    # no lock, we start: mount
	    mount -t tmpfs -o nodev,size=$DIRSIZE $RAMNAME $RAMDIR
	    # populate the ramdisk on success
	    [ $? -eq 0 ] && cp -rfp $ORIGINALDIR -T $RAMDIR
	    # set a lock on success
	    [ $? -eq 0 ] && set -o noclobber && echo $RAMDIR > $RAMLOCK && set +o noclobber
	else
	    # lock, we restart: simple remount
	    mount -t tmpfs -o remount,nodev,size=$DIRSIZE $RAMNAME $RAMDIR	    
	fi
	
	# go to the next RAMDIR on success
	[ $? -eq 0 ] && continue
		
	# on failure cancel previous mounts
	umount $RAMDIR
	umount $ORIGINALDIR
	# and set a fail return value
	RETURN=1
    done
    return $RETURN
}


do_stop() {
    # not root? fail
    [ `id -u` -eq 0 ] || return 2

    # set default return value to success
    RETURN=0
    
    # proceed for each directory
    for RAMDIR in $RAMDIRS; do
	# RAMDIR non-existant? odd. silent fail
	[ -d $RAMDIR ] || continue
		
	# ORIGINALDIR non-existant? nowhere to save, fail with warning
	# (this should never happen)
	ORIGINALDIR=`dirname $RAMDIR`/.`basename $RAMDIR`-orig
	[ ! -d $ORIGINALDIR ] && RETURN=1 && continue
	
	# lock check, fail with warning
	RAMLOCK=/var/lock/shush-`echo $RAMDIR | sed s@/@@g`.lock
	[ -h $RAMLOCK ] && RETURN=1 && continue # symlink
	[ ! -f $RAMLOCK ] && RETURN=1 && continue  # missing lock

        # Merge back to permanent storage
	rm -f $RAMLOCK
        /usr/bin/rsync --archive --delete $RAMDIR/ $ORIGINALDIR/

	# unmount it all
        umount -l $RAMDIR
        umount -l $ORIGINALDIR

	# remove the solid directory now useless, if empty
	rmdir $ORIGINALDIR
    done
    return $RETURN
}

do_save() {
    # not root? fail
    [ `id -u` -eq 0 ] || return 2

    # set default return value to success
    RETURN=0
            
    # proceed for each directory
    for RAMDIR in $RAMDIRS; do
	# RAMDIR non-existant? odd. silent fail
	[ -d $RAMDIR ] || continue
		
	# ORIGINALDIR non-existant? nothing to save then, skip silently
	ORIGINALDIR=`dirname $RAMDIR`/.`basename $RAMDIR`-orig
	[ -d $ORIGINALDIR ] || continue

	# check lock, fail with warning
	RAMLOCK=/var/lock/shush-`echo $RAMDIR | sed s@/@@g`.lock
	[ -h $RAMLOCK ] && RETURN=1 && continue  # symlink
	[ ! -f $RAMLOCK ] && RETURN=1 && continue # missing lock
		
        # Merge back to permanent storage
	rm -f $RAMLOCK
        /usr/bin/rsync --archive --delete $RAMDIR/ $ORIGINALDIR/
	set -o noclobber && echo $RAMDIR > $RAMLOCK && set +o noclobber
    done
    return $RETURN
}

do_status() {
    RETURN=0
    
    # proceed for each directory
    for RAMDIR in $RAMDIRS; do
	# RAMDIR non-existant? odd. silent fail
	[ -d $RAMDIR ] || continue
	
	RAMLOCK=/var/lock/shush-`echo $RAMDIR | sed s@/@@g`.lock
        if [ -f $RAMLOCK ]; then
	    echo "$RAMDIR on $RAMNAME"
	    ISON=1 # record that we have at least one RAMDIR
	else
	    echo "$RAMDIR is not on $RAMNAME"
	fi
    done
}  	   

case "$1" in
    start)
	log_daemon_msg "Starting $DESC" "$RAMDIRS"
	do_start
	log_end_msg $?
	;;
    stop)
	log_daemon_msg "Stopping $DESC" "$RAMDIRS"
	do_stop
	log_end_msg $?
	;;
    status)
	do_status
	;;
    save|reload)
	log_daemon_msg "Updating hard disk copies" "$RAMDIRS"
	do_save
	log_end_msg $?
	;;
    restart)
	do_status
	log_daemon_msg "Restarting $DESC"
	if [ $ISON -ne 0 ]; then
	    do_save
	    do_start
	    log_end_msg $?
	else
	    echo " not active, use start instead of restart"
	    log_end_msg 1
	fi
	;;
    
    *)
	echo "Usage: $0 {start|stop|status|save|restart}" >&2
	exit 3
	;;
esac


# EOF
