# HG changeset patch # User root@sonne.dd.dtele.de # Date 1235843568 -3600 # Node ID b4b46fe7bf9fd6dbd9ad5c564dbd8236b9f54af0 started as shell prototype diff -r 000000000000 -r b4b46fe7bf9f Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sat Feb 28 18:52:48 2009 +0100 @@ -0,0 +1,21 @@ +DESTDIR = +prefix = /usr/local +sbindir = ${prefix}/sbin +man8dir = ${prefix}/usr/share/man/man8 + +all: tele-watch tele-watch.8.gz +install: all + install -m 0755 -d ${DESTDIR}/${sbindir} + install -m 0755 tele-watch ${DESTDIR}/${sbindir}/ + + install -m 0755 -d ${DESTDIR}/${man8dir} + install -m 0644 tele-watch.8.gz ${DESTDIR}/${man8dir} + +clean: + -rm -f tele-watch.8.gz + +%.gz: % + gzip -f $< + +%.8: % + pod2man --section 8 $< >$@ diff -r 000000000000 -r b4b46fe7bf9f default --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/default Sat Feb 28 18:52:48 2009 +0100 @@ -0,0 +1,2 @@ +# the directory to watch +WATCHPOINT="/home" diff -r 000000000000 -r b4b46fe7bf9f init.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/init.d Sat Feb 28 18:52:48 2009 +0100 @@ -0,0 +1,155 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: tele-watch +# Required-Start: $local_fs $remote_fs +# Required-Stop: $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: watcher for dtele home directory +# Description: tele-watch watches a list of directories +# and enforces the dtele directory policy +### END INIT INFO + +# Author: Heiko Schlittermann +# +# Please remove the "Author" lines above and replace them +# with your own name if you copy and modify this script. + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Description of the service" +NAME=daemonexecutablename +DAEMON=/usr/sbin/$NAME +DAEMON_ARGS="--options args" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other 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 + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 + exit 3 + ;; +esac + +: diff -r 000000000000 -r b4b46fe7bf9f tele-watch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tele-watch Sat Feb 28 18:52:48 2009 +0100 @@ -0,0 +1,134 @@ +#! /bin/bash -e +# (c) Heiko Schlittermann + +ME=$(basename $0) +WATCHPOINTS= + +function abs_path() { + local a="$1" + case "$a" in + /*) echo "$a";; + *) t="$(cd $t && pwd)";; + esac +} + +if test "$#" = 0; then + echo "need at least one directory to watch" + exit 1 +fi + +for watch; do + w=${watch%:*} + t=${watch#*:} + + test "$w:$t" = "$watch" || { + echo "to many ':' in \"$watch\"" >&2 + exit 1 + } + + w=$(abs_path "$w") + t=$(abs_path "$t") + + if test -f "$w/.target"; then + read pid target <"$w/.target" + + kill -0 $pid 2>/dev/null && { + echo "already watched by $pid for $target" >&2 + exit 1 + } + fi + + echo "$$ $t" > "$w/.target" + WATCHPOINTS="${WATCHPOINTS:+$WATCHPOINTS }$w" +done + +inotifywait -q -m --format "%e %w %f" -e create,move,delete $WATCHPOINTS | while read EVENT WATCHER NAME +do + echo "$EVENT -- $WATCHER $NAME" + + case "$EVENT" in + *ISDIR*) ;; + *) continue;; + esac + + read dummy TARGET <$WATCHER/.target + DIRS=$(cd $TARGET && echo *) + + case "$EVENT" in + *CREATE*) + for dir in $DIRS; do + mkdir "/.m/$dir/$NAME" + echo "$NAME" >"$WATCHER/$NAME/.name" + ln -s "/.m/$dir/$NAME" "$WATCHER/$NAME/$dir" + done + ;; + *MOVED_TO*) + name=$(tail -1 "$WATCHER/$NAME/.name") + for link in "$WATCHER/$NAME/"*; do + test -L "$link" || continue + dst=$(readlink $link) + if test "$(basename $dst)" = "$name"; then + new="$(dirname $dst)/$NAME" + mv -v "$dst" "$new" + ln -vsf "$new" "$link" + fi + done + echo "$NAME" >>"$WATCHER/$NAME/.name" + ;; + *DELETE*) + for dir in $DIRS; do + mkdir -p "/.m/$dir/,old" + mv -v "/.m/$dir/$NAME" "/.m/$dir/,old/$NAME-$(date +%Y%m%d-%H%M%S)" + done + esac +done +exit + +=head1 NAME + +tele-watch - guard the dtele directory policy + +=head1 SYNOPSIS + + tele-watch ""... + +=head1 DESCRIPTION + +B should run as a daemon. + +B watches the list of directories I... (absolute path names) +via "inotify" and performs some actions on: + +=over + +=item CREATION of new directory + +It checks F and assumes, that all directories there should +reflect in the newly created directory: + + /_tmp -> /.m/_tmp/NEW1/ + /homepage -> /.m/homepage/NEW1/ + ... + +After done this it writes the name of the newly created directory into +the file F<< /.name >> + +=item RENAMING of a directory + +If the directory gets renamed, the above links needs to be updated. + +=item DELETION of a directory + +If the root directory is removed, the targets of the former links should +be removed, we do our best, to do this. (Actually not removing the +targets, but moving them into an F folder.) + +=back + +=head1 AUTHOR + +Heiko Schlittermann + +=cut + +# vim:tw=72 sts=4 ts=4 sw=4 aw ai sm: