Inotify - Introduction
Pour certaines applications, il peut être très utile de surveiller les changements apportés à certains fichiers ou répertoires.
Par exemple, un système de backup peut être intéressé à connaitre tous les fichiers qui ont été ajoutés, enlevés ou modifiés. Cette même surveillance peut s’avérer très pratique pour des processus daemon utilisant des fichiers de configuration. Elle lui permettrait d’adapter sa paramétrisation aux nouvelles modifications.
La solution proposée par Linux s’appelle inotify
.
inotify
permet de surveiller 12 événements distincts :
Event | Description |
---|---|
IN_ACCESS | File was accessed (read() ) |
IN_ATTRIB | File metadata changed |
IN_CLOSE_WRITE | File opened for writing was closed |
IN_CLOSE_NOWRITE | File opened read-only was closed |
IN_CREATE | File/directory created inside watched directory |
IN_DELETE | File/directory deleted from inside watched directory |
IN_DELETE_SELF | Watched file/directory was itself deleted |
IN_MODIFY | File was modified |
IN_MOVE_SELF | Watched file/directory was itself moved |
IN_MOVED_FROM | File moved out of watched directory |
IN_MOVED_TO | File moved into watched directory |
IN_OPEN | File was opened |
Inotify - Opérations
Le mécanisme inotify de Linux propose divers services pour la surveillance de
fichiers ou de répertoires. Il est intéressant de noter que ceux-ci peuvent être
bloquants ou non bloquants. Dans le cas de services bloquants, les services
de multiplexage (par exemple epoll
) peuvent être mis en œuvre pour attendre sur
des événements.
Opération | syscall |
---|---|
Créer une instance de surveillance | inotify_init1 |
Ajouter un nouvel article à surveiller | inotify_add_watch |
Éliminer un article de la surveillance | inotify_rm_watch |
Lire les événements survenus | read |
Fermer une instance de surveillance | close |
Créer une instance de surveillance
Pour créer une instance de surveillance, Linux propose l’appel système
inotify_init1()
.
#include <sys/inotify.h>
int inotify_init1(int flags);
Exemple
int ifd = inotify_init1(0);
if (ifd == -1)
/* error */
Comportement
- La fonction
inotify_init1()
crée une nouvelle instance de surveillance. La méthode retourne un descripteur de fichier. En cas d’erreur, la valeur-1
est retournée. - Si l’on souhaite un service non bloquant, il suffit de passer
IN_NONBLOCK
dans l’argumentflags
.
Ajouter un article à surveiller
Pour ajouter un nouvel article dans l’instance de surveillance, Linux propose
l’appel système inotify_add_watch()
.
#include <sys/inotify.h>
int inotify_add_watch (int fd, const char* pathname, uint32_t mask);
Exemple
int wd = inotify_add_watch(ifd, "/path/to/file_dir", IN_ALL_EVENTS);
if (wd == -1)
/* error */
Comportement
- La méthode
inotify_add_watch()
ajoute à l’instance de surveillancefd
un nouvel article (fichier ou répertoire) spécifié par le 2e argumentpathname
. Les événements que l’on souhaite surveiller sont indiqués par le 3e argumentmask
. - La méthode retourne un descripteur correspondant à l’article. Ce dernier sera
associé à chaque événement de ce même article. En cas d’erreur, la valeur
-1
est retournée. - Le processus doit naturellement disposer des droits pour surveiller un fichier ou un répertoire.
Lire les événements
La lecture des événements se réalise simplement avec la méthode read()
.
#include <sys/inotify.h>
#include <unistd.h>
#include <limits.h>
ssize_t read(int fd, void *buf, size_t len);
Exemple
char buff[sizeof(struct inotify_event)+NAME_MAX+1];
ssize_t len = read (ifd, buff, sizeof(buff));
if (len == -1)
/* error */
char* p = buff;
while (len > 0) {
struct inotify_event* event = (struct inotify_event*)p;
/* process event... */
len -= sizeof(struct inotify_event) + event->len;
p += sizeof(struct inotify_event) + event->len;
}
Comportement
- La méthode
read()
retourne dans lebuff
une liste d’événements
Arguments
- La
struct inotify_event
fournit les informations suivantesstruct inotfy_event { int wd; // watch descriptor uint32_t mask; // maks of events uint32_t cookie; // unique cookie associating related events -> rename(2) uint32_t len; // size of name field char name[]; // optional null-terminated name };
wd
identifie l’article surveillé pour lequel l’événement a été levé.mask
contient les bits décrivant l’événementcookie
est une valeur entière unique permettant de mettre en relation deux événements. Ceci arrive si l’on renomme un fichier ou un répertoire. Dans les autres cas,cookie
vaut0
.name
identifie le nom relatif du fichier ou du répertoire pour lequel l’événement a été levé.len
décrit le nombre de caractères contenus dansname
incluant le caractère0
terminant le string.