linux-man.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Jan Kara <jack@suse.cz>,
	Matthew Bobrowski <mbobrowski@mbobrowski.org>,
	linux-man@vger.kernel.org
Subject: [PATCH 3/3] fanotify.7, fanotify_init.2: Document FAN_REPORT_NAME
Date: Mon, 24 Aug 2020 11:03:26 +0300	[thread overview]
Message-ID: <20200824080326.5012-4-amir73il@gmail.com> (raw)
In-Reply-To: <20200824080326.5012-1-amir73il@gmail.com>

Document fanotify_init(2) flag FAN_REPORT_NAME and the format of the
event info type FAN_EVENT_INFO_TYPE_DFID_NAME.

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@gmail.com>
---
 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


  parent reply	other threads:[~2020-08-24  8:03 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-24  8:03 [PATCH 0/3] Fanotify man page updates for v5.9 Amir Goldstein
2020-08-24  8:03 ` [PATCH 1/3] fanotify.7, fanotify_mark.2: Generalize documentation of FAN_REPORT_FID Amir Goldstein
2020-08-24  9:49   ` Jan Kara
2020-08-24 23:50   ` Matthew Bobrowski
2020-08-25  8:19     ` Amir Goldstein
2020-08-25 10:07       ` Matthew Bobrowski
2020-08-25 11:45   ` Michael Kerrisk (man-pages)
2020-08-25 12:07     ` Amir Goldstein
2020-08-24  8:03 ` [PATCH 2/3] fanotify.7, fanotify_init.2: Document FAN_REPORT_DIR_FID Amir Goldstein
2020-08-24  9:53   ` Jan Kara
2020-08-24 23:24   ` Matthew Bobrowski
2020-08-24  8:03 ` Amir Goldstein [this message]
2020-08-24 10:00   ` [PATCH 3/3] fanotify.7, fanotify_init.2: Document FAN_REPORT_NAME Jan Kara
2020-08-24 23:28   ` Matthew Bobrowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200824080326.5012-4-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=jack@suse.cz \
    --cc=linux-man@vger.kernel.org \
    --cc=mbobrowski@mbobrowski.org \
    --cc=mtk.manpages@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).