#!/bin/sh
# Authors: Vitaly Lipatov <lav@etersoft.ru>
#          Konstantin Baev <kipruss@altlinux.org>
# 2006, 2007, 2008, 2009, 2010 Public domain

# chkconfig: 345 03 80
# description: etercifs CIFS support for Linux kernel
#
# modulename: etercifs
#
### BEGIN INIT INFO
# Provides: etercifs
# Required-Start: $syslog
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: etercifs CIFS support for Linux kernel
# Description: etercifs CIFS support for Linux kernel, linux cifs module
### END INIT INFO

RMMOD=/sbin/rmmod
MODPROBE=/sbin/modprobe
INSMOD=/sbin/insmod
MODINFO=/sbin/modinfo
# against run with sudo
export PATH=$PATH:/sbin:/usr/sbin

. /usr/share/etercifs/functions.sh

PACKAGEINFO=/usr/share/etercifs/package.conf
if [ -f "$PACKAGEINFO" ] ; then
   . $PACKAGEINFO
else
   fatal "Not found package information file $PACKAGEINFO"
fi

CONFIGFILE=/etc/sysconfig/etercifs.conf
if [ -f $CONFIGFILE ] ; then
    . $CONFIGFILE
else
    fatal "Not found configuration file $CONFIGFILE"
fi

[ -n "$BUILT" ] || BUILT=0
[ -n "$DKMS" ] || DKMS=1

ORIGMODULENAME=cifs

# FIXME: %_initdir
OUTFORMAT=/etc/init.d/outformat
[ -x $OUTFORMAT ] || OUTFORMAT=/etc/init.d/etercifs.outformat

if which tput >/dev/null && test -x $OUTFORMAT ; then
        . $OUTFORMAT
else
    MOVE_TO_COL(){ :; }
    SETCOLOR_SUCCESS(){ :; }
    SETCOLOR_FAILURE(){ :; }
    SETCOLOR_WARNING(){ :; }
    SETCOLOR_NORMAL(){ :; }
fi

# TODO: use /etc/init.d/functions (see eterbug 5283 too)
# Mandriva compatibility (eterbug 5283)
gprintf()
{
    printf "$@"
}

# TODO: use printf?
success()
{
    MOVE_TO_COL
    echo -n '[ '
    SETCOLOR_SUCCESS
    echo -n 'DONE'
    SETCOLOR_NORMAL
    echo ' ]'
}

failure()
{
    MOVE_TO_COL
    echo -n '['
    SETCOLOR_FAILURE
    echo -n 'FAILED'
    SETCOLOR_NORMAL
    echo ']'
}

passed()
{
    MOVE_TO_COL
    echo -n '['
    SETCOLOR_WARNING
    echo -n 'PASSED'
    SETCOLOR_NORMAL
    echo ']'
}

get_pid()
{
    # TODO: use pgrep
    PIDOF=/bin/pidof
    if [ -x $PIDOF ] ; then
        dpid=`$PIDOF $1`
    else
        dpid="$(ps axh | grep $1 | grep -v grep | sed -e 's/ *\(.*\)/\1/' -e 's/ \+/ /g' | grep -v " /bin/sh " | grep -v "^$$ " |  cut -f1 -d\  | head -1)"
    fi
    return $dpid
}

get_module_version()
{
    MODVER=`$MODINFO etercifs | grep ^version:`
    MODVER=`echo $MODVER | sed 's|version:||g'`
    MODVER=`echo $MODVER | sed 's| ||g'`
}

get_loaded_module_version()
{
    LOADEDMODVER=`cat /sys/module/$MODULENAME/version 2>/dev/null`
}

is_loaded()
{
    get_pid $1
    test -n "$dpid"
}

is_moduled()
{
    lsmod | grep "^$MODULENAME" > /dev/null
}

is_origmoduled()
{
    lsmod | grep "^$ORIGMODULENAME" > /dev/null
}

check_for_old_kernel()
{
    detect_host_kernel
    split_kernel_version
    if [ "$N1" -eq 2 ] && [ "$N2" -eq 6 ] ; then
        if [ "$N3" -ge 29 ] ; then
            return 0
        fi
    fi
    check_for_centos > /dev/null
    if [ -n "$SPECIFIC_CENTOS" ] && [ "$CENTOS" -ge 54 ] ; then
        return 0
    fi
    return 1
}

