On Mon, Aug 24, 2020 at 11:03:26AM +0300, Amir Goldstein wrote: > Document fanotify_init(2) flag FAN_REPORT_NAME and the format of the > event info type FAN_EVENT_INFO_TYPE_DFID_NAME. These names sure are becoming a little bit of a mouth full. :) > The fanotify_fid.c example is extended to also report the name of the > created file or sub-directory. > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> Other than what Jan has already mentioned in regards to the spelling correction, the patch looks good to me! Feel free to add: Reviewed-by: Matthew Bobrowski <mbobrowski@xxxxxxxxxxxxxx> > --- > man2/fanotify_init.2 | 54 +++++++++++++++++++++++++++++ > man7/fanotify.7 | 81 ++++++++++++++++++++++++++++++++++---------- > 2 files changed, 118 insertions(+), 17 deletions(-) > > diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2 > index c58ae4493..a2e2a17fc 100644 > --- a/man2/fanotify_init.2 > +++ b/man2/fanotify_init.2 > @@ -223,6 +223,60 @@ flag, no event will be reported. > See > .BR fanotify (7) > for additional details. > +.TP > +.BR FAN_REPORT_NAME " (since Linux 5.9)" > +Events for fanotify groups initialized with this flag will contain additional > +information about the name of the directory entry correlated to an event. > +This flag must be provided in conjunction with the flag > +.BR FAN_REPORT_DIR_FID . > +Providing this flag value without > +.BR FAN_REPORT_DIR_FID > +will result in the error > +.BR EINVAL . > +This flag may be combined with the flag > +.BR FAN_REPORT_FID . > +An additional record of type > +.BR FAN_EVENT_INFO_TYPE_DFID_NAME , > +which encapsulates the information about the directory entry is included > +alongside the generic event metadata structure and substitutes the additional > +information record of type > +.BR FAN_EVENT_INFO_TYPE_DFID . > +The additional record includes a file handle that identifies a directory > +filesystem object followed by a name that identifies an entry in that > +directory. > +For the directory entry modification events > +.BR FAN_CREATE , > +.BR FAN_DELETE , > +and > +.BR FAN_MOVE , > +the reported name is that of the created/deleted/moved directory entry. > +For other events that occur on a directory object, the reported file handle > +is that of the directory object itself and the reported name is '.'. > +For other events that occur on a non-directory object, the reported file handle > +is that of the parent directory object and the reported name is the name of a > +directory entry where the object was located at the time of the event. > +The rational behind this logic is that the reported directory file handle can > +be passed to > +.BR open_by_handle_at (2) > +to get an open directory file descriptor and that file descriptor along with > +the reported name can be used to call > +.BR fstatat (2). > +The same rule that applies to record type > +.BR FAN_EVENT_INFO_TYPE_DFID > +also applies to record type > +.BR FAN_EVENT_INFO_TYPE_DFID_NAME \ - > +if a non-directory object has no parent, either the event will not be reported > +or it will be reported without the directory entry information. > +Note that there is no guarantee that the filesystem object will be found at the > +location described by the directory entry information at the time the event is > +received. > +See > +.BR fanotify (7) > +for additional details. > +.TP > +.B FAN_REPORT_DFID_NAME > +This is a synonym for > +.RB ( FAN_REPORT_DIR_FID | FAN_REPORT_NAME ). > .PP > The > .I event_f_flags > diff --git a/man7/fanotify.7 b/man7/fanotify.7 > index 00fc56368..5046fce02 100644 > --- a/man7/fanotify.7 > +++ b/man7/fanotify.7 > @@ -470,6 +470,12 @@ the > .IR file_handle > identifies the modified directory and not the created/deleted/moved child > object. > +If the value of > +.I info_type > +field is > +.BR FAN_EVENT_INFO_TYPE_DFID_NAME , > +the file handle is followed by a null terminated string that identifies the > +created/deleted/moved directory entry name. > For other events such as > .BR FAN_OPEN , > .BR FAN_ATTRIB , > @@ -490,7 +496,18 @@ field is > the > .IR file_handle > identifies the directory object correlated to the event or the parent directory > -of the non-directory object correlated to the event. > +of a non-directory object correlated to the event. > +If the value of > +.I info_type > +field is > +.BR FAN_EVENT_INFO_TYPE_DFID_NAME , > +the > +.IR file_handle > +identifies the same directory object that would be reported with > +.BR FAN_EVENT_INFO_TYPE_DFID > +and the file handle is followed by a null terminated string that identifies the > +name of a directory entry in that directory, or '.' to identify the directory > +object itself. > .PP > The following macros are provided to iterate over a buffer containing > fanotify event metadata returned by a > @@ -675,12 +692,17 @@ events for the monitored directory itself. > Fanotify monitoring of directories is not recursive: > to monitor subdirectories under a directory, > additional marks must be created. > -(But note that the fanotify API provides no way of detecting when a > -subdirectory has been created under a marked directory, > -which makes recursive monitoring difficult.) > -Monitoring mounts offers the capability to monitor a whole directory tree. > +The > +.B FAN_CREATE > +event can be used for detecting when a subdirectory has been created under > +a marked directory. > +An additional mark must then be set on the newly created subdirectory. > +This approach is racy, because it can lose events that occurred inside the > +newly created subdirectory, before a mark is added on that subdirectory. > +Monitoring mounts offers the capability to monitor a whole directory tree > +in a race free manner. > Monitoring filesystems offers the capability to monitor changes made from > -any mount of a filesystem instance. > +any mount of a filesystem instance in a race free manner. > .PP > The event queue can overflow. > In this case, events are lost. > @@ -964,9 +986,8 @@ main(int argc, char *argv[]) > .EE > .\" > .SS Example program: fanotify_fid.c > -The second program is an example of fanotify being used with > -.B FAN_REPORT_FID > -enabled. > +The second program is an example of fanotify being used with a group that > +identifies objects by file handles. > The program marks the filesystem object that is passed as > a command-line argument > and waits until an event of type > @@ -987,7 +1008,7 @@ This is followed by the creation of a regular file, > This results in a > .B FAN_CREATE > event being generated and reported against the file's parent watched > -directory object. > +directory object and with the created file name. > Program execution ends once all events captured within the buffer have > been processed. > .PP > @@ -997,6 +1018,7 @@ been processed. > Listening for events. > FAN_CREATE (file created): > Directory /home/user has been modified. > + Entry 'testfile.txt' is not a subdirectory. > All events processed successfully. Program exiting. > > $ \fBtouch /home/user/testfile.txt\fP # In another terminal > @@ -1011,7 +1033,7 @@ This specific action results in a > .B FAN_CREATE > event being generated and is reported with the > .B FAN_ONDIR > -flag set. > +flag set and with the created directory name. > .PP > .in +4n > .EX > @@ -1019,6 +1041,7 @@ flag set. > Listening for events. > FAN_CREATE | FAN_ONDIR (subdirectory created): > Directory /home/user has been modified. > + Entry 'testdir' is a subdirectory. > All events processed successfully. Program exiting. > > $ \fBmkdir \-p /home/user/testdir\fP # In another terminal > @@ -1051,6 +1074,8 @@ main(int argc, char **argv) > 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, "Invalid number of command line arguments.\en"); > @@ -1064,10 +1089,10 @@ main(int argc, char **argv) > } > > > - /* Create an fanotify file descriptor with FAN_REPORT_FID as a flag > - so that program can receive fid events. */ > + /* Create an fanotify file descriptor with FAN_REPORT_DFID_NAME as a flag > + so that program can receive fid events with directory entry name. */ > > - fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0); > + fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_DFID_NAME, 0); > if (fd == \-1) { > perror("fanotify_init"); > exit(EXIT_FAILURE); > @@ -1103,7 +1128,13 @@ main(int argc, char **argv) > > /* Ensure that the event info is of the correct type */ > > - if (fid\->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) { > + 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, "Received unexpected event info type.\en"); > exit(EXIT_FAILURE); > } > @@ -1114,8 +1145,8 @@ main(int argc, char **argv) > if (metadata\->mask == (FAN_CREATE | FAN_ONDIR)) > printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\en"); > > - /* metadata\->fd is set to FAN_NOFD when FAN_REPORT_FID is > - enabled. To obtain a file descriptor for the file object > + /* metadata\->fd is set to FAN_NOFD when the group identifies objects > + by file handles. To obtain a file descriptor for the file object > corresponding to an event you can use the struct file_handle > that\(aqs provided within the fanotify_event_info_fid in > conjunction with the open_by_handle_at(2) system call. > @@ -1149,6 +1180,22 @@ main(int argc, char **argv) > path[path_len] = \(aq\e0\(aq; > printf("\etDirectory \(aq%s\(aq has been modified.\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("\etEntry \(aq%s\(aq does not exist.\en", file_name); > + } else if ((sb.st_mode & S_IFMT) == S_IFDIR) { > + printf("\etEntry \(aq%s\(aq is a subdirectory.\en", file_name); > + } else { > + printf("\etEntry \(aq%s\(aq is not a subdirectory.\en", > + file_name); > + } > + } > + > /* Close associated file descriptor for this event */ > > close(event_fd); > -- > 2.17.1 > /M