Provided by: manpages-fr_4.23.1-1_all bug

NOM

       inotify - Surveiller les événements des systèmes de fichiers

DESCRIPTION

       L'API  inotify  fournit un mécanisme pour surveiller les événements au niveau des systèmes
       de fichiers. Inotify peut être utilisé pour surveiller des  fichiers  individuels  ou  des
       répertoires. Quand un répertoire est surveillé, inotify va signaler des événements pour le
       répertoire lui-même et pour les fichiers de ce répertoire.

       Les appels système suivants sont utilisés avec cette interface de programmation :

       -  inotify_init(2) crée une instance inotify et  renvoie  un  descripteur  de  fichier  se
          référant  à  cette  instance  inotify. L'appel système plus récent inotify_init1(2) est
          comme  inotify_init(2),  mais  a  un  argument  flags  qui  fournit  un  accès  à   des
          fonctionnalités supplémentaires.

       -  inotify_add_watch(2)  manipule  la  « liste  de  surveillance » associée à une instance
          inotify. Chaque élément (« watch ») de la liste de surveillance indique le chemin  d'un
          fichier  ou d'un répertoire, avec un ensemble d'événements que le noyau doit surveiller
          pour le fichier indiqué par ce chemin. inotify_add_watch(2) crée un nouvel  élément  de
          surveillance  ou  modifie un élément existant. Chaque élément a un unique « descripteur
          de surveillance », un entier renvoyé par inotify_add_watch(2) lorsque cet  élément  est
          créé.

       -  Quand  les  événements  ont  lieu  pour  des  fichiers  et  répertoires surveillés, ces
          événements sont rendus disponibles à l’application comme des  données  structurées  qui
          peuvent  être  lues depuis le descripteur de fichier inotify en utilisant read(2) (voir
          plus bas).

       -  inotify_rm_watch(2) retire un élément d'une liste de surveillance inotify.

       -  Quand tous les descripteurs de fichier se référant  à  une  instance  inotify  ont  été
          fermés (en utilisant close(2)), l'objet sous-jacent et ses ressources sont libérés pour
          être réutilisés par  le  noyau ;  tous  les  éléments  de  surveillance  associés  sont
          automatiquement libérés.

       Avec  une programmation prudente, une application peut utiliser inotify pour surveiller et
       mettre en cache efficacement  l’état  d’un  ensemble  d’objets  de  système  de  fichiers.
       Cependant,  les  applications  robustes devraient prendre en compte que des bogues dans la
       logique de surveillance ou  des  situations  de  compétition  du  type  décrit  ci-dessous
       pourraient  laisser  le  cache incohérent avec l’état du système de fichiers. Réaliser des
       vérifications de cohérence et reconstruire le cache en  cas  de  détection  d’incohérences
       serait sans doute sage.

   Lecture d’événements d’un descripteur de fichier inotify
       Pour  déterminer  quels  événements  ont  eu lieu, une application va lire avec read(2) le
       descripteur de fichier inotify. Si aucun événement n'a eu lieu, alors, en supposant  qu'il
       s'agisse  d'un descripteur de fichier bloquant, read(2) se bloquera jusqu'à ce qu'au moins
       un événement ait lieu (à moins qu'elle ne soit  interrompue  par  un  signal,  auquel  cas
       l'appel échouera avec l'erreur EINTR ; consultez signal(7)).

       Chaque  lecture  (avec  read(2))  réussie renvoie un tampon contenant une ou plusieurs des
       structures suivantes :

           struct inotify_event {
               int      wd;       /* Descripteur de surveillance */
               uint32_t mask;     /* Masque décrivant l’événement */
               uint32_t cookie;   /* Cookie unique d'association des
                                     événements (pour rename(2)) */
               uint32_t len;      /* Taille du champ name */
               char     name[];   /* Nom optionnel terminé par un nul */
           };

       wd identifie l'élément de surveillance pour lequel cet événement a lieu. Il s'agit de l'un
       des descripteurs de surveillance renvoyés par un précédent appel à inotify_add_watch(2).

       mask contient des bits qui décrivent l'événement qui a eu lieu (voir ci-dessous).

       cookie  est  un  entier unique qui relie les événements. Ce n'est actuellement utilisé que
       pour les événements de renommage, et permet  à  la  paire  d'événements  IN_MOVED_FROM  et
       IN_MOVED_TO  en  résultant  d'être  associée par l'application. Pour tous les autres types
       d'événements, cookie est mis à 0.

       Le champ name n'est présent que lorsqu'un événement est renvoyé pour un  fichier  au  sein
       d'un répertoire surveillé. Il identifie le chemin du fichier dans le répertoire surveillé.
       Ce chemin est terminé par un caractère NULL et peut inclure d'autres octets nuls  (« \0 »)
       pour ajuster des lectures successives à une limite d'adressage convenable.

       Le  champ len compte tous les octets de name, incluant les caractères nuls. La longueur de
       chaque structure inotify_event vaut donc sizeof(structinotify_event)+len.

       Le comportement,  lorsque  le  tampon  donné  à  read(2)  est  trop  petit  pour  renvoyer
       l'information   sur  le  prochain  événement,  dépend  de  la  version  du  noyau :  avant
       Linux 2.6.21, read(2) renvoie  0 ;  depuis  Linux 2.6.21,  read(2)  échoue  avec  l'erreur
       EINVAL. Indiquer un tampon de taille

           sizeof(struct inotify_event) + NAME_MAX + 1

       est suffisant pour lire au moins un événement.

   Événements inotify
       L'argument   mask   passé  à  inotify_add_watch(2)  et  le  champ  mask  de  la  structure
       inotify_event renvoyés lors de la lecture avec read(2) d'un descripteur de fichier inotify
       sont  tous deux des masques binaires identifiant les événements inotify. Les bits suivants
       peuvent être définis dans l'argument  mask  lors  de  l'appel  à  inotify_add_watch(2)  et
       peuvent être renvoyés dans le champ mask renvoyé par read(2).

           IN_ACCESS (+)
                  Accès au fichier (par exemple read(2), execve(2)).

           IN_ATTRIB (*)
                  Modification  des  métadonnées,  par  exemple,  les  permissions  (par  exemple
                  chmod(2)), les horodatages (par exemple utimensat(2)),  les  attributs  étendus
                  (setxattr(2)),  le compteur de liens (depuis Linux 2.6.25 ; par exemple pour la
                  cible de link(2) et unlink(2)) et les UID ou GID (par exemple chown(2)).

           IN_CLOSE_WRITE (+)
                  Fichier ouvert en écriture fermé.

           IN_CLOSE_NOWRITE (*)
                  Fichier ou répertoire non ouverts en écriture fermés.

           IN_CREATE (+)
                  Fichier ou répertoire créés dans le répertoire surveillé (par  exemple  open(2)
                  O_CREAT, mkdir(2), link(2), symlink(2), bind(2) sur un socket de domaine UNIX).

           IN_DELETE (+)
                  Fichier ou répertoire supprimés dans le répertoire surveillé.

           IN_DELETE_SELF
                  Fichier  ou répertoire surveillés supprimés (cet événement se produit également
                  si un objet est déplacé vers un autre système de fichiers, puisque mv(1)  copie
                  effectivement  le  fichier vers l’autre système de fichiers puis le supprime du
                  système de fichiers d’origine). De plus, un événement IN_IGNORED  sera  ensuite
                  généré pour le descripteur de surveillance.

           IN_MODIFY (+)
                  Fichier modifié (par exemple write(2), truncate(2)).

           IN_MOVE_SELF
                  Fichier ou répertoire surveillés déplacés.

           IN_MOVED_FROM (+)
                  Généré pour le répertoire contenant l'ancien nom quand un fichier est renommé.

           IN_MOVED_TO (+)
                  Généré  pour  le  répertoire  contenant  le  nouveau  nom  quand un fichier est
                  renommé.

           IN_OPEN (*)
                  Fichier ou répertoire ouvert.

       La surveillance par Inotify est basée sur les inodes :  lorsqu'un  fichier  est  surveillé
       (mais pas lors de la surveillance d'un répertoire contenant un fichier), un événement peut
       être créé sur tout lien vers le fichier (dans le même répertoire  ou  dans  un  répertoire
       différent).

       Lors de la surveillance d'un répertoire :

       -  les  événements marqués précédemment par un astérisque (*) peuvent avoir lieu à la fois
          pour le répertoire et pour les objets à l’intérieur du répertoire ;

       -  les événements marqués par un  signe  plus  (+)  n’ont  lieu  que  pour  les  objets  à
          l’intérieur du répertoire (et non pour le répertoire lui-même).

       Note :  lorsqu'un  répertoire  est  surveillé,  les  événements ne sont pas créés pour les
       fichiers contenus dans le répertoire quand des événements sont exécutés  avec  un  nom  de
       chemin (par exemple, un lien) qui se trouve hors du répertoire surveillé.

       Lorsque  les  événements sont créés pour les objets dans un répertoire surveillé, le champ
       name dans la structure  inotify_event  renvoyée  identifie  le  nom  du  fichier  dans  ce
       répertoire.

       La  macro IN_ALL_EVENTS est définie comme un masque binaire de tous les événements décrits
       ci-dessus. Cette macro peut  être  utilisée  comme  l'argument  mask  lors  de  l'appel  à
       inotify_add_watch(2).

       Deux macros supplémentaires de convenance sont définies :

           IN_MOVE
                  Équivalent à IN_MOVED_FROM | IN_MOVED_TO.

           IN_CLOSE
                  Équivalent à IN_CLOSE_WRITE | IN_CLOSE_NOWRITE.

       Les  bits  supplémentaires  suivants  peuvent  être  indiqués dans l'argument mask lors de
       l'appel à inotify_add_watch(2) :

           IN_DONT_FOLLOW (depuis Linux 2.6.15)
                  Ne pas déréférencer chemin s'il s'agit d'un lien symbolique.

           IN_EXCL_UNLINK (depuis Linux 2.6.36)
                  Par  défaut,  lors  de  la  surveillance  d'événements  sur  les  entrées  d'un
                  répertoire,  des  événements  sont  créés  pour  ces  entrées  même  après leur
                  suppression du répertoire. De nombreux événements inintéressants pour certaines
                  applications  peuvent ainsi être créés (par exemple, lors de la surveillance de
                  /tmp, où de nombreuses applications créent des fichiers  temporaires  donc  les
                  noms   sont   immédiatement  supprimés).  Indiquer  IN_EXCL_UNLINK  modifie  le
                  comportement par défaut, de telle sorte qu'aucun événement n'est créé pour  ces
                  entrées après leur suppression du répertoire surveillé.

           IN_MASK_ADD
                  Si une instance de surveillance existe déjà pour l’objet de système de fichiers
                  correspondant à chemin, ajouter (avec un OU binaire) les événements de mask  au
                  masque de surveillance (au lieu de remplacer le masque) ; il résulte une erreur
                  EINVAL si IN_MASK_CREATE est aussi spécifié.

           IN_ONESHOT
                  Surveiller l’objet de système  de  fichiers  correspondant  à  chemin  jusqu'au
                  premier événement, puis le supprimer de la liste de surveillance.

           IN_ONLYDIR (depuis Linux 2.6.15)
                  Surveiller chemin seulement s'il s'agit d'un répertoire ; il résulte une erreur
                  ENOTDIR si chemin n'est pas un répertoire. Utiliser cet attribut fournit à  une
                  application  un  moyen  sans  problème  de concurrence de s'assurer qu'un objet
                  surveillé est un répertoire.

           IN_MASK_CREATE (depuis Linux 4.18)
                  Surveiller chemin seulement s'il n'y a pas déjà une surveillance  qui  lui  est
                  associée ; il résulte une erreur EEXIST si chemin est déjà surveillé.

                  Utiliser  cet  attribut  fournit à une application un moyen de s'assurer que de
                  nouveaux éléments de surveillance ne modifient  pas  ceux  qui  existent  déjà.
                  C'est  utile  parce que plusieurs chemins peuvent faire référence au même inœud
                  et plusieurs appels à inotify_add_watch(2) sans cet  attribut  peuvent  écraser
                  des masques de surveillance existants.

       Les bits suivants peuvent avoir été définis dans le champ mask renvoyé par read(2) :

           IN_IGNORED
                  Le   surveillant   a   été   retiré   explicitement   (inotify_rm_watch(2))  ou
                  automatiquement (le fichier a été effacé, ou  le  système  de  fichiers  a  été
                  démonté). Consultez également BOGUES.

           IN_ISDIR
                  Le sujet de cet événement est un répertoire.

           IN_Q_OVERFLOW
                  Queue des événements surchargée (wd vaut alors -1).

           IN_UNMOUNT
                  Le  système  de fichiers contenant l'objet surveillé a été démonté. De plus, un
                  événement IN_IGNORED sera ensuite généré pour le descripteur de surveillance.

   Exemples
       Soit une application surveillant le répertoire rép et le fichier rép/monfichier pour  tous
       les  événements.  Les  exemples ci-dessous montrent quelques événements qui seront générés
       pour ces deux objets.

           fd = open("rép/monfichier", O_RDWR);
                  Génère des événements IN_OPEN à la fois pour rép et rép/monfichier.

           read(fd, buf, count);
                  Génère des événements IN_ACCESS à la fois pour rép et rép/monfichier.

           write(fd, buf, count);
                  Génère des événements IN_MODIFY à la fois pour rép et rép/monfichier.

           fchmod(fd, mode);
                  Génère des événements IN_ATTRIB à la fois pour rép et rép/monfichier.

           close(fd);
                  Génère des événements IN_CLOSE_WRITE à la fois pour rép et rép/monfichier.

       Soit  une  application  surveillant  les  répertoires  rép1  et  rép2,   et   le   fichier
       rép1/monfichier.  Les  exemples  suivants montrent quelques événements qui pourraient être
       générés.

           link("rép1/monfichier", "rép2/nouveau");
                  Génère un événement IN_ATTRIB pour monfichier et un  événement  IN_CREATE  pour
                  rép2.

           rename("rép1/monfichier", "rép2/monfichier");
                  Génère un événement IN_MOVED_FROM pour dir1, un événement IN_MOVED_TO pour rép2
                  et un événement IN_MOVE_SELF pour monfichier. Les événements  IN_MOVED_FROM  et
                  IN_MOVED_TO auront la même valeur cookie.

       Soient  rép1/xx  et  rép2/yy  les  (seuls)  liens  vers le même ficher, et une application
       surveillant rép1, rép2, rép1/xx et rép2/yy. L’exécution des appels suivants  dans  l’ordre
       donné ci-dessous générera les événements suivants :

           unlink("rép2/yy");
                  Génère un événement IN_ATTRIB pour xx (à cause du changement de son compteur de
                  liens) et un événement IN_DELETE pour rép2.

           unlink("rép1/xx");
                  Génère des événements IN_ATTRIB, IN_DELETE_SELF et IN_IGNORED  pour  xx  et  un
                  événement IN_DELETE pour rép1.

       Soit  une  application  surveillant le répertoire rép et le répertoire (vide) rép/sousrép.
       Les exemples suivants montrent quelques événements qui pourraient être générés.

           mkdir("rép/nouveau", mode);
                  Génère un événement IN_CREATE | IN_ISDIR pour rép.

           rmdir("rép/sousrép");
                  Génère des événements IN_DELETE_SELF et IN_IGNORED pour sousrép et un événement
                  IN_DELETE | IN_ISDIR pour rép.

   /proc interfaces
       Les  interfaces  suivantes  peuvent  être utilisées pour limiter la quantité de mémoire du
       noyau utilisée par inotify :

       /proc/sys/fs/inotify/max_queued_events
              La  valeur  dans  ce  fichier   est   utilisée   lorsqu'une   application   appelle
              inotify_init(2)  pour  définir  la  limite  maximale  du  nombre des événements qui
              peuvent entrer dans la file d'attente de  l'instance  inotify  correspondante.  Les
              événements  au-delà  de  cette limite sont annulés, mais un événement IN_Q_OVERFLOW
              est systématiquement généré.

       /proc/sys/fs/inotify/max_user_instances
              Cela indique la limite maximale du nombre  d'instances  inotify  qui  peuvent  être
              créées par identifiant utilisateur réel.

       /proc/sys/fs/inotify/max_user_watches
              Cela  indique  la limite maximale du nombre de « watch » qui peuvent être créés par
              identifiant utilisateur réel.

STANDARDS

       Linux.

HISTORIQUE

       Inotify a été inclus dans Linux 2.6.13. Les interfaces bibliothèque  nécessaires  ont  été
       ajoutées  dans  la  glibc 2.4  (IN_DONT_FOLLOW, IN_MASK_ADD et IN_ONLYDIR ont été ajoutées
       dans la glibc 2.5).

NOTES

       Les descripteurs de fichier  inotify  peuvent  être  surveillés  en  utilisant  select(2),
       poll(2) et epoll(7). Lorsqu'un événement est disponible, le descripteur de fichier indique
       qu'il est accessible en lecture.

       Depuis  Linux 2.6.25,  il  est  possible  d'être  notifié  par  des   signaux   pour   des
       entrées-sorties  des  descripteurs de fichier inotify ; consultez la discussion de F_SETFL
       (pour la configuration de l'attribut O_ASYNC), F_SETOWN, et  F_SETSIG  dans  fcntl(2).  La
       structure siginfo_t (décrite dans sigaction(2)) qui est passée au gestionnaire de signal a
       les champs suivants définis : si_fd est défini avec le numéro de descripteur  de  fichiers
       inotify ; si_signo est défini avec le numéro du signal ; si_code est défini avec POLL_IN ;
       et si_band est défini avec POLLIN.

       Si deux événements inotify de sortie successifs produits sur  le  descripteur  de  fichier
       inotify  sont  identiques (wd, mask, cookie, et name identiques), alors ils sont fusionnés
       en un seul événement si l'événement le plus ancien n'a toujours pas été lu (mais consultez
       la  section  BOGUES).  Cela  permet  de  réduire  la  quantité  de mémoire en espace noyau
       nécessaire à la file d'événements, mais signifie  également  qu'une  application  ne  peut
       utiliser inotify pour compter de manière fiable les événements liés à un fichier.

       Les événements renvoyés lors de la lecture d'un descripteur de fichier inotify forment une
       file ordonnée. Ainsi, par exemple, il est garanti que lors du renommage  d'un  répertoire,
       les  événements  seront  produits  dans  l'ordre  convenable sur le descripteur de fichier
       inotify.

       L'ensemble des descripteurs surveillés grâce à un descripteur de fichier inotify peut être
       vu  dans l'entrée du descripteur de fichier inotify dans le répertoire /proc/pid/fdinfo du
       processus. Consultez proc(5) pour de plus amples détails.  FIONREAD  ioctl(2)  renvoie  le
       nombre d'octets disponibles à la lecture dans un descripteur de fichier inotify.

   Limites et réserves
       L'interface inotify ne fournit aucun renseignement sur l'utilisateur ou le processus qui a
       déclenché l'événement inotify. En particulier, un processus en  train  de  surveiller  des
       événements  à  l'aide  d'inotify  ne  dispose  d'aucun  moyen  facile  pour distinguer les
       événements qu'il déclenche lui-même de ceux qui ont été déclenchés par d'autres processus.

       Inotify ne signale que les événements déclenchés par un programme en espace utilisateur  à
       l’aide  de  l’interface  de  programmation  de  système  de fichiers. Par conséquent, elle
       n’intercepte pas les événements qui surviennent sur les systèmes  de  fichiers  en  réseau
       (les applications doivent avoir recours à la scrutation (polling) pour intercepter ce type
       d’événements). De plus, divers pseudo-systèmes de fichiers comme /proc, /sys  et  /dev/pts
       ne sont pas surveillables avec inotify.

       L'interface  inotify  ne  signale  pas  les  accès  ni  les  modifications  de fichier qui
       pourraient survenir à cause de mmap(2), msync(2) ou munmap(2).

       L'interface inotify identifie les fichiers affectés par leur nom. Cependant, au moment  où
       l'application  traite un événement inotify, ce nom de fichier peut avoir déjà été supprimé
       ou renommé.

       L’interface inotify identifie les événements à l’aide  de  descripteurs  de  surveillance.
       L’application  est responsable de mettre en cache une correspondance (si nécessaire) entre
       les descripteurs de fichier et les chemins. Soyez vigilants aux renommages  de  répertoire
       qui pourraient affecter plusieurs chemins en cache.

       La  surveillance  inotify  des  répertoires  n'est  pas  récursive :  pour  surveiller les
       sous-répertoires, des éléments de surveillance supplémentaires doivent  être  créés.  Cela
       peut être assez long pour les répertoires contenant une grande arborescence.

       Si  la  surveillance  concerne  une  arborescence  dans  son intégralité, et si un nouveau
       sous-répertoire est créé dans ce répertoire ou si un répertoire existant est renommé  dans
       cette  arborescence, soyez conscient qu'au moment où vous créez un élément de surveillance
       pour le nouveau sous-répertoire, de nouveaux fichiers (et sous-répertoires)  peuvent  déjà
       exister   dans   le   sous-répertoire.   Ainsi,   vous  devriez  analyser  le  contenu  du
       sous-répertoire immédiatement  après  avoir  ajouté  l'élément  de  surveillance  (et,  si
       nécessaire,  ajouter  des  éléments  de  surveillance pour tous les sous-répertoires qu’il
       contient).

       Remarquez que la file d'événements peut déborder. Dans ce cas, des événements sont perdus.
       Les  applications  robustes  devraient  gérer  correctement  la  possibilité de perdre des
       événements. Par exemple, la reconstruction de tout ou partie  du  cache  de  l’application
       pourrait être nécessaire (une approche simple, mais éventuellement coûteuse, est de fermer
       le descripteur de fichier inotify, vider le cache, créer un nouveau descripteur de fichier
       inotify  et recréer les éléments de surveillance et les entrées du cache pour les objets à
       surveiller).

       Si un système de fichiers est monté par dessus un répertoire  surveillé,  aucun  événement
       n'est  généré,  pas plus que pour les objets se trouvant directement sous le nouveau point
       de montage. Si le système de fichiers est par la  suite  démonté,  les  événements  seront
       créés pour le répertoire et les objets qu'il contient.

   Traitement des événements rename()
       Comme  noté  précédemment,  la paire d’événements IN_MOVED_FROM et IN_MOVED_TO générée par
       rename(2) peut être assemblée à l’aide de la valeur de cookie partagé. Cependant, la tâche
       d’assemblage peut poser quelques problèmes.

       Ces  deux  événements  sont  normalement consécutifs dans le flux d’événements disponibles
       lors de la lecture depuis le descripteur de fichiers  inotify.  Cependant,  ce  n’est  pas
       garanti.  Si  plusieurs  processus  déclenchent des événements pour des objets surveillés,
       alors (rarement) un nombre arbitraire d’autres événements pourrait  apparaître  entre  les
       événements  IN_MOVED_FROM  et  IN_MOVED_TO.  De  plus,  il  n'est pas garanti que la paire
       d'événements soit insérée de façon atomique dans la file : il pourrait  y  avoir  un  bref
       intervalle au cours duquel IN_MOVED_FROM est apparu, mais pas IN_MOVED_TO.

       L’assemblage  de  la paire d’événements IN_MOVED_FROM et IN_MOVED_TO générés par rename(2)
       pose donc intrinsèquement un risque de situation de compétition (n’oubliez pas que  si  un
       objet  est  renommé en dehors d’un répertoire surveillé, un événement IN_MOVED_TO pourrait
       ne même pas être envoyé).  Des  approches  heuristiques  (par  exemple  supposer  que  les
       événements  sont  toujours consécutifs) permettent d’assurer un assemblage dans la plupart
       des cas, mais manqueront forcément certains cas, forçant  l’application  à  percevoir  les
       événements  IN_MOVED_FROM  et  IN_MOVED_TO  comme  indépendants.  Si  les  descripteurs de
       surveillance  sont  détruits  et  recréés  par  conséquent,  alors  ces  descripteurs   de
       surveillance  seront  incohérents  avec  les  descripteurs  de  surveillance dans tous les
       événements  en  attente  (la  recréation  du  descripteur  de  fichier   inotify   et   la
       reconstruction du cache pourrait être utile dans ce cas).

       Les  applications  devraient aussi considérer la possibilité que l’événement IN_MOVED_FROM
       soit le dernier événement ayant pu entrer dans le tampon renvoyé pour  l’appel  actuel  de
       read(2)  et  l’événement  IN_MOVED_TO  accompagnant  pourrait  n’être récupéré que lors de
       l’appel read(2) suivant, ce qui devrait être fait avec un (léger) délai pour permettre que
       l'insertion  de  la  paire  d'événements IN_MOVED_FROM+IN_MOVED_TO ne soit pas atomique et
       aussi qu'il n'y ait pas d'événement IN_MOVED_TO.

BOGUES

       Avant Linux 3.19, fallocate(2) ne créait pas d'événements inotify. Depuis Linux 3.19,  les
       appels à fallocate(2) créent des événements IN_MODIFY.

       Avant Linux 2.6.16, l'attribut IN_ONESHOT de mask ne fonctionne pas.

       Tel que conçu et implémenté à l’origine, l’attribut IN_ONESHOT ne forçait pas à générer un
       appel IN_IGNORED lorsque la surveillance était supprimée après un événement. Cependant, en
       conséquence   involontaire  d’autres  modifications,  depuis  Linux 2.6.36,  un  événement
       IN_IGNORED est généré dans ce cas.

       Avant Linux 2.6.25, le code du noyau qui était censé regrouper deux événements  successifs
       (c'est-à-dire que les deux événements les plus récents pouvaient être fusionnés si le plus
       ancien des deux n'avait toujours pas été lu) vérifiait à la place si l'événement  le  plus
       récent pouvait être fusionné à l'événement non lu le plus ancien.

       Quand  un  descripteur  de  surveillance  est supprimé en appelant inotify_rm_watch(2) (ou
       parce qu’un fichier de surveillance est supprimé ou que le  système  de  fichiers  qui  le
       contient  est  démonté),  tous  les  événements  non lus en attente pour ce descripteur de
       fichier restent disponibles en  lecture.  Comme  les  descripteurs  de  surveillance  sont
       ensuite   alloués   avec  inotify_add_watch(2),  le  noyau  boucle  sur  l’intervalle  des
       descripteurs de surveillance possibles (1 à INT_MAX)  de  façon  incrémentielle.  Lors  de
       l’allocation  d’un  descripteur de surveillance libre, aucune vérification n’est effectuée
       pour voir si ce numéro de descripteur de surveillance a des événements non lus en  attente
       dans  la  file  inotify. Ainsi, un descripteur de surveillance pourrait être réalloué même
       quand des événements non lus en attente existent pour une  incarnation  précédente  de  ce
       numéro  de  descripteur  de  surveillance,  avec comme résultat que l’application pourrait
       alors lire ces événements et les interpréter  comme  appartenant  au  fichier  associé  au
       descripteur  de  surveillance  nouvellement  recyclé.  En  pratique, la probabilité d’être
       victime de ce bogue devrait être extrêmement basse, puisqu’il nécessite qu’une application
       boucle  sur  INT_MAX descripteurs  de surveillance, relâche un descripteur de surveillance
       tout en laissant des événements non lus pour ce descripteur de fichier  dans  la  file  et
       ensuite recycle ce descripteur de surveillance. Pour cette raison, et parce qu’il n’y a eu
       aucun rapports de  bogue  à  propos  de  réelles  applications,  dans  Linux 3.15,  aucune
       modification de noyau n’a encore été faite pour éliminer ce bogue éventuel.

EXEMPLES

       Le  programme  suivant  montre  l’utilisation  de l’interface de programmation inotify. Il
       marque les répertoires passés en arguments de ligne de commande et attend  les  événements
       de type IN_OPEN, IN_CLOSE_NOWRITE et IN_CLOSE_WRITE.

       La   sortie   suivante   a   été   enregistrée   lors   de   la  modification  du  fichier
       /home/utilisateur/temp/toto et  de  l’affichage  du  contenu  du  répertoire  /tmp.  Avant
       d’ouvrir le fichier et le répertoire, un événement IN_OPEN est survenu. Après la fermeture
       du fichier, un événement IN_CLOSE_WRITE est survenu. Après la fermeture du répertoire,  un
       événement  IN_CLOSE_NOWRITE  est  survenu.  L’exécution  du programme s’est terminée quand
       l’utilisateur a appuyé sur la touche Entrée.

   Sortie de l’exemple
           $ ./a.out /tmp /home/utilisateur/temp
           Appuyer sur la touche Entrée pour quitter.
           En écoute d’événements.
           IN_OPEN : /home/utilisateur/temp/toto [fichier]
           IN_CLOSE_WRITE : /home/utilisateur/temp/toto [fichier]
           IN_OPEN : /tmp/ [répertoire]
           IN_CLOSE_NOWRITE : /tmp/ [répertoire]

           Arrêt de l’écoute d’événements.

   Source du programme

       #include <errno.h>
       #include <poll.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/inotify.h>
       #include <unistd.h>
       #include <string.h>

       /* Lire tous les événements inotify disponibles à partir du
          descripteur de fichier « fd ».
          wd est le tableau des descripteurs de surveillance pour
          les répertoires en argv.
          argc est la taille de wd et argv.
          argv est la liste des répertoires surveillés.
          L’entrée 0 de wd et argv n’est pas utilisée. */

       static void
       handle_events(int fd, int *wd, int argc, char* argv[])
       {
           /* Certains systèmes ne peuvent pas lire de variables entières
              si elles ne sont pas alignées correctement. Sur d’autres
              systèmes, un alignement incorrect pourrait diminuer les
              performances. Par conséquent, le tampon utilisé pour lire
              le descripteur de fichier inotify devrait avoir le même
              alignement que struct inotify_event. */

           char buf[4096]
               __attribute__ ((aligned(__alignof__(struct inotify_event))));
           const struct inotify_event *event;
           ssize_t len;

           /* Boucler tant que les événements peuvent être lus à partir du
              descripteur de fichier inotify */

           for (;;) {

               /* Lire certains événements. */

               len = read(fd, buf, sizeof(buf));
               if (len == -1 && errno != EAGAIN) {
                   perror("read");
                   exit(EXIT_FAILURE);
               }

               /* Si le read() non bloquant n’a pas trouvé d’événement à
                  lire, il renvoie -1 avec errno défini à EAGAIN. Dans ce
                  cas, on sort de la boucle. */

               if (len <= 0)
                   break;

               /* Boucler sur tous les événements du tampon. */

               for (char *ptr = buf; ptr < buf + len;
                       ptr += sizeof(struct inotify_event) + event->len) {

                   event = (const struct inotify_event *) ptr;

                   /* Afficher le type d’événement. */

                   if (event->mask & IN_OPEN)
                       printf("IN_OPEN: ");
                   if (event->mask & IN_CLOSE_NOWRITE)
                       printf("IN_CLOSE_NOWRITE: ");
                   if (event->mask & IN_CLOSE_WRITE)
                       printf("IN_CLOSE_WRITE: ");

                   /* Afficher le nom du répertoire surveillé. */

                   for (size_t i = 1; i < argc; ++i) {
                       if (wd[i] == event->wd) {
                           printf("%s/", argv[i]);
                           break;
                       }
                   }

                   /* Afficher le nom du fichier. */

                   if (event->len)
                       printf("%s", event->name);

                   /* Afficher le type d’objet de système de fichiers. */

                   if (event->mask & IN_ISDIR)
                       printf(" [répertoire]\n");
                   else
                       printf(" [fichier]\n");
               }
           }
       }

       int
       main(int argc, char* argv[])
       {
           char buf;
           int fd, i, poll_num;
           int *wd;
           nfds_t nfds;
           struct pollfd fds[2];

           if (argc < 2) {
               printf(""Utilisation : %s CHEMIN [CHEMIN ...]\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           printf("Appuyer sur la touche Entrée pour quitter.\n");

           /* Créer le descripteur de fichier pour accéder à l’interface de
              programmation inotify. */

           fd = inotify_init1(IN_NONBLOCK);
           if (fd == -1) {
               perror("inotify_init1");
               exit(EXIT_FAILURE);
           }

           /* Allouer la mémoire pour les descripteurs de surveillance. */

           wd = calloc(argc, sizeof(int));
           if (wd == NULL) {
               perror("calloc");
               exit(EXIT_FAILURE);
           }

           /* Marquer les répertoires pour les événements :
              - un fichier a été ouvert ;
              - un fichier a été fermé

           for (i = 1; i < argc; i++) {
               wd[i] = inotify_add_watch(fd, argv[i],
                                         IN_OPEN | IN_CLOSE);
               if (wd[i] == -1) {
                   fprintf(stderr, "Impossible de surveiller « %s » : %s\n",
                           argv[i], strerror(errno));
                   exit(EXIT_FAILURE);
               }
           }

           /* Préparer pour la scrutation (polling). */

           nfds = 2;

           fds[0].fd = STDIN_FILENO;       /* Entrée de console */
           fds[0].events = POLLIN;

           fds[1].fd = fd;                 /* Entrée d'inotify */
           fds[1].events = POLLIN;

           /* Attendre les événements ou une entrée du terminal. */

           printf("En écoute d’événements.\n");
           while (1) {
               poll_num = poll(fds, nfds, -1);
               if (poll_num == -1) {
                   if (errno == EINTR)
                       continue;
                   perror("poll");
                   exit(EXIT_FAILURE);
               }

               if (poll_num > 0) {

                   if (fds[0].revents & POLLIN) {

                       /* Entrée de console disponible.
                          Vider l’entrée standard et quitter. */

                       while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\n')
                           continue;
                       break;
                   }

                   if (fds[1].revents & POLLIN) {

                       /* Des événements inotify sont disponibles. */

                       handle_events(fd, wd, argc, argv);
                   }
               }
           }

           printf("Arrêt de l’écoute d’événements.\n");

           /* Fermer le descripteur de fichier inotify. */

           close(fd);

           free(wd);
           exit(EXIT_SUCCESS);
       }

VOIR AUSSI

       inotifywait(1), inotifywatch(1), inotify_add_watch(2), inotify_init(2),  inotify_init1(2),
       inotify_rm_watch(2), read(2), stat(2), fanotify(7)

       Documentation/filesystems/inotify.txt dans les sources du noyau Linux

TRADUCTION

       La  traduction  française  de  cette  page  de  manuel  a  été créée par Christophe Blaess
       <https://www.blaess.fr/christophe/>, Stéphan  Rafin  <stephan.rafin@laposte.net>,  Thierry
       Vignaud  <tvignaud@mandriva.com>,  François Micaux, Alain Portal <aportal@univ-montp2.fr>,
       Jean-Philippe   Guérard   <fevrier@tigreraye.org>,   Jean-Luc   Coulon   (f5ibh)    <jean-
       luc.coulon@wanadoo.fr>,    Julien    Cristau    <jcristau@debian.org>,    Thomas   Huriaux
       <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin
       Duneau  <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis
       Barbier   <barbier@debian.org>,   David   Prévot   <david@tilapin.org>,   Thomas   Vincent
       <tvincent@debian.org> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

       Cette  traduction  est  une  documentation libre ; veuillez vous reporter à la GNU General
       Public  License  version 3  ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   concernant   les
       conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.

       Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un
       message à ⟨debian-l10n-french@lists.debian.org⟩.