.\" -*- coding: UTF-8 -*- .\" Copyright (C) 2013, Heinrich Schuchardt .\" and Copyright (C) 2014, Michael Kerrisk .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this .\" manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of .\" this manual under the conditions for verbatim copying, provided that .\" the entire resulting derived work is distributed under the terms of .\" a permission notice identical to this one. .\" .\" Since the Linux kernel and libraries are constantly changing, this .\" manual page may be incorrect or out-of-date. The author(s) assume. .\" no responsibility for errors or omissions, or for damages resulting. .\" from the use of the information contained herein. The author(s) may. .\" not have taken the same level of care in the production of this. .\" manual, which is licensed free of charge, as they might when working. .\" professionally. .\" .\" Formatted or processed versions of this manual, if unaccompanied by .\" the source, must acknowledge the copyright and authors of this work. .\" %%%LICENSE_END .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH FANOTIFY 7 "1 novembre 2020" Linux "Manuel du programmeur Linux" .SH NOM fanotify – Surveiller les événements des systèmes de fichiers .SH DESCRIPTION L’interface de programmation fanotify permet la notification et l’interception des événements du système de fichiers. La recherche de virus et la gestion de stockage hiérarchisé font partie des cas d’utilisation. Dans l’interface originelle seul un ensemble limité d’événements était pris en charge. En particulier, les événements de création, de suppression ou de déplacement n’étaient pas pris en charge. La prise en charge de ces évènements a été ajoutée dans Linux\ 5.1. Consultez \fBinotify\fP(7) pour plus de précisions sur l’interface qui ne notifiait pas ces évènements avant Linux\ 5.1. .PP La capacité de surveiller tous les objets d’un système de fichiers monté, la capacité de décider des droits d’accès et la possibilité de lire ou modifier les fichiers avant qu’ils ne soient accédés par d’autres applications font partie des capacités supplémentaires à celles de l’interface de programmation \fBinotify\fP(7). .PP Les appels système suivants sont utilisés avec cette interface de programmation\ : \fBfanotify_init\fP(2), \fBfanotify_mark\fP(2), \fBread\fP(2), \fBwrite\fP(2) et \fBclose\fP(2). .SS "fanotify_init(), fanotify_mark() et groupes de notification" L’appel système \fBfanotify_init\fP(2) crée et initialise un groupe de notifications fanotify et renvoie un descripteur de fichier le référençant. .PP Un groupe de notifications fanotify est un objet interne au noyau qui contient une liste de fichiers, répertoires, système de fichiers et points de montages pour lesquels des événements seront créés. .PP Pour chaque entrée dans un groupe de notifications fanotify, deux masques binaires sont présents\ : le masque \fImark\fP et le masque \fIignore\fP. Le masque \fImark\fP définit les activités de fichier pour lesquelles un événement doit être créé. Le masque \fIignore\fP définit les activités pour lesquelles aucun événement ne doit être créé. Avoir ces deux types de masque permet à un système de fichiers, un point de montage ou à un répertoire d’être marqué pour recevoir des événements, tout en ignorant en même temps les événements pour des objets spécifiques dans ce point de montage ou répertoire. .PP L’appel système \fBfanotify_mark\fP(2) ajoute un fichier, répertoire, système de fichiers ou point de montage à un groupe de notifications et indique les événements qui doivent être signalés (ou ignorés), ou supprime ou modifie une telle entrée. .PP Le masque \fIignore\fP peut servir pour un cache de fichier. Les événements intéressants pour un cache de fichier sont la modification et la fermeture d’un fichier. Ainsi, le répertoire ou point de montage en cache va être marqué pour recevoir ces événements. Après la réception du premier événement informant qu’un fichier a été modifié, l’entrée correspondante du cache sera désactivée. Aucun autre événement de modification pour ce fichier ne sera utile jusqu’à sa fermeture. Ainsi, l’événement de modification peut être ajouté au masque \fIignore\fP. Lors de la réception d’un événement de fermeture, l’événement de modification peut être supprimé du masque \fIignore\fP et l’entrée de cache de fichier peut être mise à jour. .PP Les entrées des groupes de notification fanotify font référence aux fichiers et répertoires à l’aide de leur numéro d’inœud et aux montages à l’aide de leur identifiant de montage. Si les fichiers ou répertoires sont renommés ou déplacés dans le même montage, les entrées correspondantes survivent. Si les fichiers ou répertoires sont supprimés ou déplacés dans un autre montage ou si les montages sont démontés, les entrées correspondantes sont supprimées. .SS "La file d’événements" Comme les événements surviennent sur les objets de système de fichiers surveillés par un groupe de notifications, le système fanotify génère les événements qui sont collectés dans une file. Ces événements peuvent être lus (en utilisant \fBread\fP(2) ou similaire) à partir du descripteur de fichier fanotify renvoyé par \fBfanotify_init\fP(2). .PP Deux types d’événements sont créés\ : les événements de \fInotification\fP et les événements de \fIpermission\fP. Les événements de notification sont surtout informatifs et ne nécessitent pas d’action à prendre par l’application qui les reçoit à part pour la fermeture du descripteur de fichier valable passé dans l’événement (voir ci\-dessous). Les événements de permission sont des demandes à l’application qui les reçoit pour décider si les droits d’accès à un fichier doivent être attribués. Pour ces événements, le destinataire doit écrire une réponse qui décide d’attribuer l’accès ou non. .PP Un événement est supprimé de la file d’événements du groupe fanotify quand il a été lu. Les événements de permission qui ont été lus sont gardés dans une liste interne du groupe fanotify jusqu’à ce qu’une décision d’attribution de droits ait été prise en écrivant dans le descripteur de fichier fanotify ou que le descripteur de fichier fanotify soit fermé. .SS "Lecture d’événements fanotify" Appeler \fBread\fP(2) pour le descripteur de fichier renvoyé par \fBfanotify_init\fP(2) bloque (si l’attribut \fBFAN_NONBLOCK\fP n’est pas indiqué dans l’appel de \fBfanotify_init\fP(2)) jusqu’à ce qu’un événement de fichier survienne ou que l’appel soit interrompu par un signal (consultez \fBsignal\fP(7)). .PP L’utilisation d’un des attributs \fBFAN_REPORT_FID\fP et \fBFAN_REPORT_DIR_FID\fP dans \fBfanotify_init\fP(2) influence quelles structures sont renvoyées à l’écouteur d’évènement pour chaque évènement. Les évènements rapportés à un groupe initialisé avec un de ces attributs utiliseront des gestionnaires de fichiers pour identifier des objets du système de fichiers au lieu de descripteurs de fichier. .TP Après un appel réussi à \fBread\fP(2), le tampon de lecture contient une ou plus des structures suivantes\ : .PP .in +4n .EX struct fanotify_event_metadata { __u32 event_len; __u8 vers; __u8 reserved; __u16 metadata_len; __aligned_u64 mask; __s32 fd; __s32 pid; }; .EE .in .PP Dans le cas d’un groupe fanotify qui identifie des objets de système de fichiers par des gestionnaires de fichiers, sont attendus un ou plusieurs enregistrements d’informations supplémentaires de la structure détaillée ci\-dessous qui suit la structure générique \fIfanotify_event_metadata\fP dans le tampon de lecture\ : .PP .in +4n .EX struct fanotify_event_info_header { __u8 info_type; __u8 pad; __u16 len; }; struct fanotify_event_info_fid { struct fanotify_event_info_header hdr; __kernel_fsid_t fsid; unsigned char file_handle[0]; }; .EE .in .PP Pour des raisons de performances, une grande taille de tampon (par exemple 4096\ octets) est conseillée pour que plusieurs événements puissent être récupérés en une seule lecture. .PP La valeur de retour de \fBread\fP(2) est le nombre d’octets placés dans le tampon, ou\ \fB\-1\fP en cas d’erreur (mais consultez \fBBOGUES\fP). .PP Les champs de la structure \fIfanotify_event_metadata\fP sont les suivants. .TP \fIevent_len\fP C’est la taille des données pour l’événement actuel et la position du prochain événement dans le tampon. À moins que le groupe identifie des objets du système de fichiers par des gestionnaires de fichiers, la valeur d’\fIevent_len\fP est toujours \fBFAN_EVENT_METADATA_LEN\fP. Pour un groupe qui identifie les objets du système de fichiers par des gestionnaires de fichiers, \fIevent_len\fP inclut aussi des enregistrements d’identificateur de fichier de taille variable. .TP \fIvers\fP Ce champ contient un numéro de version pour la structure. Il doit être comparé à \fBFANOTIFY_METADATA_VERSION\fP pour vérifier que les structures renvoyées pendant l’exécution correspondent aux structures définies à la compilation. En cas d’erreur de correspondance, l’application devrait arrêter d’essayer d’utiliser le descripteur de fichier fanotify. .TP \fIreserved\fP Ce champ n’est pas utilisé. .TP \fImetadata_len\fP C’est la taille de la structure. Le champ a été introduit pour faciliter l’implémentation d’en\-têtes facultatifs par type d’événement. Aucun en\-tête facultatif n’existe dans l’implémentation actuelle. .TP \fImask\fP C’est un masque binaire décrivant l’événement (voir ci\-dessous). .TP \fIfd\fP C’est un descripteur de fichier ouvert pour l’objet actuellement accédé ou \fBFAN_NOFD\fP si un dépassement de file est survenu. Avec un groupe fanotify qui identifie les objets de système d’exploitation par des gestionnaires de fichiers, les applications doivent escompter que cette valeur soit \fBFAN_NOFD\fP pour chaque évènement qu’elles reçoivent. Le descripteur de fichier peut être utilisé pour accéder au contenu du fichier ou répertoire surveillé. L’application qui lit est responsable de la fermeture de ce descripteur de fichier. .IP Lors d’un appel de \fBfanotify_init\fP(2), l’appelant pourrait indiquer (à l’aide de l’argument \fIevent_f_flags\fP) plusieurs attributs d’état de fichier à définir dans la description de fichier ouverte qui correspond à ce descripteur de fichier. De plus, l’attribut d’état de fichier \fBFMODE_NONOTIFY\fP (interne au noyau) est défini dans la description de fichier ouverte. L’attribut supprime la création d’événement fanotify. Ainsi, quand le destinataire de l’événement fanotify accède au fichier ou répertoire notifié en utilisant ce descripteur de fichier, aucun événement supplémentaire n’est créé. .TP \fIpid\fP Si l’attribut \fBFAN_REPORT_TID\fP était réglé dans \fBfanotify_init\fP(2), c’est l’identifiant (TID) du thread qui a provoqué cet évènement. Sinon, c’est le PID du processus qui a provoqué cet évènement. .PP Un programme écoutant les événements fanotify peut comparer ce PID au PID renvoyé par \fBgetpid\fP(2) pour déterminer si l’événement est provoqué par l’écoutant lui\-même ou par un autre processus accédant au fichier. .PP Le masque binaire \fImask\fP indique les événements survenus pour un seul objet de système de fichiers. Plusieurs bits pourraient être définis dans ce masque si plus d’un événement est survenu pour l’objet de système de fichiers surveillé. En particulier, les événements consécutifs pour le même objet de système de fichiers et originaires du même processus pourraient être fusionnés dans un seul événement, mais deux événements de permission ne sont jamais fusionnés dans une entrée de file. .PP Les bits pouvant apparaître dans \fImask\fP sont les suivants. .TP \fBFAN_ACCESS\fP Un fichier ou un répertoire (mais consultez \fBBOGUES\fP) a été accédé (en lecture). .TP \fBFAN_OPEN\fP Un fichier ou un répertoire a été ouvert. .TP \fBFAN_OPEN_EXEC\fP Un fichier a été ouvert dans le but d’être exécuté. Consultez NOTES dans \fBfanotify_mark\fP(2) pour plus de détails. .TP \fBFAN_ATTRIB\fP Une métadonnée de fichier ou d’un répertoire a été modifiée. .TP \fBFAN_CREATE\fP Un fichier enfant ou un répertoire a été créé dans le répertoire surveillé. .TP \fBFAN_DELETE\fP Un fichier enfant ou un répertoire a été supprimé dans le répertoire surveillé. .TP \fBFAN_DELETE_SELF\fP Un fichier ou un répertoire a été supprimé. .TP \fBFAN_MOVED_FROM\fP Un fichier ou un répertoire a été déplacé du répertoire surveillé. .TP \fBFAN_MOVED_TO\fP Un fichier ou un répertoire a été déplacé du répertoire parent surveillé. .TP \fBIN_MOVE_SELF\fP Un fichier ou un répertoire surveillé a été déplacé. .TP \fBFAN_MODIFY\fP Un fichier a été modifié. .TP \fBFAN_CLOSE_WRITE\fP Un fichier qui était ouvert en écriture (\fBO_WRONLY\fP ou \fBO_RDWR\fP) a été fermé. .TP \fBFAN_CLOSE_NOWRITE\fP Un fichier ou un répertoire, qui était ouvert en lecture seule (\fBO_RDONLY\fP), a été fermé. .TP \fBFAN_Q_OVERFLOW\fP La file d’événements a dépassé la limite de 16384\ entrées. Cette limite peut être écrasée en indiquant l’attribut \fBFAN_UNLIMITED_QUEUE\fP lors de l’appel de \fBfanotify_init\fP(2). .TP \fBFAN_ACCESS_PERM\fP Une application veut lire un fichier ou répertoire, par exemple en utilisant \fBread\fP(2) ou \fBreaddir\fP(2). Le lecteur doit écrire une réponse (telle que décrite ci\-dessous) qui détermine si le droit d’accès à l’objet de système de fichiers sera attribué. .TP \fBFAN_OPEN_PERM\fP Une application veut ouvrir un fichier ou un répertoire. Le lecteur doit écrire une réponse qui détermine si le droit d’ouvrir l’objet de système de fichiers sera attribué. .TP \fBFAN_OPEN_PERM\fP Une application veut ouvrir un fichier pour une exécution. Le lecteur doit écrire une réponse qui détermine si le droit d’ouvrir l’objet de système de fichiers sera attribué. Consultez NOTES dans \fBfanotify_mark\fP(2) pour plus de détails. .PP Pour vérifier tous les événements fermés, le masque binaire suivant pourrait être utilisé\ : .TP \fBFAN_CLOSE\fP Un fichier a été fermé. C’est un synonyme de\ : .IP FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE .PP Pour vérifier tous les événements de déplacement, le masque binaire suivant pourrait être utilisé\ : .TP \fBFAN_MOVE\fP Un fichier ou un répertoire a été déplacé. C’est un synonyme de\ : .IP FAN_MOVED_FROM | FAN_MOVED_TO .PP Les bits suivants peuvent apparaître dans \fImask\fP seulement conjointement avec d’autres bits de type d’évènement\ : .TP \fBFAN_ONDIR\fP Les évènements décrits dans le \fImask\fP se sont déroulés dans un objet de répertoire. Le rapport d’évènements dans des répertoires requiert le réglage de cet attribut dans le masque \fImark\fP. Consultez \fBfanotify_mark\fP(2) pour plus de détails. L’attribut \fBFAN_ONDIR\fP est rapporté dans un masque d’évènement seulement si le groupe fanotify identifie les objets de système d’exploitation avec des gestionnaires de fichiers. .PP Les champs de la structure \fIfanotify_event_info_fid\fP sont les suivants. .TP \fIhdr\fP C’est une structure de type \fIfanotify_event_info_header\fP. C’est un en\-tête générique qui contient des informations utilisées pour décrire un enregistrement d’informations supplémentaires attaché à l’évènement. Par exemple, quand un descripteur de fichier fanotify est créé en utilisant \fBFAN_REPORT_FID\fP, un enregistrement unique est supposé être attaché à l’évènement avec la valeur de champ \fIinfo_type\fP de \fBFAN_EVENT_INFO_TYPE_FID\fP. Quand un descripteur de fichier fanotify est créé en utilisant la combinaison de \fBFAN_REPORT_FID\fP et \fBFAN_REPORT_DIR_FID\fP, il peut y avoir deux enregistrements d’informations attachés à l’évènement\ : un avec une valeur de champ \fIinfo_type\fP de \fBFAN_EVENT_INFO_TYPE_DFID\fP, identifiant un objet de répertoire parent, et un avec une valeur de champ \fIinfo_type\fP de \fBFAN_EVENT_INFO_TYPE_FID\fP, identifiant un objet non répertoire. Le \fIfanotify_event_info_header\fP contient un champ \fIlen\fP. La valeur de \fIlen\fP est la taille de l’enregistrement d’informations supplémentaires incluant le \fIfanotify_event_info_header\fP lui\-même. La taille totale de tous les enregistrements d’informations supplémentaires n’est pas supposée être supérieure à (\ \fIevent_len\fP\ \-\ \fImetadata_len\fP\ ). .TP \fIfsid\fP C’est un identifiant unique du système de fichiers contenant l’objet associé avec l’évènement. C’est une structure de type \fI__kernel_fsid_t\fP et elle contient la même valeur que \fIf_fsid\fP lors de l’appel \fBstatfs\fP(2). .TP \fIfile_handle\fP C’est une structure de taille variable de type \fIstruct gestionnaire_fichier\fP. C’est un gestionnaire opaque qui correspond à un objet précis de système de fichiers comme renvoyé par \fBname_to_handle_at\fP(2). Il peut être utilisé uniquement pour identifier un fichier d’un système de fichiers et peut être passé comme argument à \fBopen_by_handle_at\fP(2). Remarquez que pour les évènements de modification d’entrée de répertoire \fBFAN_CREATE\fP, \fBFAN_DELETE\fP et \fBFAN_MOVE\fP, \fIgestionnaire_fichier\fP identifie le répertoire modifié et non l’objet enfant créé/supprimé/déplacé. Si la valeur du champ \fIinfo_type\fP est \fBFAN_EVENT_INFO_TYPE_DFID_NAME\fP, le gestionnaire de fichiers est suivi par un octet NULL final qui identifie le nom d’entrée de répertoire créé/supprimé/déplacé. Pour les autres évènements tels que \fBFAN_OPEN\fP, \fBFAN_ATTRIB\fP, \fBFAN_DELETE_SELF\fP et \fBFAN_MOVE_SELF\fP, si la valeur du champ \fIinfo_type\fP est \fBFAN_EVENT_INFO_TYPE_FID\fP, le \fIgestionnaire_fichier\fP identifie l’objet corrélé à l’évènement. Si la valeur du champ \fIinfo_type\fP est \fBFAN_EVENT_INFO_TYPE_DFID\fP, le \fIgestionnaire_fichier\fP identifie l’objet de répertoire corrélé à l’évènement ou le répertoire parent d’un objet non répertoire corrélé à l’évènement. Si la valeur du champ \fIinfo_type\fP est \fBFAN_EVENT_INFO_TYPE_DFID_NAME\fP, le \fIgestionnaire_fichier\fP identifie le même objet de répertoire qui aurait été rapporté avec \fBFAN_EVENT_INFO_TYPE_DFID\fP et le gestionnaire de fichiers est suivi par un octet NULL\ final qui identifie le nom de l’entrée de répertoire dans ce répertoire ou «\ .\ » pour identifier l’objet du répertoire. .PP Les macros suivantes sont fournies pour itérer sur un tampon contenant les métadonnées d’événement fanotify renvoyées par \fBread\fP(2) à partir d’un descripteur de fichier fanotify. .TP \fBFAN_EVENT_OK(meta, len)\fP Cette macro compare la taille restante \fIlen\fP du tampon \fImeta\fP à la taille de la structure de métadonnées et au champ \fIevent_len\fP de la première structure de métadonnées du tampon. .TP \fBFAN_EVENT_NEXT(meta, len)\fP Cette macro utilise la taille indiquée dans le champ \fIevent_len\fP de la structure de métadonnées pointée par \fImeta\fP pour calculer l’adresse de la prochaine structure de métadonnées qui suit \fImeta\fP. \fIlen\fP est le nombre d’octets de métadonnées qui restent actuellement dans le tampon. La macro renvoie un pointeur vers la prochaine structure de métadonnées qui suit \fImeta\fP et réduit \fIlen\fP du nombre d’octets dans la structure de métadonnées qui a été sautée (c’est\-à\-dire qu’elle soustrait \fImeta\->event_len\fP de \fIlen\fP). .PP De plus, il existe\ : .TP \fBFAN_EVENT_METADATA_LEN\fP .\" Cette macro renvoie la taille (en octet) de la structure \fIfanotify_event_metadata\fP. C’est la taille minimale (et actuellement la seule taille) de métadonnées d’événements. .SS "Surveiller un descripteur de fichier fanotify pour les événements" Quand un événement fanotify survient, le descripteur de fichier fanotify est indiqué comme lisible lorsque passé à \fBepoll\fP(7), \fBpoll\fP(2) ou \fBselect\fP(2). .SS "Traitement des événements de permission" Pour les événements de permission, l’application doit écrire (avec \fBwrite\fP(2)) une structure de la forme suivante sur le descripteur de fichier fanotify\ : .PP .in +4n .EX struct fanotify_response { __s32 fd; __u32 response; }; .EE .in .PP Les membres de cette structure sont les suivants\ : .TP \fIfd\fP C’est le descripteur de fichier de la structure \fIfanotify_event_metadata\fP. .TP \fIresponse\fP Ce champ indique si les droits doivent être attribués ou non. Cette valeur doit être soit \fBFAN_ALLOW\fP pour permettre l’opération de fichier, soit \fBFAN_DENY\fP pour refuser l’opération de fichier. .PP .\" Si l’accès est refusé, l’appel d’application faisant la demande recevra une erreur \fBEPERM\fP. .SS "Fermeture du descripteur de fichier fanotify" Quand tous les descripteurs de fichier se référant au groupe de notifications fanotify sont fermés, le groupe fanotify est libéré et ses ressources sont libérées pour être réutilisées par le noyau. Lors de l’appel de \fBclose\fP(2), les événements de permission restants seront définis à permis. .SS /proc/[pid]/fdinfo Le fichier \fI/proc/[pid]/fdinfo/[fd]\fP contient des renseignements sur les marques fanotify pour le descripteur de fichier \fIfd\fP du processus \fIpid\fP. Consultez \fBproc\fP(5) pour plus de précisions. .SH ERREURS En plus des erreurs habituelles de \fBread\fP(2), les erreurs suivantes peuvent survenir lors de la lecture d’un descripteur de fichier fanotify. .TP \fBEINVAL\fP Le tampon est trop petit pour contenir l’événement. .TP \fBEMFILE\fP La limite par processus du nombre de fichiers ouverts a été atteinte. Consultez la description de \fBRLIMIT_NOFILE\fP dans \fBgetrlimit\fP(2). .TP \fBENFILE\fP La limite du nombre de fichiers ouverts sur le système a été atteinte. Consultez \fI/proc/sys/fs/file\-max\fP dans \fBproc\fP(5). .TP \fBETXTBSY\fP Cette erreur est renvoyée par \fBread\fP(2) si \fBO_RDWR\fP ou \fBO_WRONLY\fP ont été indiqués dans l’argument \fIevent_f_flags\fP lors de l’appel \fBfanotify_init\fP(2) et qu’un événement est survenu pour un fichier surveillé actuellement en cours d’exécution. .PP En plus des erreurs habituelles de \fBwrite\fP(2), les erreurs suivantes peuvent survenir lors de l’écriture sur un descripteur de fichier fanotify. .TP \fBEINVAL\fP Les droits d’accès fanotify ne sont pas activés dans la configuration du noyau ou la valeur de \fIresponse\fP dans la structure de réponse n’est pas valable. .TP \fBENOENT\fP Le descripteur de fichier \fIfd\fP dans la structure de réponse n’est pas valable. Cela pourrait survenir quand une réponse pour l’événement de permission a déjà été écrite. .SH VERSIONS L’interface de programmation fanotify a été introduite dans la version\ 2.6.36 du noyau Linux et activée dans la version\ 2.6.37. La prise en charge de fdinfo a été ajoutée dans la version\ 3.8. .SH CONFORMITÉ L’interface de programmation fanotify est spécifique à Linux. .SH NOTES L’interface de programmation fanotify n’est disponible que si le noyau a été construit avec l’option de configuration \fBCONFIG_FANOTIFY\fP activée. De plus, le traitement de permission fanotify n’est disponible que si l’option de configuration \fBCONFIG_FANOTIFY_ACCESS_PERMISSIONS\fP est activée. .SS "Limites et réserves" Fanotify ne signale que les événements déclenchés par un programme en espace utilisateur à l’aide d’une 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. .PP L'interface fanotify ne signale pas les accès ni les modifications de fichier qui pourraient survenir à cause de \fBmmap\fP(2), \fBmsync\fP(2) ou \fBmunmap\fP(2). .PP Les événements pour répertoire ne sont créés que si le répertoire lui\-même est ouvert, lu et fermé. Ajouter, supprimer ou modifier les enfants d’un répertoire marqué ne crée pas d’événement pour le répertoire surveillé lui\-même. .PP La surveillance fanotify des répertoires n'est pas récursive\ : pour surveiller les sous\-répertoires, des marques supplémentaires doivent être créées. L’évènement \fBFAN_CREATE\fP peut être utilisé pour détecter quand un sous\-répertoire a été créé dans un répertoire marqué. Une marque supplémentaire doit être définie dans le sous\-répertoire nouvellement créé. Cette approche crée une situation de compétition, parce qu’elle peut perdre les évènements qui se produisent dans le nouveau sous\-répertoire avant qu’une marque soit ajoutée dans ce sous\-répertoire. La surveillance des montages offre la capacité de surveiller un arbre entier de répertoires sans ce problème de chronologie. La surveillance de système de fichiers offre la capacité de surveiller tout montage d’une instance de système de fichiers sans situation de compétition. .PP La file d'événements peut déborder. Dans ce cas, les événements sont perdus. .SH BOGUES .\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35 Avant Linux\ 3.19, \fBfallocate\fP(2) ne créait pas d'événement fanotify. Depuis Linux\ 3.19, les appels à \fBfallocate\fP(2) créent des événements \fBFAN_MODIFY\fP. .PP Dans Linux\ 3.17, les bogues suivants existent\ : .IP * 3 Dans Linux, un objet du système de fichiers pourrait être accessible par de multiples chemins. Par exemple, une partie d'un système de fichiers pourrait être remontée avec l'option \fI\-\-bind\fP de \fBmount\fP(8). Un écoutant ayant marqué un montage ne sera notifié que des événements déclenchés pour un objet du système de fichiers utilisant le même montage. Tout autre événement passera inaperçu. .IP * .\" FIXME . A patch was proposed. Quand un événement est créé, aucune vérification n’est effectuée pour voir si l’identifiant utilisateur du processus recevant a le droit de lire ou écrire le fichier avant de passer un descripteur de fichier pour ce fichier. Cela pose un risque de sécurité quand la capacité \fBCAP_SYS_ADMIN\fP est définie pour un programme exécuté par les utilisateurs ordinaires. .IP * Si un appel de \fBread\fP(2) traite plusieurs événements de la file fanotify et qu’une erreur survient, la valeur de retour sera la taille totale des événements copiés correctement dans le tampon d’espace utilisateur avant que l’erreur ne survienne. La valeur de retour ne sera pas\ \fB\-1\fP et \fIerrno\fP ne sera pas définie. Ainsi, l’application lisant n’a aucun moyen de détecter l’erreur. .SH EXEMPLES Les deux programmes ci\-dessous montrent l’utilisation de l’API de fanotify. .SS "Exemple de programme : fanotify_example.c" Le programme suivant montre l’utilisation de fanotify pour une information d’évènement d’objet passé sous la forme d’un descripteur de fichier. Le programme marque le point de montage passé en argument de ligne de commande et attend les événements de type \fBFAN_PERM_OPEN\fP et \fBFAN_CLOSE_WRITE\fP. Quand un événement de permission survient, une réponse \fBFAN_ALLOW\fP est donnée. .PP La sortie suivante de session d’interpréteur de commande montre un exemple de l’exécution de ce programme. Cette session concerne l’édition du fichier \fI/home/utilisateur/temp/notes\fP. Avant d’ouvrir le fichier, un événement \fBFAN_OPEN_PERM\fP est survenu. Après la fermeture du fichier, un événement \fBFAN_CLOSE_WRITE\fP est survenu. L’exécution du programme se termine quand l’utilisateur appuie sur la touche Entrée. .PP .in +4n .EX # \fB./fanotify_exemple /home\fP Appuyer sur la touche Entrée pour quitter. En écoute d’événements. FAN_OPEN_PERM : Fichier /home/utilisateur/temp/notes FAN_CLOSE_WRITE : Fichier /home/utilisateur/temp/notes Arrêt de l’écoute d’événements. .EE .in .SS "Source du programme : fanotify_example.c" \& .EX #define _GNU_SOURCE /* Nécessaire pour obtenir la définition de O_LARGEFILE */ #include #include #include #include #include #include #include #include /* Lire tous les événements fanotify disponibles à partir du descripteur de fichier «\ fd\ » */ static void handle_events(int fd) { const struct fanotify_event_metadata *metadata; struct fanotify_event_metadata buf[200]; ssize_t len; char path[PATH_MAX]; ssize_t path_len; char procfd_path[PATH_MAX]; struct fanotify_response response; /* Boucler tant que les événements peuvent être lus à partir du descripteur de fichier fanotify */ for (;;) { /* Lire certains événements */ len = read(fd, buf, sizeof(buf)); if (len == \-1 && errno != EAGAIN) { perror("read"); exit(EXIT_FAILURE); } /* Vérifier si la fin des données disponibles est atteinte */ if (len <= 0) break; /* Pointer vers le premier événement du tampon */ metadata = buf; /* Boucler sur tous les événements du tampon */ while (FAN_EVENT_OK(metadata, len)) { /* Vérifier que les structures au moment de l’exécution et de la compilation correspondent */ if (metadata\->vers != FANOTIFY_METADATA_VERSION) { fprintf(stderr, "Non correspondance de version de métadonnées fanotify.\en"); exit(EXIT_FAILURE); } /* metadata\->fd contient soit FAN_NOFD, indiquant un dépassement de file, soit un descripteur de fichier (un entier positif). Ici, le dépassement de file est simplement ignoré. */ if (metadata\->fd >= 0) { /* Traiter l’événement de permission d’ouverture */ if (metadata\->mask & FAN_OPEN_PERM) { printf("FAN_OPEN_PERM\ : "); /* Permettre d’ouvrir le fichier */ response.fd = metadata\->fd; response.response = FAN_ALLOW; write(fd, &response, sizeof(response)); } /* Traiter l’événement de fermeture de fichier ouvert en écriture */ if (metadata\->mask & FAN_CLOSE_WRITE) printf("FAN_CLOSE_WRITE\ : "); /* Récupérer et afficher le chemin du fichier accédé */ snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", metadata\->fd); path_len = readlink(procfd_path, path, sizeof(path) \- 1); if (path_len == \-1) { perror("readlink"); exit(EXIT_FAILURE); } path[path_len] = \(aq\e0\(aq; printf("File %s\en", path); /* Fermer le descripteur de fichier de l’événement */ close(metadata\->fd); } /* Avancer au prochain événement */ metadata = FAN_EVENT_NEXT(metadata, len); } } } int main(int argc, char *argv[]) { char buf; int fd, poll_num; nfds_t nfds; struct pollfd fds[2]; /* Vérifier qu’un point de montage est fourni */ if (argc != 2) { fprintf(stderr, "Utilisation\ : %s MONTAGE\en", argv[0]); exit(EXIT_FAILURE); } printf("Appuyer sur la touche Entrée pour quitter.\en"); /* Créer le descripteur de fichier pour accéder à l’interface de programmation fanotify */ fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK, O_RDONLY | O_LARGEFILE); if (fd == \-1) { perror("fanotify_init"); exit(EXIT_FAILURE); } /* Marquer le montage pour\ : – les événements de permission avant d’ouvrir les fichiers\ ; – les événements de notification après fermeture de descripteur de fichier ouvert en écriture. */ if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD, argv[1]) == \-1) { perror("fanotify_mark"); exit(EXIT_FAILURE); } /* Préparer pour la scrutation (polling) */ nfds = 2; /* Entrée de console */ fds[0].fd = STDIN_FILENO; fds[0].events = POLLIN; /* Entrée de fanotify */ fds[1].fd = fd; fds[1].events = POLLIN; /* Boucle en attente d’arrivée d’événements */ printf("En écoute d’événements.\en"); while (1) { poll_num = poll(fds, nfds, \-1); if (poll_num == \-1) { if (errno == EINTR) /* Interrompu par un signal */ continue; /* Redémarrage de poll() */ perror("poll"); /* Erreur inattendue */ 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 != \(aq\en\(aq) continue; break; } if (fds[1].revents & POLLIN) { /* Des événements fanotify sont disponibles */ handle_events(fd); } } } printf("Arrêt de l’écoute d’événements.\en"); exit(EXIT_SUCCESS); } .EE .\" .SS "Exemple de programme : fanotify_fid.c" Le second programme est un exemple d’utilisation de fanotify avec un groupe qui identifie des objets avec des gestionnaires de fichier. Le programme marque l’objet de système de fichiers qui est passé comme argument de ligne de commande et attend jusqu’à ce qu’un évènement de type \fBFAN_CREATE\fP se produise. Le masque d’évènement indique quel type d’objet de système de fichiers, soit un fichier ou un répertoire, est créé. Une fois que tous les évènements du tampon ont été lus et traités de la manière appropriée, le programme se termine. .PP Les sessions d’interpréteur de commande suivantes montrent deux invocations différentes avec des actions différentes réalisées sur l’objet désiré. .PP La première session montre une marque placée sur \fI/home/utilisateur\fP. Cela est suivi par la création d’un fichier normal, \fI/home/utilisateur/fichiertest.txt\fP. Cela aboutit à un évènement \fBFAN_CREATE\fP généré et rapporté à l’objet de répertoire surveillé parent du fichier et à la création du nom de fichier. L’exécution du programme se termine une fois que tous les évènements capturés du tampon ont été traités. .PP .in +4n .EX # \fB./fanotify_fid /home/user\fP Écoute de tous les évènements. FAN_CREATE (fichier créé) : Répertoire /home/utilisateur a été modifié. Entrée \(aqfichiertest.txt\(aq n’est pas un sous\-répertoire. Tous les évènements ont été traités avec succès. Fin du programme. $ \fBtouch /home/utilisateur/fichiertest.txt\fP # Dans un autre terminal .EE .in .PP La première session montre une marque placée sur \fI/home/utilisateur\fP. C’est suivi par la création d’un répertoire, \fI/home/utilisateur/réptest\fP. Cette action spécifique aboutit à la génération d’un évènement \fBFAN_CREATE\fP et est rapporté avec l’attribut \fBFAN_ONDIR\fP défini et avec la création du nom de répertoire. .PP .in +4n .EX # \fB./fanotify_fid /home/user\fP Écoute de tous les évènements. FAN_CREATE | FAN_ONDIR (sous_répertoire créé) : Répertoire /home/utilisateur a été modifié. Entrée \(aqréptest\(aq est un sous\-répertoire. Tous les évènements ont été traités avec succès. Fin du programme. $ \fBmkdir \-p /home/utilisateur/réptest\fP # Dans un autre terminal .EE .in .SS "Source du programme : fanotify_fid.c" \& .EX #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #define BUF_SIZE 256 int main(int argc, char **argv) { int fd, ret, event_fd, mount_fd; ssize_t len, path_len; char path[PATH_MAX]; char procfd_path[PATH_MAX]; char events_buf[BUF_SIZE]; struct file_handle *file_handle; struct fanotify_event_metadata *metadata; struct fanotify_event_info_fid *fid; const char *file_name; struct stat sb; if (argc != 2) { fprintf(stderr, "nb d’arguments de ligne de commande non valable.\en"); exit(EXIT_FAILURE); } mount_fd = open(argv[1], O_DIRECTORY | O_RDONLY); if (mount_fd == \-1) { perror(argv[1]); exit(EXIT_FAILURE); } /* Créer un descripteur de fichier avec FAN_REPORT_DFID_NAME sous forme d’attribut de façon que le programme puisse recevoir des évènements fid avec des noms de répertoire d’entrée */ fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, 0); if (fd == \-1) { perror("fanotify_init"); exit(EXIT_FAILURE); } /* Placer une marque sur un objet de système de fichiers fourni dans argv[1]. */ ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR, FAN_CREATE | FAN_ONDIR, AT_FDCWD, argv[1]); if (ret == \-1) { perror("fanotify_mark"); exit(EXIT_FAILURE); } printf("En écoute d’événements.\en"); /* Lire les évènements de la file d’évènements d’un tampon */ len = read(fd, events_buf, sizeof(events_buf)); if (len == \-1 && errno != EAGAIN) { perror("read"); exit(EXIT_FAILURE); } /* Traiter tous les événements du tampon */ for (metadata = (struct fanotify_event_metadata *) events_buf; FAN_EVENT_OK(metadata, len); metadata = FAN_EVENT_NEXT(metadata, len)) { fid = (struct fanotify_event_info_fid *) (metadata + 1); file_handle = (struct file_handle *) fid\->handle; /* Assurer que les infos d’évènements soient du type correct */ if (fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_FID || fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) { file_name = NULL; } else if (fid\->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) { file_name = file_handle\->f_handle + file_handle\->handle_bytes; } else { fprintf(stderr, "Type inattendu d’évènement reçu.\en"); exit(EXIT_FAILURE); } if (metadata\->mask == FAN_CREATE) printf("FAN_CREATE (file created):\en"); if (metadata\->mask == (FAN_CREATE | FAN_ONDIR)) printf("FAN_CREATE | FAN_ONDIR (sous_répertoire créé) :\en"); /* metadata\->fd est défini à FAN_NOFD quand le groupe identifie les objets avec des gestionnaires de fichiers. Pour obtenir un descripteur de fichier pour l’objet de fichier correspondant à à un évènement, utiliser struct gestionnaire_fichier qui est fourni dans le fanotify_event_info_fid conjointement avec l’appel système open_by_handle_at(2). Une vérification pour ESTALE est faite pour supporter la situation où le gestionnaire de fichiers pour l’objet ait été détruit avant cet appel système. */ event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY); if (event_fd == \-1) { if (errno == ESTALE) { printf("Le gestionnaire de fichiers n’est plus valable, " "le fichier a été supprimé\en"); continue; } else { perror("open_by_handle_at"); exit(EXIT_FAILURE); } } snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", event_fd); /* Récupérer et afficher le chemin de l’entrée modifiée */ path_len = readlink(procfd_path, path, sizeof(path) \- 1); if (path_len == \-1) { perror("readlink"); exit(EXIT_FAILURE); } path[path_len] = \(aq\e0\(aq; printf("\eLe répertoire \(aq%s\(aq a été modifié\en", path); if (file_name) { ret = fstatat(event_fd, file_name, &sb, 0); if (ret == \-1) { if (errno != ENOENT) { perror("fstatat"); exit(EXIT_FAILURE); } printf("\etL’entrée \(aq%s\(aq n’existe pas\en", file_name); } else if ((sb.st_mode & S_IFMT) == S_IFDIR) { printf("\etL’entrée \(aq%s\(aq est un sous\-répertoire\en", file_name); } else { printf("\etL’entrée \(aq%s\(aq n’est pas un sous\-répertoire\en", file_name); } } /* Fermer le descripteur de fichier de cet événement */ close(event_fd); } printf("Tous les évènements traités avec succès, fin du programme.\en"); exit(EXIT_SUCCESS); } .EE .SH "VOIR AUSSI" .ad l \fBfanotify_init\fP(2), \fBfanotify_mark\fP(2), \fBinotify\fP(7) .SH COLOPHON Cette page fait partie de la publication\ 5.10 du projet \fIman\-pages\fP Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse \%https://www.kernel.org/doc/man\-pages/. .PP .SH TRADUCTION La traduction française de cette page de manuel a été créée par Christophe Blaess , Stéphan Rafin , Thierry Vignaud , François Micaux, Alain Portal , Jean-Philippe Guérard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas Huriaux , Nicolas François , Florentin Duneau , Simon Paillard , Denis Barbier , David Prévot et Jean-Paul Guillonneau . .PP Cette traduction est une documentation libre ; veuillez vous reporter à la .UR https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 .UE concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE. .PP Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à .MT debian-l10n-french@lists.debian.org .ME .