INOTIFY

Schnitstelle zur Überwachung von Dateisystemereignissen.
Zur Zeit funktioniert nur inotify und nicht fanotify vernünftig.
Die Überwachung ist auch mit dem Programm iwatch möglich:

apt-get install iwatch
iwatch /meinVerzeichnis

Beispiel: Überwache das /tmp-Verzeichnis rekursiv auf Dateierstellung und Änderungen:

iwatch -r -e create,write -c "ls %f" /tmp

Beispiel: Überwache das /tmp-Verzeichnis rekursiv auf Dateierstellung und Änderungen,
Mache das als Daemon und überprüfe die Datei mit dem AVIRA-Virenscanner.
Der Virenscanner kann zwar den Dateizugriff nicht sperren aber z.B. eine Mail senden oder einen
Kdialog öffnen(wenn er vernünftig konfiguriert ist):
Ändere zunächst die Datei /etc/inotify.xml in etwa wie folgt:

inotify.xml
  <?xml version="1.0" ?>
<!DOCTYPE config SYSTEM "/etc/iwatch.dtd" >
 
<config charset="utf-8">
  <guard email="iwatch@localhost" name="IWatch"/>
  <watchlist>
    <title>AVIRA-Scanner</title>
    <contactpoint email="alarm@meine.domaene.de" name="Avirafilescanner"/>
    <path type="recursive" events="create,modify" alert="off" exec="avscan --batch %f">/tmp</path>
    <path type="recursive" events="create,modify" alert="off" exec="avscan --batch %f">/home</path>
    <path type="recursive" events="create,modify" alert="off" exec="avscan --batch %f">/root</path>
    <path type="recursive" events="create,modify" alert="off" exec="avscan --batch %f">/var/tmp</path>
  </watchlist>
</config>

Starte dann die Überwachung mit:

iwatch -d

(Der Nachteil ist das immerwährende Erstellen von avscan-Prozessen und nicht von Threads.
Das muss man ausprobieren ob die Systembelastung im Rahmen bleibt).

Beispiel-C-code:

inotify.c
/*
inotify.c 
 *
 *  Copyright (C) NAKAMURA Minoru <nminoru@nminoru.jp>
 *
 *  gcc -Wall -o inotify inotify.c
 *  http://www.nminoru.jp/~nminoru/data/200701/inotify.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h> /* for offsetof */
#include <string.h> /* for memmove */
#include <errno.h>
#include <limits.h>
#include <sys/inotify.h>
 
 
#define MAX_WATCHPOINT_DIRS (32)
 
static void display_inotify_event(struct inotify_event *inotify_p);
 