umount_cifs()
{
    WASCIFS=
    if mount | grep cifs 2>/dev/null ; then
        WASCIFS=1
    fi
    echo -n "Unmounting CIFS resources... "
    umount -t cifs -a || { failure ; return 1; }
    success

    if cat /proc/mounts | grep ' cifs ' ; then
        echo -n "Unmounting lost CIFS resources..."
        # we have something to unmount, which is not in /etc/mtab
        for i in $(cat /proc/mounts | grep ' cifs ' | cut -d' ' -f2); do
            umount "$i" || { failure; return 1; }
        done
        success
    fi
    return 0
}

mount_cifs()
{
    echo -n "Mounting CIFS resources... "
    mount -t cifs -a || { failure ; return 1; }
    success
}

load_module()
{
    local i
    if is_origmoduled ; then
        umount_cifs
        if [ "$?" -eq 1 ] ; then
            return
        fi
        check_for_old_kernel
        if [ "$?" -eq 1 ]; then
            sleep 2s
        fi
        echo -n "Removing vanilla kernel module $ORIGMODULENAME... "
        $RMMOD $ORIGMODULENAME --wait
        success
    fi

    get_module_version

    echo -n "Loading kernel module $MODULENAME $MODVER... "

    if [ "$MODULEVERSION" != "$MODVER" ] && [ "$CHECK_VERSION" -eq 1 ] ; then
            failure
            show_module_version
            echo "    Please, run 'service etercifs build' to build the etercifs module (recommended)"
            #echo "    or run 'CHECK_VERSION=0 service etercifs restart' to disable check."
            return
    fi

    $MODPROBE $MODULENAME && { success ; return ; }
    echo -n "$MODULENAME from Etersoft is not found, "
    echo -n "trying to compile it..."
    if [ $BUILT -ne 1 ] ; then
        build_module
        BUILT=1
        start
    fi
}

start()
{
    load_module
    if is_moduled ; then
        test -n "$WASCIFS" && mount_cifs || :
    fi
}

stop()
{
    umount_cifs
    if [ "$?" -eq 1 ] ; then
        return
    fi
    check_for_old_kernel
    if [ "$?" -eq 1 ]; then
        sleep 2s
    fi
    echo -n "Unloading kernel module $MODULENAME... "
    is_moduled || { passed ; return ; }
    $RMMOD $MODULENAME --wait
    success
}

show_module_version()
{
    if [ $MODVER ] ; then
        echo "    kernel module $MODULENAME version $MODVER is built for current kernel"
    else
        echo "    kernel module $MODULENAME is built"
    fi
    if [ "$MODULEVERSION" != "$MODVER" ] ; then
        [ $MODVER ] && echo "    WARNING!!! Versions of the package $MODULENAME and built module $MODULENAME DON'T MATCH!!!"
    fi
}

show_loaded_module_version()
{
    if [ $LOADEDMODVER ] ; then
        echo "    kernel module $MODULENAME version $LOADEDMODVER is loaded"
        if [ "$MODULEVERSION" != "$LOADEDMODVER" ] ; then
            [ $MODVER ] && echo "    WARNING!!! Versions of the package $MODULENAME and loaded module $MODULENAME DON'T MATCH!!!"
        fi
    else
        echo "    WARNING!!! Can't get version of loaded module $MODULENAME!"
    fi
}

status()
{
    local PRECOMP
    echo "Package $MODULENAME $PACKAGEVEREL"
    echo "CIFS kernel module status:"
    if is_moduled ; then
        get_module_version
        show_module_version
        get_loaded_module_version
        show_loaded_module_version
    else
        if is_origmoduled ; then
            echo "    vanilla kernel module $ORIGMODULENAME loaded"
        fi
        echo "    WARNING!!! Kernel module $MODULENAME is not loaded!"
        echo "    WINE@Etersoft won't run on the CIFS resource!"
    fi
}

build_module()
{
    if [ -r $SRC_DIR/dkms.conf ] && [ `which dkms 2>/dev/null` ] && [ $DKMS -eq 1 ] ; then
        cd $DATADIR
        DKMSBUILD=1 sh buildmodule.sh
    else
        cd $DATADIR
        sh buildmodule.sh
    fi
}

test_build_module()
{
    cd $DATADIR
    TESTBUILD=1 sh buildmodule.sh
}

case "$1" in
    start)
        start
        ;;
    condstop|stop)
        stop
        ;;
    restart)
        stop
        start
        ;;
    build)
        build_module
        ;;
    testbuild)
        test_build_module
        ;;
    status)
        status
        ;;
    condrestart)
        if is_moduled ; then
            stop
            start
        else
            echo -n "Etersoft CIFS module..." && passed
        fi
        ;;
    *)
        echo "Usage: etercifs {start|stop|restart|build|testbuild|condrestart|condstop|status}"
esac