static int wd_array[MAX_WATCHPOINT_DIRS];
 
 
int main(int argc, char **argv)
{
    int i, max_wd;
    uint32_t imask = IN_ALL_EVENTS;
    if (argc < 3) {
	printf("%s notify for filechange \n",argv[0]);
	printf("-a access a file\n");
	printf("-m modify a file\n");	
        printf("Usage: -a [directory-to-watch1 [directory-to-watch2 ...]]\n");
        printf("Usage: -w [directory-to-watch1 [directory-to-watch2 ...]]\n");
        printf("Example: %s -a /home\n",argv[0]);
        exit(EXIT_SUCCESS);
    }
    if (strcmp(argv[1],"-a") == 0){
	printf("%s\n",argv[1]);
	imask = IN_ACCESS;}
    if (strcmp(argv[1],"-m") == 0){
	printf("%s\n",argv[1]);
	imask = IN_MODIFY;}
 
    int fd  = inotify_init();
 
    if (fd == -1) {
        perror("inotify_init");
        exit(EXIT_FAILURE);
    }
 
    max_wd = (MAX_WATCHPOINT_DIRS > argc -1 ) ? argc -1: MAX_WATCHPOINT_DIRS;
 
    for (i=1 ; i<max_wd ; i++) {
	printf("argv: %s imask: %d\n",argv[i+1],imask);
        int wd = inotify_add_watch(fd, argv[i+1],imask );
 
        if (wd < 0) {
            perror("error inotify_add_watch");
            exit(EXIT_FAILURE);
        }
        wd_array[i] = wd;
    }
 
    for (;;) {
        int i, aux=0, ret;
        char name_buf[PATH_MAX];
        char buffer[65536];
 
    reread:
        ret = read(fd, buffer + aux, sizeof(buffer) - aux);
        if (ret == -1) {
            if (ret == -EINTR)
                goto reread;
            perror("read");
            exit(EXIT_FAILURE);
        }
        ret += aux;
 
        if (ret < sizeof(struct inotify_event)) {
            fprintf(stderr, "short of red bytes\n");
            exit(EXIT_FAILURE);
        }
 
        i = 0;
        while (i < ret) {
            struct inotify_event *inotify_p;
            inotify_p = (struct inotify_event *)(buffer + i);
 
            if (ret < i + offsetof(struct inotify_event, name)) {
                aux = ret - i;
                memmove(buffer, buffer + i, aux);
                goto reread;
            }
 
            int size = sizeof(struct inotify_event) + inotify_p->len;
            if (ret < i + size) {
 
                aux = ret - i;
                memmove(buffer, buffer + i, aux);
                goto reread;                
            }
 
            display_inotify_event(inotify_p);
            i += size;
        }
    }
 
    for (i=0 ; i<max_wd ; i++) {
        int ret = inotify_rm_watch(fd, wd_array[i]);
        if (ret == -1) {
            perror("inotify_rm_watch");
            exit(EXIT_FAILURE);
        }
    }
 
    close(fd);
 
    return 0;
}
 
 
static void display_inotify_event(struct inotify_event *inotify_p)
{
    int ret = 0;
    char buffer[256];
    uint32_t mask = inotify_p->mask;
 
    // File was accessed (read) (*).
    if (mask & IN_ACCESS)
        ret += sprintf(buffer + ret, "ACCESS ");
 
    // Metadata   changed
    if (mask & IN_ATTRIB)
        ret += sprintf(buffer + ret, "ATTRIB ");
 
    // File opened for writing was closed (*).
    if (mask & IN_CLOSE_WRITE)
        ret += sprintf(buffer + ret, "CLOSE_WRITE ");
 
    // File not opened for writing was closed (*).
    if (mask &  IN_CLOSE_NOWRITE)
        ret += sprintf(buffer + ret, "CLOSE_NOWRITE ");
 
    // File/directory created in watched directory (*).
    if (mask & IN_CREATE)
        ret += sprintf(buffer + ret, "CREATE ");
 
    // File/directory deleted from watched directory (*).
    if (mask & IN_DELETE)
        ret += sprintf(buffer + ret, "DELETE ");
 
    // Watched file/directory was itself deleted.
    if (mask & IN_DELETE_SELF)
        ret += sprintf(buffer + ret, "DELETE_SELF ");
 
    // File was modified (*).
    if (mask & IN_MODIFY)
        ret += sprintf(buffer + ret, "MODIFY ");
 
    // Watched file/directory was itself moved.
    if (mask & IN_MOVE_SELF)
        ret += sprintf(buffer + ret, "MODIFY_SELF ");
 
    // File moved out of watched directory (*).
    if (mask & IN_MOVED_FROM)
        ret += sprintf(buffer + ret, "MOVE_FROM ");
 
    // File moved into watched directory (*).
    if (mask & IN_MOVED_TO)
        ret += sprintf(buffer + ret, "MOVE_TO ");
 
    // File was opened (*).
    if (mask & IN_OPEN)
        ret += sprintf(buffer + ret, "OPEN ");
 
    // Watch  was removed explicitly (inotify_rm_watch(2)) or
    // automatically (file was deleted, or  file  system  was
    // unmounted).
    if (mask & IN_IGNORED)
        ret += sprintf(buffer + ret, "IGNORED ");
 
    // Subject of this event is a directory.
    if (mask & IN_ISDIR)
        ret += sprintf(buffer + ret, "ISDIR ");
 
    // Event queue overflowed (wd is -1 for this event).
    if (mask & IN_Q_OVERFLOW)
        ret += sprintf(buffer + ret, "Q_OVERFLOW ");
 
    // File system containing watched object was unmounted.
    if (mask & IN_UNMOUNT)
        ret += sprintf(buffer + ret, "Q_UNMOUNT ");
 
/*    printf("%d %x %u %u \"%s\" [%s]\n",
           inotify_p->wd, 
           inotify_p->mask,
           inotify_p->cookie,
           inotify_p->len,
           &inotify_p->name,
           buffer);
*/
	printf("%s\t%s\n",&inotify_p->name,buffer);
}


siehe auch : AVIRA for Linux