All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] Man pages for the fanotify API
@ 2014-02-26 19:53 xypron.glpk-Mmb7MZpHnFY
       [not found] ` <1393444390-16012-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: xypron.glpk-Mmb7MZpHnFY @ 2014-02-26 19:53 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, xypron.glpk-Mmb7MZpHnFY

From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>

The fanotify API is part of the Linux kernel since 2.6.36.

It is especially useful to scan files for malware.
Commercial products using this API have been published.

Outdated descriptions of the API are contained in the orginal commits:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=2a3edf86040a7e15684525a2aadc29f532c51325
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=52c923dd079df49f58016a9e56df184b132611d6

A suggestion for man-pages has been made by Stephan Mueller
http://permalink.gmane.org/gmane.linux.man/2400
but has not been picked up.

A further attempt was made by me in 2012,
http://article.gmane.org/gmane.linux.man/3399

Unfortunately no response has been received from Eric Paris the original author
of the API.

Since then I have used the API both in test programs and in an open source
project and continuously updated my version of the documentation.

A review was provided by David Simmons
http://git.xypron.de/?p=fanotify-manpages.git;a=commit;h=7b8d05cbcef5269b33301e6fa0870cfd905b87cd

A html version of the appended man pages is available at
http://www.xypron.de/projects/fanotify-manpages/

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 |  173 +++++++++++++++++++++
 man2/fanotify_mark.2 |  197 ++++++++++++++++++++++++
 man7/fanotify.7      |  410 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 780 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..04785cd
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,173 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" 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.
+.\"
+.TH FANOTIFY_INIT 2 2013-08-21 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.nf
+.B #include <linux/fcntl.h>
+.B #include <sys/fanotify.h>
+.sp
+.B "int fanotify_init(unsigned int flags, unsigned int event_f_flags);"
+.fi
+.SH DESCRIPTION
+.BR fanotify_init()
+initializes a new fanotify group and returns a file descriptor for the event
+queue.
+.PP
+The call requires the
+.B CAP_SYS_ADMIN
+capability. This constraint might be relaxed in future versions of the API.
+Hence additional local capability checks have been implemented as indicated
+below.
+.PP
+.IR flags
+defines the behavior of the file descriptor. It is a bitmask composed of the
+following values:
+.TP
+.B FAN_CLOEXEC
+sets the close-on-exec flag (
+.I FD_CLOEXEC
+) on the new file descriptor. When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed. See the
+description of the
+.I O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+enables the non-blocking flag (
+.I O_NONBLOCK
+) for the file descriptor. Reading from the file descriptor will not block.
+Instead if no data is available an error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_CLASS_NOTIF
+sets a priority level which does not allow making access decisions.
+.TP
+.B FAN_CLASS_CONTENT
+sets a priority level which allows making access decisions.
+.TP
+.B FAN_CLASS_PRE_CONTENT
+sets a priority level which allows changing the file content prior to access.
+Only one of the values
+.B FAN_CLASS_NOTIF,
+.B FAN_CLASS_CONTENT,
+or
+.B FAN_CLASS_PRE_CONTENT
+may be set.
+.TP
+.B FAN_UNLIMITED_QUEUE
+removes the limit on the size of the event queue. This flag requires the
+.nh
+.B CAP_SYS_ADMIN
+.hy
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+removes the limit on the number of marks. This flag requires the
+.nh
+.B CAP_SYS_ADMIN
+.hy
+capability.
+.PP
+.IR event_f_flags
+defines the file flags, with which file descriptors for fanotify events shall
+be created. For explanations of possible values see parameter
+.I flags
+of the 
+.BR open (2)
+system call. Useful values are
+.TP
+.B O_RDONLY
+read only access.
+.TP
+.B O_WRONLY
+write only access.
+.TP
+.B O_RDWR
+read and write access.
+.TP
+.B O_CLOEXEC
+enable close-on-exec.
+.TP
+.B O_LARGEFILE
+support files exceeding 2 GB. Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by a fanotify group.
+.SH RETURN VALUES
+If the system call is successful a new file descriptor is returned.
+In case of an error \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+indicates one of the following situations:
+.br
+- The number of listeners exceeds
+.nh
+.B FANOTIFY_DEFAULT_MAX_LISTENERS.
+.hy
+.br
+- Flag
+.nh
+.B FAN_UNLIMITED_QUEUE
+.hy
+was set without owning the
+.nh
+.B CAP_SYS_ADMIN
+.hy
+capability.
+.br
+- Flag
+.nh
+.B FAN_UNLIMITED_MARKS
+.hy
+was set without owning the
+.nh
+.B CAP_SYS_ADMIN
+.hy
+capability.
+.TP
+.B ENOMEM
+Out of memory, the allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+Operation not permitted
+.SH VERSIONS
+Fanotify_init was introduced in version 2.6.36 of the Linux kernel and enabled
+in version 2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify (7),
+.BR fanotify_mark (2)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..aa71c3d
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,197 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" 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.
+.\"
+.TH FANOTIFY_MARK 2 2013-08-27 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \-  add, remove, or modify a fanotify mark on a filesystem
+object.
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.B int fanotify_mark (int fanotify_fd, unsigned int flags, uint64_t mask, \
+int dfd, const char *pathname);
+.fi
+.SH DESCRIPTION
+.BR fanotify_mark (2)
+adds, removes, or modifies a fanotify mark on a filesystem.
+.PP
+.I fd
+is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bitmask describing the modification to perform. It is composed of the
+following values:
+.TP
+.B FAN_MARK_ADD
+Add the events in
+.I mask. 
+.TP
+.B FAN_MARK_REMOVE
+Remove the events in
+.I mask. 
+.TP
+.B FAN_MARK_DONT_FOLLOW
+Do not follow symbolic links.
+.TP
+.B FAN_MARK_ONLYDIR
+Fail if the path to be marked is not a directory.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount to be marked.
+.TP
+.B FAN_MARK_IGNORED_MASK
+Add to or remove from the ignored event mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignored mask shall survive modify events. If this flag is not set the
+ignored mask is cleared if a modify event occurs for the fanotify group.
+.TP
+.B FAN_MARK_FLUSH
+Remove all events from the whole group.
+.PP
+Only one of
+.B FAN_MARK_ADD, FAN_MARK_REMOVE,
+or
+.B FAN_MARK_FLUSH
+should be set.
+.PP
+The following composed value exists
+.TP
+.B FAN_ALL_MARK_FLAGS
+A mask with all mark bits set
+.nh
+(FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_DONT_FOLLOW | FAN_MARK_ONLYDIR |
+FAN_MARK_MOUNT | FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY |
+FAN_MARK_FLUSH).
+.hy
+.PP
+.I mask
+defines which events shall be listened to. It is a bitmask composed of the
+following values:
+.TP
+.B FAN_ACCESS
+A file was accessed (read).
+.TP
+.B FAN_MODIFY
+A file was modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+An readonly file was closed.
+.TP
+.B FAN_OPEN
+A file was opened.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue overflowed.
+.TP
+.B FAN_OPEN_PERM
+A file open permission was requested.
+.TP
+.B FAN_ACCESS_PERM
+An access permission for a file was requested.
+.TP
+.B FAN_ONDIR
+The event occurred against a directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+An event for a child of a monitored directory occurred.
+.PP
+The following composed value is defined
+.TP
+.B FAN_CLOSE
+A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+.I dfd
+is a file descriptor.
+.IP - 2
+If 
+.I pathname
+is NULL
+.I dfd
+defines the path to be marked.
+.IP - 2
+If
+.I pathname
+is NULL and dfd takes the special value
+.B AT_FDCWD
+defined in <fcntl.h> the current working directory is to be marked.
+.IP - 2
+If
+.I pathname
+is absolute it defines the path to be marked.
+.IP - 2
+If
+.I pathname
+is relative it defines a path relative to the path indicated by the file
+descriptor in
+.I dfd
+to be marked.
+.IP - 2
+If
+.I pathname
+is relative and dfd takes the special value
+.B AT_FDCWD
+it defines a path relative to the current working directory to be marked.
+.PP
+.I pathname
+is an absolute or relative path to be marked.
+.SH RETURN VALUES
+If the system call is successful 0 is returned. In case of an error \-1 is
+returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags ,
+or
+.IR mask .
+.TP
+.B ENOENT
+The directory indicated by
+.IR pathname
+is not valid. This error also occurs when trying to remove a mark from a
+directory or mount which is not marked.
+.TP
+.B ENOMEM
+Out of memory.
+.TP
+.B ENOSPC
+Too many marks.
+.SH VERSIONS
+Fanotify_mark was introduced in version 2.6.36 of the Linux kernel and enabled
+in version 2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify (7),
+.BR fanotify_init (2)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..5d32f1c
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,410 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" 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.
+.\"
+.TH FANOTIFY 7 2014-02-26 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring file system events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of file system events. Use cases
+are virus scanning and hierarchical storage management.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes a
+.B fanotify
+group and returns a file descriptor
+referring to it.
+.br
+.BR fanotify_mark (2)
+adds or removes a file, a directory, or a mount from the notification group.
+.PP
+When all file descriptors referring to the
+.B fanotify
+group are closed, the
+notification group is released and the resources are freed for reuse by the
+kernel.
+.PP
+An application first calls
+.BR fanotify_init (2)
+to receive a file descriptor. It uses
+.BR fanotify_mark (2)
+to define which files, directories, or mounts events shall be created.
+.PP
+Calling
+.BR poll (2)
+or
+.BR ppoll (2)
+will block until either a file event occurs or it is interrupted by a signal
+(see
+.nh
+.BR signal (7)).
+.hy
+If events are able to be read this will be advertised in the returned events
+mask as
+.B POLLIN
+and if compiled with
+.B _XOPEN_SOURCE
+as
+.B POLLRDNORM. 
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+will block (if flag
+.nh
+.B FAN_NONBLOCK
+.hy
+is not set in the call to
+.nh
+.BR fanotify_init (2))
+.hy
+until either a file event occurs or it is interrupted by a signal
+(see
+.nh
+.BR signal (7)).
+.BR read (2)
+.hy
+will return the length of the filled buffer or -1 in case of an error.
+
+Each successful call to
+.BR read (2)
+returns a buffer containing one or more of the following structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+is the length of the data for this event and the offset to the next event
+in the buffer. This length might be longer than the size of structure
+.nh
+.I fanotify_event_metadata.
+.hy
+Therefore it is recommended to use a larger buffer size when reading,
+e.g. 4096 bytes.
+.TP
+.I vers
+holds the version of the
+.B fanotify
+API. The value should be checked against
+.nh
+.B FANOTIFY_METADATA_VERSION.
+.hy
+.TP
+.I reserved
+is not used.
+.TP
+.I metadata_len
+is the length of the structure. The field was introduced to facilitate the
+implementation of optional headers per event type.
+.TP
+.I mask
+is a bitmask describing the event.
+.TP
+.I fd
+is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred. The reading application is responsible for
+closing this file descriptor.
+.TP
+.I pid
+is the ID of the process that caused the event.
+.PP
+The bitmask in
+.I mask
+is composed of the following values:
+.TP
+.B FAN_ACCESS
+file was accessed.
+.TP
+.B FAN_OPEN
+file was opened.
+.TP
+.B FAN_MODIFY
+file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+writable file closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+unwritable file closed.
+.TP
+.B FAN_Q_OVERFLOW
+event queue overflowed.
+.TP
+.B FAN_ACCESS_PERM
+file accessed in perm check.
+.TP
+.B FAN_OPEN_PERM
+file open in perm check.
+.TP
+.B FAN_ONDIR
+event occurred against directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+event for a child of a directory occurred.
+.PP
+To check for any close event the following bitmask may be used
+.TP
+.B FAN_CLOSE
+a file was closed 
+.nh
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.hy
+.PP
+The following macros are provided to iterate over a buffer of
+.B fanotify
+event metadata:
+.TP
+.B FAN_EVENT_OK(meta, len)
+checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+lets the pointer
+.I meta
+point to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.I len.
+.PP
+For permission events the application must
+.BR write (2)
+to the
+.B fanotify
+file descriptor a structure
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+is the file descriptor from structure
+.I fanotify_event_metadata.
+.TP
+.I response
+must be either
+.br
+.B FAN_ALLOW
+to allow the file operation or
+.br
+.B FAN_DENY
+to deny the file operation.
+.PP
+To end listening it is sufficient to
+.BR close (2)
+the
+.B fanotify
+file descriptor. The open permission events will be set to allowed, and all
+resources will be returned to the kernel.
+.PP
+File /proc/<pid>/fdinfo/<fd> contains information about fanotify marks for
+file descriptor fd of process pid. See
+.nh
+.I Documentation/filesystems/proc.txt
+.hy
+for details.
+.SH ERRORS
+The following errors may occur when reading from the
+.B fanotify
+file descriptor:
+.TP
+.B EAGAIN
+a nonblocking call did not return any data.
+.TP
+.B EFAULT
+the read buffer is outside your accessible address space.
+.TP
+.B EINTR
+a signal has occurred.
+.TP
+.B EINVAL
+the buffer is too short to hold the event.
+.PP
+The following errors may occur when writing to the
+.B fanotify
+file descriptor:
+.TP
+.B EFAULT
+the write buffer is outside your accessible address space.
+.TP
+.B EINVAL
+.B fanotify
+access permissions are not enabled or the value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+the file descriptor
+.I fd
+in the response structure is not valid. This might occur because the file was
+already deleted by another thread or process.
+.SH VERSIONS
+The
+.B fanotify
+API was introduced in version 2.6.36 of the Linux kernel and enabled in
+version 2.6.37. Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The
+.B fanotify
+API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+To enable the
+.B fanotify
+API the following setting in the Kernel configuration is needed:
+CONFIG_FANOTIFY=y. For permission handling
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API. It creates a thread waiting for FAN_PERM_OPEN and FAN_CLOSE_WRITE events
+for mount /home. If a permission event arises a FAN_ALLOW response is given.
+When a line feed is entered a signal is sent to stop the listening thread.
+.PP
+The example does not cover handling signals arising while not waiting for a new
+event.
+.PP
+.nf
+#include <linux/fcntl.h>
+#include <linux/limits.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+static void *run(void *data) {
+    char buf[4096];
+    int fd;
+    const struct fanotify_event_metadata *metadata;
+    int len;
+    char path[PATH_MAX];
+    int path_len;
+    struct fanotify_response response;
+    if (-1 == (fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT,
+            O_RDONLY | O_LARGEFILE))) {
+        perror("Cannot init");
+        return NULL;
+    }
+    if (-1 == (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+            FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD, "/home"))) {
+        perror("Cannot mark");
+        close(fd);
+        return NULL;
+    }
+    while (-1 != (len = read(fd, (void *) &buf, sizeof (buf)))) {
+        metadata = (struct fanotify_event_metadata *) buf;
+        while (FAN_EVENT_OK(metadata, len)) {
+            if (metadata->fd != FAN_NOFD) {
+                if (metadata->fd >= 0) {
+                    if (metadata->mask & FAN_OPEN_PERM) {
+                        printf("FAN_OPEN_PERM: ");
+                        response.fd = metadata->fd;
+                        response.response = FAN_ALLOW;
+                        write(fd, &response, sizeof (
+                                struct fanotify_response));
+                    }
+                    if (metadata->mask & FAN_CLOSE_WRITE) {
+                        printf("FAN_CLOSE_WRITE: ");
+                    }
+                    sprintf(path, "/proc/self/fd/%d", metadata->fd);
+                    path_len = readlink(path, path, sizeof (path) - 1);
+                    if (path_len > 0) {
+
+                        path[path_len] = 0x00;
+                        printf("File %s", path);
+                    }
+                    close(metadata->fd);
+                }
+                printf("\\n");
+            }
+            metadata = FAN_EVENT_NEXT(metadata, len);
+        }
+    }
+    close(fd);
+    return NULL;
+}
+
+int main(int argc, char *argv[]) {
+    pthread_attr_t attr;
+    pthread_t thread;
+    void *result;
+    if (pthread_attr_init(&attr)) {
+        return EXIT_FAILURE;
+    }
+    if (pthread_create(&thread, &attr, run, NULL)) {
+        return EXIT_FAILURE;
+    }
+    printf("Press any key to terminate\\n");
+    getchar();
+    if (0 != pthread_kill(thread, SIGUSR1)) {
+        return EXIT_FAILURE;
+    }
+    pthread_join(thread, &result);
+    return EXIT_SUCCESS;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.nh
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/1] Man pages for the fanotify API
       [not found] ` <1393444390-16012-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-03-14 16:42   ` Michael Kerrisk (man-pages)
       [not found]     ` <53233160.9000106-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-03-14 16:42 UTC (permalink / raw)
  To: xypron.glpk-Mmb7MZpHnFY
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, Eric Paris, Stephan Mueller,
	James Hunt

Heinrich,

Thank you for pushing this again. Let's see if we can get this done this time. 
My apologies for not following up on previous attempts. The pages are a good
start, but need some work.

I've added a few people to the CC. Eric, Stephan, James, maybe you have some 
input or review comments.

Eric! Your input here would be really helpful.

On 02/26/2014 08:53 PM, xypron.glpk-Mmb7MZpHnFY@public.gmane.org wrote:
> From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> 
> The fanotify API is part of the Linux kernel since 2.6.36.
> 
> It is especially useful to scan files for malware.
> Commercial products using this API have been published.
> 
> Outdated descriptions of the API are contained in the orginal commits:
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=2a3edf86040a7e15684525a2aadc29f532c51325
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=52c923dd079df49f58016a9e56df184b132611d6
> 
> A suggestion for man-pages has been made by Stephan Mueller
> http://permalink.gmane.org/gmane.linux.man/2400
> but has not been picked up.

Yes, unfortunately that effort petered out, and I didn't 
have the time to push it along.

Is the information in your pages a superset of that in
Stephan's pages?

> A further attempt was made by me in 2012,
> http://article.gmane.org/gmane.linux.man/3399
> 
> Unfortunately no response has been received from Eric Paris the original author
> of the API.

Eric, are you listening?

> Since then I have used the API both in test programs and in an open source
> project and continuously updated my version of the documentation.

Good to hear.

> A review was provided by David Simmons
> http://git.xypron.de/?p=fanotify-manpages.git;a=commit;h=7b8d05cbcef5269b33301e6fa0870cfd905b87cd
> 
> A html version of the appended man pages is available at
> http://www.xypron.de/projects/fanotify-manpages/
> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> ---
>  man2/fanotify_init.2 |  173 +++++++++++++++++++++
>  man2/fanotify_mark.2 |  197 ++++++++++++++++++++++++
>  man7/fanotify.7      |  410 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 780 insertions(+)
>  create mode 100644 man2/fanotify_init.2
>  create mode 100644 man2/fanotify_mark.2
>  create mode 100644 man7/fanotify.7
> 
> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
> new file mode 100644
> index 0000000..04785cd
> --- /dev/null
> +++ b/man2/fanotify_init.2
> @@ -0,0 +1,173 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 

Could you add LICENSE_START and LICENSE_END tags to the license on
each page please.
(See https://www.kernel.org/doc/man-pages/licenses.html#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.
> +.\"
> +.TH FANOTIFY_INIT 2 2013-08-21 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_init \- create and initialize fanotify group
> +.SH SYNOPSIS
> +.nf
> +.B #include <linux/fcntl.h>

I think you mean <sys/fcntl.h>

> +.B #include <sys/fanotify.h>
> +.sp
> +.B "int fanotify_init(unsigned int flags, unsigned int event_f_flags);"

The formatting here is not correct. Look at the formatting of the
SYNOPSIS in any other page, to see the required form here. Please
fix all SYNOPSIS sections.

> +.fi
> +.SH DESCRIPTION
> +.BR fanotify_iqnit()
> +initializes a new fanotify group and returns a file descriptor for the event
> +queue.
> +.PP
> +The call requires the
> +.B CAP_SYS_ADMIN
> +capability. This constraint might be relaxed in future versions of the API.
> +Hence additional local capability checks have been implemented as indicated
> +below.
> +.PP
> +.IR flags

Please start all new sentences on new source lines (see man-pages(7):

> +defines the behavior of the file descriptor. It is a bitmask composed of the

==>
    defines the behavior of the file descriptor. 
    It is a bitmask composed of the

> +following values:
> +.TP
> +.B FAN_CLOEXEC
> +sets the close-on-exec flag (
> +.I FD_CLOEXEC
> +) 

Formatting here should be

.BR ( FD_CLOEXEC )

(There are other instances below to fix.)

on the new file descriptor. When calling
> +.BR execve (2)
> +the inherited file descriptor of the child process will be closed. See the
> +description of the
> +.I O_CLOEXEC

All constants should be formatted bold

.B O_CLOEXEC

> +flag in
> +.BR open (2).
> +.TP
> +.B FAN_NONBLOCK
> +enables the non-blocking flag (
> +.I O_NONBLOCK

Broken formatting; see above

> +) for the file descriptor. Reading from the file descriptor will not block.
> +Instead if no data is available an error
> +.B EAGAIN
> +will occur.

Where will that error occur? On a read()? This needs to be clarified.
(I see that you say this in fanotify.7, but the reader on this page will 
be puzzled.)

> +.TP
> +.B FAN_CLASS_NOTIF
> +sets a priority level which does not allow making access decisions.

This sentence is very unclear. Decisions? What decisions are these, 
and how does one "make" these decisions?

> +.TP
> +.B FAN_CLASS_CONTENT
> +sets a priority level which allows making access decisions.

See above.

> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +sets a priority level which allows changing the file content prior to access.

Is this explained in more detail somewhere?

> +Only one of the values
> +.B FAN_CLASS_NOTIF,
> +.B FAN_CLASS_CONTENT,
> +or
> +.B FAN_CLASS_PRE_CONTENT
> +may be set.
> +.TP
> +.B FAN_UNLIMITED_QUEUE
> +removes the limit on the size of the event queue. This flag requires the
> +.nh
> +.B CAP_SYS_ADMIN
> +.hy
> +capability.

So if FAN_UNLIMITED_QUEUE is not specified, what are the limits? That's 
not explained.

> +.TP
> +.B FAN_UNLIMITED_MARKS
> +removes the limit on the number of marks. This flag requires the
> +.nh
> +.B CAP_SYS_ADMIN
> +.hy
> +capability.

So if FAN_UNLIMITED_MARKS is not specified, what are the limits? That's 
not explained.

> +.PP
> +.IR event_f_flags
> +defines the file flags, with which file descriptors for fanotify events shall
> +be created. For explanations of possible values see parameter
> +.I flags
> +of the 
> +.BR open (2)
> +system call. Useful values are
> +.TP
> +.B O_RDONLY
> +read only access.
> +.TP
> +.B O_WRONLY
> +write only access.
> +.TP
> +.B O_RDWR
> +read and write access.
> +.TP
> +.B O_CLOEXEC
> +enable close-on-exec.
> +.TP
> +.B O_LARGEFILE
> +support files exceeding 2 GB. Failing to set this flag will result in an
> +.B EOVERFLOW
> +error when trying to open a large file which is monitored by a fanotify group.
> +.SH RETURN VALUES

RETURN VALUE (no S)

> +If the system call is successful a new file descriptor is returned.
> +In case of an error \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags .
> +.B FAN_ALL_INIT_FLAGS
> +defines all allowable bits.
> +.TP
> +.B EMFILE
> +indicates one of the following situations:
> +.br
> +- The number of listeners exceeds

Please drop the .nh/.hy tags. It's better to have hyphenation than large
amounts of whitespace in the lines.

> +.nh
> +.B FANOTIFY_DEFAULT_MAX_LISTENERS.
> +.hy

The next two cases give EPERM, not EMFILE:

> +.br
> +- Flag
> +.nh
> +.B FAN_UNLIMITED_QUEUE
> +.hy
> +was set without owning the
> +.nh
> +.B CAP_SYS_ADMIN
> +.hy
> +capability.
> +.br
> +- Flag
> +.nh
> +.B FAN_UNLIMITED_MARKS
> +.hy
> +was set without owning the
> +.nh
> +.B CAP_SYS_ADMIN
> +.hy
> +capability.
> +.TP
> +.B ENOMEM
> +Out of memory, the allocation of memory for the notification group failed. 
> +.TP
> +.B EPERM
> +Operation not permitted
> +.SH VERSIONS
> +Fanotify_init 

.BR fanotify_init ()

> was introduced in version 2.6.36 of the Linux kernel and enabled
> +in version 2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify (7),
> +.BR fanotify_mark (2)

Order SEE ALSO entries by section, and then alphabetically within the section.

> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
> new file mode 100644
> index 0000000..aa71c3d
> --- /dev/null
> +++ b/man2/fanotify_mark.2
> @@ -0,0 +1,197 @@
> +.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" 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.
> +.\"
> +.TH FANOTIFY_MARK 2 2013-08-27 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_mark \-  add, remove, or modify a fanotify mark on a filesystem
> +object.
> +.SH SYNOPSIS
> +.nf
> +.B #include <sys/fanotify.h>
> +.sp
> +.B int fanotify_mark (int fanotify_fd, unsigned int flags, uint64_t mask, \
> +int dfd, const char *pathname);

Please break this over two lines.
See also my earlier comment about formatting in the SYNOPSIS.

> +.fi
> +.SH DESCRIPTION
> +.BR fanotify_mark (2)
> +adds, removes, or modifies a fanotify mark on a filesystem.
> +.PP
> +.I fd
> +is the file descriptor returned by
> +.BR fanotify_init (2).
> +.PP
> +.I flags
> +is a bitmask describing the modification to perform. It is composed of the
> +following values:
> +.TP
> +.B FAN_MARK_ADD
> +Add the events in
> +.I mask. 

Correct formatting here is

.IR mark .

(Please fix other instances.)

> +.TP
> +.B FAN_MARK_REMOVE
> +Remove the events in
> +.I mask. 
> +.TP
> +.B FAN_MARK_DONT_FOLLOW
> +Do not follow symbolic links.
> +.TP
> +.B FAN_MARK_ONLYDIR
> +Fail if the path to be marked is not a directory.
> +.TP
> +.B FAN_MARK_MOUNT
> +The path indicates a mount to be marked.
> +.TP
> +.B FAN_MARK_IGNORED_MASK
> +Add to or remove from the ignored event mask.
> +.TP
> +.B FAN_MARK_IGNORED_SURV_MODIFY
> +The ignored mask shall survive modify events. If this flag is not set the
> +ignored mask is cleared if a modify event occurs for the fanotify group.
> +.TP
> +.B FAN_MARK_FLUSH
> +Remove all events from the whole group.
> +.PP
> +Only one of
> +.B FAN_MARK_ADD, FAN_MARK_REMOVE,
> +or
> +.B FAN_MARK_FLUSH
> +should be set.

What happens if you specify more than one of these?
Explain this in the page, please.

> +.PP
> +The following composed value exists
> +.TP
> +.B FAN_ALL_MARK_FLAGS
> +A mask with all mark bits set
> +.nh
> +(FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_DONT_FOLLOW | FAN_MARK_ONLYDIR |
> +FAN_MARK_MOUNT | FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY |
> +FAN_MARK_FLUSH).
> +.hy

Yes, but FAN_ALL_MARK_FLAGS is irrelevant. It's only used inside the kernel 
to check the validity of the flags argument... So, remove the preceding
paragraph.

> +.PP
> +.I mask
> +defines which events shall be listened to. It is a bitmask composed of the
> +following values:
> +.TP
> +.B FAN_ACCESS
> +A file was accessed (read).
> +.TP
> +.B FAN_MODIFY
> +A file was modified (write).
> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +An readonly file was closed.
> +.TP
> +.B FAN_OPEN
> +A file was opened.
> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue overflowed.
> +.TP
> +.B FAN_OPEN_PERM
> +A file open permission was requested.
> +.TP
> +.B FAN_ACCESS_PERM
> +An access permission for a file was requested.
> +.TP
> +.B FAN_ONDIR
> +The event occurred against a directory.
> +.TP
> +.B FAN_EVENT_ON_CHILD
> +An event for a child of a monitored directory occurred.
> +.PP
> +The following composed value is defined
> +.TP
> +.B FAN_CLOSE
> +A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +.I dfd
> +is a file descriptor.
> +.IP - 2
> +If 
> +.I pathname
> +is NULL
> +.I dfd
> +defines the path to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is NULL and dfd takes the special value
> +.B AT_FDCWD
> +defined in <fcntl.h> the current working directory is to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is absolute it defines the path to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is relative it defines a path relative to the path indicated by the file
> +descriptor in
> +.I dfd
> +to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is relative and dfd 

.I dfd

> takes the special value
> +.B AT_FDCWD
> +it defines a path relative to the current working directory to be marked.
> +.PP
> +.I pathname
> +is an absolute or relative path to be marked.
> +.SH RETURN VALUES

RETURN VALUE (no S)

> +If the system call is successful 0 is returned. In case of an error \-1 is
      ^^^^^^^^^^^^^^^
If
.BR fanotify_mark()
is successful....

> +returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
Missing errors:
ENOTDIR (FAN_MARK_ONLYDIR)

> +.TP
> +.B EBADF
> +An invalid file descriptor was passed in
> +.IR fanotify_fd .
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags ,
> +or
> +.IR mask .

EINVAL: ==> fd was not an fanotify file descriptor.
/
> +.TP
> +.B ENOENT
> +The directory indicated by
> +.IR pathname
> +is not valid. This error also occurs when trying to remove a mark from a
> +directory or mount which is not marked.
> +.TP
> +.B ENOMEM
> +Out of memory.
> +.TP
> +.B ENOSPC
> +Too many marks.
> +.SH VERSIONS
> +Fanotify_mark 

.BR fanotify_mark ()

> was introduced in version 2.6.36 of the Linux kernel and enabled
> +in version 2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify (7),
> +.BR fanotify_init (2)

Ordering...

> diff --git a/man7/fanotify.7 b/man7/fanotify.7
> new file mode 100644
> index 0000000..5d32f1c
> --- /dev/null
> +++ b/man7/fanotify.7
> @@ -0,0 +1,410 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" 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.
> +.\"
> +.TH FANOTIFY 7 2014-02-26 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify \- monitoring file system events

Change all instances of "file system" to "filesystem"

> +.SH DESCRIPTION
> +The
> +.B fanotify
> +API provides notification and interception of file system events. Use cases
> +are virus scanning and hierarchical storage management.
> +
> +The following system calls are used with this API:
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR poll (2),
> +.BR ppoll (2),
> +.BR read (2),
> +.BR write (2),
> +and
> +.BR close (2).
> +.PP
> +.BR fanotify_init (2)
> +creates and initializes a
> +.B fanotify
> +group and returns a file descriptor
> +referring to it.

At this point, you need to explain what an "fanotify group" is.
You never really explain it in the entire page.

> +.br

s/.br/.PP/

> +.BR fanotify_mark (2)
> +adds or removes a file, a directory, or a mount from the notification group.
> +.PP
> +When all file descriptors referring to the
> +.B fanotify
> +group are closed, the
> +notification group is released and the resources are freed for reuse by the
> +kernel.
> +.PP
> +An application first calls
> +.BR fanotify_init (2)
> +to receive a file descriptor. It uses
> +.BR fanotify_mark (2)
> +to define which files, directories, or mounts events shall be created.

I think the last sentence isn't quite right. Don't you mean something like:

It uses fanotify_mark(2) to add files, directories, and mounts to the set
of objects to be monitored.

?


> +.PP
> +Calling
> +.BR poll (2)
> +or
> +.BR ppoll (2)

Where does the file descriptor given to poll() come from.
Tell the reader!

Now, I'm sure that you can use select() and epoll here has well. I'd rewrite this
as a more general statement: 

    the file descriptor inidcates as readable when given
    top select(2), poll(2), and epoll(7).

> +will block until either a file event occurs or it is interrupted by a signal
> +(see
> +.nh

Please drop *all* .nh/.hy pairs in all three pages.

> +.BR signal (7)).
> +.hy
> +If events are able to be read this will be advertised in the returned events
> +mask as
> +.B POLLIN

Drop this piece:
[[
> +and if compiled with
> +.B _XOPEN_SOURCE
> +as
> +.B POLLRDNORM. 
]]

> +.PP
> +Calling
> +.BR read (2)
> +for the file descriptor returned by
> +.BR fanotify_init (2)
> +will block (if flag
> +.nh
> +.B FAN_NONBLOCK
> +.hy
> +is not set in the call to
> +.nh
> +.BR fanotify_init (2))
> +.hy
> +until either a file event occurs or it is interrupted by a signal
> +(see
> +.nh
> +.BR signal (7)).
> +.BR read (2)
> +.hy
> +will return the length of the filled buffer or -1 in case of an error.
> +
> +Each successful call to
> +.BR read (2)
> +returns a buffer containing one or more of the following structures:
> +
> +.in +4n
> +.nf
> +struct fanotify_event_metadata {
> +    __u32 event_len;
> +    __u8 vers;
> +    __u8 reserved;
> +    __u16 metadata_len;
> +    __aligned_u64 mask;
> +    __s32 fd; 
> +    __s32 pid;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I event_len
> +is the length of the data for this event and the offset to the next event
> +in the buffer. This length might be longer than the size of structure
> +.nh
> +.I fanotify_event_metadata.
> +.hy
> +Therefore it is recommended to use a larger buffer size when reading,
> +e.g. 4096 bytes.
> +.TP
> +.I vers
> +holds the version of the
> +.B fanotify
> +API. The value should be checked against
> +.nh
> +.B FANOTIFY_METADATA_VERSION.
> +.hy
> +.TP
> +.I reserved
> +is not used.
> +.TP
> +.I metadata_len
> +is the length of the structure. The field was introduced to facilitate the
> +implementation of optional headers per event type.
> +.TP
> +.I mask
> +is a bitmask describing the event.
> +.TP
> +.I fd
> +is an open file descriptor for the object being accessed or
> +.B FAN_NOFD
> +if a queue overflow occurred. The reading application is responsible for
> +closing this file descriptor.
> +.TP
> +.I pid
> +is the ID of the process that caused the event.
> +.PP
> +The bitmask in
> +.I mask
> +is composed of the following values:
> +.TP
> +.B FAN_ACCESS
> +file was accessed.
> +.TP
> +.B FAN_OPEN
> +file was opened.
> +.TP
> +.B FAN_MODIFY
> +file was modified.
> +.TP
> +.B FAN_CLOSE_WRITE
> +writable file closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +unwritable file closed.
> +.TP
> +.B FAN_Q_OVERFLOW
> +event queue overflowed.
> +.TP
> +.B FAN_ACCESS_PERM
> +file accessed in perm check.
> +.TP
> +.B FAN_OPEN_PERM
> +file open in perm check.
> +.TP
> +.B FAN_ONDIR
> +event occurred against directory.
> +.TP
> +.B FAN_EVENT_ON_CHILD
> +event for a child of a directory occurred.
> +.PP
> +To check for any close event the following bitmask may be used
> +.TP
> +.B FAN_CLOSE
> +a file was closed 
> +.nh
> +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.hy
> +.PP
> +The following macros are provided to iterate over a buffer of
> +.B fanotify
> +event metadata:
> +.TP
> +.B FAN_EVENT_OK(meta, len)
> +checks the remaining length
> +.I len
> +of the buffer
> +.I meta
> +against the length of the metadata structure and the
> +.I event_len
> +field of the first metadata structure in the buffer.
> +.TP
> +.B FAN_EVENT_NEXT(meta, len)
> +lets the pointer
> +.I meta
> +point to the next metadata structure using the length indicated in the
> +.I event_len
> +field of the metadata structure and reduces the remaining length of the
> +buffer
> +.I len.
> +.PP
> +For permission events the application must
> +.BR write (2)
> +to the
> +.B fanotify
> +file descriptor a structure
> +
> +.in +4n
> +.nf
> +struct fanotify_response {
> +        __s32 fd;
> +        __u32 response;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I fd
> +is the file descriptor from structure
> +.I fanotify_event_metadata.
> +.TP
> +.I response
> +must be either
> +.br
> +.B FAN_ALLOW
> +to allow the file operation or
> +.br
> +.B FAN_DENY
> +to deny the file operation.
> +.PP
> +To end listening it is sufficient to
> +.BR close (2)
> +the
> +.B fanotify
> +file descriptor. The open permission events will be set to allowed, and all
> +resources will be returned to the kernel.
> +.PP
> +File /proc/<pid>/fdinfo/<fd> contains information about fanotify marks for
> +file descriptor fd of process pid. See
> +.nh
> +.I Documentation/filesystems/proc.txt
> +.hy
> +for details.
> +.SH ERRORS
> +The following errors may occur when reading from the
> +.B fanotify
> +file descriptor:
> +.TP
> +.B EAGAIN
> +a nonblocking call did not return any data.
> +.TP
> +.B EFAULT
> +the read buffer is outside your accessible address space.
> +.TP
> +.B EINTR
> +a signal has occurred.
> +.TP
> +.B EINVAL
> +the buffer is too short to hold the event.
> +.PP
> +The following errors may occur when writing to the
> +.B fanotify
> +file descriptor:
> +.TP
> +.B EFAULT
> +the write buffer is outside your accessible address space.
> +.TP
> +.B EINVAL
> +.B fanotify
> +access permissions are not enabled or the value of
> +.I response
> +in the response structure is not valid.
> +.TP
> +.B ENOENT
> +the file descriptor
> +.I fd
> +in the response structure is not valid. This might occur because the file was
> +already deleted by another thread or process.
> +.SH VERSIONS
> +The
> +.B fanotify
> +API was introduced in version 2.6.36 of the Linux kernel and enabled in
> +version 2.6.37. Fdinfo support was added in version 3.8.
> +.SH "CONFORMING TO"
> +The
> +.B fanotify
> +API is Linux-specific.
> +.SH NOTES
> +The notification is based on the kernel filesystem notification system
> +.B fsnotify.
> +.PP
> +To enable the
> +.B fanotify
> +API the following setting in the Kernel configuration is needed:
> +CONFIG_FANOTIFY=y. For permission handling
> +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
> +.SH EXAMPLE
> +The following program demonstrates the usage of the
> +.B fanotify
> +API. It creates a thread waiting for FAN_PERM_OPEN and FAN_CLOSE_WRITE events

Format all constants with

.B

> +for mount /home. If a permission event arises a FAN_ALLOW response is given.
> +When a line feed is entered a signal is sent to stop the listening thread.

Please ad a sample run or two in the page, and explain the example output.

> +.PP
> +The example does not cover handling signals arising while not waiting for a new
> +event.

Some general remarkks about the program.
* Add more vertical white space to break up the logical steps would be good.
* Add some (good) comments explaining what is happening at signicant points.
  
> +.PP

Add
.SS Program source
here.

> +.nf
> +#include <linux/fcntl.h>
> +#include <linux/limits.h>
> +#include <pthread.h>
> +#include <signal.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/fanotify.h>
> +#include <unistd.h>
> +
> +static void *run(void *data) {

The norm for man-pages is

static void *
run (void *data)
{

(Please fix main() also)

> +    char buf[4096];
> +    int fd;
> +    const struct fanotify_event_metadata *metadata;
> +    int len;
> +    char path[PATH_MAX];
> +    int path_len;
> +    struct fanotify_response response;

Blank line here.

> +    if (-1 == (fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT,
> +            O_RDONLY | O_LARGEFILE))) {


Needlessly hard to read. Please write this as:

    fd = fanotify_init()
    if (fd == \-1) {
        ...


Also, all '-' characters in code should be escaped (\-)

> +        perror("Cannot init");

perror("fanotify_init");

and similar elsewhere below.

> +        return NULL;
> +    }
> +    if (-1 == (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
> +            FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD, "/home"))) {

Please write

    if (fanotify_mark() == \-1)

> +        perror("Cannot mark");
> +        close(fd);
> +        return NULL;
> +    }

> +    while (-1 != (len = read(fd, (void *) &buf, sizeof (buf)))) {

See above.

> +        metadata = (struct fanotify_event_metadata *) buf;

Comment explaining while look

> +        while (FAN_EVENT_OK(metadata, len)) {
> +            if (metadata->fd != FAN_NOFD) {
> +                if (metadata->fd >= 0) {
> +                    if (metadata->mask & FAN_OPEN_PERM) {
> +                        printf("FAN_OPEN_PERM: ");
> +                        response.fd = metadata->fd;
> +                        response.response = FAN_ALLOW;
> +                        write(fd, &response, sizeof (
> +                                struct fanotify_response));
> +                    }

> +                    if (metadata->mask & FAN_CLOSE_WRITE) {
> +                        printf("FAN_CLOSE_WRITE: ");
> +                    }

> +                    sprintf(path, "/proc/self/fd/%d", metadata->fd);
> +                    path_len = readlink(path, path, sizeof (path) - 1);
> +                    if (path_len > 0) {
> +
> +                        path[path_len] = 0x00;

"0x00" is idiosyncratic. Please write '\0'.

> +                        printf("File %s", path);
> +                    }
> +                    close(metadata->fd);
> +                }
> +                printf("\\n");
> +            }
> +            metadata = FAN_EVENT_NEXT(metadata, len);
> +        }
> +    }
> +    close(fd);
> +    return NULL;
> +}
> +
> +int main(int argc, char *argv[]) {
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
See formatting comment above.

> +    pthread_attr_t attr;
> +    pthread_t thread;
> +    void *result;

Blank line

> +    if (pthread_attr_init(&attr)) {
> +        return EXIT_FAILURE;
> +    }

Please add error diagnostics to all of these calls. And, the norm in 
man-pages is exit().

e = pthread_create();
if (e != 0) {
    errno = e;
    perror("pthread_create");
    exit(EXIT_FAILURE);
}

Or add this macro (or similar) to simplify the diagnotic:

#define errExitEN(en, msg) \
    			do { errno = en; perror(msg); \
    			     exit(EXIT_FAILURE); } while (0)

> +    if (pthread_create(&thread, &attr, run, NULL)) {
> +        return EXIT_FAILURE;
> +    }

See above comment on diagnostics.

> +    printf("Press any key to terminate\\n");
> +    getchar();
> +    if (0 != pthread_kill(thread, SIGUSR1)) {
> +        return EXIT_FAILURE;
> +    }

See above comment on diagnostics.

> +    pthread_join(thread, &result);

See above comment on diagnostics.

> +    return EXIT_SUCCESS;

exit()

> +}
> +.fi
> +.SH "SEE ALSO"
> +.ad l
> +.nh
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR inotify (7)

The idea of an fanotify(7) page is a good one. And, modulo a 
lack of comments and lack of a demo, thanks for including an
example program. But, having got to the end of the page, 
I still don't feel like I have a good overview of fanotify.

Somewhere near the top of the page, there should be an explanation
of the steps in overview. Something like:

1. Create an fanotify instance
2. Add marks
3. Execute a read loop to handle events.
   a) Loop through the events
      (each read() may return multiple events)
      *) Deal with each event
         (Explain write() here.)
         (Explain that (all) events may open file descriptors.)
4. Close the file descriptors.

See what I mean?

I'll have a lot more comments, but would you be willing to fix up these
points Heinrich, and then I can take another pass.

Cheers,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/1] Man pages for the fanotify API
       [not found]     ` <53233160.9000106-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-03-16 15:32       ` xypron.glpk-Mmb7MZpHnFY
       [not found]         ` <1394983959-5392-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: xypron.glpk-Mmb7MZpHnFY @ 2014-03-16 15:32 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	stephan.mueller-fwYZOkdEjagAvxtiuMwx3w,
	james.hunt-GeWIH/nMZzLQT0dZR+AlfA, Heinrich Schuchardt

From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>

Michael,

thank you for all your comments. I reflected these in the appended
revised patch.

I studied the proposal by Stephan Mueller dated 2011 but the proposed pages are
not a superset of his proposal due to some changes in the API
(e.g. FAN_READONLY_FALLBACK).

Include linux/fcntl.h is needed for O_LARGEFILE.

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 |  199 ++++++++++++++++++++
 man2/fanotify_mark.2 |  216 ++++++++++++++++++++++
 man7/fanotify.7      |  497 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 912 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..2847f09
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,199 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-03-14 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <linux/fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+.BR fanotify_init()
+initializes a new fanotify group and returns a file descriptor for the event
+queue.
+.PP
+The file decriptor is used in calls to
+.BR fanotify_mark (2)
+to define for which files, directories, or mounts fanotify events shall be
+created.
+These events are received by reading from the file descriptor.
+Some events only inform that a file has been accessed.
+Other events allow to decide if another application may access a file.
+Decisions upon the permission to access files are made by writing to the file
+descriptor.
+An overview is provided in
+.BR fanotify (7).
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+By indicating in
+.I flags
+which kind of operations will be executed a logical sequence can be defined
+in which events are forwarded to the listeners. The following bitmasks define
+the kind of usage.
+Only one of them may be used when calling
+.B fanotify_init()
+.TP
+.B FAN_CLASS_PRE_CONTENT
+sets a priority level which allows to receive events notifying that a file has
+been accessed and events for permission decisions before the file is accessed.
+This priority level is intended for event listeners that need to access files
+before they contain their final data.
+It is useful for hierarchical storage managers.
+.TP
+.B FAN_CLASS_CONTENT
+sets a priority level which allows to receive events notifying that a file has
+been accessed and events for permission decisions before the file is accessed.
+This priority level is intended for event listeners that need to access files
+when they already contain their final content.
+This may be used by malware detection programs.
+.TP
+.B FAN_CLASS_NOTIF
+sets a priority level which allows only to receive events notifying that a file
+has been accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners will receive events in this order of priority levels.
+The call sequence among listeners of the same priority level is undefined.
+.PP
+Calling
+.BR fanotify_init()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Hence additional local capability checks have been implemented as indicated
+below.
+.PP
+.IR flags
+defines the behavior of the file descriptor.
+It is a bitmask composed of the following values:
+.TP
+.B FAN_CLOEXEC
+sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+enables the non-blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead if no data is available in a call to
+.BR read (2)
+an error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_CLASS_PRE_CONTENT
+see above.
+.TP
+.B FAN_CLASS_CONTENT
+see above.
+.TP
+.B FAN_CLASS_NOTIF
+see above.
+.TP
+.B FAN_UNLIMITED_QUEUE
+removes the limit of 16384 events on the size of the event queue.
+This flag requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+removes the limiti of 8192 marks on the number of marks.
+This flag requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+.IR event_f_flags
+defines the file flags, with which file descriptors for fanotify events shall
+be created.
+For explanations of possible values see parameter
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are
+.TP
+.B O_RDONLY
+read only access.
+.TP
+.B O_WRONLY
+write only access.
+.TP
+.B O_RDWR
+read and write access.
+.TP
+.B O_CLOEXEC
+enable close-on-exec.
+.TP
+.B O_LARGEFILE
+support files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by a fanotify group.
+.SH RETURN VALUE
+If the system
+.BR fanotify_init ()
+is successful a new file descriptor is returned.
+In case of an error \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+indicates the number of listeners exceeds 128.
+.TP
+.B ENOMEM
+Out of memory, the allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+Operation not permitted because capability
+.B CAP_SYS_ADMIN
+is missing.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..9439d18
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,216 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-03-14 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify a fanotify mark on a filesystem
+object.
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark (int " fanotify_fd ", unsigned int " flags ,
+.BI "                   uint64_t " mask ", int " dfd ,
+.BI "                   const char *" pathname );
+.fi
+.SH DESCRIPTION
+.BR fanotify_mark (2)
+adds, removes, or modifies a fanotify mark on a filesystem.
+.PP
+.I fd
+is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bitmask describing the modification to perform.
+It is composed of the following values:
+.TP
+.B FAN_MARK_ADD
+Add the events in
+.IR mask .
+.I mask
+must be nonempty or an error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+Remove the events in
+.IR mask .
+.I mask
+must be nonempty or an error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_DONT_FOLLOW
+Do not follow symbolic links.
+.TP
+.B FAN_MARK_ONLYDIR
+Fail if the path to be marked is not a directory.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount to be marked.
+.TP
+.B FAN_MARK_IGNORED_MASK
+Add to or remove from the ignored event mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignored mask shall survive modify events.
+If this flag is not set the ignored mask is cleared if a modify event occurs
+for the fanotify group.
+.TP
+.B FAN_MARK_FLUSH
+Remove all events from the whole group.
+.PP
+Only one of
+.BR FAN_MARK_ADD , FAN_MARK_REMOVE ,
+or
+.B FAN_MARK_FLUSH
+can be used. Failure to do so results in an error
+.BR EINVAL .
+.PP
+.I mask
+defines which events shall be listened to.
+It is a bitmask composed of the following values:
+.TP
+.B FAN_ACCESS
+A file was accessed (read).
+.TP
+.B FAN_MODIFY
+A file was modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+An readonly file was closed.
+.TP
+.B FAN_OPEN
+A file was opened.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue overflowed.
+.TP
+.B FAN_OPEN_PERM
+A file open permission was requested.
+.TP
+.B FAN_ACCESS_PERM
+An access permission for a file was requested.
+.TP
+.B FAN_ONDIR
+The event occurred against a directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+An event for a child of a monitored directory occurred.
+.PP
+The following composed value is defined
+.TP
+.B FAN_CLOSE
+A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+.I dfd
+is a file descriptor.
+.IP - 2
+If 
+.I pathname
+is NULL
+.I dfd
+defines the path to be marked.
+.IP - 2
+If
+.I pathname
+is NULL and dfd takes the special value
+.B AT_FDCWD
+defined in <fcntl.h> the current working directory is to be marked.
+.IP - 2
+If
+.I pathname
+is absolute it defines the path to be marked.
+.IP - 2
+If
+.I pathname
+is relative it defines a path relative to the path indicated by the file
+descriptor in
+.I dfd
+to be marked.
+.IP - 2
+If
+.I pathname
+is relative and
+.I dfd
+takes the special value
+.B AT_FDCWD
+it defines a path relative to the current working directory to be marked.
+.PP
+.I pathname
+is an absolute or relative path to be marked.
+.SH RETURN VALUE
+If
+.BR fanotify_mark ()
+is successful 0 is returned.
+In case of an error \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags ,
+or
+.IR mask ,
+or
+.I fd
+was not a fanotify file descriptor.
+.TP
+.B ENOENT
+The directory indicated by
+.IR pathname
+is not valid.
+This error also occurs when trying to remove a mark from a directory or mount
+which is not marked.
+.TP
+.B ENOMEM
+Out of memory.
+.TP
+.B ENOSPC
+Too many marks.
+.TP
+.B ENOTDIR
+.I flags
+contains
+.B FAN_MARK_ONLYDIR
+and
+.I dfd
+does not point to a directory.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..1174488
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,497 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-03-14 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases are virus scanning and hierarchical storage management.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes a fanotify notification group and returns a file
+descriptor referring to it.
+A fanotify notification group is an internal object of the kernel which holds a
+list of files, directories and mounts for which events shall be created when a
+file is accessed, and a list of files for which a decision is pending whether
+access shall be granted.
+.PP
+When all file descriptors referring to the group are closed, the group is
+released and the resources are freed for reuse by the kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, a directory, or a mount from the group and specifies which events
+shall be reported, or removes or modifies such an entry.
+.PP
+The fanotify file descriptor signals when data becomes available when passed to
+either of
+.BR epoll (7),
+.BR poll (2),
+.BR select (2).
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if flag
+.B FAN_NONBLOCK
+is not set in the call to
+.BR fanotify_init (2))
+until either a file event occurs or it is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or -1 in case of an error.
+In case of success the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.I fanotify_event_metadata.
+Therefore it is recommended to use a larger buffer size when reading,
+e.g. 4096 bytes.
+.TP
+.I vers
+holds the version of the
+.B fanotify
+API. The value should be checked against
+.B FANOTIFY_METADATA_VERSION.
+.TP
+.I reserved
+is not used.
+.TP
+.I metadata_len
+is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+.TP
+.I mask
+is a bitmask describing the event.
+.TP
+.I fd
+is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The reading application is responsible for closing this file descriptor.
+.TP
+.I pid
+is the ID of the process that caused the event.
+A program listening to fanotify events can compare this pid to the pid returned
+by
+.BR getpid (2)
+to detect if the event is caused internally or is due to a file access by another
+program.
+.PP
+The bitmask in
+.I mask
+is composed of the following values:
+.TP
+.B FAN_ACCESS
+file was accessed.
+.TP
+.B FAN_OPEN
+file was opened.
+.TP
+.B FAN_MODIFY
+file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+writable file closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+unwritable file closed.
+.TP
+.B FAN_Q_OVERFLOW
+event queue overflowed.
+.TP
+.B FAN_ACCESS_PERM
+file accessed in perm check.
+.TP
+.B FAN_OPEN_PERM
+file open in perm check.
+.TP
+.B FAN_ONDIR
+event occurred against directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+event for a child of a directory occurred.
+.PP
+To check for any close event the following bitmask may be used
+.TP
+.B FAN_CLOSE
+a file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer of
+.B fanotify
+event metadata:
+.TP
+.B FAN_EVENT_OK(meta, len)
+checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+lets the pointer
+.I meta
+point to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.I len.
+.PP
+For permission events the application must
+.BR write (2)
+to the
+.B fanotify
+file descriptor a structure
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+is the file descriptor from structure
+.I fanotify_event_metadata.
+.TP
+.I response
+must be either
+.br
+.B FAN_ALLOW
+to allow the file operation or
+.br
+.B FAN_DENY
+to deny the file operation.
+.PP
+To end listening it is sufficient to
+.BR close (2)
+the
+.B fanotify
+file descriptor.
+The open permission events will be set to allowed, and all resources will be
+returned to the kernel.
+.PP
+File /proc/<pid>/fdinfo/<fd> contains information about fanotify marks for
+file descriptor fd of process pid. See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+The following errors may occur when reading from the
+.B fanotify
+file descriptor:
+.TP
+.B EAGAIN
+a nonblocking call did not return any data.
+.TP
+.B EFAULT
+the read buffer is outside your accessible address space.
+.TP
+.B EINTR
+a signal has occurred.
+.TP
+.B EINVAL
+the buffer is too short to hold the event.
+.PP
+The following errors may occur when writing to the
+.B fanotify
+file descriptor:
+.TP
+.B EFAULT
+the write buffer is outside your accessible address space.
+.TP
+.B EINVAL
+fanotify access permissions are not enabled or the value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+the file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The
+.B fanotify
+API was introduced in version 2.6.36 of the Linux kernel and enabled in
+version 2.6.37. Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The
+.B fanotify
+API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+To enable the
+.B fanotify
+API the following setting in the Kernel configuration is needed:
+CONFIG_FANOTIFY=y. For permission handling
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API. It creates a thread waiting for
+.B FAN_PERM_OPEN
+and
+.B FAN_CLOSE_WRITE
+events
+for mount /home.
+If a permission event arises a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file /home/user/temp/notes.
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occured.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occured.
+The example program ended when hitting the enter key.
+.SS Example output
+.nf
+Press enter key to terminate.
+Listening for events.
+FAN_OPEN_PERM: File /home/zfsdt/temp/notes
+FAN_CLOSE_WRITE: File /home/zfsdt/temp/notes
+
+Listening for events stopped.
+.fi
+.SS Program source
+.nf
+#include <linux/fcntl.h>
+#include <linux/limits.h>
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+#define RUNNING 1
+#define STOPPING 2
+
+static int status;
+
+// Handle available events.
+static void
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    int len;
+    char path[PATH_MAX];
+    int path_len;
+    struct fanotify_response response;
+
+    // Loop while events can be read from fanotify file descriptor.
+    for(;;) {
+
+        // Read next events.
+        len = read(fd, (void *) &buf, sizeof (buf));
+        if (len > 0) {
+
+            // Point to the first event in the buffer.
+            metadata = (struct fanotify_event_metadata *) buf;
+
+            // Loop over all events in the buffer.
+            while (FAN_EVENT_OK(metadata, len)) {
+
+                // Check event contains a file descriptor.
+                if (metadata\->fd >= 0) {
+
+                    // Handle open permission event.
+                    if (metadata\->mask & FAN_OPEN_PERM) {
+                        printf("FAN_OPEN_PERM: ");
+                        // Allow file to be opened.
+                        response.fd = metadata\->fd;
+                        response.response = FAN_ALLOW;
+                        write(fd, &response, sizeof (
+                                  struct fanotify_response));
+                    }
+
+                    // Handle closing of writable file event.
+                    if (metadata\->mask & FAN_CLOSE_WRITE) {
+                        printf("FAN_CLOSE_WRITE: ");
+                    }
+
+                    // Determine path of the file accessed.
+                    sprintf(path, "/proc/self/fd/%d", metadata\->fd);
+                    path_len = readlink(path, path, sizeof (path) \- 1);
+
+                    // Write path.
+                    if (path_len > 0) {
+                        path[path_len] = '\\0';
+                        printf("File %s", path);
+                    }
+
+                    // Close the file descriptor of the event.
+                    close(metadata\->fd);
+                    printf("\\n");
+                }
+
+                // Forward pointer to next event.
+                metadata = FAN_EVENT_NEXT(metadata, len);
+            }
+        } else {
+
+            // No more events are available.
+            break;
+        }
+    }
+}
+
+// Worker thread.
+static void *
+run(void *data)
+{
+    int fd;
+    nfds_t nfds;
+    struct pollfd fds;
+
+    // Create the file descriptor for accessing the fanotify API.
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return NULL;
+    }
+
+    // Mark the home mount for
+    // \- permission events before opening files
+    // \- notification events after closing a write enabled file descriptor.
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,
+                      "/home") == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return NULL;
+    }
+
+    // Prepare for polling.
+    nfds = 1;
+    fds.fd = fd;
+    fds.events = POLLIN;
+    fds.revents = 0;
+    status = RUNNING;
+
+    // This is the loop to wait for  incoming events.
+    printf("Listening for events.\\n");
+    while (status == RUNNING) {
+        int ret;
+
+        // Poll for 1 s.
+        ret = poll(&fds, nfds, 1000);
+        if (ret > 0) {
+            if (fds.revents & POLLIN) {
+                // Events are available.
+                handle_events(fd);
+            }
+            fds.revents = 0;
+        }
+        if (ret == \-1 && errno != EINTR) {
+            perror("poll");
+            break;
+        }
+    }
+
+    // Close fanotify file descriptor.
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+    pthread_attr_t attr;
+    pthread_t thread;
+    void *result;
+
+    printf("Press enter key to terminate.\\n");
+
+    // Create a worker thread for monitoring file events.
+    if (pthread_attr_init(&attr)) {
+        return EXIT_FAILURE;
+    }
+    if (pthread_create(&thread, &attr, run, NULL)) {
+        return EXIT_FAILURE;
+    }
+
+    // Wait for user input.
+    getchar();
+
+    // Terminate worker thread.
+    status = STOPPING;
+    pthread_join(thread, &result);
+    return EXIT_SUCCESS;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/1] Man pages for the fanotify API
       [not found]         ` <1394983959-5392-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-03-17 15:45           ` Michael Kerrisk (man-pages)
       [not found]             ` <53271880.4090100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-03-17 15:45 UTC (permalink / raw)
  To: xypron.glpk-Mmb7MZpHnFY
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	stephan.mueller-fwYZOkdEjagAvxtiuMwx3w,
	james.hunt-GeWIH/nMZzLQT0dZR+AlfA

Hello Heinrich,

On 03/16/2014 04:32 PM, xypron.glpk-Mmb7MZpHnFY@public.gmane.org wrote:
> From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> 
> Michael,
> 
> thank you for all your comments. I reflected these in the appended
> revised patch.

Thanks. It's getting a lot better. More comments below.

> I studied the proposal by Stephan Mueller dated 2011 but the proposed pages are
> not a superset of his proposal due to some changes in the API
> (e.g. FAN_READONLY_FALLBACK).
> 
> Include linux/fcntl.h is needed for O_LARGEFILE.

See my comments on this below.

I'll swap the order of your text a little, since it's most sensible to 
comment on fanotify(7) first.

> diff --git a/man7/fanotify.7 b/man7/fanotify.7
> new file mode 100644
> index 0000000..1174488
> --- /dev/null
> +++ b/man7/fanotify.7
> @@ -0,0 +1,497 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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

Some observations:
* The ignore mask isn't described on this page at all. Shouldn't it
  be described here?

> +.TH FANOTIFY 7 2014-03-14 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify \- monitoring filesystem events
> +.SH DESCRIPTION
> +The
> +.B fanotify
> +API provides notification and interception of filesystem events.
> +Use cases are virus scanning and hierarchical storage management.
> +
> +The following system calls are used with this API:
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR poll (2),
> +.BR ppoll (2),
> +.BR read (2),
> +.BR write (2),
> +and
> +.BR close (2).
> +.PP
> +.BR fanotify_init (2)
> +creates and initializes a fanotify notification group and returns a file
> +descriptor referring to it.
> +A fanotify notification group is an internal object of the kernel which holds a
> +list of files, directories and mounts for which events shall be created when a
> +file is accessed, and a list of files for which a decision is pending whether
> +access shall be granted.
> +.PP
> +When all file descriptors referring to the group are closed, the group is
> +released and the resources are freed for reuse by the kernel.
> +.PP
> +.BR fanotify_mark (2)
> +adds a file, a directory, or a mount from the group and specifies which events

s/from/to/

> +shall be reported, or removes or modifies such an entry.
> +.PP
> +The fanotify file descriptor signals when data becomes available when passed to
> +either of
> +.BR epoll (7),
> +.BR poll (2),
> +.BR select (2).

This needs to be more precise:

    When an fanotify event occurs, the fanotify file descriptor indicates 
    as readable when passed to select(2), poll(2), and epoll(7).

> +.PP
> +Calling
> +.BR read (2)
> +for the file descriptor returned by
> +.BR fanotify_init (2)
> +blocks (if flag
> +.B FAN_NONBLOCK
> +is not set in the call to
> +.BR fanotify_init (2))
> +until either a file event occurs or it is interrupted by a signal
> +(see
> +.BR signal (7)).
> +
> +The return value of
> +.BR read (2)
> +is the length of the filled buffer or -1 in case of an error.

s/-1/\-1/ in all instances please.

> +In case of success the read buffer contains one or more of the following
> +structures:
> +
> +.in +4n
> +.nf
> +struct fanotify_event_metadata {
> +    __u32 event_len;
> +    __u8 vers;
> +    __u8 reserved;
> +    __u16 metadata_len;
> +    __aligned_u64 mask;
> +    __s32 fd; 
> +    __s32 pid;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I event_len
> +is the length of the data for the current event and the offset to the next

In this entire list, please make the first sentence a complete sentence.

"This is the length..."

> +event in the buffer.
> +This length might be longer than the size of structure
> +.I fanotify_event_metadata.
> +Therefore it is recommended to use a larger buffer size when reading,
> +e.g. 4096 bytes.
> +.TP
> +.I vers
> +holds the version of the

"This field holds..."

> +.B fanotify
> +API. The value should be checked against
> +.B FANOTIFY_METADATA_VERSION.

Formatting: 
.BR FANOTIFY_METADATA_VERSION .

Please check for other similar instances

> +.TP
> +.I reserved
> +is not used.

"This field is not used."

> +.TP
> +.I metadata_len
> +is the length of the structure.
> +The field was introduced to facilitate the implementation of optional headers
> +per event type.

Are there any such optional headers so far? If not, then add a sentence to say so.
If there are, mention an example.

> +.TP
> +.I mask
> +is a bitmask describing the event.

Change all instances to "bit mask"

> +.TP
> +.I fd
> +is an open file descriptor for the object being accessed or
> +.B FAN_NOFD
> +if a queue overflow occurred.

What happens if the application hits its file descriptor limit?
This probably needs to be explained in this page. 

> +The reading application is responsible for closing this file descriptor.
> +.TP
> +.I pid
> +is the ID of the process that caused the event.
> +A program listening to fanotify events can compare this pid to the pid returned

s/pid/PID/g in the above line.

> +by
> +.BR getpid (2)
> +to detect if the event is caused internally 

"is caused internally" is unnecessarily obscure. I think you mean
"is caused by the calling process itself", right? Better to say that.

> or is due to a file access by another
> +program.
> +.PP
> +The bitmask in
> +.I mask
> +is composed of the following values:
> +.TP
> +.B FAN_ACCESS
> +file was accessed.

Again, make each entry in this list a complete sentence, please.

> +.TP
> +.B FAN_OPEN
> +file was opened.
> +.TP
> +.B FAN_MODIFY
> +file was modified.
> +.TP
> +.B FAN_CLOSE_WRITE
> +writable file closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +unwritable file closed.
> +.TP
> +.B FAN_Q_OVERFLOW
> +event queue overflowed.
> +.TP
> +.B FAN_ACCESS_PERM
> +file accessed in perm check.

"perm check" ==> please explain this normal language. At the 
very least, "permission check", but it probably would be good
to say a word or two about what you mean, or give an example.


> +.TP
> +.B FAN_OPEN_PERM
> +file open in perm check.
> +.TP
> +.B FAN_ONDIR
> +event occurred against directory.
> +.TP
> +.B FAN_EVENT_ON_CHILD
> +event for a child of a directory occurred.
> +.PP
> +To check for any close event the following bitmask may be used
> +.TP
> +.B FAN_CLOSE
> +a file was closed 
> +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The following macros are provided to iterate over a buffer of
> +.B fanotify
> +event metadata:

add the words: "returned by a read(2) from an fanotify file descriptor:"

> +.TP
> +.B FAN_EVENT_OK(meta, len)
> +checks the remaining length
> +.I len
> +of the buffer
> +.I meta
> +against the length of the metadata structure and the
> +.I event_len
> +field of the first metadata structure in the buffer.
> +.TP
> +.B FAN_EVENT_NEXT(meta, len)
> +lets the pointer
s/lets/sets/
> +.I meta
> +point to the next metadata structure using the length indicated in the
> +.I event_len
> +field of the metadata structure and reduces the remaining length of the
> +buffer
> +.I len.
> +.PP
> +For permission events the application must

Add comma after "events"

> +.BR write (2)
> +to the
> +.B fanotify
> +file descriptor a structure

==> must write(2) a structure of the following form to the fanotify
    file descriptor:

> +
> +.in +4n
> +.nf
> +struct fanotify_response {
> +        __s32 fd;
> +        __u32 response;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I fd
> +is the file descriptor from structure
> +.I fanotify_event_metadata.

Formatting!

.IR xxx .

> +.TP
> +.I response
> +must be either
> +.br
> +.B FAN_ALLOW
> +to allow the file operation or
> +.br

Remove both ".br" above.

> +.B FAN_DENY
> +to deny the file operation.
> +.PP
> +To end listening it is sufficient to

Add comma after "listening"

> +.BR close (2)
> +the
> +.B fanotify
> +file descriptor.
> +The open permission events will be set to allowed, and all resources will be
> +returned to the kernel.
> +.PP
> +File /proc/<pid>/fdinfo/<fd> contains information about fanotify marks for

s/File/The file/

And apply .I formatting to the /proc pathname here.

Note: sometimes you are formatting "fanotify" bold, and sometimes not.
There appears to be no consistent reason. Choose one or the other, and 
stick with it.

> +file descriptor fd of process pid. See
> +.I Documentation/filesystems/proc.txt
> +for details.
> +.SH ERRORS
> +The following errors may occur when reading from the
> +.B fanotify
> +file descriptor:
> +.TP
> +.B EAGAIN
> +a nonblocking call did not return any data.

Again, complete sentrence in this list please.

> +.TP
> +.B EFAULT
> +the read buffer is outside your accessible address space.
> +.TP
> +.B EINTR
> +a signal has occurred.

"The call was interrupted by a signal handler."

> +.TP
> +.B EINVAL
> +the buffer is too short to hold the event.
> +.PP
> +The following errors may occur when writing to the
> +.B fanotify
> +file descriptor:
> +.TP
> +.B EFAULT
> +the write buffer is outside your accessible address space.
> +.TP
> +.B EINVAL
> +fanotify access permissions are not enabled or the value of
> +.I response
> +in the response structure is not valid.
> +.TP
> +.B ENOENT
> +the file descriptor
> +.I fd
> +in the response structure is not valid.
> +This might occur because the file was already deleted by another thread or
> +process.
> +.SH VERSIONS
> +The
> +.B fanotify
> +API was introduced in version 2.6.36 of the Linux kernel and enabled in
> +version 2.6.37. Fdinfo support was added in version 3.8.
> +.SH "CONFORMING TO"
> +The
> +.B fanotify
> +API is Linux-specific.
> +.SH NOTES
> +The notification is based on the kernel filesystem notification system
> +.B fsnotify.
> +.PP
> +To enable the
> +.B fanotify
> +API the following setting in the Kernel configuration is needed:
> +CONFIG_FANOTIFY=y. For permission handling
> +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
> +.SH EXAMPLE
> +The following program demonstrates the usage of the
> +.B fanotify
> +API. It creates a thread waiting for
> +.B FAN_PERM_OPEN
> +and
> +.B FAN_CLOSE_WRITE
> +events
> +for mount /home.
> +If a permission event arises a

s/arises/occurs,/ 

(note comma)

> +.B FAN_ALLOW
> +response is given.
> +.PP
> +The following output was recorded while editing file /home/user/temp/notes.

Please format pathname as

.IR /home/user/temp/notes .

> +Before the file was opened a
> +.B FAN_OPEN_PERM
> +event occured.

occurred

> +After the file was closed a
> +.B FAN_CLOSE_WRITE
> +event occured.
> +The example program ended when hitting the enter key.
> +.SS Example output

Show the command used to start the program, even it is as simple as

    $ ./a.out

Indent the shell session with

    .in +4n
    .in

> +.nf
> +Press enter key to terminate.
> +Listening for events.
> +FAN_OPEN_PERM: File /home/zfsdt/temp/notes
> +FAN_CLOSE_WRITE: File /home/zfsdt/temp/notes
> +
> +Listening for events stopped.
> +.fi
> +.SS Program source

Question: why is this program mulithreaded? I think that just adds unneeded
complexity (don't make someone learn threads in order to learn fanotify...). 
If there's no good reason for multithreading, please simplify.(Use poll() to
monitor both STDIN_FILENO and the fanotify FD.)

Aslo, how about making the monitored pathname a command-line argument 
\to the program?

> +.nf
> +#include <linux/fcntl.h>
> +#include <linux/limits.h>

These includes are NOT correct.

#include <limits.h>
#include <fcntl.h>

Now, if you really need O_LARGEFIL, you could define _GNU_SOURCE at the
top of the program. However, I don't think it's needed at all.
The accepted way of doing this is CC -D_FILE_OFFSET_NBITS=64, in 
the cases where it is needed. So, drop O_LARGEFILE.

> +#include <errno.h>
> +#include <poll.h>
> +#include <pthread.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/fanotify.h>
> +#include <unistd.h>
> +
> +#define RUNNING 1
> +#define STOPPING 2
> +
> +static int status;
> +
> +// Handle available events.

The above very generic comment conveys little info.
Should it be something like

"Read all available fanotify events from the file descriptor 'fd'"

?

> +static void
> +handle_events(int fd)
> +{
> +    const struct fanotify_event_metadata *metadata;
> +    char buf[4096];
> +    int len;
> +    char path[PATH_MAX];
> +    int path_len;
> +    struct fanotify_response response;
> +
> +    // Loop while events can be read from fanotify file descriptor.

Sorry, could I ask you to reformat all comments as

    /* ... */

It's just that that is the norm in man pages.

Also, add a blank line after comments.

> +    for(;;) {
> +
> +        // Read next events.

"Read some events"

> +        len = read(fd, (void *) &buf, sizeof (buf));
> +        if (len > 0) {

Change the logic here.

    if (len <= 0)
        break

And then deindent all of the following code by one level.

By the way, what does it mean if read() returns 0?
Does that need to be documented in DESCRIPTION?

> +
> +            // Point to the first event in the buffer.
> +            metadata = (struct fanotify_event_metadata *) buf;
> +
> +            // Loop over all events in the buffer.
> +            while (FAN_EVENT_OK(metadata, len)) {
> +
> +                // Check event contains a file descriptor.

"Check that event contains a file descriptor"

> +                if (metadata\->fd >= 0) {
> +
> +                    // Handle open permission event.
> +                    if (metadata\->mask & FAN_OPEN_PERM) {
> +                        printf("FAN_OPEN_PERM: ");
> +                        // Allow file to be opened.
> +                        response.fd = metadata\->fd;
> +                        response.response = FAN_ALLOW;
> +                        write(fd, &response, sizeof (
> +                                  struct fanotify_response));
> +                    }
> +
> +                    // Handle closing of writable file event.
> +                    if (metadata\->mask & FAN_CLOSE_WRITE) {
> +                        printf("FAN_CLOSE_WRITE: ");
> +                    }
> +
> +                    // Determine path of the file accessed.
> +                    sprintf(path, "/proc/self/fd/%d", metadata\->fd);
> +                    path_len = readlink(path, path, sizeof (path) \- 1);
> +
> +                    // Write path.

Kill that last comment.

> +                    if (path_len > 0) {
> +                        path[path_len] = '\\0';
> +                        printf("File %s", path);
> +                    }
> +
> +                    // Close the file descriptor of the event.
> +                    close(metadata\->fd);
> +                    printf("\\n");
> +                }
> +
> +                // Forward pointer to next event.
> +                metadata = FAN_EVENT_NEXT(metadata, len);
> +            }
> +        } else {
> +
> +            // No more events are available.
> +            break;
> +        }
> +    }
> +}
> +
> +// Worker thread.
> +static void *
> +run(void *data)
> +{
> +    int fd;
> +    nfds_t nfds;
> +    struct pollfd fds;
> +
> +    // Create the file descriptor for accessing the fanotify API.
> +    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
> +                       O_RDONLY | O_LARGEFILE);
> +    if (fd == \-1) {
> +        perror("fanotify_init");
> +        return NULL;
> +    }
> +
> +    // Mark the home mount for
> +    // \- permission events before opening files
> +    // \- notification events after closing a write enabled file descriptor.
> +    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
> +                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,
> +                      "/home") == \-1) {
> +        perror("fanotify_mark");
> +        close(fd);
> +        return NULL;
> +    }
> +
> +    // Prepare for polling.
> +    nfds = 1;
> +    fds.fd = fd;
> +    fds.events = POLLIN;
> +    fds.revents = 0;
> +    status = RUNNING;
> +
> +    // This is the loop to wait for  incoming events.
> +    printf("Listening for events.\\n");
> +    while (status == RUNNING) {
> +        int ret;
> +
> +        // Poll for 1 s.
> +        ret = poll(&fds, nfds, 1000);
> +        if (ret > 0) {
> +            if (fds.revents & POLLIN) {
> +                // Events are available.
> +                handle_events(fd);
> +            }
> +            fds.revents = 0;
> +        }
> +        if (ret == \-1 && errno != EINTR) {
> +            perror("poll");
> +            break;
> +        }
> +    }
> +
> +    // Close fanotify file descriptor.
> +    close(fd);
> +    printf("Listening for events stopped.\\n");
> +    return NULL;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +    pthread_attr_t attr;
> +    pthread_t thread;
> +    void *result;
> +
> +    printf("Press enter key to terminate.\\n");
> +
> +    // Create a worker thread for monitoring file events.
> +    if (pthread_attr_init(&attr)) {
> +        return EXIT_FAILURE;
> +    }
> +    if (pthread_create(&thread, &attr, run, NULL)) {
> +        return EXIT_FAILURE;
> +    }
> +
> +    // Wait for user input.
> +    getchar();
> +
> +    // Terminate worker thread.
> +    status = STOPPING;
> +    pthread_join(thread, &result);
> +    return EXIT_SUCCESS;
> +}
> +.fi
> +.SH "SEE ALSO"
> +.ad l
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR inotify (7)

In your next patch, could you also add fanoty(7) to the SEE ALSO of inotify(7).
And, I don't know if you feel qualified to do so, but it might be good to 
have a (brief) section in fanotify(7) that compares and contrasts with 
inotify(7).

> 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> ---
>  man2/fanotify_init.2 |  199 ++++++++++++++++++++
>  man2/fanotify_mark.2 |  216 ++++++++++++++++++++++
>  man7/fanotify.7      |  497 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 912 insertions(+)
>  create mode 100644 man2/fanotify_init.2
>  create mode 100644 man2/fanotify_mark.2
>  create mode 100644 man7/fanotify.7
> 
> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
> new file mode 100644
> index 0000000..2847f09
> --- /dev/null
> +++ b/man2/fanotify_init.2
> @@ -0,0 +1,199 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_INIT 2 2014-03-14 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_init \- create and initialize fanotify group
> +.SH SYNOPSIS
> +.B #include <linux/fcntl.h>

This should be <fcntl.h>

> +.br
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
> +.SH DESCRIPTION

I think that at the start of both this page and fanotify_mark.2, it would be
good to write:

    For an overview of the fanotify API, see fanoify(7).

> +.BR fanotify_init()
> +initializes a new fanotify group and returns a file descriptor for the event
> +queue.
> +.PP
> +The file decriptor is used in calls to

descriptor

> +.BR fanotify_mark (2)
> +to define for which files, directories, or mounts fanotify events shall be
> +created.
> +These events are received by reading from the file descriptor.
> +Some events only inform that a file has been accessed.
> +Other events allow to decide if another application may access a file.

Better ==>

Other events can be used to control whether another application may access 
a file.

> +Decisions upon the permission to access files are made by writing to the file

Better would be something like:

Permission to access files is granted by writing to the...

> +descriptor.
> +An overview is provided in
> +.BR fanotify (7).
> +.PP
> +Multiple programs may be using the fanotify interface at the same time to
> +monitor the same files. 
> +By indicating in
> +.I flags
> +which kind of operations will be executed a logical sequence can be defined
> +in which events are forwarded to the listeners. The following bitmasks define
> +the kind of usage.
> +Only one of them may be used when calling
> +.B fanotify_init()
> +.TP
> +.B FAN_CLASS_PRE_CONTENT

Complete sentence at the start of each list item please.

> +sets a priority level which allows to receive events notifying that a file has

"allows to" is not quite correct English. Reword to something like:
"allows the receipt of events"

(And the same for other instances below.)

> +been accessed and events for permission decisions before the file is accessed.
> +This priority level is intended for event listeners that need to access files
> +before they contain their final data.
> +It is useful for hierarchical storage managers.
> +.TP
> +.B FAN_CLASS_CONTENT
> +sets a priority level which allows to receive events notifying that a file has
> +been accessed and events for permission decisions before the file is accessed.

s/before/after/?

> +This priority level is intended for event listeners that need to access files
> +when they already contain their final content.
> +This may be used by malware detection programs.
> +.TP
> +.B FAN_CLASS_NOTIF
> +sets a priority level which allows only to receive events notifying that a file
> +has been accessed.
> +Permission decisions before the file is accessed are not possible.
> +.PP
> +Listeners will receive events in this order of priority levels.

I have an idea what you might mean with that last sentence, but I'm
just guessing. Can you clarify?

> +The call sequence among listeners of the same priority level is undefined.
> +.PP
> +Calling
> +.BR fanotify_init()
> +requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +This constraint might be relaxed in future versions of the API.
> +Hence additional local capability checks have been implemented as indicated
> +below.
> +.PP
> +.IR flags

Complete sentence at the start of each list item please.

> +defines the behavior of the file descriptor.
> +It is a bitmask composed of the following values:
> +.TP
> +.B FAN_CLOEXEC
> +sets the close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +on the new file descriptor.
> +When calling
> +.BR execve (2)
> +the inherited file descriptor of the child process will be closed.
> +See the description of the
> +.B O_CLOEXEC
> +flag in
> +.BR open (2).
> +.TP
> +.B FAN_NONBLOCK
> +enables the non-blocking flag
> +.RB ( O_NONBLOCK )
> +for the file descriptor.
> +Reading from the file descriptor will not block.
> +Instead if no data is available in a call to
> +.BR read (2)
> +an error
> +.B EAGAIN
> +will occur.
> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +see above.
> +.TP
> +.B FAN_CLASS_CONTENT
> +see above.
> +.TP
> +.B FAN_CLASS_NOTIF
> +see above.
> +.TP
> +.B FAN_UNLIMITED_QUEUE
> +removes the limit of 16384 events on the size of the event queue.
> +This flag requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.TP
> +.B FAN_UNLIMITED_MARKS
> +removes the limiti of 8192 marks on the number of marks.

s/limiti/limit/

> +This flag requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.PP
> +.IR event_f_flags
> +defines the file flags, with which file descriptors for fanotify events shall
> +be created.
> +For explanations of possible values see parameter
> +.I flags
> +of the 
> +.BR open (2)
> +system call.
> +Useful values are
> +.TP
> +.B O_RDONLY
> +read only access.
> +.TP
> +.B O_WRONLY
> +write only access.
> +.TP
> +.B O_RDWR
> +read and write access.
> +.TP
> +.B O_CLOEXEC
> +enable close-on-exec.
> +.TP
> +.B O_LARGEFILE
> +support files exceeding 2 GB.
> +Failing to set this flag will result in an
> +.B EOVERFLOW
> +error when trying to open a large file which is monitored by a fanotify group.
> +.SH RETURN VALUE
> +If the system
> +.BR fanotify_init ()
> +is successful a new file descriptor is returned.

Better ==>
On success,
.BR fanotify_init ()
returns a new file descriptor.

> +In case of an error \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags .
> +.B FAN_ALL_INIT_FLAGS
> +defines all allowable bits.

That last sentence isn't needed.

> +.TP
> +.B EMFILE
> +indicates the number of listeners exceeds 128.

Complete sentence please. Was this limit discussed in the main text of
any of these three pages. It would be good to do so, and to clarify 
whethr or not it can be overridden.

> +.TP
> +.B ENOMEM
> +Out of memory, the allocation of memory for the notification group failed. 
> +.TP
> +.B EPERM
> +Operation not permitted because capability
> +.B CAP_SYS_ADMIN
> +is missing.
> +.SH VERSIONS
> +.BR fanotify_init ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_mark (2),
> +.BR fanotify (7)
> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
> new file mode 100644
> index 0000000..9439d18
> --- /dev/null
> +++ b/man2/fanotify_mark.2
> @@ -0,0 +1,216 @@
> +.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_MARK 2 2014-03-14 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_mark \- add, remove, or modify a fanotify mark on a filesystem
> +object.
> +.SH SYNOPSIS
> +.nf
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_mark (int " fanotify_fd ", unsigned int " flags ,
> +.BI "                   uint64_t " mask ", int " dfd ,

Please rename "fdf" to "dirfd" throughout the page,
since that is the norm for this argument in other pages.

> +.BI "                   const char *" pathname );
> +.fi
> +.SH DESCRIPTION
> +.BR fanotify_mark (2)
> +adds, removes, or modifies a fanotify mark on a filesystem.
> +.PP
> +.I fd
> +is the file descriptor returned by
> +.BR fanotify_init (2).
> +.PP
> +.I flags
> +is a bitmask describing the modification to perform.
> +It is composed of the following values:
> +.TP
> +.B FAN_MARK_ADD
> +Add the events in
> +.IR mask .
> +.I mask
> +must be nonempty or an error

s/an error/the error/
(and other instances below)

> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_REMOVE
> +Remove the events in
> +.IR mask .
> +.I mask
> +must be nonempty or an error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_DONT_FOLLOW
> +Do not follow symbolic links.
> +.TP
> +.B FAN_MARK_ONLYDIR
> +Fail if the path to be marked is not a directory.
> +.TP
> +.B FAN_MARK_MOUNT
> +The path indicates a mount to be marked.

Can you explain FAN_MARK_MOUNT a little more please.
Why do we need it?

> +.TP
> +.B FAN_MARK_IGNORED_MASK
> +Add to or remove from the ignored event mask.
> +.TP
> +.B FAN_MARK_IGNORED_SURV_MODIFY
> +The ignored mask shall survive modify events.
> +If this flag is not set the ignored mask is cleared if a modify event occurs
> +for the fanotify group.
> +.TP
> +.B FAN_MARK_FLUSH
> +Remove all events from the whole group.
> +.PP
> +Only one of
> +.BR FAN_MARK_ADD , FAN_MARK_REMOVE ,

Formatting above is broken

.BR FAN_MARK_ADD , 
.BR FAN_MARK_REMOVE ,

> +or
> +.B FAN_MARK_FLUSH
> +can be used. Failure to do so results in an error
> +.BR EINVAL .
> +.PP
> +.I mask
> +defines which events shall be listened to.
> +It is a bitmask composed of the following values:
> +.TP
> +.B FAN_ACCESS
> +A file was accessed (read).
> +.TP
> +.B FAN_MODIFY
> +A file was modified (write).
> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +An readonly file was closed.
> +.TP
> +.B FAN_OPEN
> +A file was opened.
> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue overflowed.
> +.TP
> +.B FAN_OPEN_PERM
> +A file open permission was requested.
> +.TP
> +.B FAN_ACCESS_PERM
> +An access permission for a file was requested.

I think it would be good to explain here hte difference between 
"open permission" and "access permission".

> +.TP
> +.B FAN_ONDIR
> +The event occurred against a directory.
> +.TP
> +.B FAN_EVENT_ON_CHILD
> +An event for a child of a monitored directory occurred.
> +.PP
> +The following composed value is defined
> +.TP
> +.B FAN_CLOSE
> +A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +.I dfd
> +is a file descriptor.

Change the preceding to

The pathname to be marked is determined by
the file descriptor
.I dirfd
and the pathname specified in
.IR pathname :

> +.IP - 2

Use
.IP * 3
here please, and for the rest
.IP * will suffice.

> +If 
> +.I pathname
> +is NULL

Each of you "If" sentences here needs a commad between the predicate 
and the governed clause.

    If pathname is NULL,


> +.I dfd
> +defines the path to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is NULL and dfd takes the special value

s/takes/has/

> +.B AT_FDCWD
> +defined in <fcntl.h> the current working directory is to be marked.

"defined in <fcntl.h>" is not needed.

> +.IP - 2
> +If
> +.I pathname
> +is absolute it defines the path to be marked.

Add "and dirfd is ignored"

> +.IP - 2
> +If
> +.I pathname
> +is relative it defines a path relative to the path indicated by the file
> +descriptor in
> +.I dfd
> +to be marked.
> +.IP - 2
> +If
> +.I pathname
> +is relative and
> +.I dfd
> +takes the special value
> +.B AT_FDCWD
> +it defines a path relative to the current working directory to be marked.
> +.PP
> +.I pathname
> +is an absolute or relative path to be marked.

This last sentence could now be removed.

> +.SH RETURN VALUE
> +If
> +.BR fanotify_mark ()
> +is successful 0 is returned.

successful,

> +In case of an error \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EBADF
> +An invalid file descriptor was passed in
> +.IR fanotify_fd .
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags ,

Remove the preceding comma.

> +or
> +.IR mask ,
> +or
> +.I fd
> +was not a fanotify file descriptor.
> +.TP
> +.B ENOENT
> +The directory indicated by
> +.IR pathname
> +is not valid.

"not valid" is vague. Please explain more clearly.

> +This error also occurs when trying to remove a mark from a directory or mount
> +which is not marked.
> +.TP
> +.B ENOMEM
> +Out of memory.
> +.TP
> +.B ENOSPC
> +Too many marks.
> +.TP
> +.B ENOTDIR
> +.I flags
> +contains
> +.B FAN_MARK_ONLYDIR
> +and
> +.I dfd
> +does not point to a directory.

I think above you must also mention "and pathname is NULL"

> +.SH VERSIONS
> +.BR fanotify_mark ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_init (2),
> +.BR fanotify (7)


Thanks,

Michael



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/1] Man pages for the fanotify API
       [not found]             ` <53271880.4090100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-03-22 16:42               ` xypron.glpk-Mmb7MZpHnFY
       [not found]                 ` <1395506528-10026-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: xypron.glpk-Mmb7MZpHnFY @ 2014-03-22 16:42 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	stephan.mueller-fwYZOkdEjagAvxtiuMwx3w,
	james.hunt-GeWIH/nMZzLQT0dZR+AlfA, Heinrich Schuchardt

From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>

Michael,

thank you for your further comments, which I used to update
the appended patch.

O_LARGEFILE is definitely needed on 32-bit Linux when working
with permission events for files exceeding 2GB.

gcc -D_FILE_OFFSET_BITS=64
is also needed but not sufficient.

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 |  208 ++++++++++++++++++++
 man2/fanotify_mark.2 |  239 +++++++++++++++++++++++
 man7/fanotify.7      |  519 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 966 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..888c20d
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,208 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-03-22 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_init()
+initializes a new fanotify group and returns a file descriptor for the event
+queue.
+.PP
+The file descriptor is used in calls to
+.BR fanotify_mark (2)
+to define for which files, directories, or mounts fanotify events shall be
+created.
+These events are received by reading from the file descriptor.
+Some events only inform that a file has been accessed.
+Other events can be used to control if another application may access a file.
+Decisions upon the permission is granted by writing to the file descriptor.
+An overview is provided in
+.BR fanotify (7).
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+Yet the number of fanotify groups per user is limited to 128.
+This value cannot be overridden.
+.PP
+By indicating in
+.I flags
+which kind of operations will be executed a logical sequence can be defined
+in which events are forwarded to the listeners. The following bitmasks define
+the kind of usage.
+Only one of them may be used when calling
+.BR fanotify_init ().
+.TP
+.B FAN_CLASS_PRE_CONTENT
+This priority level allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files before they
+contain their final data.
+This may be used hierarchical storage managers.
+.TP
+.B FAN_CLASS_CONTENT
+This priority level allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files when they already
+contain their final content.
+This may be used by malware detection programs.
+.TP
+.B FAN_CLASS_NOTIF
+This sets a priority level which only allows the receipt of events notifying
+that a file has been accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners with different priority levels will receive events in the sequence
+.BR FAN_CLASS_PRE_CONTENT ,
+.BR FAN_CLASS_CONTENT ,
+.BR FAN_CLASS_NOTIF .
+The call sequence among listeners of the same priority level is undefined.
+.PP
+Calling
+.BR fanotify_init()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Hence additional local capability checks have been implemented as indicated
+below.
+.PP
+.IR flags
+defines the behavior of the file descriptor.
+It is a bitmask composed of the following values:
+.TP
+.B FAN_CLOEXEC
+This flag sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+This flag enables the non-blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead if no data is available in a call to
+.BR read (2)
+an error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_CLASS_PRE_CONTENT
+See above.
+.TP
+.B FAN_CLASS_CONTENT
+See above.
+.TP
+.B FAN_CLASS_NOTIF
+See above.
+.TP
+.B FAN_UNLIMITED_QUEUE
+This flag removes the limit of 16384 events on the size of the event queue.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+This flag removes the limit of 8192 marks on the number of marks.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+.IR event_f_flags
+This parameter defines the file flags, with which file descriptors for fanotify
+events shall be created.
+For explanations of possible values see parameter
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are
+.TP
+.B O_RDONLY
+This value allows only read access.
+.TP
+.B O_WRONLY
+This value allows only write access.
+.TP
+.B O_RDWR
+This value allows read and write access.
+.TP
+.B O_CLOEXEC
+This flag enables close-on-exec.
+.TP
+.B O_LARGEFILE
+This flag enables support files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by a fanotify group
+on a 32-bit system.
+.SH RETURN VALUE
+On success
+.BR fanotify_init ()
+returns a new file descriptor.
+In case of an error \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+The number of fanotify groups of the user exceeds 128.
+.TP
+.B ENOMEM
+The allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+The operation is not permitted because capability
+.B CAP_SYS_ADMIN
+is missing.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..b4617c8
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,239 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-03-22 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify a fanotify mark on a filesystem
+object.
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark (int " fanotify_fd ", unsigned int " flags ,
+.BI "                   uint64_t " mask ", int " dirfd ,
+.BI "                   const char *" pathname );
+.fi
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_mark (2)
+adds, removes, or modifies a fanotify mark on a filesystem.
+.PP
+.I fanotify_fd
+is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bitmask describing the modification to perform.
+It is composed of the following values:
+.TP
+.B FAN_MARK_ADD
+The events in parameter
+.I mask
+will be added to the marke mask (or to the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+The events in paramter
+.I mask
+will be removed from the mark mask (or from the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_DONT_FOLLOW
+Symbolic links shall not be followed.
+.TP
+.B FAN_MARK_ONLYDIR
+If the path to be marked is not a directory the error
+.B ENOTDIR
+shall be raised.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount point to be marked.
+If the path is not itself a mount point the mount point containing the path
+will be marked.
+All directories, subdirectories, and the contained files of the mount point
+will be monitored.
+.TP
+.B FAN_MARK_IGNORED_MASK
+The events in parameter
+.I mask
+shall be added to or removed from the ignore mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignore mask shall survive modify events.
+If this flag is not set, the ignore mask is cleared, if a modify event occurs
+for the fanotify group.
+.TP
+.B FAN_MARK_FLUSH
+Remove all events from the whole group.
+.PP
+Only one of
+.BR FAN_MARK_ADD ,
+.BR FAN_MARK_REMOVE ,
+or
+.B FAN_MARK_FLUSH
+can be used.
+Failure to do so results in the error
+.BR EINVAL .
+.PP
+.I mask
+defines which events shall be listened to (or which shall be ignored).
+It is a bitmask composed of the following values:
+.TP
+.B FAN_ACCESS
+A file was accessed (read).
+.TP
+.B FAN_MODIFY
+A file was modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+An readonly file was closed.
+.TP
+.B FAN_OPEN
+A file was opened.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue overflowed.
+.TP
+.B FAN_OPEN_PERM
+A file open permission was requested.
+.TP
+.B FAN_ACCESS_PERM
+An access permission for a file was requested.
+.TP
+.B FAN_ONDIR
+The event occurred against a directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+An event for a child of a monitored directory occurred.
+.PP
+The following composed value is defined
+.TP
+.B FAN_CLOSE
+A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The path to be marked is determined by the file descriptor
+.I dirfd
+and the pathname specified in
+.IR pathname :
+.IP * 3
+If 
+.I pathname
+is NULL
+.I dirfd
+defines the path to be marked.
+.IP *
+If
+.I pathname
+is NULL and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+the current working directory is to be marked.
+.IP *
+If
+.I pathname
+is absolute it defines the path to be marked, and
+.I dirfd
+is ignored.
+.IP *
+If
+.I pathname
+is relative, it defines a path relative to the path indicated by the file
+descriptor in
+.I dirfd
+to be marked.
+.IP *
+If
+.I pathname
+is relative and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+it defines a path relative to the current working directory to be marked.
+.SH RETURN VALUE
+On success
+.BR fanotify_mark ()
+returns 0.
+In case of an error \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags
+or
+.IR mask ,
+or
+.I fanotify_fd
+was not a fanotify file descriptor.
+.TP
+.B ENOENT
+The directory indicated by
+.IR pathname
+does not exist.
+This error also occurs when trying to remove a mark from a directory or mount
+which is not marked.
+.TP
+.B ENOMEM
+The necessory memory could not be allocated.
+.TP
+.B ENOSPC
+The number of marks exceeds the limit of 8192 and
+.B FAN_UNLIMITED_MARKS
+was not specified in the call to
+.BR fanotify_init (2).
+.TP
+.B ENOTDIR
+.I flags
+contains
+.B FAN_MARK_ONLYDIR
+and
+.I dirfd
+does not point to a directory and
+.I pathname
+is NULL.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..e30882d
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,519 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-03-22 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases are virus scanning and hierarchical storage management.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes a fanotify notification group and returns a file
+descriptor referring to it.
+.PP
+A fanotify notification group is an internal object of the kernel which holds a
+list of files, directories and mount points for which events shall be created.
+.PP
+For each entry two bit masks exist.
+One mask (the mark mask) defines for which file activities an event shall be
+created.
+Another mask (the ignore mask) defines for which activities no event shall be
+created.
+Having these two types of masks allows that a mount point or directory is
+marked for receiving events, but no event is raised for specified contained
+file system objects.
+.PP
+A possible usage of the ignore mask is for a file cache.
+Events of interest for a file cache are modification of a file and closing
+of the same. Hence the cached directory or mount point is to be marked to
+receive these events.
+After receiving the first event informing that a file has been modified, the
+corresponding cache entry will be invalidated.
+No further modification events for this file are of interest until the file is
+closed.
+Hence the modify event can be added to the ignore mask.
+Upon receiving the closed event the modify event can be removed from the ignore
+mask and the file cache entry can be updated.
+.PP
+Two types of events exist.
+Notification events are only informative and require no action to be taken by
+the receiving application except for closing the file descriptor passed in the
+event.
+Permission events are requests to decide whether permission for a file access
+shall be granted. For these events a response has to be sent.
+.PP
+When all file descriptors referring to the fanotify notification group are
+closed, the group is released and the resources are freed for reuse by the
+kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, a directory, or a mount to the group and specifies which events
+shall be reported (or ignored), or removes or modifies such an entry.
+.PP
+When a fanotify event occurs the fanotify file descriptor indicates as
+readable when passed to
+.BR epoll (7),
+.BR poll (2),
+or
+.BR select (2).
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if flag
+.B FAN_NONBLOCK
+is not set in the call to
+.BR fanotify_init (2))
+until either a file event occurs or it is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or \-1 in case of an error.
+In case of success the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+This is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.I fanotify_event_metadata.
+Therefore it is recommended to use a larger buffer size when reading,
+e.g. 4096 bytes.
+.TP
+.I vers
+The structures fanotify_event_metadata and fanotify_response have been changed
+repeatedly. 
+This field holds the version information about the structures.
+It must be compared to
+.B FANOTIFY_METADATA_VERSION
+to verify that the structures at runtime match the structures at compile
+time.
+In case of a mismatch the fanotify file descriptor has to be closed.
+.TP
+.I reserved
+This field is not used.
+.TP
+.I metadata_len
+This is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+.TP
+.I mask
+This is a bitmask describing the event.
+.TP
+.I fd
+This is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The reading application is responsible for closing this file descriptor.
+.TP
+.I pid
+This is the ID of the process that caused the event.
+A program listening to fanotify events can compare this pid to the pid returned
+by
+.BR getpid (2)
+to detect if the event is caused by the listener itself or is due to a file
+access by another program.
+.PP
+The bitmask in
+.I mask
+signals which events have occured for a single file system object.
+More than one of the following flags can be set at once in the bitmask.
+.TP
+.B FAN_ACCESS
+A file was accessed.
+.TP
+.B FAN_OPEN
+A file was opened.
+.TP
+.B FAN_MODIFY
+A file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+An read only file was closed.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue exceeded the limit of 16384 entries. This limit can be
+overriden in the call to
+.BR fanotify_init (2)
+by setting flag
+.BR FAN_UNLIMITED_QUEUE .
+.TP
+.B FAN_ACCESS_PERM
+An application wants to access a file.
+A decision has to be taken if the permission to access the file is granted.
+.TP
+.B FAN_OPEN_PERM
+An application wants to open a file.
+A decision has to be taken if the permission to open the file is granted.
+.TP
+.B FAN_ONDIR
+The event concerns a monitored directory.
+.TP
+.B FAN_EVENT_ON_CHILD
+The event concerns the child of a monitored directory.
+.PP
+To check for any close event the following bitmask may be used:
+.TP
+.B FAN_CLOSE
+A file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer with fantify
+event metadata.
+.TP
+.B FAN_EVENT_OK(meta, len)
+This macro checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+This macro lets the pointer
+.I meta
+point to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.I len.
+.PP
+For permission events, the application must
+.BR write (2)
+a structure of the following form to the 
+.B fanotify
+file descriptor
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+This is the file descriptor from structure
+.I fanotify_event_metadata.
+.TP
+.I response
+This field contains the decision if the permission is granted.
+It's value must be either
+.B FAN_ALLOW
+to allow the file operation or
+.B FAN_DENY
+to deny the file operation.
+.PP
+To end listening, it is sufficient to
+.BR close (2)
+the fanotify file descriptor.
+The open permission events will be set to allowed, and all resources will be
+returned to the kernel.
+.PP
+The file 
+.I /proc/<pid>/fdinfo/<fd>
+contains information about fanotify marks for file descriptor fd of process
+pid. See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+The following errors may occur when reading from the
+.B fanotify
+file descriptor:
+.TP
+.B EAGAIN
+A nonblocking call did not return any data.
+.TP
+.B EFAULT
+The read buffer is outside of the accessible address space.
+.TP
+.B EINTR
+The call was interrupted by a signal handler.
+.TP
+.B EINVAL
+The buffer is too short to hold the event.
+.PP
+The following errors may occur when writing to the
+.B fanotify
+file descriptor:
+.TP
+.B EFAULT
+The write buffer is outside of the accessible address space.
+.TP
+.B EINVAL
+Fanotify access permissions are not enabled or the value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+The file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The fanotify API was introduced in version 2.6.36 of the Linux kernel and
+enabled in version 2.6.37. Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The fanotify API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+To enable the fanotify API the following setting in the Kernel configuration is
+needed:
+CONFIG_FANOTIFY=y. For permission handling
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API. It marks the mount passed as argument and waits for events of type
+.B FAN_PERM_OPEN
+and
+.BR FAN_CLOSE_WRITE .
+When a permission event arises a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file 
+.IR /home/user/temp/notes .
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occurred.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occurred.
+The example program ended when hitting the enter key.
+.SS Example output
+.in +4n
+.nf
+# ./fanotify_example /home
+Press enter key to terminate.
+Listening for events.
+FAN_OPEN_PERM: File /home/zfsdt/temp/notes
+FAN_CLOSE_WRITE: File /home/zfsdt/temp/notes
+
+Listening for events stopped.
+.fi
+.in
+.SS Program source
+.nf
+#define _GNU_SOURCE // needed for O_LARGEFILE
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+// Handle available events.
+static void
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    int len;
+    char path[PATH_MAX];
+    int path_len;
+    struct fanotify_response response;
+
+    // Loop while events can be read from fanotify file descriptor.
+    for(;;) {
+
+        // Read next events.
+        len = read(fd, (void *) &buf, sizeof(buf));
+        if (len > 0) {
+
+            // Point to the first event in the buffer.
+            metadata = (struct fanotify_event_metadata *) buf;
+
+            // Loop over all events in the buffer.
+            while (FAN_EVENT_OK(metadata, len)) {
+
+                // Assure that run time and compile time structures match.
+                assert(metadata\->vers == FANOTIFY_METADATA_VERSION);
+
+                // Check event contains a file descriptor.
+                if (metadata\->fd >= 0) {
+
+                    // Handle open permission event.
+                    if (metadata\->mask & FAN_OPEN_PERM) {
+                        printf("FAN_OPEN_PERM: ");
+
+                        // Allow file to be opened.
+                        response.fd = metadata\->fd;
+                        response.response = FAN_ALLOW;
+                        write(fd, &response, sizeof(
+                                  struct fanotify_response));
+                    }
+
+                    // Handle closing of writable file event.
+                    if (metadata\->mask & FAN_CLOSE_WRITE) {
+                        printf("FAN_CLOSE_WRITE: ");
+                    }
+
+                    // Determine path of the file accessed.
+                    sprintf(path, "/proc/self/fd/%d", metadata\->fd);
+                    path_len = readlink(path, path, sizeof(path) \- 1);
+
+                    // Write path.
+                    if (path_len > 0) {
+                        path[path_len] = '\\0';
+                        printf("File %s", path);
+                    }
+
+                    // Close the file descriptor of the event.
+                    close(metadata\->fd);
+                    printf("\\n");
+                }
+
+                // Forward pointer to next event.
+                metadata = FAN_EVENT_NEXT(metadata, len);
+            }
+        } else {
+
+            // No more events are available.
+            break;
+        }
+    }
+}
+
+int
+main(int argc, char *argv[])
+{
+    char buf;
+    int fd, ret;
+    nfds_t nfds;
+    struct pollfd fds[2];
+
+    // Check mount point is supplied.
+    if (argc != 2) {
+        printf("Usage: %s MOUNT\\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("Press enter key to terminate.\\n");
+
+    // Create the file descriptor for accessing the fanotify API.
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return EXIT_FAILURE;
+    }
+
+    // Mark the mount for
+    // \- permission events before opening files
+    // \- notification events after closing a write enabled file descriptor.
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,
+                      argv[1]) == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return EXIT_FAILURE;
+    }
+
+    // Prepare for polling.
+    nfds = 2;
+    // Console input.
+    fds[0].fd = STDIN_FILENO;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+    // Fanotify input.
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    // This is the loop to wait for incoming events.
+    printf("Listening for events.\\n");
+    for(;;) {
+        ret = poll(fds, nfds, \-1);
+        if (ret > 0) {
+            if (fds[0].revents & POLLIN) {
+                // Console input is available. Empty stdin and quit.
+                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n');
+                break;
+            }
+            if (fds[1].revents & POLLIN) {
+                // Fanotify events are available.
+                handle_events(fd);
+                fds[1].revents = 0;
+            }
+        } else if (ret == \-1 && errno != EINTR) {
+            perror("poll");
+            break;
+        }
+    }
+
+    // Close fanotify file descriptor.
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return EXIT_SUCCESS;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/1] Man pages for the fanotify API
       [not found]                 ` <1395506528-10026-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-03-24 21:23                   ` Michael Kerrisk (man-pages)
       [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-03-24 21:23 UTC (permalink / raw)
  To: xypron.glpk-Mmb7MZpHnFY
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	stephan.mueller-fwYZOkdEjagAvxtiuMwx3w,
	james.hunt-GeWIH/nMZzLQT0dZR+AlfA

[Eric-- heads up. I'm pretty sure there's a bug in the fanotify API.
See the discussion of FAN_MARK_FLUSH below.]


Hello Heinrich,

Many more comments below. Sorry, but this is a complex API, and 
there are many corner cases to consider....

==

Some of my past comments seem to have got dropped. Rather than just
sending me a new draft of the page, could you also answer / comment 
on each of the substantial points/questions in this mail (could be
as simple as saying "fixed in new draft"), then I am able to
know what questions remain open.

Some of my substantial points are at the top of this mail, others 
are listed below.

==

What permissions does one need on a file to watch it with
fanotify? That should be documented.

==

The pages say nothing about merging of events. Merging can happen
for non-permission events, but not for permission events.
Something needs to be said about this, probably in fanotify(7)
If you are unsure of what I mean, just add the following in
fanotify(7)

.\" FIXME Document merging of events

==

The discussion of monitoring of directories could be clearer.
To begin with, it wasn't immediately obvious from reading the
page whether one could monitor children of a directory. See the 
text in fanotify_mark.2 for FAN_MARK_MOUNT.  The discussion of 
FAN_ONDIR/FAN_EVENT_ON_CHILD should say somethingsimilar, noting 
that FAN_ONDIR on its own gives just monitoring of directories; 
to monitor children you need  FAN_ONDIR | FAN_EVENT_ON_CHILD.

And some questions. If I monitor a directory ("xxx") and its 
children, creating, modifying, and deleting files in that directory 
generates events as I'd expect. But, if I create a subdirectory 
("xxx/yyy") in that directory, it does not generate an event, and
creating objects in that subdirectory also does not generate events
(i.e., unlike with mount points, monitoring directories is not truly
recursive). Are both of these points correct? If yes, they need 
to be documented in the man page. (rmdir() of the subdirectory
also seems not to generate an event.)

On the other hand, open() and close() of the subdir xxx/yyy 
DO generate events. Strange. What is the rationale, for generating
events there, but not on mkdir()/rmdir(), do you know? 

And, given the above state of affairs, is it possible to reliably
monitor an entire directory subtree (that is not a mount point)?
The lack of mkdir(2)/rmdir(2) notification seems to make that task
difficult or, probably, impossible to do reliably. If it is
possible, the man page should explain how. If it is not pssible, 
the fanotify(7) page should say so explicitly, and I'd be inclined
to put it under the heading BUGS.

fanotify(7) should also mention that fanotify() doesn't detect 
file deletions (unlink(2)) and renames (rename()). Again, 
I'd put this under BUGS.

==

There needs to be some explanation of the events that are generated
for directories. To begin with, *which* events are generated for
directories?

* opening a directory for reading gives FAN_OPEN
* closing the file descriptor from the previous
  step gives FAN_CLOSE
* Changing the directory contents (adding a file)
  seems to give no event for the directory itself
  (but will give an event on the new file, if we
  are monitoring children of the directory)
* Other???

==

Somewhere, this detail about permission events should be made 
clearer:

* Can only set permission events if FAN_CLASS_PRE_CONTENT or 
  FAN_CLASS_CONTENT (not FAN_CLASS_CONTENT) was used to create 
  FAN fd. (EINVAL)

==

I asked this earlier (in a different wording), but it seems not to have 
been addressed:

    What happens if the application hits its file descriptor limit
    (RLIMIT_NOFILES) when handling read()s from the FAN FD? (EMFILE).

This needs to be covered under the errors for read(2).

And now I think of a related question: what if we hit the system-wide
limit on the number of open files (/proc/sys/fs/file-max)? (I suspect 
ENFILE.)

And yet another related question: what if the file in question
is being executed? In this case, we can't get an ETXTBUSY from read().

==

I notice that the FDs returned by read()s from the FAN FD have the
FMODE_NONOTIFY flag (fcntl(F_GETFL)) flag set. If you know what that's 
about, it would be good to say something about. But, if not, do not 
worry--just place a FIXME in the page source of fanotify(7)

.\" FIXME
.\"    The FDs returned by read()s from the FAN FD have the
.\"    FMODE_NONOTIFY flag (fcntl(F_GETFL)) flag set.
.\"    What is the purpose?

Cheers,

Michael


On 03/22/2014 05:42 PM, xypron.glpk-Mmb7MZpHnFY@public.gmane.org wrote:
> From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> 
> Michael,
> 
> thank you for your further comments, which I used to update
> the appended patch.
> 
> O_LARGEFILE is definitely needed on 32-bit Linux when working
> with permission events for files exceeding 2GB.
> 
> gcc -D_FILE_OFFSET_BITS=64
> is also needed but not sufficient.

I'm still a little doubtful about this. How have you verified that 
O_LARGEFILE  is required (or where did you get the info)?

Again, I start with fanotify(7) first.
 
> Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> ---
>  man2/fanotify_init.2 |  208 ++++++++++++++++++++
>  man2/fanotify_mark.2 |  239 +++++++++++++++++++++++
>  man7/fanotify.7      |  519 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 966 insertions(+)
>  create mode 100644 man2/fanotify_init.2
>  create mode 100644 man2/fanotify_mark.2
>  create mode 100644 man7/fanotify.7
> 
> --- /dev/null
> +++ b/man7/fanotify.7
> @@ -0,0 +1,519 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY 7 2014-03-22 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify \- monitoring filesystem events
> +.SH DESCRIPTION
> +The
> +.B fanotify
> +API provides notification and interception of filesystem events.
> +Use cases are virus scanning and hierarchical storage management.
> +
> +The following system calls are used with this API:
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR poll (2),
> +.BR ppoll (2),
> +.BR read (2),
> +.BR write (2),
> +and
> +.BR close (2).
> +.PP
> +.BR fanotify_init (2)
> +creates and initializes a fanotify notification group and returns a file
                           ^^^^^^^^^^
It all depends how you pronounce the name, but I assume "F-A-notify"
and so I'd always write it as "an fanotify" (and in multiple places below).

> +descriptor referring to it.
> +.PP
> +A fanotify notification group is an internal object of the kernel which holds a
> +list of files, directories and mount points for which events shall be created.
> +.PP
> +For each entry two bit masks exist.

Okay. Now I start to get to more subtle editing...

"entry" needs clarification to help the reader know that you mean the 
aforementioned "list".

==>

    For each entry in the fanotify list, 

(Note addition of a comma.)

> +One mask (the mark mask) defines for which file activities an event shall be
> +created.
> +Another mask (the ignore mask) defines for which activities no event shall be
> +created.
> +Having these two types of masks allows that a mount point or directory is
> +marked for receiving events, but no event is raised for specified contained
> +file system objects.

I'd write this as something like:

    Having these two types of masks allows a mount point or directory to be 
    marked for receiving events while at the same time ignoring events for a 
    subdirectory under that mount point or directory.

> +.PP
> +A possible usage of the ignore mask is for a file cache.
> +Events of interest for a file cache are modification of a file and closing
> +of the same. Hence the cached directory or mount point is to be marked to
                ^
Please start each new sentence on a new source line. See man-pages(7).

> +receive these events.

> +After receiving the first event informing that a file has been modified, the
> +corresponding cache entry will be invalidated.
> +No further modification events for this file are of interest until the file is
> +closed.
> +Hence the modify event can be added to the ignore mask.
> +Upon receiving the closed event the modify event can be removed from the ignore
                                  ^
Add comma.

> +mask and the file cache entry can be updated.
> +.PP
> +Two types of events exist.
> +Notification events are only informative and require no action to be taken by
> +the receiving application except for closing the file descriptor passed in the
> +event.
> +Permission events are requests to decide whether permission for a file access

s/are requests/are requests to the receiving application/


> +shall be granted. For these events a response has to be sent.
                     ^
Start each new sentence on a new source line.

"For these events a response has to be sent." could be made a bit more precise 
to help the reader:

    For these events, the recipient must write a response to .....

> +.PP
> +When all file descriptors referring to the fanotify notification group are
s/the/an/
> +closed, the group is released and the resources are freed for reuse by the
> +kernel.
> +.PP
> +.BR fanotify_mark (2)
> +adds a file, a directory, or a mount to the group and specifies which events

s/the group/an fanotify group/

> +shall be reported (or ignored), or removes or modifies such an entry.
> +.PP
> +When a fanotify event occurs the fanotify file descriptor indicates as
                               ^
Add comma. (I appreciate this is tricky for nonnative speakers. German
and English have quite different comma rules.)

> +readable when passed to
> +.BR epoll (7),
> +.BR poll (2),
> +or
> +.BR select (2).
> +.PP
> +Calling
> +.BR read (2)
> +for the file descriptor returned by
> +.BR fanotify_init (2)
> +blocks (if flag

if *the* flag

> +.B FAN_NONBLOCK
> +is not set in the call to

s/set/specified/

> +.BR fanotify_init (2))
> +until either a file event occurs or it is interrupted by a signal
> +(see
> +.BR signal (7)).
> +
> +The return value of
> +.BR read (2)
> +is the length of the filled buffer or \-1 in case of an error.
> +In case of success the read buffer contains one or more of the following
                     ^
Add comma

> +structures:
> +
> +.in +4n
> +.nf
> +struct fanotify_event_metadata {
> +    __u32 event_len;
> +    __u8 vers;
> +    __u8 reserved;
> +    __u16 metadata_len;
> +    __aligned_u64 mask;
> +    __s32 fd; 
> +    __s32 pid;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I event_len
> +This is the length of the data for the current event and the offset to the next
> +event in the buffer.
> +This length might be longer than the size of structure
> +.I fanotify_event_metadata.
> +Therefore it is recommended to use a larger buffer size when reading,
            ^
Add comma

> +e.g. 4096 bytes.

Change "e.g." to "for example,"

> +.TP
> +.I vers
> +The structures fanotify_event_metadata and fanotify_response have been changed
> +repeatedly. 

Have they? I don't know. But this statement is rather strong. Is it correct?
If it is true, it would be good to mention a few of the changes, and when
they occurred.

> +This field holds the version information about the structures.

"holds a version number for the structures"

> +It must be compared to
> +.B FANOTIFY_METADATA_VERSION
> +to verify that the structures at runtime match the structures at compile
> +time.
> +In case of a mismatch the fanotify file descriptor has to be closed.
                        ,
Comma

> +.TP
> +.I reserved
> +This field is not used.
> +.TP
> +.I metadata_len
> +This is the length of the structure.
> +The field was introduced to facilitate the implementation of optional headers
> +per event type.

To repeat a point I already made:

Are there any such optional headers so far? If not, then add a sentence to 
say so. If there are, mention an example.

> +.TP
> +.I mask
> +This is a bitmask describing the event.

Please use "bit mask" throughout.

> +.TP
> +.I fd
> +This is an open file descriptor for the object being accessed or
> +.B FAN_NOFD
> +if a queue overflow occurred.
> +The reading application is responsible for closing this file descriptor.

Maybe say

"for closing this file descriptor (if the value is other than FAN_NOFD)"

> +.TP
> +.I pid
> +This is the ID of the process that caused the event.
> +A program listening to fanotify events can compare this pid to the pid returned

s/pid/PID/g in previous line.

> +by
> +.BR getpid (2)
> +to detect if the event is caused by the listener itself or is due to a file
> +access by another program.
> +.PP
> +The bitmask in
> +.I mask
> +signals which events have occured for a single file system object.

"occurred"

> +More than one of the following flags can be set at once in the bitmask.

"One or more of the following flags may be set in the bit mask".

> +.TP
> +.B FAN_ACCESS
> +A file was accessed.
> +.TP
> +.B FAN_OPEN
> +A file was opened.
> +.TP
> +.B FAN_MODIFY
> +A file was modified.
> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +An read only file was closed.

s/An read only/A read-only/
(two changes)


> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue exceeded the limit of 16384 entries. This limit can be
> +overriden in the call to
> +.BR fanotify_init (2)
> +by setting flag

s/flag/the flag/

> +.BR FAN_UNLIMITED_QUEUE .
> +.TP
> +.B FAN_ACCESS_PERM
> +An application wants to access a file.

s/a file/the file/

But, what does "access a file" mean? How is it different from "open a 
file"? That needs to be explained. For example, FAN_ACCESS_PERM does 
not block open(), but does act as a gateway on at least the following:  
execve(2), read(2) (but not write(2)), read contents of a directory 
(getdents(2)?). There needs to be some kind of general statement here 
(or somewhere) about what the difference is between FAN_ACCESS_PERM 
and FAN_OPEN_PERM.

> +A decision has to be taken if the permission to access the file is granted.
> +.TP
> +.B FAN_OPEN_PERM
> +An application wants to open a file.

s/a file/the file/

> +A decision has to be taken if the permission to open the file is granted.
> +.TP
> +.B FAN_ONDIR
> +The event concerns a monitored directory.

I don't think this is correct. It looks to me like FAN_ONDIR is used
only as an input flag in fanotify_mark(). It isn't returned by read(). 
Please confirm.

> +.TP
> +.B FAN_EVENT_ON_CHILD
> +The event concerns the child of a monitored directory.

I don't think this is correct. It looks to me like FAN_EVENT_ON_CHILD 
is used only as an input flag in fanotify_mark(). It isn't returned by 
read(). Please confirm.

> +.PP
> +To check for any close event the following bitmask may be used:
                               ^
Add comma

> +.TP
> +.B FAN_CLOSE
> +A file was closed 
> +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The following macros are provided to iterate over a buffer with fantify

Typo: "fantify"

> +event metadata.
> +.TP
> +.B FAN_EVENT_OK(meta, len)
> +This macro checks the remaining length
> +.I len
> +of the buffer
> +.I meta
> +against the length of the metadata structure and the
> +.I event_len
> +field of the first metadata structure in the buffer.
> +.TP
> +.B FAN_EVENT_NEXT(meta, len)
> +This macro lets the pointer

s/lets/sets/

> +.I meta
> +point to the next metadata structure using the length indicated in the

s/point/to point/
s/indicated/specified/.

> +.I event_len
> +field of the metadata structure and reduces the remaining length of the
> +buffer
> +.I len.

.IR len .

> +.PP
> +For permission events, the application must
> +.BR write (2)
> +a structure of the following form to the 
> +.B fanotify
> +file descriptor

s/$/:/

> +
> +.in +4n
> +.nf
> +struct fanotify_response {
> +        __s32 fd;
> +        __u32 response;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I fd
> +This is the file descriptor from structure

s/structure/the structure/

> +.I fanotify_event_metadata.
> +.TP
> +.I response
> +This field contains the decision if the permission is granted.

"This field indicates whether or not permission is to be granmted."

> +It's value must be either

s/It's/Its/


> +.B FAN_ALLOW
> +to allow the file operation or
> +.B FAN_DENY
> +to deny the file operation.

Here, there needs to be text that explains what happens 
to the denied application.

> +.PP
> +To end listening, it is sufficient to
> +.BR close (2)
> +the fanotify file descriptor.
> +The open permission events will be set to allowed, and all resources will be

s/open/outstanding/

> +returned to the kernel.
> +.PP
> +The file 
> +.I /proc/<pid>/fdinfo/<fd>
> +contains information about fanotify marks for file descriptor fd of process
> +pid. See

       ^
New sentence, new source line.

> +.I Documentation/filesystems/proc.txt
> +for details.
> +.SH ERRORS
> +The following errors may occur when reading from the
> +.B fanotify
> +file descriptor:

Since EAGAIN, EFAULT, and EINTR are standard errors for read(),
I would omit them from this list. Instead, you could introduce the 
list with something like:

    In addition to the usual errors for read(2), the following errors
    can occur when reading from an fanotify file descriptor:
 
> +.TP
> +.B EAGAIN
> +A nonblocking call did not return any data.
> +.TP
> +.B EFAULT
> +The read buffer is outside of the accessible address space.
> +.TP
> +.B EINTR
> +The call was interrupted by a signal handler.
> +.TP
> +.B EINVAL
> +The buffer is too short to hold the event.
> +.PP
> +The following errors may occur when writing to the
> +.B fanotify
> +file descriptor:

See above. I'd omit EFAULT, here.

> +.TP
> +.B EFAULT
> +The write buffer is outside of the accessible address space.
> +.TP
> +.B EINVAL
> +Fanotify access permissions are not enabled or the value of

I do not understand this piece "Fanotify access permissions are not 
enabled". What does it mean?  (I think some rewriting is needed here.)

> +.I response
> +in the response structure is not valid.

> +.TP
> +.B ENOENT
> +The file descriptor
> +.I fd
> +in the response structure is not valid.
> +This might occur because the file was already deleted by another thread or
> +process.
> +.SH VERSIONS
> +The fanotify API was introduced in version 2.6.36 of the Linux kernel and
> +enabled in version 2.6.37. Fdinfo support was added in version 3.8.
> +.SH "CONFORMING TO"
> +The fanotify API is Linux-specific.
> +.SH NOTES
> +The notification is based on the kernel filesystem notification system
> +.B fsnotify.
> +.PP
> +To enable the fanotify API the following setting in the Kernel configuration is
> +needed:
> +CONFIG_FANOTIFY=y. For permission handling
> +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
> +.SH EXAMPLE
> +The following program demonstrates the usage of the
> +.B fanotify
> +API. It marks the mount passed as argument and waits for events of type
        ^
New sentence on new source line.

> +.B FAN_PERM_OPEN
> +and
> +.BR FAN_CLOSE_WRITE .
> +When a permission event arises a
                                 ^

Add comma

> +.B FAN_ALLOW
> +response is given.
> +.PP
> +The following output was recorded while editing file 
> +.IR /home/user/temp/notes .

But below, the directory is /home/zfsdt/temp/notes
Something needs to be fixed, either here, or below.
 
> +Before the file was opened a
                             ^
Add comma.

> +.B FAN_OPEN_PERM
> +event occurred.
> +After the file was closed a
                            ^
Add comma

> +.B FAN_CLOSE_WRITE
> +event occurred.
> +The example program ended when hitting the enter key.
> +.SS Example output
> +.in +4n
> +.nf
> +# ./fanotify_example /home
> +Press enter key to terminate.
> +Listening for events.
> +FAN_OPEN_PERM: File /home/zfsdt/temp/notes
> +FAN_CLOSE_WRITE: File /home/zfsdt/temp/notes
> +
> +Listening for events stopped.
> +.fi
> +.in

A lot of my comments from the last review of this program seem 
_not_ to have been taken into account. Could you please also
review previous mails.

> +.SS Program source
> +.nf
> +#define _GNU_SOURCE // needed for O_LARGEFILE
> +#include <assert.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <poll.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/fanotify.h>
> +#include <unistd.h>
> +
> +// Handle available events.
> +static void
> +handle_events(int fd)
> +{
> +    const struct fanotify_event_metadata *metadata;
> +    char buf[4096];
> +    int len;

len should be ssize_t.

> +    char path[PATH_MAX];
> +    int path_len;

path_len should be ssize_t.

> +    struct fanotify_response response;
> +
> +    // Loop while events can be read from fanotify file descriptor.

Please change all comments to

    /* ... */

(It's the norm in man pages.)

And please ensure an empty line follows all standalone comments


> +    for(;;) {
> +
> +        // Read next events.
> +        len = read(fd, (void *) &buf, sizeof(buf));
> +        if (len > 0) {

Please simplify this logic; there's no need to indent this long block. 
Make it:

            len = read()
            if (len <= 0)
                break;

            metadata = (struct fanotify_event_metadata *) buf;
            ....

> +
> +            // Point to the first event in the buffer.
> +            metadata = (struct fanotify_event_metadata *) buf;
> +
> +            // Loop over all events in the buffer.
> +            while (FAN_EVENT_OK(metadata, len)) {
> +
> +                // Assure that run time and compile time structures match.
> +                assert(metadata\->vers == FANOTIFY_METADATA_VERSION);

Drop the assert(); use real if() checks and error handling.

> +                // Check event contains a file descriptor.
> +                if (metadata\->fd >= 0) {
> +
> +                    // Handle open permission event.
> +                    if (metadata\->mask & FAN_OPEN_PERM) {
> +                        printf("FAN_OPEN_PERM: ");
> +
> +                        // Allow file to be opened.
> +                        response.fd = metadata\->fd;
> +                        response.response = FAN_ALLOW;
> +                        write(fd, &response, sizeof(
> +                                  struct fanotify_response));
> +                    }
> +
> +                    // Handle closing of writable file event.
> +                    if (metadata\->mask & FAN_CLOSE_WRITE) {
> +                        printf("FAN_CLOSE_WRITE: ");
> +                    }
> +
> +                    // Determine path of the file accessed.
> +                    sprintf(path, "/proc/self/fd/%d", metadata\->fd);
> +                    path_len = readlink(path, path, sizeof(path) \- 1);
> +
> +                    // Write path.
> +                    if (path_len > 0) {
> +                        path[path_len] = '\\0';
> +                        printf("File %s", path);
> +                    }

The above code is broken. If readlink() returns -1, not only is
the error not diagnosed, but printf() will display bogus info.

For clarity, I suggest using two variables, instead of using 'path'
as both input and output in the readlink() call. Something like:

            snprintf(procfd_path, sizeof(procfd_path) - 1,
                    "/proc/self/fd/%d", md->fd);
            path_len = readlink(procfd_path, target, sizeof(target) - 1);
            if (path_len == -1) {
                perror("readlink");
                exit(EXIT_FAILURE);
	    }
            target[path_len] = '\0';

> +
> +                    // Close the file descriptor of the event.
> +                    close(metadata\->fd);
> +                    printf("\\n");
> +                }
> +
> +                // Forward pointer to next event.
> +                metadata = FAN_EVENT_NEXT(metadata, len);
> +            }
> +        } else {
> +
> +            // No more events are available.
> +            break;
> +        }
> +    }
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +    char buf;
> +    int fd, ret;
> +    nfds_t nfds;
> +    struct pollfd fds[2];
> +
> +    // Check mount point is supplied.
> +    if (argc != 2) {
> +        printf("Usage: %s MOUNT\\n", argv[0]);
> +        return EXIT_FAILURE;
> +    }
> +
> +    printf("Press enter key to terminate.\\n");
> +
> +    // Create the file descriptor for accessing the fanotify API.
> +    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
> +                       O_RDONLY | O_LARGEFILE);
> +    if (fd == \-1) {
> +        perror("fanotify_init");
> +        return EXIT_FAILURE;
> +    }
> +
> +    // Mark the mount for
> +    // \- permission events before opening files
> +    // \- notification events after closing a write enabled file descriptor.
> +    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
> +                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,

Why 'FAN_NOFD' here?

> +                      argv[1]) == \-1) {
> +        perror("fanotify_mark");
> +        close(fd);
> +        return EXIT_FAILURE;
> +    }
> +
> +    // Prepare for polling.
> +    nfds = 2;
> +    // Console input.
> +    fds[0].fd = STDIN_FILENO;
> +    fds[0].events = POLLIN;
> +    fds[0].revents = 0;
> +    // Fanotify input.
> +    fds[1].fd = fd;
> +    fds[1].events = POLLIN;
> +    fds[1].revents = 0;
> +
> +    // This is the loop to wait for incoming events.
> +    printf("Listening for events.\\n");
> +    for(;;) {
> +        ret = poll(fds, nfds, \-1);
> +        if (ret > 0) {
> +            if (fds[0].revents & POLLIN) {
> +                // Console input is available. Empty stdin and quit.
> +                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n');

Too easy to misread. Make it

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

or better:

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


> +                break;
> +            }
> +            if (fds[1].revents & POLLIN) {
> +                // Fanotify events are available.
> +                handle_events(fd);
> +                fds[1].revents = 0;
> +            }
> +        } else if (ret == \-1 && errno != EINTR) {
> +            perror("poll");
> +            break;
> +        }
> +    }
> +
> +    // Close fanotify file descriptor.
> +    close(fd);
> +    printf("Listening for events stopped.\\n");
> +    return EXIT_SUCCESS;
> +}
> +.fi
> +.SH "SEE ALSO"
> +.ad l
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR inotify (7)
> 


> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
> new file mode 100644
> index 0000000..888c20d
> --- /dev/null
> +++ b/man2/fanotify_init.2
> @@ -0,0 +1,208 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_INIT 2 2014-03-22 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_init \- create and initialize fanotify group
> +.SH SYNOPSIS
> +.B #include <fcntl.h>
> +.br
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_init()

Add space before "()"

> +initializes a new fanotify group and returns a file descriptor for the event
> +queue.

s/event queue/event queue associated with the group/

> +.PP
> +The file descriptor is used in calls to
> +.BR fanotify_mark (2)
> +to define for which files, directories, or mounts fanotify events shall be
> +created.

Make it: 

to specify the files, directories, and mounts for which fanotify events 
shall be created.

> +These events are received by reading from the file descriptor.
> +Some events only inform that a file has been accessed.

Make it:
Some events are only informative, indicating that a file a has been accessed.

> +Other events can be used to control if another application may access a file.
> +Decisions upon the permission is granted by writing to the file descriptor.

s/upon/about/
s/is granted/are made/

> +An overview is provided in
> +.BR fanotify (7).

Probably can drop the preceding sentence since it repeats the point made at 
the start?

> +.PP
> +Multiple programs may be using the fanotify interface at the same time to
> +monitor the same files. 
> +Yet the number of fanotify groups per user is limited to 128.

s/Yet/In the current implementation,/

> +This value cannot be overridden.

s/value/limit/

I find the bracketed piece ([[[[...]]]]) below quite unclear. After
reading, I still do not understand what is going on. In particular,
it is not at all clear what the difference between FAN_CLASS_PRE_CONTENT
and FAN_CLASS_CONTENT is. Could you expand/clarify?

Also, the term 'priority level' could do with some clarification.

Also, you split the discussion of 'flags' over two places. It would be 
easier to read if all of the flags were discussed in contiguous 
paragraphs. I would rephrase the discussion like this:

    The flags argument specifies options that control the behavior of
    the call. This argument should include exactly one of the following, 
    which set the priority level <blah blah>:


       FAN_CLASS_PRE_CONTENT

       FAN_CLASS_CONTENT

       FAN_CLASS_NOTIF

           (And it looks as though NOTIF is the default, since it is zero.
           Maybe say this?)

[[[[

> +.PP
> +By indicating in
> +.I flags
> +which kind of operations will be executed a logical sequence can be defined
> +in which events are forwarded to the listeners. The following bitmasks define
> +the kind of usage.

(By the way, the FAN_CLASS constants are _not_ bit masks, see the comments in
include/uapi/linux/fanotify.h )

> +Only one of them may be used when calling
> +.BR fanotify_init ().
> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +This priority level allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files before they
> +contain their final data.
> +This may be used hierarchical storage managers.

s/used/used by/

> +.TP
> +.B FAN_CLASS_CONTENT
> +This priority level allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files when they already
> +contain their final content.
> +This may be used by malware detection programs.
> +.TP
> +.B FAN_CLASS_NOTIF
> +This sets a priority level which only allows the receipt of events notifying
> +that a file has been accessed.
> +Permission decisions before the file is accessed are not possible.
> +.PP

]]]]

> +Listeners with different priority levels will receive events in the sequence
> +.BR FAN_CLASS_PRE_CONTENT ,
> +.BR FAN_CLASS_CONTENT ,
> +.BR FAN_CLASS_NOTIF .
> +The call sequence among listeners of the same priority level is undefined.
> +.PP
> +Calling
> +.BR fanotify_init()
> +requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +This constraint might be relaxed in future versions of the API.
> +Hence additional local capability checks have been implemented as indicated

s/Hence/Therefore,/

> +below.
> +.PP
> +.IR flags
> +defines the behavior of the file descriptor.
> +It is a bitmask composed of the following values:
> +.TP
> +.B FAN_CLOEXEC
> +This flag sets the close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +on the new file descriptor.
> +When calling
> +.BR execve (2)
> +the inherited file descriptor of the child process will be closed.
> +See the description of the
> +.B O_CLOEXEC
> +flag in
> +.BR open (2).
> +.TP
> +.B FAN_NONBLOCK
> +This flag enables the non-blocking flag
> +.RB ( O_NONBLOCK )
> +for the file descriptor.
> +Reading from the file descriptor will not block.
> +Instead if no data is available in a call to
          ^
Comma

> +.BR read (2)
> +an error
> +.B EAGAIN
> +will occur.
> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +See above.
> +.TP
> +.B FAN_CLASS_CONTENT
> +See above.
> +.TP
> +.B FAN_CLASS_NOTIF
> +See above.
> +.TP
> +.B FAN_UNLIMITED_QUEUE
> +This flag removes the limit of 16384 events on the size of the event queue.
> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.TP
> +.B FAN_UNLIMITED_MARKS
> +This flag removes the limit of 8192 marks on the number of marks.
> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.PP
> +.IR event_f_flags
> +This parameter defines the file flags, with which file descriptors for fanotify

Start this sentence as

The event_f_flags argument defines....

And s/parameter/argument/ throughout. (This is the norm for man-pages.)

And:
s/falgs,/flags/

> +events shall be created.
> +For explanations of possible values see parameter
                                      ^
comma

> +.I flags
> +of the 
> +.BR open (2)
> +system call.
> +Useful values are

s/$/:/

> +.TP
> +.B O_RDONLY
> +This value allows only read access.
> +.TP
> +.B O_WRONLY
> +This value allows only write access.
> +.TP
> +.B O_RDWR
> +This value allows read and write access.
> +.TP
> +.B O_CLOEXEC
> +This flag enables close-on-exec.
> +.TP
> +.B O_LARGEFILE
> +This flag enables support files exceeding 2 GB.
> +Failing to set this flag will result in an
> +.B EOVERFLOW
> +error when trying to open a large file which is monitored by a fanotify group
> +on a 32-bit system.
> +.SH RETURN VALUE
> +On success

s/$/,/

> +.BR fanotify_init ()
> +returns a new file descriptor.
> +In case of an error \-1 is returned, and
                      ^
Comma

> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags .
> +.B FAN_ALL_INIT_FLAGS
> +defines all allowable bits.
> +.TP
> +.B EMFILE
> +The number of fanotify groups of the user exceeds 128.
> +.TP
> +.B ENOMEM
> +The allocation of memory for the notification group failed. 
> +.TP
> +.B EPERM
> +The operation is not permitted because capability
> +.B CAP_SYS_ADMIN
> +is missing.
> +.SH VERSIONS
> +.BR fanotify_init ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_mark (2),
> +.BR fanotify (7)
> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
> new file mode 100644
> index 0000000..b4617c8
> --- /dev/null
> +++ b/man2/fanotify_mark.2
> @@ -0,0 +1,239 @@
> +.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_MARK 2 2014-03-22 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_mark \- add, remove, or modify a fanotify mark on a filesystem
> +object.

Remove '.'

> +.SH SYNOPSIS
> +.nf
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_mark (int " fanotify_fd ", unsigned int " flags ,

Remove space before '('

> +.BI "                   uint64_t " mask ", int " dirfd ,
> +.BI "                   const char *" pathname );
> +.fi
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_mark (2)
> +adds, removes, or modifies a fanotify mark on a filesystem.
> +.PP
> +.I fanotify_fd
> +is the file descriptor returned by

The
+.I fanotify_fd
argument is the file descriptor returned by

> +.BR fanotify_init (2).
> +.PP
> +.I flags
> +is a bitmask describing the modification to perform.
> +It is composed of the following values:

At the end of this list, you say that only one of FAN_MARK_ADD, 
FAN_MARK_REMOVE, or FAN_MARK_FLUSH can be used. I'd put that 
information at the front, and restructure the discussion like this:

[[
.I flags 
is a bit mask describing the modifications to perform.
It must include exactly one of the following

FAN_MARK_ADD
    ...
FAN_MARK_REMOVE
    ...
FAN_MARK_FLUSH
    ...

If none of the above is specified, or more than one is specified, 
the call fails with the error
.BR EINVAL .

In addition,
.I flags
may contain zero or more of the following:
...
]]

> +.TP
> +.B FAN_MARK_ADD
> +The events in parameter
> +.I mask
> +will be added to the marke mask (or to the ignore mask).

"marke" ==> "mark"

> +.I mask
> +must be nonempty or the error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_REMOVE
> +The events in paramter
> +.I mask
> +will be removed from the mark mask (or from the ignore mask).
> +.I mask
> +must be nonempty or the error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_DONT_FOLLOW
> +Symbolic links shall not be followed.
> +.TP
> +.B FAN_MARK_ONLYDIR
> +If the path to be marked is not a directory the error

I think it might be better to say

"The filesystem object to be marked..."

For example, if pathname is NULL, then there is no "pathname" involved. 
Instead, we are using the file descriptor 'dirfd' to identify the object
to be marked.

> +.B ENOTDIR
> +shall be raised.

Is this error listed in the ERRORS section?

> +.TP
> +.B FAN_MARK_MOUNT
> +The path indicates a mount point to be marked.
> +If the path is not itself a mount point the mount point containing the path
> +will be marked.
> +All directories, subdirectories, and the contained files of the mount point
> +will be monitored.
> +.TP
> +.B FAN_MARK_IGNORED_MASK
> +The events in parameter
> +.I mask
> +shall be added to or removed from the ignore mask.
> +.TP
> +.B FAN_MARK_IGNORED_SURV_MODIFY
> +The ignore mask shall survive modify events.
> +If this flag is not set, the ignore mask is cleared, if a modify event occurs
> +for the fanotify group.
> +.TP
> +.B FAN_MARK_FLUSH
> +Remove all events from the whole group.

I want to be clear here. This means erase the entire set of marks
for the group associated with 'fanotify_fd', right. In that case,
s/events/marks/ above.

And, you need to explain the requirements for the other arguments:

Is 'mask' ignored? (Looks like it is.)

What about other flags in 'flags'? Are they ignored?

What about 'dirfd' and 'pathname'? It looks like they are NOT
ignored. (And this smells a lot like an API design bug.) For example,
specifying a nonexistent 'pathname' with FAN_MARK_FLUSH gives ENOENT,
and specifying 'pathname" as NULL with 'dirfd' as AT_FDCWD gives EBADF.

fanotify_mark(fan_fd, FAN_MARK_FLUSH, 0, 0, NULL);
as shown here
http://git.infradead.org/users/eparis/fanotify-example.git/blob/HEAD:/fanotify.c
works, but only fortuitously, because 'dirfd' refers to STDIN_FILENO. 
However, if fails if FD 0 is closed, or if FAN_MARK_ONLYDIR is specified 
in 'flags'

Something should be said about this in the BUGS section of either fanotify(7) 
or fanotify_mark(2).

> +.PP
> +Only one of
> +.BR FAN_MARK_ADD ,
> +.BR FAN_MARK_REMOVE ,
> +or
> +.B FAN_MARK_FLUSH
> +can be used.
> +Failure to do so results in the error
> +.BR EINVAL .
> +.PP
> +.I mask
> +defines which events shall be listened to (or which shall be ignored).
> +It is a bitmask composed of the following values:

There is some confusion in the following list. Various flags below
are only *returned* by read() on the FAN FD. They can't be set during
fanotify_mark().

Also, the whole list is worded strangely. Essentially, you've taken
the list from fanotify(7), but the wording there relates to events
that have occurred, whereas the list below should be talking about 
the events the application wants to monitor. See what I mean?

> +.TP
> +.B FAN_ACCESS
> +A file was accessed (read).

    ==> Report file access events (read)

> +.TP
> +.B FAN_MODIFY
> +A file was modified (write).

    Report file modification events (write).

And so on...

> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +An readonly file was closed.
> +.TP
> +.B FAN_OPEN
> +A file was opened.
> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue overflowed.

This isn't correct. One can't specify FAN_Q_OVERFLOW in 'mask'
(EINVAL)

> +.TP
> +.B FAN_OPEN_PERM
> +A file open permission was requested.
> +.TP
> +.B FAN_ACCESS_PERM
> +An access permission for a file was requested.
> +.TP
> +.B FAN_ONDIR
> +The event occurred against a directory.

Above is an example of what I mean by strange wording.
This should say something like:

    Monitor events on a directory

> +.TP
> +.B FAN_EVENT_ON_CHILD
> +An event for a child of a monitored directory occurred.

Above is an example of what I mean by strange wording.
This should, I think, say something like:

     Report events for children of a subdirectory.

> +.PP
> +The following composed value is defined
> +.TP
> +.B FAN_CLOSE
> +A file was closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The path to be marked is determined by the file descriptor
> +.I dirfd
> +and the pathname specified in
> +.IR pathname :
> +.IP * 3
> +If 
> +.I pathname
> +is NULL

s/$/,/

> +.I dirfd
> +defines the path to be marked.

Here, I think you need to say that 'dirfd' can refer to any type of 
file, not just a directory. (But see nu next comment 
below.)

> +.IP *
> +If
> +.I pathname
> +is NULL and
          ^
Comma
> +.I dirfd
> +takes the special value
> +.BR AT_FDCWD ,
> +the current working directory is to be marked.
> +.IP *
> +If
> +.I pathname
> +is absolute it defines the path to be marked, and
              ^
Comma

> +.I dirfd
> +is ignored.
> +.IP *
> +If
> +.I pathname
> +is relative, it defines a path relative to the path indicated by the file
> +descriptor in
> +.I dirfd
> +to be marked.

(See my comment above.) Here, I imagine that 'dirfd' must refer to a 
directory (as is the case for openat(). for example). If so, that 
needs to be explained here.

> +.IP *
> +If
> +.I pathname
> +is relative and
> +.I dirfd
> +takes the special value
> +.BR AT_FDCWD ,
> +it defines a path relative to the current working directory to be marked.

s/it/pathname/

> +.SH RETURN VALUE
> +On success

s/$/,/

> +.BR fanotify_mark ()
> +returns 0.
> +In case of an error \-1 is returned, and
                      ^
comma

> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EBADF
> +An invalid file descriptor was passed in
> +.IR fanotify_fd .
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags
> +or
> +.IR mask ,
> +or
> +.I fanotify_fd
> +was not a fanotify file descriptor.
> +.TP
> +.B ENOENT
> +The directory indicated by
> +.IR pathname
> +does not exist.

'pathname' doen't need to be a directory...

> +This error also occurs when trying to remove a mark from a directory or mount
> +which is not marked.

And again, can't the pathname also be for a file?

I'd write that last piece as a separate list entry:

    .TP
    .B ENOENT
    Tried to remove a mark from an object that is not marked.

> +.TP
> +.B ENOMEM
> +The necessory memory could not be allocated.

necessary

> +.TP
> +.B ENOSPC
> +The number of marks exceeds the limit of 8192 and
> +.B FAN_UNLIMITED_MARKS
> +was not specified in the call to
> +.BR fanotify_init (2).
> +.TP
> +.B ENOTDIR
> +.I flags
> +contains
> +.B FAN_MARK_ONLYDIR
> +and
> +.I dirfd
> +does not point to a directory and
> +.I pathname
> +is NULL.

What about the case where *pathname* is not a directory? 

I suggest rewriting as follows:

    flags contains FAN_MARK_ONLYDIR, but the object specified by
    pathname and dirfd is not a directory.

> +.SH VERSIONS
> +.BR fanotify_mark ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_init (2),
> +.BR fanotify (7)
> diff --git a/man7/fanotify.7 b/man7/fanotify.7
> new file mode 100644
> index 0000000..e30882d


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Man pages for the fanotify API: merging of events
       [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-03-25 15:39                       ` Heinrich Schuchardt
       [not found]                         ` <5331A343.9070403-Mmb7MZpHnFY@public.gmane.org>
  2014-03-26 19:09                       ` [PATCH 1/1] Man pages for the fanotify API Eric Paris
                                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-03-25 15:39 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ

Hello Michael,

could , please, help me to get the following fixed:

On 24.03.2014 22:23, Michael Kerrisk (man-pages) wrote:
> The pages say nothing about merging of events. Merging can happen
> for non-permission events, but not for permission events.
> Something needs to be said about this, probably in fanotify(7)
> If you are unsure of what I mean, just add the following in
> fanotify(7)
>
> .\" FIXME Document merging of events
At least there was: "The bitmask in *mask* signals which events
have occured for a single file system object. More than one of the
following flags can be set at once in the bitmask."

But this of cause does not describe that consecutive events might have 
been merged (=> Needs to be fixed in man page).

In the current coding permission events are not merged with other
events.

This feature did not exist in the kernel until two months ago, while the 
API is much older.

See patch
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=13116dfd13c8c9d60ea04ece13419af2de8e2e37

What I am unsure about is, whether the fanotify manpage should make any 
assumption that this feature will hold true for future kernel releases.

To me not merging permission events with other events seems rather to be 
a fix for some coding internal problem not something that typically 
would go into the specification.

What is your opinion?

Best regards

Heinrich Schuchardt
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: Man pages for the fanotify API: merging of events
       [not found]                         ` <5331A343.9070403-Mmb7MZpHnFY@public.gmane.org>
@ 2014-03-25 16:37                           ` Jan Kara
  0 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-03-25 16:37 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Michael Kerrisk (man-pages),
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ

  Hello,

On Tue 25-03-14 16:39:47, Heinrich Schuchardt wrote:
> could , please, help me to get the following fixed:
> 
> On 24.03.2014 22:23, Michael Kerrisk (man-pages) wrote:
> >The pages say nothing about merging of events. Merging can happen
> >for non-permission events, but not for permission events.
> >Something needs to be said about this, probably in fanotify(7)
> >If you are unsure of what I mean, just add the following in
> >fanotify(7)
> >
> >.\" FIXME Document merging of events
> At least there was: "The bitmask in *mask* signals which events
> have occured for a single file system object. More than one of the
> following flags can be set at once in the bitmask."
> 
> But this of cause does not describe that consecutive events might
> have been merged (=> Needs to be fixed in man page).
> 
> In the current coding permission events are not merged with other
> events.
> 
> This feature did not exist in the kernel until two months ago, while
> the API is much older.
> 
> See patch
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=13116dfd13c8c9d60ea04ece13419af2de8e2e37
> 
> What I am unsure about is, whether the fanotify manpage should make
> any assumption that this feature will hold true for future kernel
> releases.
  So, we certainly guarantee that two permission events are never merged
(because they may need response from userspace and the number of permission
requests and responses should better match). Other merging is at a
discretion of the kernel - it may happen but does not have to.

> To me not merging permission events with other events seems rather
> to be a fix for some coding internal problem not something that
> typically would go into the specification.
  Yes, it's just making life simpler for the kernel.

								Honza
-- 
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/1] Man pages for the fanotify API
       [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2014-03-25 15:39                       ` Man pages for the fanotify API: merging of events Heinrich Schuchardt
@ 2014-03-26 19:09                       ` Eric Paris
  2014-04-06  0:01                       ` [PATCH 0/1] Manpages " xypron.glpk-Mmb7MZpHnFY
  2014-04-06  0:01                       ` [PATCH 1/1] Manpages for the fanotify API xypron.glpk-Mmb7MZpHnFY
  3 siblings, 0 replies; 22+ messages in thread
From: Eric Paris @ 2014-03-26 19:09 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: xypron.glpk-Mmb7MZpHnFY, linux-man-u79uwXL29TY76Z2rM5mHXA,
	stephan.mueller-fwYZOkdEjagAvxtiuMwx3w,
	james.hunt-GeWIH/nMZzLQT0dZR+AlfA

On Mon, 2014-03-24 at 22:23 +0100, Michael Kerrisk (man-pages) wrote:
> [Eric-- heads up. I'm pretty sure there's a bug in the fanotify API.
> See the discussion of FAN_MARK_FLUSH below.]
> 
> 
> Hello Heinrich,
> 
> Many more comments below. Sorry, but this is a complex API, and 
> there are many corner cases to consider....
> 
> ==
> 
> Some of my past comments seem to have got dropped. Rather than just
> sending me a new draft of the page, could you also answer / comment 
> on each of the substantial points/questions in this mail (could be
> as simple as saying "fixed in new draft"), then I am able to
> know what questions remain open.
> 
> Some of my substantial points are at the top of this mail, others 
> are listed below.
> 
> ==
> 
> What permissions does one need on a file to watch it with
> fanotify? That should be documented.

CAP_SYS_ADMIN   that's all you need...

Some question just came up about if this is what we want (probably not),
but that's all the perms you need.

> 
> ==
> 
> The pages say nothing about merging of events. Merging can happen
> for non-permission events, but not for permission events.
> Something needs to be said about this, probably in fanotify(7)
> If you are unsure of what I mean, just add the following in
> fanotify(7)
> 
> .\" FIXME Document merging of events
> 
> ==
> 
> The discussion of monitoring of directories could be clearer.
> To begin with, it wasn't immediately obvious from reading the
> page whether one could monitor children of a directory. See the 
> text in fanotify_mark.2 for FAN_MARK_MOUNT.  The discussion of 
> FAN_ONDIR/FAN_EVENT_ON_CHILD should say somethingsimilar, noting 
> that FAN_ONDIR on its own gives just monitoring of directories; 
> to monitor children you need  FAN_ONDIR | FAN_EVENT_ON_CHILD.
> 
> And some questions. If I monitor a directory ("xxx") and its 
> children, creating, modifying, and deleting files in that directory 
> generates events as I'd expect. But, if I create a subdirectory 
> ("xxx/yyy") in that directory, it does not generate an event, and
> creating objects in that subdirectory also does not generate events
> (i.e., unlike with mount points, monitoring directories is not truly
> recursive). Are both of these points correct? If yes, they need 
> to be documented in the man page. (rmdir() of the subdirectory
> also seems not to generate an event.)
> 
> On the other hand, open() and close() of the subdir xxx/yyy 
> DO generate events. Strange. What is the rationale, for generating
> events there, but not on mkdir()/rmdir(), do you know? 
> 
> And, given the above state of affairs, is it possible to reliably
> monitor an entire directory subtree (that is not a mount point)?
> The lack of mkdir(2)/rmdir(2) notification seems to make that task
> difficult or, probably, impossible to do reliably. If it is
> possible, the man page should explain how. If it is not pssible, 
> the fanotify(7) page should say so explicitly, and I'd be inclined
> to put it under the heading BUGS.
> 
> fanotify(7) should also mention that fanotify() doesn't detect 
> file deletions (unlink(2)) and renames (rename()). Again, 
> I'd put this under BUGS.

I think you are correct.  fanotify does not provide
link()/unlink()/rename()/mkdir()/rmdir() notification.  Noting this is a
good idea.  Calling it a 'bug' is questionable, but not not a big deal
to me...

> I asked this earlier (in a different wording), but it seems not to have 
> been addressed:
> 
>     What happens if the application hits its file descriptor limit
>     (RLIMIT_NOFILES) when handling read()s from the FAN FD? (EMFILE).
> 
> This needs to be covered under the errors for read(2).
> 
> And now I think of a related question: what if we hit the system-wide
> limit on the number of open files (/proc/sys/fs/file-max)? (I suspect 
> ENFILE.)
> 
> And yet another related question: what if the file in question
> is being executed? In this case, we can't get an ETXTBUSY from read().

I don't honestly remember...


--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 0/1] Manpages for the fanotify API
       [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2014-03-25 15:39                       ` Man pages for the fanotify API: merging of events Heinrich Schuchardt
  2014-03-26 19:09                       ` [PATCH 1/1] Man pages for the fanotify API Eric Paris
@ 2014-04-06  0:01                       ` xypron.glpk-Mmb7MZpHnFY
       [not found]                         ` <1396742468-4752-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  2014-04-06  0:01                       ` [PATCH 1/1] Manpages for the fanotify API xypron.glpk-Mmb7MZpHnFY
  3 siblings, 1 reply; 22+ messages in thread
From: xypron.glpk-Mmb7MZpHnFY @ 2014-04-06  0:01 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ, Heinrich Schuchardt

From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>

Hello Michael,

please, find the answer to your most prominent questions
in this mail.

I put the patch into a separate mail.

Best regards

Heinrich Schuchardt

==

 >> What permissions does one need on a file to watch it with
 >> fanotify? That should be documented.
The only permission needed is CAP_SYS_ADMIN and read permission
on the mount, directory, or file marked.

==

 >> The pages say nothing about merging of events. Merging can happen
 >> for non-permission events, but not for permission events.
 >> Something needs to be said about this, probably in fanotify(7)
 >> If you are unsure of what I mean, just add the following in
 >> fanotify(7)

You missed this sentence: "The bitmask in mask signals which events
have occured for a single file system object. More than one of the
following flags can be set at once in the bitmask."

Jan Kara wrote, that the only guarantee given is, that no two
permission events will be merged.

I reworked fanotify.7.

==

 >> The discussion of monitoring of directories could be clearer.
 >> To begin with, it wasn't immediately obvious from reading the
 >> page whether one could monitor children of a directory. See the
 >> text in fanotify_mark.2 for FAN_MARK_MOUNT.  The discussion of
 >> FAN_ONDIR/FAN_EVENT_ON_CHILD should say somethingsimilar, noting
 >> that FAN_ONDIR on its own gives just monitoring of directories;
 >> to monitor children you need  FAN_ONDIR | FAN_EVENT_ON_CHILD.
For monitoring children FAN_ONDIR is not needed.

 >> And some questions. If I monitor a directory ("xxx") and its
 >> children, creating, modifying, and deleting files in that directory
 >> generates events as I'd expect. But, if I create a subdirectory
 >> ("xxx/yyy") in that directory, it does not generate an event, and
 >> creating objects in that subdirectory also does not generate events
 >> (i.e., unlike with mount points, monitoring directories is not truly
 >> recursive). Are both of these points correct? If yes, they need
 >> to be documented in the man page. (rmdir() of the subdirectory
 >> also seems not to generate an event.)
Not all fsnotify events are passed to fanotify. Some of the missing
events are:
FS_MOVED_FROM   0x00000040  /* File was moved from X */
FS_MOVED_TO     0x00000080  /* File was moved to Y */
FS_CREATE       0x00000100  /* Subfile was created */
FS_DELETE       0x00000200  /* Subfile was deleted */
FS_DELETE_SELF  0x00000400  /* Self was deleted */
FS_MOVE_SELF    0x00000800  /* Self was moved */
Cf. http://lkml.iu.edu/hypermail/linux/kernel/0907.3/00243.html

I added to fanotify.7
Currently only a limited set of events is supported.
Up to now there is no support for create, delete, and move events.

==

There needs to be some explanation of the events that are generated
for directories. To begin with, *which* events are generated for
directories?

* opening a directory for reading gives FAN_OPEN
* closing the file descriptor from the previous
  step gives FAN_CLOSE
* Changing the directory contents (adding a file)
  seems to give no event for the directory itself
  (but will give an event on the new file, if we
  are monitoring children of the directory)
* Other???

==

 >> Somewhere, this detail about permission events should be made
 >> clearer:
 >>
 >> * Can only set permission events if FAN_CLASS_PRE_CONTENT or
 >>   FAN_CLASS_CONTENT (not FAN_CLASS_CONTENT) was used to create
 >>   FAN fd. (EINVAL)
Fixed in fanotify_init.2

==

 >> I asked this earlier (in a different wording), but it seems not to
 >> have been addressed:
 >>
 >>    What happens if the application hits its file descriptor limit
 >>    (RLIMIT_NOFILES) when handling read()s from the FAN FD? (EMFILE).
 >>
 >> This needs to be covered under the errors for read(2).
When diving deeper into the code EMFILE can be found in get_unusedfd.
FIXED in fanotify.7

 >> And now I think of a related question: what if we hit the system-wide
 >> limit on the number of open files (/proc/sys/fs/file-max)? (I suspect
 >> ENFILE.)
I could not verify this. But I guess you can reproduce all error codes
of open(2) in some part of the fanotify API.

 >> And yet another related question: what if the file in question
 >> is being executed? In this case, we can't get an ETXTBUSY from read().
Do you mean ETXTBSY? I could observe that read creates this error when
receiving an event for an executing file and fanotify_init was called with
O_RDWR.
Fixed in fanotify.7

==

 >> I notice that the FDs returned by read()s from the FAN FD have the
 >> FMODE_NONOTIFY flag (fcntl(F_GETFL)) flag set. If you know what that's
 >> about, it would be good to say something about. But, if not, do not
 >> worry--just place a FIXME in the page source of fanotify(7)

Fixed in fanotify.7
If the listener accesses the file through the file descriptor provided
no additional events are created.

==

 >> It all depends how you pronounce the name, but I assume "F-A-notify"
 >> and so I'd always write it as "an fanotify" (and in multiple places below).

No indication has been given by Eric Paris that the first letters of fanotify
are an abbreviation, so I think of fanotify as a proper name pronounced
[fænoutifai].
Cf. http://lkml.iu.edu/hypermail/linux/kernel/0907.3/00243.html

==

 >> I'm still a little doubtful about this. How have you verified that
 >> O_LARGEFILE  is required (or where did you get the info)?
I tested on 32bit and it is definitely needed there.

==

 >> +    // Mark the mount for
 >> >+    // \- permission events before opening files
 >> >+    // \- notification events after closing a write enabled file descriptor.
 >> >+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
 >> >+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,
> Why 'FAN_NOFD' here?
>
 >> >+                      argv[1]) == \-1) {
 >> >+        perror("fanotify_mark");
 >> >+        close(fd);
 >> >+        return EXIT_FAILURE;
 >> >+    }

As described in fanotify_mark(2) the value of dfd is irrelevant if pathname is not NULL.

FAN_NOFD takes the value -1, which no file descriptor ever can have.

I changed this to -1 now.

==

 >> Having these two types of masks allows a mount point or directory to be
 >> marked for receiving events while at the same time ignoring events for a
 >> subdirectory under that mount point or directory.
This would be incomplete. Files and directories can be ignored.
I partially adopted you wording in fanotify.7

==
 >>> The structures fanotify_event_metadata and fanotify_response have been
 >>> changed repeatedly.

 >> Have they? I don't know. But this statement is rather strong. Is it correct?
 >> If it is true, it would be good to mention a few of the changes, and when
 >> they occurred.
In the Git log you will find at least 4 different version. With fields added
and removed, alignment changed, and fieldtype changed. The last change was in
 2.6.37. I removed the sentence with repeatedly. It is sufficient to indicate
that the value of the field should be checked.

==


 >> I don't think this is correct. It looks to me like FAN_ONDIR is used
 >> only as an input flag in fanotify_mark(). It isn't returned by read().
 >> Please confirm.
You are right.
Fixed in fanotify.7

==

 >> I don't think this is correct. It looks to me like FAN_EVENT_ON_CHILD
 >> is used only as an input flag in fanotify_mark(). It isn't returned by
 >> read(). Please confirm.

You are right.
Fixed in fanotify.7

==
 >> Here, there needs to be text that explains what happens
 >> to the denied application.
If access has been denied the requesting application call will receive an error
EPERM.

==

 >> I do not understand this piece "Fanotify access permissions are not
 >> enabled". What does it mean?  (I think some rewriting is needed here.)
... in the Kernel configuration ...
Fixed in fanotify.7

==

FAN_ACCESS_PERM
The name is misleading. The permission check is done before executing a file
or listing a directory.


Heinrich Schuchardt (1):
  Manpages for the fanotify API

 man2/fanotify_init.2 |  201 ++++++++++++++++++
 man2/fanotify_mark.2 |  260 +++++++++++++++++++++++
 man7/fanotify.7      |  576 ++++++++++++++++++++++++++++++++++++++++++++++++++
 man7/inotify.7       |    1 +
 4 files changed, 1038 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/1] Manpages for the fanotify API
       [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
                                         ` (2 preceding siblings ...)
  2014-04-06  0:01                       ` [PATCH 0/1] Manpages " xypron.glpk-Mmb7MZpHnFY
@ 2014-04-06  0:01                       ` xypron.glpk-Mmb7MZpHnFY
  3 siblings, 0 replies; 22+ messages in thread
From: xypron.glpk-Mmb7MZpHnFY @ 2014-04-06  0:01 UTC (permalink / raw)
  To: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ, Heinrich Schuchardt

From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>

Missing man pages for the fanotify API are provided.

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 |  201 ++++++++++++++++++
 man2/fanotify_mark.2 |  260 +++++++++++++++++++++++
 man7/fanotify.7      |  576 ++++++++++++++++++++++++++++++++++++++++++++++++++
 man7/inotify.7       |    1 +
 4 files changed, 1038 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..a27de6c
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,201 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-03-22 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_init ()
+initializes a new fanotify group and returns a file descriptor for the event
+queue associated with the group.
+.PP
+The file descriptor is used in calls to
+.BR fanotify_mark (2)
+to specify the files, directories, and mounts fanotify events shall be created.
+These events are received by reading from the file descriptor.
+Some events are only informative, indicating that a file has been accessed.
+Other events can be used to control if another application may access a file,
+or directory.
+Permission to access file system objects is granted by writing to the file
+descriptor.
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+In the current implementation the number of fanotify groups per user is limited
+to 128.
+This limit cannot be overridden.
+.PP
+Calling
+.BR fanotify_init()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Therefore additional local capability checks have been implemented as indicated
+below.
+.PP
+The
+.I flags
+argument contains a multi-bit field defining the usage type of the listening
+application and further single bit fields specifying the behavior of the file
+descriptor.
+.PP
+The usage type indicates, which kind of operations will be executed.
+Only one of the following values may be used when calling
+.BR fanotify_init ().
+.TP
+.B FAN_CLASS_PRE_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files before they
+contain their final data.
+This may be used hierarchical storage managers.
+.TP
+.B FAN_CLASS_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files when they already
+contain their final content.
+This may be used by malware detection programs.
+.TP
+.B FAN_CLASS_NOTIF
+This is the default value.
+It only allows the receipt of events notifying that a file has been accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners with different values will receive events in the sequence
+.BR FAN_CLASS_PRE_CONTENT ,
+.BR FAN_CLASS_CONTENT ,
+.BR FAN_CLASS_NOTIF .
+The call sequence among listeners of the same value is undefined.
+.PP
+The following bit mask values can be set additionally in
+.IR flags .
+.TP
+.B FAN_CLOEXEC
+This flag sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+This flag enables the non-blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead, if no data is available in a call to
+.BR read (2)
+the error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_UNLIMITED_QUEUE
+This flag removes the limit of 16384 events on the size of the event queue.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+This flag removes the limit of 8192 marks on the number of marks.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+The argument
+.I event_f_flags
+defines the file flags, with which file descriptors for fanotify events shall
+be created.
+For explanations of possible values, see argument
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are:
+.TP
+.B O_RDONLY
+This value allows only read access.
+.TP
+.B O_WRONLY
+This value allows only write access.
+.TP
+.B O_RDWR
+This value allows read and write access.
+.TP
+.B O_CLOEXEC
+This flag enables close-on-exec.
+.TP
+.B O_LARGEFILE
+This flag enables support files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by a fanotify group
+on a 32-bit system.
+.SH RETURN VALUE
+On success,
+.BR fanotify_init ()
+returns a new file descriptor.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+The number of fanotify groups of the user exceeds 128.
+.TP
+.B ENOMEM
+The allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+The operation is not permitted because capability
+.B CAP_SYS_ADMIN
+is missing.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..73cebef
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,260 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-03-22 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify a fanotify mark on a filesystem
+object
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
+.BI "                  uint64_t " mask ", int " dirfd ,
+.BI "                  const char *" pathname );
+.fi
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_mark (2)
+adds, removes, or modifies a fanotify mark on a filesystem.
+.PP
+Read access is needed for the file system object to be marked.
+.PP
+The
+.I fanotify_fd
+argument is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bit mask describing the modification to perform.
+It must include one of the following values:
+.TP
+.B FAN_MARK_ADD
+The events in argument
+.I mask
+will be added to the mark mask (or to the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+The events in paramter
+.I mask
+will be removed from the mark mask (or from the ignore mask).
+.I mask
+must be nonempty or the error
+.TP
+.B FAN_MARK_FLUSH
+Remove all marks from the whole fanotify group.
+If
+.I mask
+contains
+.B FAN_MARK_MOUNT
+all marks for mounts are removed from the group.
+Otherwise all marks for directories and files are removed.
+.PP
+If none of the values above is specified, or more than one is specified, the
+call fails with the error
+.BR EINVAL .
+.PP
+In addition
+.I flags
+may contain zero or more of the following:
+.TP
+.B FAN_MARK_DONT_FOLLOW
+Symbolic links shall not be followed.
+.TP
+.B FAN_MARK_ONLYDIR
+If the the file system object to be marked is not a directory, the error
+.B ENOTDIR
+shall be raised.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount point to be marked.
+If the path is not itself a mount point the mount point containing the path
+will be marked.
+All directories, subdirectories, and the contained files of the mount point
+will be monitored.
+.TP
+.B FAN_MARK_IGNORED_MASK
+The events in argument
+.I mask
+shall be added to or removed from the ignore mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignore mask shall survive modify events.
+If this flag is not set, the ignore mask is cleared, if a modify event occurs
+for the fanotify group.
+.PP
+.I mask
+defines which events shall be listened to (or which shall be ignored).
+It is a bit mask composed of the following values:
+.TP
+.B FAN_ACCESS
+Create an event, when a file is accessed (read).
+.TP
+.B FAN_MODIFY
+Create an event, when a file is modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+Create an event, when a writeable file is closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+Create an event, when a readonly file is closed.
+.TP
+.B FAN_OPEN
+Create an event, when a file is opened.
+.TP
+.B FAN_OPEN_PERM
+Create an event, when a permission to open a file is requested.
+.TP
+.B FAN_ACCESS_PERM
+Create an event, when a permission to execute a file or list a directory is
+requested.
+.TP
+.B FAN_ONDIR
+Events for directories shall be created.
+.TP
+.B FAN_EVENT_ON_CHILD
+Events for the immediate children of marked directories shall be created.
+This does not cover the members of subdirectories.
+To monitor complete directory trees it is necessary to mark the relevant
+mount.
+.PP
+The following composed value is defined
+.TP
+.B FAN_CLOSE
+A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The file system object to be marked is determined by the file descriptor
+.I dirfd
+and the pathname specified in
+.IR pathname :
+.IP * 3
+If 
+.I pathname
+is NULL,
+.I dirfd
+defines the file system object to be marked.
+.IP *
+If
+.I pathname
+is NULL, and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+the current working directory is to be marked.
+.IP *
+If
+.I pathname
+is absolute it defines the file system object to be marked, and
+.I dirfd
+is ignored.
+.IP *
+If
+.I pathname
+is relative, it defines a file system object relative to the directory
+indicated by the file descriptor in
+.I dirfd
+to be marked.
+.IP *
+If
+.I pathname
+is relative and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+.I pathname
+defines a file system object relative to the current working directory to be
+marked.
+.SH RETURN VALUE
+On success
+.BR fanotify_mark ()
+returns 0.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags
+or
+.IR mask ,
+or
+.I fanotify_fd
+was not a fanotify file descriptor.
+.TP
+.B ENOENT
+The file system object indicated by
+.IR dirfd
+and
+.IR pathname
+does not exist.
+This error also occurs when trying to remove a mark from an object which is not
+marked.
+.TP
+.B ENOMEM
+The necessary memory could not be allocated.
+.TP
+.B ENOSPC
+The number of marks exceeds the limit of 8192 and
+.B FAN_UNLIMITED_MARKS
+was not specified in the call to
+.BR fanotify_init (2).
+.TP
+.B ENOTDIR
+.I flags
+contains
+.BR FAN_MARK_ONLYDIR ,
+and
+.I dirfd
+and
+.I pathname
+do not specify a directory.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "BUGS"
+Up to Kernel 3.14
+.I dfd
+and
+.I pathname
+must indicate a valid path, if
+.I flags
+contains
+.B FAN_MARK_FLUSH.
+This path is not used.
+.SH "SEE ALSO"
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..7abc4d2
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,576 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-03-24 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases are virus scanning and hierarchical storage management.
+Currently only a limited set of events is supported.
+Up to now there is no support for create, delete, and move events.
+
+Additinal capabilities compared to the
+.IR inotify (7)
+API are monitoring of complete mounts, access permission decisions, and the
+possibility to read or modify files before access by other applications.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes a fanotify notification group and returns a file
+descriptor referring to it.
+.PP
+A fanotify notification group is an internal object of the kernel which holds a
+list of files, directories and mount points for which events shall be created.
+.PP
+For each entry in a fanotify notification group, two bit masks exist.
+One mask (the mark mask) defines for which file activities an event shall be
+created.
+Another mask (the ignore mask) defines for which activities no event shall be
+created.
+Having these two types of masks allows that a mount point or directory is
+marked for receiving events, while at the same time ignoring events for
+specified contained file system objects.
+.PP
+A possible usage of the ignore mask is for a file cache.
+Events of interest for a file cache are modification of a file and closing
+of the same. Hence the cached directory or mount point is to be marked to
+receive these events.
+After receiving the first event informing that a file has been modified, the
+corresponding cache entry will be invalidated.
+No further modification events for this file are of interest until the file is
+closed.
+Hence the modify event can be added to the ignore mask.
+Upon receiving the closed event, the modify event can be removed from the
+ignore mask and the file cache entry can be updated.
+.PP
+The entries in the fanotify notification groups refer to files and directories
+via their inode number and to mounts via their mount id.
+If files or directories are renamed or moved the respective entries survive.
+If files or directories are deleted or mounts are unmounted the corresponding
+entries are deleted.
+.PP
+Two types of events exist.
+Notification events are only informative and require no action to be taken by
+the receiving application except for closing the file descriptor passed in the
+event.
+Permission events are requests to the receiving application to decide whether
+permission for a file access shall be granted.
+For these events, the recipient has to write a response which decides whether
+access is granted or not.
+.PP
+When all file descriptors referring to the fanotify notification group are
+closed, the fanotify group is released and the resources are freed for reuse by
+the kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, a directory, or a mount to the group and specifies which events
+shall be reported (or ignored), or removes or modifies such an entry.
+.PP
+When a fanotify event occurs, the fanotify file descriptor indicates as
+readable when passed to
+.BR epoll (7),
+.BR poll (2),
+or
+.BR select (2).
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if the flag
+.B FAN_NONBLOCK
+is not specified in the call to
+.BR fanotify_init (2)),
+until either a file event occurs or it is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or \-1 in case of an error.
+In case of success, the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+This is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.I fanotify_event_metadata.
+Therefore, it is recommended to use a larger buffer size when reading,
+for example 4096 bytes.
+.TP
+.I vers
+This field holds a version number for the structures.
+It must be compared to
+.B FANOTIFY_METADATA_VERSION
+to verify that the structures at runtime match the structures at compile
+time.
+In case of a mismatch, the fanotify file descriptor has to be closed.
+.TP
+.I reserved
+This field is not used.
+.TP
+.I metadata_len
+This is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+Non exist yet.
+.TP
+.I mask
+This is a bit mask describing the event.
+.TP
+.I fd
+This is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The file descriptor can be used to access the contents of the monitored file or
+directory.
+It has flag
+.B FMODE_NONOTIFY
+set (see
+.BR fcntl (2)).
+This flag suppresses fanotify event generation.
+Hence when the receiver of the fanotify event accesses the notified file or
+directory using this file descriptor no additional events will be created.
+The reading application is responsible for closing the file descriptor.
+.TP
+.I pid
+This is the ID of the process that caused the event.
+A program listening to fanotify events can compare this PID to the PID returned
+by
+.BR getpid (2),
+to detect, if the event is caused by the listener itself, or is due to a file
+access by another program.
+.PP
+The bit mask in
+.I mask
+signals which events have occured for a single file system object.
+More than one of the following flags can be set at once in the bit mask.
+.TP
+.B FAN_ACCESS
+A file was accessed.
+.TP
+.B FAN_OPEN
+A file was opened.
+.TP
+.B FAN_MODIFY
+A file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+A read-only file was closed.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue exceeded the limit of 16384 entries.
+This limit can be overriden in the call to
+.BR fanotify_init (2)
+by setting flag
+.BR FAN_UNLIMITED_QUEUE .
+.TP
+.B FAN_ACCESS_PERM
+An application wants to execute a file or list a directory.
+A decision has to be taken, if the permission to access the file system object
+shall be granted.
+.TP
+.B FAN_OPEN_PERM
+An application wants to open a file or directory.
+A decision has to be taken, if the permission to open the file system object
+shall be granted.
+.PP
+To check for any close event, the following bit mask may be used:
+.TP
+.B FAN_CLOSE
+A file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer with fanotify
+event metadata returned by
+.IR read (2)
+from a fanotify file descriptor.
+.TP
+.B FAN_EVENT_OK(meta, len)
+This macro checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+This macro sets the pointer
+.I meta
+to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.I len.
+.PP
+For permission events, the application must
+.BR write (2)
+a structure of the following form to the 
+.B fanotify
+file descriptor:
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+This is the file descriptor from the structure
+.IR fanotify_event_metadata.
+.TP
+.I response
+This field indicates whether or not the permission is to be granted.
+Its value must be either
+.B FAN_ALLOW
+to allow the file operation or
+.B FAN_DENY
+to deny the file operation.
+.PP
+If access has been denied the requesting application call will receive an
+error
+.BR EPERM .
+.PP
+To end listening, it is sufficient to
+.BR close (2)
+the fanotify file descriptor.
+The outstanding permission events will be set to allowed, and all resources
+will be returned to the kernel.
+.PP
+The file 
+.I /proc/<pid>/fdinfo/<fd>
+contains information about fanotify marks for file descriptor fd of process
+pid.
+See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+In addition to the usual errors for
+.IR read (2),
+the following errors can occur when reading from the fanotify file descriptor:
+.TP
+.B EINVAL
+The buffer is too short to hold the event.
+.TP
+.B EMFILE
+Too many files are open.
+.TP
+.B ETXTBSY
+A write enabled file descriptor shall be created for a file that is executing.
+This occurs if
+.IR fanotify_init (2)
+was called with
+.B O_RDWR
+or
+.B O_WRONLY
+and an event for a monitored file, which is executed, is read.
+.PP
+In addition to the usual errors for
+.IR write (2),
+the following errors can occur when writing to the fanotify file descriptor:
+.TP
+.B EINVAL
+Fanotify access permissions are not enabled in the Kernel configuration or the
+value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+The file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The fanotify API was introduced in version 2.6.36 of the Linux kernel and
+enabled in version 2.6.37.
+Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The fanotify API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+To enable the fanotify API the following setting in the Kernel configuration is
+needed:
+CONFIG_FANOTIFY=y. For permission handling
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API.
+It marks the mount passed as argument and waits for events of type
+.B FAN_PERM_OPEN
+and
+.BR FAN_CLOSE_WRITE .
+When a permission event occurs, a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file 
+.IR /home/user/temp/notes .
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occurred.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occurred.
+The example program ended when hitting the enter key.
+.SS Example output
+.in +4n
+.nf
+#define _GNU_SOURCE // needed for O_LARGEFILE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+/* Read all available fanotify events from the file descriptor 'fd' */
+
+int
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    ssize_t len;
+    char path[PATH_MAX];
+    ssize_t path_len;
+    char procfd_path[PATH_MAX];
+    struct fanotify_response response;
+
+    /* Loop while events can be read from fanotify file descriptor. */
+
+    for(;;) {
+
+        /* Read some events. */
+
+        len = read(fd, (void *) &buf, sizeof(buf));
+        if (len == \-1 && errno != EINTR) {
+            perror("read");
+            return EXIT_FAILURE;
+        }
+
+        /* Check if end of available data reached. */
+
+        if (len == 0)
+            break;
+
+        /* Point to the first event in the buffer. */
+
+        metadata = (struct fanotify_event_metadata *) buf;
+
+        /* Loop over all events in the buffer. */
+
+        while (FAN_EVENT_OK(metadata, len)) {
+
+            /* Assert that run time and compile time structures match. */
+
+            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
+                fprintf(stderr, "Mismatch of fanotify metadata version.\\n");
+                return EXIT_FAILURE;
+            }
+
+            /* Check that the event contains a file descriptor. */
+
+            if (metadata\->fd >= 0) {
+
+                /* Handle open permission event. */
+
+                if (metadata\->mask & FAN_OPEN_PERM) {
+                    printf("FAN_OPEN_PERM: ");
+
+                    /* Allow file to be opened. */
+
+                    response.fd = metadata\->fd;
+                    response.response = FAN_ALLOW;
+                    write(fd, &response, sizeof(
+                              struct fanotify_response));
+                }
+
+                /* Handle closing of writable file event. */
+
+                if (metadata\->mask & FAN_CLOSE_WRITE) {
+                    printf("FAN_CLOSE_WRITE: ");
+                }
+
+                /* Determine path of the file accessed. */
+
+                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");
+                    return EXIT_FAILURE;
+                }
+
+                path[path_len] = '\\0';
+                printf("File %s", path);
+
+                /* Close the file descriptor of the event. */
+
+                close(metadata\->fd);
+                printf("\\n");
+            }
+
+            /* Forward pointer to next event. */
+
+            metadata = FAN_EVENT_NEXT(metadata, len);
+        }
+    }
+    return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char *argv[])
+{
+    char buf;
+    int fd, poll_num, ret;
+    nfds_t nfds;
+    struct pollfd fds[2];
+    ret = EXIT_SUCCESS;
+
+    /* Check mount point is supplied. */
+
+    if (argc != 2) {
+        printf("Usage: %s MOUNT\\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("Press enter key to terminate.\\n");
+
+    /* Create the file descriptor for accessing the fanotify API. */
+
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return EXIT_FAILURE;
+    }
+
+    /* Mark the mount for
+       \- permission events before opening files
+       \- notification events after closing a write enabled file descriptor. */
+
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
+                      argv[1]) == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return EXIT_FAILURE;
+    }
+
+    /* Prepare for polling. */
+
+    nfds = 2;
+
+    /* Console input. */
+
+    fds[0].fd = STDIN_FILENO;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+
+    /* Fanotify input. */
+
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    /* This is the loop to wait for incoming events. */
+
+    printf("Listening for events.\\n");
+    while (ret == EXIT_SUCCESS) {
+        poll_num = poll(fds, nfds, \-1);
+        if (poll_num > 0) {
+            if (fds[0].revents & POLLIN) {
+
+                /* Console input is available. Empty stdin and quit. */
+
+                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
+                    continue;
+                break;
+            }
+            if (fds[1].revents & POLLIN) {
+
+                /* Fanotify events are available. */
+
+                ret = handle_events(fd);
+                fds[1].revents = 0;
+            }
+        } else if (poll_num == \-1 && errno != EINTR) {
+            perror("poll");
+            ret = EXIT_FAILURE;
+        }
+    }
+
+    /* Close fanotify file descriptor. */
+
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return ret;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
diff --git a/man7/inotify.7 b/man7/inotify.7
index e1cabe2..f9605ef 100644
--- a/man7/inotify.7
+++ b/man7/inotify.7
@@ -505,6 +505,7 @@ instead checked if the most recent event could be coalesced with the
 .I oldest
 unread event.
 .SH SEE ALSO
+.BR fanotify (7),
 .BR inotifywait (1),
 .BR inotifywatch (1),
 .BR inotify_add_watch (2),
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/1] Manpages for the fanotify API
       [not found]                         ` <1396742468-4752-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-04-06 12:18                           ` Michael Kerrisk (man-pages)
       [not found]                             ` <5341461A.3090405-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2014-04-07  8:56                           ` [PATCH 0/1] Manpages for the fanotify API Jan Kara
  1 sibling, 1 reply; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-04-06 12:18 UTC (permalink / raw)
  To: xypron.glpk-Mmb7MZpHnFY
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ

Hello Heinrich,

Thanks for the new drafts.

I'm teaching a course over the coming week, so it may sometime before I can
do a detailed review of the pages. I have a few comments in the meantime:

On 04/06/2014 02:01 AM, xypron.glpk-Mmb7MZpHnFY@public.gmane.org wrote:
> From: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> 
> Hello Michael,
> 
> please, find the answer to your most prominent questions
> in this mail.
> 
> I put the patch into a separate mail.
> 
> Best regards
> 
> Heinrich Schuchardt
> 
> ==
> 
>  >> The pages say nothing about merging of events. Merging can happen
>  >> for non-permission events, but not for permission events.
>  >> Something needs to be said about this, probably in fanotify(7)
>  >> If you are unsure of what I mean, just add the following in
>  >> fanotify(7)
> 
> You missed this sentence: "The bitmask in mask signals which events
> have occured for a single file system object. More than one of the
> following flags can be set at once in the bitmask."
> 
> Jan Kara wrote, that the only guarantee given is, that no two
> permission events will be merged.
> 
> I reworked fanotify.7.

I think you've misunderstood what I mean by merging.

Say there is a read on a file being monitored with FAN_CLASS_NOTIFY. 
Suppose also that the reader of the fanotify FD does not yet
read the event. Now suppose a second read occurs on the monitored
file. Are there now two events in the queue, or one (because the 
identical events have been merged)? For "inotify", the answer 
is "1". I suspect it is the same for fanotify. The man page
should say something about this (if I am correct).

> ==
> 
> There needs to be some explanation of the events that are generated
> for directories. To begin with, *which* events are generated for
> directories?
> 
> * opening a directory for reading gives FAN_OPEN
> * closing the file descriptor from the previous
>   step gives FAN_CLOSE
> * Changing the directory contents (adding a file)
>   seems to give no event for the directory itself
>   (but will give an event on the new file, if we
>   are monitoring children of the directory)
> * Other???

Did the piece of text above get overlooked?

> ==
> 
>  >> I asked this earlier (in a different wording), but it seems not to
>  >> have been addressed:
>  >>
>  >>    What happens if the application hits its file descriptor limit
>  >>    (RLIMIT_NOFILES) when handling read()s from the FAN FD? (EMFILE).
>  >>
>  >> This needs to be covered under the errors for read(2).
> When diving deeper into the code EMFILE can be found in get_unusedfd.
> FIXED in fanotify.7

Your text needs to explicitly mention the RLIMIT_NOFILES limit.
There are other reasons for "too many files open" (e.g., ENFILE).

>  >> And now I think of a related question: what if we hit the system-wide
>  >> limit on the number of open files (/proc/sys/fs/file-max)? (I suspect
>  >> ENFILE.)
> I could not verify this. But I guess you can reproduce all error codes
> of open(2) in some part of the fanotify API.

I'd add ENFILE to the list of errors, mentioning that its cause is hitting
the system-wide limit on the number of open files (/proc/sys/fs/file-max)

> ==
> 
>  >> I notice that the FDs returned by read()s from the FAN FD have the
>  >> FMODE_NONOTIFY flag (fcntl(F_GETFL)) flag set. If you know what that's
>  >> about, it would be good to say something about. But, if not, do not
>  >> worry--just place a FIXME in the page source of fanotify(7)
> 
> Fixed in fanotify.7
> If the listener accesses the file through the file descriptor provided
> no additional events are created.

Ahh -- thanks for filling in that piece. I see that you refer to 
fcntl(2) when discussing that flag. But fcntl(2) does not
mention that flag. I would rather see an explanation of this flag 
in the fanotify pages.

> ==
> 
>  >> It all depends how you pronounce the name, but I assume "F-A-notify"
>  >> and so I'd always write it as "an fanotify" (and in multiple places below).
> 
> No indication has been given by Eric Paris that the first letters of fanotify
> are an abbreviation, so I think of fanotify as a proper name pronounced
> [fænoutifai].
> Cf. http://lkml.iu.edu/hypermail/linux/kernel/0907.3/00243.html

I'm not sure what I should be noting in that URL.

See Eric's usage ("an fanotify") in these places:

http://lwn.net/Articles/339253/
https://lkml.org/lkml/2010/8/22/94
https://lkml.org/lkml/2009/8/28/258

> ==
> 
>  >> +    // Mark the mount for
>  >> >+    // \- permission events before opening files
>  >> >+    // \- notification events after closing a write enabled file descriptor.
>  >> >+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
>  >> >+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, FAN_NOFD,
>> Why 'FAN_NOFD' here?
>>
>  >> >+                      argv[1]) == \-1) {
>  >> >+        perror("fanotify_mark");
>  >> >+        close(fd);
>  >> >+        return EXIT_FAILURE;
>  >> >+    }
> 
> As described in fanotify_mark(2) the value of dfd is irrelevant if pathname is not NULL.
> 
> FAN_NOFD takes the value -1, which no file descriptor ever can have.
> 
> I changed this to -1 now.

My point was that FAN_NOFD is a constant used by another part of the API. It's
confusing to have it pop up here, even if it is ignored. Thanks for making
the change.

> ==
>  >>> The structures fanotify_event_metadata and fanotify_response have been
>  >>> changed repeatedly.
> 
>  >> Have they? I don't know. But this statement is rather strong. Is it correct?
>  >> If it is true, it would be good to mention a few of the changes, and when
>  >> they occurred.
> In the Git log you will find at least 4 different version. With fields added
> and removed, alignment changed, and fieldtype changed. The last change was in
>  2.6.37. I removed the sentence with repeatedly. It is sufficient to indicate
> that the value of the field should be checked.

Thanks. This was my point really: there have been no version
changes since the API was released to user space. Thanks
for the wording change.

==

I noticed some of the following that need to be fixed:
* "file system" ==> "filesystem"
* New sentences should be started on new source lines.

==

Some other questions that I think of in the light of recent changes I made to
inotify(7) (see http://man7.org/linux/man-pages/man7/inotify.7.html#NOTES):

       Inotify reports only events that a user-space program triggers
       through the filesystem API.  As a result, it does not catch remote
       events that occur on network filesystems. [...]  Furthermore,
       various pseudo-filesystems such as /proc, /sys, and /dev/pts are not
       monitorable with inotify.

       The inotify API does not report file accesses and modifications that
       may occur because of mmap(2) and msync(2).

Do there need to be analogous statements in fanotify(7)? I expect so.

Could I ask you to address the comments in this mail in a new draft of
the pages. I'd hope then to be able to review that next draft in a
week or so.

Cheers,

Michael



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/1] Manpages for the fanotify API
       [not found]                             ` <5341461A.3090405-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-04-07  8:48                               ` Jan Kara
  2014-04-13 14:05                               ` fanotify API: FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME Heinrich Schuchardt
  2014-04-20 11:56                               ` [PATCH 1/1] Manpages for the fanotify API Heinrich Schuchardt
  2 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-04-07  8:48 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: xypron.glpk-Mmb7MZpHnFY, linux-man-u79uwXL29TY76Z2rM5mHXA,
	eparis-H+wXaHxf7aLQT0dZR+AlfA, jack-AlSwsSmVLrQ

On Sun 06-04-14 14:18:34, Michael Kerrisk (man-pages) wrote:
> >  >> The pages say nothing about merging of events. Merging can happen
> >  >> for non-permission events, but not for permission events.
> >  >> Something needs to be said about this, probably in fanotify(7)
> >  >> If you are unsure of what I mean, just add the following in
> >  >> fanotify(7)
> > 
> > You missed this sentence: "The bitmask in mask signals which events
> > have occured for a single file system object. More than one of the
> > following flags can be set at once in the bitmask."
> > 
> > Jan Kara wrote, that the only guarantee given is, that no two
> > permission events will be merged.
> > 
> > I reworked fanotify.7.
> 
> I think you've misunderstood what I mean by merging.
> 
> Say there is a read on a file being monitored with FAN_CLASS_NOTIFY. 
> Suppose also that the reader of the fanotify FD does not yet
> read the event. Now suppose a second read occurs on the monitored
> file. Are there now two events in the queue, or one (because the 
> identical events have been merged)? For "inotify", the answer 
> is "1". I suspect it is the same for fanotify. The man page
> should say something about this (if I am correct).
  For FAN_CLASS_NOTIFY, there's only one event in the queue in the same
way as for inotify. Actually fanotify is even more aggressive in merging
events and if you monitor for read & write and the application does read,
write, read, there will still be only one event in the queue whose mask
will be FAN_ACCESS | FAN_MODIFY.

However if you monitor with FAN_CLASS_CONTENT or FAN_CLASS_PRE_CONTENT and
you ask for doing access validation (FAN_OPEN_PERM, FAN_ACCESS_PERM mark
types), then the resuling events will not be merged. I.e. two consecutive
reads of the same file result in two FAN_ACCESS_PERM events in the queue.
If the file is also watched e.g. for FAN_MODIFY, such event may but needn't
be merged with the FAN_ACCESS_PERM events (what happens will be actually
dependent on kernel version).

								Honza
-- 
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/1] Manpages for the fanotify API
       [not found]                         ` <1396742468-4752-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  2014-04-06 12:18                           ` Michael Kerrisk (man-pages)
@ 2014-04-07  8:56                           ` Jan Kara
       [not found]                             ` <20140407085624.GB14927-+0h/O2h83AeN3ZZ/Hiejyg@public.gmane.org>
  1 sibling, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-04-07  8:56 UTC (permalink / raw)
  To: xypron.glpk-Mmb7MZpHnFY
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA,
	jack-AlSwsSmVLrQ

On Sun 06-04-14 02:01:08, xypron.glpk-Mmb7MZpHnFY@public.gmane.org wrote:
> There needs to be some explanation of the events that are generated
> for directories. To begin with, *which* events are generated for
> directories?
> 
> * opening a directory for reading gives FAN_OPEN
> * closing the file descriptor from the previous
>   step gives FAN_CLOSE
> * Changing the directory contents (adding a file)
>   seems to give no event for the directory itself
>   (but will give an event on the new file, if we
>   are monitoring children of the directory)
> * Other???
  That's correct. fanotify doesn't give you any other events for
directories. It's really only useful for watching files and their contents.

> FAN_ACCESS_PERM
> The name is misleading. The permission check is done before executing a file
> or listing a directory.
  AFAIK it doesn't happen before listing a directory. But if you are
convinced it does, I can check more carefully ;)

								Honza
-- 
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/1] Manpages for the fanotify API: FAN_ACCESS_PERM for readdir
       [not found]                             ` <20140407085624.GB14927-+0h/O2h83AeN3ZZ/Hiejyg@public.gmane.org>
@ 2014-04-07 18:16                               ` Heinrich Schuchardt
       [not found]                                 ` <5342EB7B.4010201-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-04-07 18:16 UTC (permalink / raw)
  To: Jan Kara
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA

Hello Jan,

> > FAN_ACCESS_PERM
> > The name is misleading. The permission check is done before executing a file
> > or listing a directory.
>   AFAIK it doesn't happen before listing a directory. But if you are
> convinced it does, I can check more carefully ;)

iterate_dir calls
security_file_permission(file, MAY_READ);
which in turn calls
fsnotify_perm(file, mask);
Which has these lines:
  51         else if (mask & MAY_READ)
  52                 fsnotify_mask = FS_ACCESS_PERM;

This is the result I get for
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <libgen.h>
int main() {
     DIR *dir;
     struct dirent *dp;
     if ((dir = opendir ("/home/test")) == NULL) {
         exit (1);
     }
     while ((dp = readdir (dir)) != NULL) {
         }
         closedir(dir);
         return 0;
}

FAN_OPEN: File /home/test
FAN_ACCESS_PERM: File /home/test
FAN_ACCESS_PERM: File /home/test

I guess it is somewhat inconsistent that
readdir results in FAN_ACCESS_PERM while
read results in FAN_ACCESS_PERM and FAN_ACCESS.

===

This is the result I get for executing
/home/test/test
which contains the following lines
!#/bin/sh
echo Hello world

FAN_OPEN: File /home/test/test
FAN_ACCESS_PERM: File /home/test/test
FAN_ACCESS: File /home/test/test
FAN_OPEN: File /home/test/test
FAN_ACCESS_PERM: File /home/test/test
FAN_ACCESS: File /home/test/test
FAN_ACCESS_PERM: File /home/test/test

The last FAN_ACCESS_PERM probably does not relate to a read() as it is 
not followed by FAN_ACCESS.

===

When running
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
     int fd;
     char buf[4096];
     ssize_t len;
     fd = open("/home/test/test", O_RDONLY);
     len = read(fd, buf, 4096);
     buf[len] = '\0';
     printf("Bytes read %d\n%s\n", len, buf);
     close(fd);
     return 0;
}

I get

FAN_OPEN: File /home/test/test
FAN_ACCESS_PERM: File /home/test/test
FAN_ACCESS: File /home/test/test

When running
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
         int fd;
         char buf[4096];
         ssize_t len;
     fd = open("/home/test/test", O_WRONLY);
     len = write(fd, "visited" , 4);
         close(fd);
         return 0;
}

I get

FAN_OPEN: File /home/test/test
FAN_MODIFY: File /home/test/test

You only receive a permission event before reading and not before writing.

The fanotify API was meant for use in a hierarchical storage management 
system. Should it not be able to inhibit writing, e.g. if the remote 
file is on a read-only medium?

I guess it would make sense to add a FAN_MODIFY_PERM event.

Best regards

Heinrich Schuchardt


--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 0/1] Manpages for the fanotify API: FAN_ACCESS_PERM for readdir
       [not found]                                 ` <5342EB7B.4010201-Mmb7MZpHnFY@public.gmane.org>
@ 2014-04-07 20:13                                   ` Jan Kara
  0 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-04-07 20:13 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Jan Kara, mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w,
	linux-man-u79uwXL29TY76Z2rM5mHXA, eparis-H+wXaHxf7aLQT0dZR+AlfA

On Mon 07-04-14 20:16:27, Heinrich Schuchardt wrote:
> Hello Jan,
> 
> >> FAN_ACCESS_PERM
> >> The name is misleading. The permission check is done before executing a file
> >> or listing a directory.
> >  AFAIK it doesn't happen before listing a directory. But if you are
> >convinced it does, I can check more carefully ;)
> 
> iterate_dir calls
> security_file_permission(file, MAY_READ);
> which in turn calls
> fsnotify_perm(file, mask);
> Which has these lines:
>  51         else if (mask & MAY_READ)
>  52                 fsnotify_mask = FS_ACCESS_PERM;
  Ah, OK, for FAN_ACCESS_PERM. But as you note below FAN_ACCESS isn't
generated for directories. That actually looks pretty inconsistent and I
guess we should fix that.

> This is the result I get for
> #include <stdlib.h>
> #include <sys/types.h>
> #include <dirent.h>
> #include <libgen.h>
> int main() {
>     DIR *dir;
>     struct dirent *dp;
>     if ((dir = opendir ("/home/test")) == NULL) {
>         exit (1);
>     }
>     while ((dp = readdir (dir)) != NULL) {
>         }
>         closedir(dir);
>         return 0;
> }
> 
> FAN_OPEN: File /home/test
> FAN_ACCESS_PERM: File /home/test
> FAN_ACCESS_PERM: File /home/test
> 
> I guess it is somewhat inconsistent that
> readdir results in FAN_ACCESS_PERM while
> read results in FAN_ACCESS_PERM and FAN_ACCESS.
> 
> ===
> 
> This is the result I get for executing
> /home/test/test
> which contains the following lines
> !#/bin/sh
> echo Hello world
> 
> FAN_OPEN: File /home/test/test
> FAN_ACCESS_PERM: File /home/test/test
> FAN_ACCESS: File /home/test/test
> FAN_OPEN: File /home/test/test
> FAN_ACCESS_PERM: File /home/test/test
> FAN_ACCESS: File /home/test/test
> FAN_ACCESS_PERM: File /home/test/test
> 
> The last FAN_ACCESS_PERM probably does not relate to a read() as it
> is not followed by FAN_ACCESS.
> 
> ===
> 
> When running
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> int main(int argc, char *argv[]) {
>     int fd;
>     char buf[4096];
>     ssize_t len;
>     fd = open("/home/test/test", O_RDONLY);
>     len = read(fd, buf, 4096);
>     buf[len] = '\0';
>     printf("Bytes read %d\n%s\n", len, buf);
>     close(fd);
>     return 0;
> }
> 
> I get
> 
> FAN_OPEN: File /home/test/test
> FAN_ACCESS_PERM: File /home/test/test
> FAN_ACCESS: File /home/test/test
> 
> When running
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> 
> int main(int argc, char *argv[]) {
>         int fd;
>         char buf[4096];
>         ssize_t len;
>     fd = open("/home/test/test", O_WRONLY);
>     len = write(fd, "visited" , 4);
>         close(fd);
>         return 0;
> }
> 
> I get
> 
> FAN_OPEN: File /home/test/test
> FAN_MODIFY: File /home/test/test
> 
> You only receive a permission event before reading and not before writing.
> 
> The fanotify API was meant for use in a hierarchical storage
> management system. Should it not be able to inhibit writing, e.g. if
> the remote file is on a read-only medium?
> 
> I guess it would make sense to add a FAN_MODIFY_PERM event.
  Well, there were different uses for fanotify() (antivirus scanners for
file servers for windows workstations was the one I remember). Storage
management might be one of those. If there's a real demand for
FAN_MODIFY_PERM, I guess we can add that. But I wouldn't like to add that
just because it sounds useful...

								Honza
-- 
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: fanotify API: FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME
       [not found]                             ` <5341461A.3090405-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2014-04-07  8:48                               ` Jan Kara
@ 2014-04-13 14:05                               ` Heinrich Schuchardt
  2014-04-20 11:56                               ` [PATCH 1/1] Manpages for the fanotify API Heinrich Schuchardt
  2 siblings, 0 replies; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-04-13 14:05 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, Eric Paris, Jan Kara

On 06.04.2014 14:18, Michael Kerrisk (man-pages) wrote:
>> ==
>> >
>> >  >> I notice that the FDs returned by read()s from the FAN FD have the
>> >  >> FMODE_NONOTIFY flag (fcntl(F_GETFL)) flag set. If you know what that's
>> >  >> about, it would be good to say something about. But, if not, do not
>> >  >> worry--just place a FIXME in the page source of fanotify(7)
>> >
>> >Fixed in fanotify.7
>> >If the listener accesses the file through the file descriptor provided
>> >no additional events are created.
> Ahh -- thanks for filling in that piece. I see that you refer to
> fcntl(2) when discussing that flag. But fcntl(2) does not
> mention that flag. I would rather see an explanation of this flag
> in the fanotify pages.
>

I wrote a small test program and found:

The flag FMODE_NONOTIFY can be read by function fcntl from userspace.
int flag = fcntl(fd, F_GETFL)

In include/uapi/asm-generic/fcntl.h I found the following comment:

/*
  * FMODE_EXEC is 0x20
  * FMODE_NONOTIFY is 0x1000000
  * These cannot be used by userspace O_* until internal and external open
  * flags are split.
  * -Eric Paris
  */

The definition of FMODE_NONOTIFY is in include/linux/fs.h but this
include is only used to compile the Kernel and not supposed to be used 
by userspace.

I think it is quite annoying that fcntl can return a flag that is not
described in the manpage of fcntl and that is not defined in fcntl.h.

But FMODE_NONOTIFY is not the only flag:

I was able to pass
0x20 (FMODE_EXEC), and
0x800 (FMODE_NOCMTIME)
to fanotify_init and received them as flag in the file descriptors for 
the fanotify events.
I wonder why fanotify_init does not check import parameter event_f_flags 
and return an error if any inappropriate value is set.

Should I put this into the BUGS section?

Should the name of the flag FMODE_NONOTIFY be mentioned at all in the 
man pages?

Or should we write:

.I fd
This is an open file descriptor for the object being accessed or
.B FAN_NOFD
if a queue overflow occurred.
The file descriptor can be used to access the contents of the monitored 
file or
directory.
It has an internal flag set, that suppresses fanotify event generation.
Hence when the receiver of the fanotify event accesses the notified file or
directory using this file descriptor no additional events will be created.
The reading application is responsible for closing the file descriptor.

Best regards

Heinrich Schuchardt
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/1] Manpages for the fanotify API
       [not found]                             ` <5341461A.3090405-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2014-04-07  8:48                               ` Jan Kara
  2014-04-13 14:05                               ` fanotify API: FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME Heinrich Schuchardt
@ 2014-04-20 11:56                               ` Heinrich Schuchardt
       [not found]                                 ` <1397994990-9068-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  2 siblings, 1 reply; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-04-20 11:56 UTC (permalink / raw)
  To: Michael Kerrisk
  Cc: Eric Paris, Jan Kara, linux-man-u79uwXL29TY76Z2rM5mHXA,
	Heinrich Schuchardt

This is an update of the patch suggested 2014-04-06.

' Say there is a read on a file being monitored with FAN_CLASS_NOTIFY.
' Suppose also that the reader of the fanotify FD does not yet
' read the event. Now suppose a second read occurs on the monitored
' file. Are there now two events in the queue, or one (because the
' identical events have been merged)? For "inotify", the answer
' is "1". I suspect it is the same for fanotify. The man page
' should say something about this (if I am correct).
Fixed:
Merging is now explicietely mentioned in fanotify.7.

'
'' '==
'' '
'' 'There needs to be some explanation of the events that are generated
'' 'for directories. To begin with,*which*  events are generated for
'' 'directories?
'' '
'' '* opening a directory for reading gives FAN_OPEN
'' '* closing the file descriptor from the previous
'' '   step gives FAN_CLOSE
'' '* Changing the directory contents (adding a file)
'' '   seems to give no event for the directory itself
'' '   (but will give an event on the new file, if we
'' '   are monitoring children of the directory)
'' '* Other???
' Did the piece of text above get overlooked?
Information on directories has been added to fanotify_mark.2 and fanotify.7.

' Your text needs to explicitly mention the RLIMIT_NOFILES limit.
' There are other reasons for "too many files open" (e.g., ENFILE).
Fixed in fanotify.7

' I'd add ENFILE to the list of errors, mentioning that its cause is hitting
' the system-wide limit on the number of open files (/proc/sys/fs/file-max)
Fixed in fanotify.7

' See Eric's usage ("an fanotify") in these places:
Fixed.

' I noticed some of the following that need to be fixed:
' * "file system" ==> "filesystem"
' * New sentences should be started on new source lines.
Fixed.

' Some other questions that I think of in the light of recent changes I made to
' inotify(7) (seehttp://man7.org/linux/man-pages/man7/inotify.7.html#NOTES):
'
'         Inotify reports only events that a user-space program triggers
'         through the filesystem API.  As a result, it does not catch remote
'         events that occur on network filesystems. [...]  Furthermore,
'         various pseudo-filesystems such as /proc, /sys, and /dev/pts are not
'         monitorable with inotify.
'
'         The inotify API does not report file accesses and modifications that
'         may occur because of mmap(2) and msync(2).
'
' Do there need to be analogous statements in fanotify(7)? I expect so.
In fanotify.7#NOTES I added the applicable parts from inotify.
procfs at least creates FAN_OPEN_PERM events.

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 | 201 ++++++++++++++++
 man2/fanotify_mark.2 | 265 +++++++++++++++++++++
 man7/fanotify.7      | 638 +++++++++++++++++++++++++++++++++++++++++++++++++++
 man7/inotify.7       |   1 +
 4 files changed, 1105 insertions(+)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..d7f60e1
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,201 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-04-18 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_init ()
+initializes a new fanotify group and returns a file descriptor for the event
+queue associated with the group.
+.PP
+The file descriptor is used in calls to
+.BR fanotify_mark (2)
+to specify the files, directories, and mounts fanotify events shall be created.
+These events are received by reading from the file descriptor.
+Some events are only informative, indicating that a file has been accessed.
+Other events can be used to control if another application may access a file,
+or directory.
+Permission to access file system objects is granted by writing to the file
+descriptor.
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+In the current implementation the number of fanotify groups per user is limited
+to 128.
+This limit cannot be overridden.
+.PP
+Calling
+.BR fanotify_init()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Therefore additional local capability checks have been implemented as indicated
+below.
+.PP
+The
+.I flags
+argument contains a multi-bit field defining the usage type of the listening
+application and further single bit fields specifying the behavior of the file
+descriptor.
+.PP
+The usage type indicates, which kind of operations will be executed.
+Only one of the following values may be used when calling
+.BR fanotify_init ().
+.TP
+.B FAN_CLASS_PRE_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files before they
+contain their final data.
+This may be used hierarchical storage managers.
+.TP
+.B FAN_CLASS_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files when they already
+contain their final content.
+This may be used by malware detection programs.
+.TP
+.B FAN_CLASS_NOTIF
+This is the default value.
+It only allows the receipt of events notifying that a file has been accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners with different values will receive events in the sequence
+.BR FAN_CLASS_PRE_CONTENT ,
+.BR FAN_CLASS_CONTENT ,
+.BR FAN_CLASS_NOTIF .
+The call sequence among listeners of the same value is undefined.
+.PP
+The following bit mask values can be set additionally in
+.IR flags .
+.TP
+.B FAN_CLOEXEC
+This flag sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+This flag enables the non-blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead, if no data is available in a call to
+.BR read (2)
+the error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_UNLIMITED_QUEUE
+This flag removes the limit of 16384 events on the size of the event queue.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+This flag removes the limit of 8192 marks on the number of marks.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+The argument
+.I event_f_flags
+defines the file flags, with which file descriptors for fanotify events shall
+be created.
+For explanations of possible values, see argument
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are:
+.TP
+.B O_RDONLY
+This value allows only read access.
+.TP
+.B O_WRONLY
+This value allows only write access.
+.TP
+.B O_RDWR
+This value allows read and write access.
+.TP
+.B O_CLOEXEC
+This flag enables close-on-exec.
+.TP
+.B O_LARGEFILE
+This flag enables support files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by an fanotify group
+on a 32-bit system.
+.SH RETURN VALUE
+On success,
+.BR fanotify_init ()
+returns a new file descriptor.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+The number of fanotify groups of the user exceeds 128.
+.TP
+.B ENOMEM
+The allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+The operation is not permitted because capability
+.B CAP_SYS_ADMIN
+is missing.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..70e0473
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,265 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-04-18 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem
+object
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
+.BI "                  uint64_t " mask ", int " dirfd ,
+.BI "                  const char *" pathname );
+.fi
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_mark (2)
+adds, removes, or modifies an fanotify mark on a filesystem.
+.PP
+Read access is needed for the filesystem object to be marked.
+.PP
+The
+.I fanotify_fd
+argument is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bit mask describing the modification to perform.
+It must include one of the following values:
+.TP
+.B FAN_MARK_ADD
+The events in argument
+.I mask
+will be added to the mark mask (or to the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+The events in paramter
+.I mask
+will be removed from the mark mask (or from the ignore mask).
+.I mask
+must be nonempty or the error
+.TP
+.B FAN_MARK_FLUSH
+Remove all marks from the whole fanotify group.
+If
+.I mask
+contains
+.B FAN_MARK_MOUNT
+all marks for mounts are removed from the group.
+Otherwise all marks for directories and files are removed.
+.PP
+If none of the values above is specified, or more than one is specified, the
+call fails with the error
+.BR EINVAL .
+.PP
+In addition
+.I flags
+may contain zero or more of the following:
+.TP
+.B FAN_MARK_DONT_FOLLOW
+Symbolic links shall not be followed.
+.TP
+.B FAN_MARK_ONLYDIR
+If the the filesystem object to be marked is not a directory, the error
+.B ENOTDIR
+shall be raised.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount point to be marked.
+If the path is not itself a mount point the mount point containing the path
+will be marked.
+All directories, subdirectories, and the contained files of the mount point
+will be monitored.
+.TP
+.B FAN_MARK_IGNORED_MASK
+The events in argument
+.I mask
+shall be added to or removed from the ignore mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignore mask shall survive modify events.
+If this flag is not set, the ignore mask is cleared, if a modify event occurs
+for the fanotify group.
+.PP
+.I mask
+defines which events shall be listened to (or which shall be ignored).
+It is a bit mask composed of the following values:
+.TP
+.B FAN_ACCESS
+Create an event, when a file or directory (see BUGS) is accessed (read).
+.TP
+.B FAN_MODIFY
+Create an event, when a file is modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+Create an event, when a writeable file is closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+Create an event, when a readonly file or directory is closed.
+.TP
+.B FAN_OPEN
+Create an event, when a file or directory is opened.
+.TP
+.B FAN_OPEN_PERM
+Create an event, when a permission to open a file or directory is requested.
+.TP
+.B FAN_ACCESS_PERM
+Create an event, when a permission to read a file or directory is requested.
+.TP
+.B FAN_ONDIR
+Events for directories shall be created.
+.TP
+.B FAN_EVENT_ON_CHILD
+Events for the immediate children of marked directories shall be created.
+This does not cover the members of subdirectories.
+To monitor complete directory trees it is necessary to mark the relevant
+mount.
+.PP
+The following composed value is defined
+.TP
+.B FAN_CLOSE
+A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The filesystem object to be marked is determined by the file descriptor
+.I dirfd
+and the pathname specified in
+.IR pathname :
+.IP * 3
+If 
+.I pathname
+is NULL,
+.I dirfd
+defines the filesystem object to be marked.
+.IP *
+If
+.I pathname
+is NULL, and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+the current working directory is to be marked.
+.IP *
+If
+.I pathname
+is absolute it defines the filesystem object to be marked, and
+.I dirfd
+is ignored.
+.IP *
+If
+.I pathname
+is relative, it defines a filesystem object relative to the directory
+indicated by the file descriptor in
+.I dirfd
+to be marked.
+.IP *
+If
+.I pathname
+is relative and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+.I pathname
+defines a filesystem object relative to the current working directory to be
+marked.
+.SH RETURN VALUE
+On success
+.BR fanotify_mark ()
+returns 0.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags
+or
+.IR mask ,
+or
+.I fanotify_fd
+was not an fanotify file descriptor.
+.TP
+.B ENOENT
+The filesystem object indicated by
+.IR dirfd
+and
+.IR pathname
+does not exist.
+This error also occurs when trying to remove a mark from an object which is not
+marked.
+.TP
+.B ENOMEM
+The necessary memory could not be allocated.
+.TP
+.B ENOSPC
+The number of marks exceeds the limit of 8192 and
+.B FAN_UNLIMITED_MARKS
+was not specified in the call to
+.BR fanotify_init (2).
+.TP
+.B ENOTDIR
+.I flags
+contains
+.BR FAN_MARK_ONLYDIR ,
+and
+.I dirfd
+and
+.I pathname
+do not specify a directory.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH CONFORMING TO
+This system call is Linux-specific.
+.SH BUGS
+Up to Kernel 3.15
+.I dfd
+and
+.I pathname
+must indicate a valid path, if
+.I flags
+contains
+.B FAN_MARK_FLUSH.
+This path is not used.
+.PP
+Up to Kernel 3.15
+.IR readdir (2)
+does not result in a
+.B FAN_ACCESS
+event.
+.SH SEE ALSO
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..ea8d73b
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,638 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-04-18 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases are virus scanning and hierarchical storage management.
+Currently only a limited set of events is supported.
+Up to now there is no support for create, delete, and move events.
+
+Additinal capabilities compared to the
+.IR inotify (7)
+API are monitoring of complete mounts, access permission decisions, and the
+possibility to read or modify files before access by other applications.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes an fanotify notification group and returns a file
+descriptor referring to it.
+.PP
+An fanotify notification group is an internal object of the kernel which holds
+a list of files, directories and mount points for which events shall be
+created.
+.PP
+For each entry in an fanotify notification group, two bit masks exist.
+One mask (the mark mask) defines for which file activities an event shall be
+created.
+Another mask (the ignore mask) defines for which activities no event shall be
+created.
+Having these two types of masks allows that a mount point or directory is
+marked for receiving events, while at the same time ignoring events for
+specified contained filesystem objects.
+.PP
+A possible usage of the ignore mask is for a file cache.
+Events of interest for a file cache are modification of a file and closing
+of the same. Hence the cached directory or mount point is to be marked to
+receive these events.
+After receiving the first event informing that a file has been modified, the
+corresponding cache entry will be invalidated.
+No further modification events for this file are of interest until the file is
+closed.
+Hence the modify event can be added to the ignore mask.
+Upon receiving the closed event, the modify event can be removed from the
+ignore mask and the file cache entry can be updated.
+.PP
+The entries in the fanotify notification groups refer to files and directories
+via their inode number and to mounts via their mount id.
+If files or directories are renamed or moved the respective entries survive.
+If files or directories are deleted or mounts are unmounted the corresponding
+entries are deleted.
+.PP
+Two types of events exist.
+Notification events are only informative and require no action to be taken by
+the receiving application except for closing the file descriptor passed in the
+event.
+Permission events are requests to the receiving application to decide whether
+permission for a file access shall be granted.
+For these events, the recipient has to write a response which decides whether
+access is granted or not.
+.PP
+When all file descriptors referring to the fanotify notification group are
+closed, the fanotify group is released and the resources are freed for reuse by
+the kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, a directory, or a mount to the group and specifies which events
+shall be reported (or ignored), or removes or modifies such an entry.
+.PP
+When an fanotify event occurs, the fanotify file descriptor indicates as
+readable when passed to
+.BR epoll (7),
+.BR poll (2),
+or
+.BR select (2).
+.PP
+All events for a fanotify group are collected in a queue.
+Consecutive events for the same filesystem object and originating from the
+same process may be merged into a single event, with the exception that two
+permission events are never merged into one queue entry.
+Queue entries for notification events are removed, when the event has been
+read.
+Queue entries for permission events are removed, when the permission
+decision has been taken by writing to the fanotify file descriptor.
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if the flag
+.B FAN_NONBLOCK
+is not specified in the call to
+.BR fanotify_init (2)),
+until either a file event occurs or it is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or \-1 in case of an error.
+In case of success, the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+This is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.I fanotify_event_metadata.
+Therefore, it is recommended to use a larger buffer size when reading,
+for example 4096 bytes.
+.TP
+.I vers
+This field holds a version number for the structures.
+It must be compared to
+.B FANOTIFY_METADATA_VERSION
+to verify that the structures at runtime match the structures at compile
+time.
+In case of a mismatch, the fanotify file descriptor has to be closed.
+.TP
+.I reserved
+This field is not used.
+.TP
+.I metadata_len
+This is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+Non exist yet.
+.TP
+.I mask
+This is a bit mask describing the event.
+.TP
+.I fd
+This is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The file descriptor can be used to access the contents of the monitored file or
+directory.
+It has internal flag
+.B FMODE_NONOTIFY
+set.
+This flag suppresses fanotify event generation.
+Hence when the receiver of the fanotify event accesses the notified file or
+directory using this file descriptor no additional events will be created.
+The reading application is responsible for closing the file descriptor.
+.TP
+.I pid
+This is the ID of the process that caused the event.
+A program listening to fanotify events can compare this PID to the PID returned
+by
+.BR getpid (2),
+to detect, if the event is caused by the listener itself, or is due to a file
+access by another program.
+.PP
+The bit mask in
+.I mask
+signals which events have occured for a single filesystem object.
+More than one of the following flags can be set at once in the bit mask.
+.TP
+.B FAN_ACCESS
+A file or a directory (see BUGS) was accessed (read).
+.TP
+.B FAN_OPEN
+A file or a directory was opened.
+.TP
+.B FAN_MODIFY
+A file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+A read-only file or a directory was closed.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue exceeded the limit of 16384 entries.
+This limit can be overriden in the call to
+.BR fanotify_init (2)
+by setting flag
+.BR FAN_UNLIMITED_QUEUE .
+.TP
+.B FAN_ACCESS_PERM
+An application wants to read a file or directory, for example using
+.IR read (2)
+or
+.IR readdir (2).
+A decision has to be taken, if the permission to access the filesystem object
+shall be granted.
+.TP
+.B FAN_OPEN_PERM
+An application wants to open a file or directory.
+A decision has to be taken, if the permission to open the filesystem object
+shall be granted.
+.PP
+To check for any close event, the following bit mask may be used:
+.TP
+.B FAN_CLOSE
+A file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer with fanotify
+event metadata returned by
+.IR read (2)
+from an fanotify file descriptor.
+.TP
+.B FAN_EVENT_OK(meta, len)
+This macro checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+This macro sets the pointer
+.I meta
+to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.I len.
+.PP
+For permission events, the application must
+.BR write (2)
+a structure of the following form to the 
+.B fanotify
+file descriptor:
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+This is the file descriptor from the structure
+.IR fanotify_event_metadata.
+.TP
+.I response
+This field indicates whether or not the permission is to be granted.
+Its value must be either
+.B FAN_ALLOW
+to allow the file operation or
+.B FAN_DENY
+to deny the file operation.
+.PP
+If access has been denied the requesting application call will receive an
+error
+.BR EPERM .
+.PP
+To end listening, it is sufficient to
+.BR close (2)
+the fanotify file descriptor.
+The outstanding permission events will be set to allowed, and all resources
+will be returned to the kernel.
+.PP
+The file 
+.I /proc/<pid>/fdinfo/<fd>
+contains information about fanotify marks for file descriptor fd of process
+pid.
+See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+In addition to the usual errors for
+.IR read (2),
+the following errors can occur when reading from the fanotify file descriptor:
+.TP
+.B EINVAL
+The buffer is too short to hold the event.
+.TP
+.B EMFILE
+Too many files are open.
+By creating a new file descpriptor, the per-process limit for the number of
+open file descriptors, given by
+.BR RLIMIT_NOFILE ,
+would be exceeded.
+See
+.BR getrlimit (2).
+.TP
+.B ENFILE
+Too many open files in system.
+By creating a new file descpriptor, the system wide maximum number of file
+descriptors would be exceeded.
+See
+.I /proc/sys/fs/file-max
+in
+.BR proc (5).
+.TP
+.B ETXTBSY
+A write enabled file descriptor shall be created for a file that is executing.
+This occurs if
+.IR fanotify_init (2)
+was called with
+.B O_RDWR
+or
+.B O_WRONLY
+and an event for a monitored file, which is executed, is read.
+.PP
+In addition to the usual errors for
+.IR write (2),
+the following errors can occur when writing to the fanotify file descriptor:
+.TP
+.B EINVAL
+Fanotify access permissions are not enabled in the Kernel configuration or the
+value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+The file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The fanotify API was introduced in version 2.6.36 of the Linux kernel and
+enabled in version 2.6.37.
+Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The fanotify API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+To enable the fanotify API the following setting in the Kernel configuration is
+needed:
+CONFIG_FANOTIFY=y. For permission handling
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.
+.SS Limitations and caveats
+Fanotify reports only events that a user-space program triggers through the
+filesystem API.
+As a result, it does not catch remote events that occur on network filesystems.
+
+The fanotify API does not report file accesses and modifications that
+may occur because of
+.BR mmap (2),
+.BR msync (2),
+and
+.BR munmap (2).
+
+Events for directories are only created if the directory itself is opened,
+read, and closed.
+Adding, removing, or changing children of a marked directory does not create
+events for the monitored directory itself.
+
+Fanotify monitoring of directories is not recursive: to monitor subdirectories
+under a directory, additional marks must be created.
+Monitoring mounts offers the capability to monitor a whole directory tree.
+
+The event queue can overflow.
+In this case, events are lost.
+.SH BUGS
+Up to Kernel 3.15
+.IR readdir (2)
+does not create a
+.B FAN_ACCESS
+event.
+.PP
+When the file descriptor
+.I fd
+passed in
+.I fanotify_event_metadata
+is created, authorization to read and write the file is not checked.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API.
+It marks the mount passed as argument and waits for events of type
+.B FAN_PERM_OPEN
+and
+.BR FAN_CLOSE_WRITE .
+When a permission event occurs, a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file 
+.IR /home/user/temp/notes .
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occurred.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occurred.
+The example program ended when hitting the enter key.
+.SS Example output
+.in +4n
+.nf
+#define _GNU_SOURCE // needed for O_LARGEFILE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+/* Read all available fanotify events from the file descriptor 'fd' */
+
+int
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    ssize_t len;
+    char path[PATH_MAX];
+    ssize_t path_len;
+    char procfd_path[PATH_MAX];
+    struct fanotify_response response;
+
+    /* Loop while events can be read from fanotify file descriptor. */
+
+    for(;;) {
+
+        /* Read some events. */
+
+        len = read(fd, (void *) &buf, sizeof(buf));
+        if (len == \-1 && errno != EAGAIN) {
+            perror("read");
+            return EXIT_FAILURE;
+        }
+
+        /* Check if end of available data reached. */
+
+        if (len == 0)
+            break;
+
+        /* Point to the first event in the buffer. */
+
+        metadata = (struct fanotify_event_metadata *) buf;
+
+        /* Loop over all events in the buffer. */
+
+        while (FAN_EVENT_OK(metadata, len)) {
+
+            /* Assert that run time and compile time structures match. */
+
+            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
+                fprintf(stderr, "Mismatch of fanotify metadata version.\\n");
+                return EXIT_FAILURE;
+            }
+
+            /* Check that the event contains a file descriptor. */
+
+            if (metadata\->fd >= 0) {
+
+                /* Handle open permission event. */
+
+                if (metadata\->mask & FAN_OPEN_PERM) {
+                    printf("FAN_OPEN_PERM: ");
+
+                    /* Allow file to be opened. */
+
+                    response.fd = metadata\->fd;
+                    response.response = FAN_ALLOW;
+                    write(fd, &response, sizeof(
+                              struct fanotify_response));
+                }
+
+                /* Handle closing of writable file event. */
+
+                if (metadata\->mask & FAN_CLOSE_WRITE) {
+                    printf("FAN_CLOSE_WRITE: ");
+                }
+
+                /* Determine path of the file accessed. */
+
+                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");
+                    return EXIT_FAILURE;
+                }
+
+                path[path_len] = '\\0';
+                printf("File %s", path);
+
+                /* Close the file descriptor of the event. */
+
+                close(metadata\->fd);
+                printf("\\n");
+            }
+
+            /* Forward pointer to next event. */
+
+            metadata = FAN_EVENT_NEXT(metadata, len);
+        }
+    }
+    return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char *argv[])
+{
+    char buf;
+    int fd, poll_num, ret;
+    nfds_t nfds;
+    struct pollfd fds[2];
+    ret = EXIT_SUCCESS;
+
+    /* Check mount point is supplied. */
+
+    if (argc != 2) {
+        printf("Usage: %s MOUNT\\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("Press enter key to terminate.\\n");
+
+    /* Create the file descriptor for accessing the fanotify API. */
+
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return EXIT_FAILURE;
+    }
+
+    /* Mark the mount for
+       \- permission events before opening files
+       \- notification events after closing a write enabled file descriptor. */
+
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
+                      argv[1]) == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return EXIT_FAILURE;
+    }
+
+    /* Prepare for polling. */
+
+    nfds = 2;
+
+    /* Console input. */
+
+    fds[0].fd = STDIN_FILENO;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+
+    /* Fanotify input. */
+
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    /* This is the loop to wait for incoming events. */
+
+    printf("Listening for events.\\n");
+    while (ret == EXIT_SUCCESS) {
+        poll_num = poll(fds, nfds, \-1);
+        if (poll_num > 0) {
+            if (fds[0].revents & POLLIN) {
+
+                /* Console input is available. Empty stdin and quit. */
+
+                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
+                    continue;
+                break;
+            }
+            if (fds[1].revents & POLLIN) {
+
+                /* Fanotify events are available. */
+
+                ret = handle_events(fd);
+                fds[1].revents = 0;
+            }
+        } else if (poll_num == \-1 && errno != EINTR) {
+            perror("poll");
+            ret = EXIT_FAILURE;
+        }
+    }
+
+    /* Close fanotify file descriptor. */
+
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return ret;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
diff --git a/man7/inotify.7 b/man7/inotify.7
index 17462c6..8943604 100644
--- a/man7/inotify.7
+++ b/man7/inotify.7
@@ -753,6 +753,7 @@ instead checked if the most recent event could be coalesced with the
 .I oldest
 unread event.
 .SH SEE ALSO
+.BR fanotify (7),
 .BR inotifywait (1),
 .BR inotifywatch (1),
 .BR inotify_add_watch (2),
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/1] Manpages for the fanotify API
       [not found]                                 ` <1397994990-9068-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-04-22 14:29                                   ` Michael Kerrisk (man-pages)
       [not found]                                     ` <53567CC2.6050708-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-04-22 14:29 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w, Eric Paris, Jan Kara,
	linux-man-u79uwXL29TY76Z2rM5mHXA

Hello Heinrich,

The pages are starting to look *much* better! I still have a number
of comments though.

As before, if you write some replies to my detailed points, that 
would help me keep track of what issues are or are not yet resolved.

=====

In an earlier mail, I commented:

* Can only set permission events if FAN_CLASS_PRE_CONTENT or 
  FAN_CLASS_CONTENT (not FAN_CLASS_CONTENT) was used to create 
  FAN fd. (EINVAL)

Did that get addressed. I can't seem to find relevant text 
covering that case in the pages.

======
On 04/20/2014 01:56 PM, Heinrich Schuchardt wrote:
> This is an update of the patch suggested 2014-04-06.
> 
> ' Say there is a read on a file being monitored with FAN_CLASS_NOTIFY.
> ' Suppose also that the reader of the fanotify FD does not yet
> ' read the event. Now suppose a second read occurs on the monitored
> ' file. Are there now two events in the queue, or one (because the
> ' identical events have been merged)? For "inotify", the answer
> ' is "1". I suspect it is the same for fanotify. The man page
> ' should say something about this (if I am correct).
> Fixed:
> Merging is now explicietely mentioned in fanotify.7.
> 
> '
> '' '==
> '' '
> '' 'There needs to be some explanation of the events that are generated
> '' 'for directories. To begin with,*which*  events are generated for
> '' 'directories?
> '' '
> '' '* opening a directory for reading gives FAN_OPEN
> '' '* closing the file descriptor from the previous
> '' '   step gives FAN_CLOSE
> '' '* Changing the directory contents (adding a file)
> '' '   seems to give no event for the directory itself
> '' '   (but will give an event on the new file, if we
> '' '   are monitoring children of the directory)
> '' '* Other???
> ' Did the piece of text above get overlooked?
> Information on directories has been added to fanotify_mark.2 and fanotify.7.
> 
> ' Your text needs to explicitly mention the RLIMIT_NOFILES limit.
> ' There are other reasons for "too many files open" (e.g., ENFILE).
> Fixed in fanotify.7
> 
> ' I'd add ENFILE to the list of errors, mentioning that its cause is hitting
> ' the system-wide limit on the number of open files (/proc/sys/fs/file-max)
> Fixed in fanotify.7
> 
> ' See Eric's usage ("an fanotify") in these places:
> Fixed.
> 
> ' I noticed some of the following that need to be fixed:
> ' * "file system" ==> "filesystem"
> ' * New sentences should be started on new source lines.
> Fixed.
> 
> ' Some other questions that I think of in the light of recent changes I made to
> ' inotify(7) (seehttp://man7.org/linux/man-pages/man7/inotify.7.html#NOTES):
> '
> '         Inotify reports only events that a user-space program triggers
> '         through the filesystem API.  As a result, it does not catch remote
> '         events that occur on network filesystems. [...]  Furthermore,
> '         various pseudo-filesystems such as /proc, /sys, and /dev/pts are not
> '         monitorable with inotify.
> '
> '         The inotify API does not report file accesses and modifications that
> '         may occur because of mmap(2) and msync(2).
> '
> ' Do there need to be analogous statements in fanotify(7)? I expect so.
> In fanotify.7#NOTES I added the applicable parts from inotify.
> procfs at least creates FAN_OPEN_PERM events.

Thanksfor all of those changes.

> Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> ---
>  man2/fanotify_init.2 | 201 ++++++++++++++++
>  man2/fanotify_mark.2 | 265 +++++++++++++++++++++
>  man7/fanotify.7      | 638 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  man7/inotify.7       |   1 +
>  4 files changed, 1105 insertions(+)
>  create mode 100644 man2/fanotify_init.2
>  create mode 100644 man2/fanotify_mark.2
>  create mode 100644 man7/fanotify.7

As before, I'll comment on fanotify.7 first.

> diff --git a/man7/fanotify.7 b/man7/fanotify.7
> new file mode 100644
> --- /dev/null
> +++ b/man7/fanotify.7
> @@ -0,0 +1,638 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY 7 2014-04-18 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify \- monitoring filesystem events
> +.SH DESCRIPTION
> +The
> +.B fanotify
> +API provides notification and interception of filesystem events.
> +Use cases are virus scanning and hierarchical storage management.

s/are/include/

> +Currently only a limited set of events is supported.

s/Currently/Currently,/

> +Up to now there is no support for create, delete, and move events.

s/Up to now/In particular,/ 
(You already said "Currently", so "Up to now" is not needed, and "
In particular" adds emphasis to the important point.)


> +
> +Additinal capabilities compared to the

Spelling: Additional

> +.IR inotify (7)
> +API are monitoring of complete mounts, access permission decisions, and the
> +possibility to read or modify files before access by other applications.
> +
> +The following system calls are used with this API:
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR poll (2),
> +.BR ppoll (2),
> +.BR read (2),
> +.BR write (2),
> +and
> +.BR close (2).
> +.PP
> +.BR fanotify_init (2)
> +creates and initializes an fanotify notification group and returns a file
> +descriptor referring to it.
> +.PP
> +An fanotify notification group is an internal object of the kernel which holds
> +a list of files, directories and mount points for which events shall be

s/directories/directories,/

> +created.
> +.PP
> +For each entry in an fanotify notification group, two bit masks exist.
> +One mask (the mark mask) defines for which file activities an event shall be
> +created.


Reads a little easier if you write: 
...defines file activities for which an event will be created.

Also, maybe s/created/generated/ is more precise?

> +Another mask (the ignore mask) defines for which activities no event shall be
> +created.

... defines file activities for which no event shall be created/generated.

> +Having these two types of masks allows that a mount point or directory is
> +marked 

Better would be:
Having these two types of masks permits a mount point or directory to be
marked 

> for receiving events, while at the same time ignoring events for
> +specified contained filesystem objects.

s/specified contained filesystem objects/
 /specific objects under that mount point or directory/

> +.PP
> +A possible usage of the ignore mask is for a file cache.
> +Events of interest for a file cache are modification of a file and closing
> +of the same. Hence the cached directory or mount point is to be marked to
> +receive these events.
> +After receiving the first event informing that a file has been modified, the
> +corresponding cache entry will be invalidated.
> +No further modification events for this file are of interest until the file is
> +closed.
> +Hence the modify event can be added to the ignore mask.

s/Hence/Hence,/

> +Upon receiving the closed event, the modify event can be removed from the
> +ignore mask and the file cache entry can be updated.
> +.PP
> +The entries in the fanotify notification groups refer to files and directories
> +via their inode number and to mounts via their mount id.

s/id/ID/

> +If files or directories are renamed or moved the respective entries survive.
> +If files or directories are deleted or mounts are unmounted the corresponding

s/unmounted/unmounted,/

> +entries are deleted.
> +.PP
> +Two types of events exist.

Make it:
Two types of events exist: notification events and permission events.

> +Notification events are only informative and require no action to be taken by
> +the receiving application except for closing the file descriptor passed in the
> +event.
> +Permission events are requests to the receiving application to decide whether
> +permission for a file access shall be granted.
> +For these events, the recipient has to write a response which decides whether
> +access is granted or not.
> +.PP
> +When all file descriptors referring to the fanotify notification group are
> +closed, the fanotify group is released and the resources are freed for reuse by
> +the kernel.
> +.PP
> +.BR fanotify_mark (2)
> +adds a file, a directory, or a mount to the group and specifies which events

Smoother would be:
...adds a file, directory, or mount...

> +shall be reported (or ignored), or removes or modifies such an entry.
> +.PP
> +When an fanotify event occurs, the fanotify file descriptor indicates as
> +readable when passed to
> +.BR epoll (7),
> +.BR poll (2),
> +or
> +.BR select (2).
> +.PP
> +All events for a fanotify group are collected in a queue.

...an fanotify....

> +Consecutive events for the same filesystem object and originating from the
> +same process may be merged into a single event, with the exception that two
> +permission events are never merged into one queue entry.
> +Queue entries for notification events are removed, when the event has been

s/removed,/removed/

> +read.
> +Queue entries for permission events are removed, when the permission

s/removed,/removed/

> +decision has been taken by writing to the fanotify file descriptor.
> +.PP
> +Calling
> +.BR read (2)
> +for the file descriptor returned by
> +.BR fanotify_init (2)
> +blocks (if the flag
> +.B FAN_NONBLOCK
> +is not specified in the call to
> +.BR fanotify_init (2)),

s/,//

> +until either a file event occurs or it is interrupted by a signal

s/it/the call/

> +(see
> +.BR signal (7)).
> +
> +The return value of
> +.BR read (2)
> +is the length of the filled buffer or \-1 in case of an error.
> +In case of success, the read buffer contains one or more of the following
> +structures:
> +
> +.in +4n
> +.nf
> +struct fanotify_event_metadata {
> +    __u32 event_len;
> +    __u8 vers;
> +    __u8 reserved;
> +    __u16 metadata_len;
> +    __aligned_u64 mask;
> +    __s32 fd; 
> +    __s32 pid;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I event_len
> +This is the length of the data for the current event and the offset to the next
> +event in the buffer.
> +This length might be longer than the size of structure
> +.I fanotify_event_metadata.

.IR fanotify_event_metadata .

Also, here, I think you need to add a few words about *why* it might be longer.
Otherwise the reader is left puzzled. (The *why* could eb a forward reference
to some explanatory text lower in the page.)

> +Therefore, it is recommended to use a larger buffer size when reading,
> +for example 4096 bytes.
> +.TP
> +.I vers
> +This field holds a version number for the structures.
> +It must be compared to
> +.B FANOTIFY_METADATA_VERSION
> +to verify that the structures at runtime match the structures at compile
> +time.
> +In case of a mismatch, the fanotify file descriptor has to be closed.
> +.TP
> +.I reserved
> +This field is not used.
> +.TP
> +.I metadata_len
> +This is the length of the structure.
> +The field was introduced to facilitate the implementation of optional headers
> +per event type.
> +Non exist yet.

s/Non exist yet/No such optional headers exist in the current implementation/

> +.TP
> +.I mask
> +This is a bit mask describing the event.
> +.TP
> +.I fd
> +This is an open file descriptor for the object being accessed or
> +.B FAN_NOFD
> +if a queue overflow occurred.
> +The file descriptor can be used to access the contents of the monitored file or
> +directory.
> +It has internal flag

s/has/has the/

> +.B FMODE_NONOTIFY
> +set.
> +This flag suppresses fanotify event generation.
> +Hence when the receiver of the fanotify event accesses the notified file or

s/Hence/Hence,/

> +directory using this file descriptor no additional events will be created.

s/descriptor/descriptor,/

> +The reading application is responsible for closing the file descriptor.
> +.TP
> +.I pid
> +This is the ID of the process that caused the event.
> +A program listening to fanotify events can compare this PID to the PID returned
> +by
> +.BR getpid (2),
> +to detect, if the event is caused by the listener itself, or is due to a file

better would be

    to determine whether the event is caused by the listener itself, or is
    due to a file

> +access by another program.
> +.PP
> +The bit mask in
> +.I mask
> +signals which events have occured for a single filesystem object.

s/occured/occurred/

> +More than one of the following flags can be set at once in the bit mask.
> +.TP
> +.B FAN_ACCESS
> +A file or a directory (see BUGS) was accessed (read).

s/see/but see/

> +.TP
> +.B FAN_OPEN
> +A file or a directory was opened.
> +.TP
> +.B FAN_MODIFY
> +A file was modified.
> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.
> +.TP
> +.B FAN_CLOSE_NOWRITE
> +A read-only file or a directory was closed.

Better:
A file that was opened only for reading was closed.

Now I know that I earlier said that FAN_ONDIR and FAN_EVENT_ON_CHILD
belong in the input events for fanotify_mark(), not here in the 
returned events. Or at least, as far as I can tell, they can't be 
in the returned events--but can you confirm this please.

> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue exceeded the limit of 16384 entries.
> +This limit can be overriden in the call to

s/overriden/overridden/

> +.BR fanotify_init (2)
> +by setting flag
> +.BR FAN_UNLIMITED_QUEUE .
> +.TP
> +.B FAN_ACCESS_PERM
> +An application wants to read a file or directory, for example using
> +.IR read (2)

s/IR/BR/

> +or
> +.IR readdir (2).

s/IR/BR/

> +A decision has to be taken, if the permission to access the filesystem object
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Better:
The reader must write a response that determines whether

> +shall be granted.
> +.TP
> +.B FAN_OPEN_PERM
> +An application wants to open a file or directory.
> +A decision has to be taken, if the permission to open the filesystem object
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The reader must write a response that determines whether

> +shall be granted.
> +.PP
> +To check for any close event, the following bit mask may be used:
> +.TP
> +.B FAN_CLOSE
> +A file was closed 
> +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The following macros are provided to iterate over a buffer with fanotify
> +event metadata returned by
> +.IR read (2)

s/IR/BR/

> +from an fanotify file descriptor.
> +.TP
> +.B FAN_EVENT_OK(meta, len)
> +This macro checks the remaining length
> +.I len
> +of the buffer
> +.I meta
> +against the length of the metadata structure and the
> +.I event_len
> +field of the first metadata structure in the buffer.
> +.TP
> +.B FAN_EVENT_NEXT(meta, len)
> +This macro sets the pointer
> +.I meta
> +to the next metadata structure using the length indicated in the
> +.I event_len
> +field of the metadata structure and reduces the remaining length of the
> +buffer
> +.I len.

.IT len .

> +.PP
> +For permission events, the application must
> +.BR write (2)
> +a structure of the following form to the 
> +.B fanotify
> +file descriptor:
> +
> +.in +4n
> +.nf
> +struct fanotify_response {
> +        __s32 fd;
> +        __u32 response;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I fd
> +This is the file descriptor from the structure
> +.IR fanotify_event_metadata.
> +.TP
> +.I response
> +This field indicates whether or not the permission is to be granted.
> +Its value must be either
> +.B FAN_ALLOW
> +to allow the file operation or
> +.B FAN_DENY
> +to deny the file operation.
> +.PP
> +If access has been denied the requesting application call will receive an

s/denined/denied,/

> +error
> +.BR EPERM .
> +.PP
> +To end listening, it is sufficient to
> +.BR close (2)
> +the fanotify file descriptor.
> +The outstanding permission events will be set to allowed, and all resources
> +will be returned to the kernel.
> +.PP
> +The file 
> +.I /proc/<pid>/fdinfo/<fd>
> +contains information about fanotify marks for file descriptor fd of process
> +pid.

Replace the preceding two lines with:

contains information about fanotify marks for file descriptor 
.I fd 
of process
.IR pid .

> +See
> +.I Documentation/filesystems/proc.txt
> +for details.
> +.SH ERRORS
> +In addition to the usual errors for
> +.IR read (2),

s/IR/BR/

> +the following errors can occur when reading from the fanotify file descriptor:
> +.TP
> +.B EINVAL
> +The buffer is too short to hold the event.
> +.TP
> +.B EMFILE

[[[
> +Too many files are open.
> +By creating a new file descpriptor, the per-process limit for the number of
> +open file descriptors, given by
> +.BR RLIMIT_NOFILE ,
> +would be exceeded.
> +See
> +.BR getrlimit (2).
]]]

I think the last 7 lines could better be:

The per-process limit on the number of open files has been reached.
See the description of
.B RLIMIT_NOFILE
in
.BR getrlimit (2).

> +.TP
> +.B ENFILE
> +Too many open files in system.
> +By creating a new file descpriptor, the system wide maximum number of file
> +descriptors would be exceeded.

I think the last three lines could better be:

The system-wide limit on the number of open files has been reached.

> +See
> +.I /proc/sys/fs/file-max
> +in
> +.BR proc (5).
> +.TP
> +.B ETXTBSY
> +A write enabled file descriptor shall be created for a file that is executing.
> +This occurs if
> +.IR fanotify_init (2)
> +was called with
> +.B O_RDWR
> +or
> +.B O_WRONLY
> +and an event for a monitored file, which is executed, is read.
> +.PP
> +In addition to the usual errors for
> +.IR write (2),

s/IR/BR/

> +the following errors can occur when writing to the fanotify file descriptor:
> +.TP
> +.B EINVAL
> +Fanotify access permissions are not enabled in the Kernel configuration or the

s/Kernel/kernel/

> +value of
> +.I response
> +in the response structure is not valid.
> +.TP
> +.B ENOENT
> +The file descriptor
> +.I fd
> +in the response structure is not valid.
> +This might occur because the file was already deleted by another thread or
> +process.
> +.SH VERSIONS
> +The fanotify API was introduced in version 2.6.36 of the Linux kernel and
> +enabled in version 2.6.37.
> +Fdinfo support was added in version 3.8.
> +.SH "CONFORMING TO"
> +The fanotify API is Linux-specific.
> +.SH NOTES
> +The notification is based on the kernel filesystem notification system
> +.B fsnotify.
> +.PP
> +To enable the fanotify API the following setting in the Kernel configuration is
> +needed:
> +CONFIG_FANOTIFY=y. For permission handling
> +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y must be set.

Commonly, statements like the above are written up as

The fanotify API is available only if the kernel was built with the 
.B CONFIG_FANOTIFY
configuration option enabled.
In addition, fanotify permission handling is available only if the
.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
configuration option is enabled.

I'd prefer some text like that, for consistency.

> +.SS Limitations and caveats
> +Fanotify reports only events that a user-space program triggers through the
> +filesystem API.
> +As a result, it does not catch remote events that occur on network filesystems.
> +
> +The fanotify API does not report file accesses and modifications that
> +may occur because of
> +.BR mmap (2),
> +.BR msync (2),
> +and
> +.BR munmap (2).
> +
> +Events for directories are only created if the directory itself is opened,

s/only created/created only/

> +read, and closed.
> +Adding, removing, or changing children of a marked directory does not create
> +events for the monitored directory itself.
> +
> +Fanotify monitoring of directories is not recursive: to monitor subdirectories
> +under a directory, additional marks must be created.

Here, I think it would be helpful to have a comment in parentheses such as

[[
(But note that the fanotify API provides no way of 
detecting when a subdirectory has been created under
a marked directry, which makes recursive monitoring
difficult.)
]]

I know that you imply this in the previous paragraph, but I think it's worth
bening more explicit, since this is a serious limitation of the API. (Really,
it's difficult for me to see how fanotify can sanely be used to do anthying
other than monitor entire mount points or individual filesystem objects.
Recursively monitoring a directory tree appears to be impossible. If I'm
wong on that, I'd be happy to be corrected.)

> +Monitoring mounts offers the capability to monitor a whole directory tree.
> +
> +The event queue can overflow.
> +In this case, events are lost.
> +.SH BUGS
> +Up to Kernel 3.15

s/Kernel 3.15/Linux 3.15,/

> +.IR readdir (2)
> +does not create a
> +.B FAN_ACCESS
> +event.
> +.PP
> +When the file descriptor
> +.I fd
> +passed in
> +.I fanotify_event_metadata
> +is created, authorization to read and write the file is not checked.

Somehow I think the warning around that last point could be bigger.
This appears to be a serious security issue, and if so, I'd say 
something about it. Yep, I know you have a patch out to try to
improve this situation.)

> +.SH EXAMPLE
> +The following program demonstrates the usage of the
> +.B fanotify
> +API.
> +It marks the mount passed as argument and waits for events of type
> +.B FAN_PERM_OPEN
> +and
> +.BR FAN_CLOSE_WRITE .
> +When a permission event occurs, a
> +.B FAN_ALLOW
> +response is given.
> +.PP
> +The following output was recorded while editing file 
> +.IR /home/user/temp/notes .
> +Before the file was opened a
> +.B FAN_OPEN_PERM
> +event occurred.
> +After the file was closed a
> +.B FAN_CLOSE_WRITE
> +event occurred.
> +The example program ended when hitting the enter key.
> +.SS Example output

Something is wrong here. There is no shell session log here.

Add heading

    .SS Program source

> +.in +4n

Don't indent the program source (but do indent the shell session log).

> +.nf
> +#define _GNU_SOURCE // needed for O_LARGEFILE

Please ensure that no line of the rendered output exceeds 80 columns.
Various lines in the program below need to be wrapped. (But fewer
will wrap after you fix the indetnation error above.)

> +#include <errno.h>
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <poll.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/fanotify.h>
> +#include <unistd.h>
> +
> +/* Read all available fanotify events from the file descriptor 'fd' */
> +
> +int
> +handle_events(int fd)
> +{
> +    const struct fanotify_event_metadata *metadata;
> +    char buf[4096];
> +    ssize_t len;
> +    char path[PATH_MAX];
> +    ssize_t path_len;
> +    char procfd_path[PATH_MAX];
> +    struct fanotify_response response;
> +
> +    /* Loop while events can be read from fanotify file descriptor. */
> +
> +    for(;;) {
> +
> +        /* Read some events. */
> +
> +        len = read(fd, (void *) &buf, sizeof(buf));
> +        if (len == \-1 && errno != EAGAIN) {
> +            perror("read");
> +            return EXIT_FAILURE;
> +        }
> +
> +        /* Check if end of available data reached. */
> +
> +        if (len == 0)
> +            break;
> +
> +        /* Point to the first event in the buffer. */
> +
> +        metadata = (struct fanotify_event_metadata *) buf;
> +
> +        /* Loop over all events in the buffer. */
> +
> +        while (FAN_EVENT_OK(metadata, len)) {
> +
> +            /* Assert that run time and compile time structures match. */
> +
> +            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
> +                fprintf(stderr, "Mismatch of fanotify metadata version.\\n");
> +                return EXIT_FAILURE;
> +            }
> +
> +            /* Check that the event contains a file descriptor. */
> +
> +            if (metadata\->fd >= 0) {
> +
> +                /* Handle open permission event. */
> +
> +                if (metadata\->mask & FAN_OPEN_PERM) {
> +                    printf("FAN_OPEN_PERM: ");
> +
> +                    /* Allow file to be opened. */
> +
> +                    response.fd = metadata\->fd;
> +                    response.response = FAN_ALLOW;
> +                    write(fd, &response, sizeof(
> +                              struct fanotify_response));
> +                }
> +
> +                /* Handle closing of writable file event. */
> +
> +                if (metadata\->mask & FAN_CLOSE_WRITE) {
> +                    printf("FAN_CLOSE_WRITE: ");
> +                }
> +
> +                /* Determine path of the file accessed. */
> +
> +                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");
> +                    return EXIT_FAILURE;
> +                }
> +
> +                path[path_len] = '\\0';
> +                printf("File %s", path);
> +
> +                /* Close the file descriptor of the event. */
> +
> +                close(metadata\->fd);
> +                printf("\\n");
> +            }
> +
> +            /* Forward pointer to next event. */
> +
> +            metadata = FAN_EVENT_NEXT(metadata, len);
> +        }
> +    }
> +    return EXIT_SUCCESS;
> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +    char buf;
> +    int fd, poll_num, ret;
> +    nfds_t nfds;
> +    struct pollfd fds[2];
> +    ret = EXIT_SUCCESS;
> +
> +    /* Check mount point is supplied. */
> +
> +    if (argc != 2) {
> +        printf("Usage: %s MOUNT\\n", argv[0]);
> +        return EXIT_FAILURE;
> +    }
> +
> +    printf("Press enter key to terminate.\\n");
> +
> +    /* Create the file descriptor for accessing the fanotify API. */
> +
> +    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
> +                       O_RDONLY | O_LARGEFILE);
> +    if (fd == \-1) {
> +        perror("fanotify_init");
> +        return EXIT_FAILURE;
> +    }
> +
> +    /* Mark the mount for
> +       \- permission events before opening files
> +       \- notification events after closing a write enabled file descriptor. */
> +
> +    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
> +                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
> +                      argv[1]) == \-1) {
> +        perror("fanotify_mark");
> +        close(fd);
> +        return EXIT_FAILURE;
> +    }
> +
> +    /* Prepare for polling. */
> +
> +    nfds = 2;
> +
> +    /* Console input. */
> +
> +    fds[0].fd = STDIN_FILENO;
> +    fds[0].events = POLLIN;
> +    fds[0].revents = 0;
> +
> +    /* Fanotify input. */
> +
> +    fds[1].fd = fd;
> +    fds[1].events = POLLIN;
> +    fds[1].revents = 0;
> +
> +    /* This is the loop to wait for incoming events. */
> +
> +    printf("Listening for events.\\n");
> +    while (ret == EXIT_SUCCESS) {
> +        poll_num = poll(fds, nfds, \-1);
> +        if (poll_num > 0) {
> +            if (fds[0].revents & POLLIN) {
> +
> +                /* Console input is available. Empty stdin and quit. */
> +
> +                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
> +                    continue;
> +                break;
> +            }
> +            if (fds[1].revents & POLLIN) {
> +
> +                /* Fanotify events are available. */
> +
> +                ret = handle_events(fd);
> +                fds[1].revents = 0;
> +            }
> +        } else if (poll_num == \-1 && errno != EINTR) {
> +            perror("poll");
> +            ret = EXIT_FAILURE;
> +        }

The logic here seems to be a little strange. Dispense with 'ret'
.
Why not just write:

    while (1) {
        if (poll_num == -1) {
            if (errno == EINTR)
                continue;
            else
                exit(EXIT_FAILURE);
        }

        if (poll_num > 0) {
            ...
        }
    }

?

> +    }
> +
> +    /* Close fanotify file descriptor. */
> +
> +    close(fd);
> +    printf("Listening for events stopped.\\n");
> +    return ret;
> +}
> +.fi
> +.SH "SEE ALSO"
> +.ad l
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR inotify (7)


> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
> new file mode 100644
> index 0000000..d7f60e1
> --- /dev/null
> +++ b/man2/fanotify_init.2
> @@ -0,0 +1,201 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_INIT 2 2014-04-18 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_init \- create and initialize fanotify group
> +.SH SYNOPSIS
> +.B #include <fcntl.h>
> +.br
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_init ()
> +initializes a new fanotify group and returns a file descriptor for the event
> +queue associated with the group.
> +.PP
> +The file descriptor is used in calls to
> +.BR fanotify_mark (2)
> +to specify the files, directories, and mounts fanotify events shall be created.

s/mounts/mounts for which/

> +These events are received by reading from the file descriptor.
> +Some events are only informative, indicating that a file has been accessed.
> +Other events can be used to control if another application may access a file,

Remove comma

> +or directory.
> +Permission to access file system objects is granted by writing to the file

s/file system/filesystem/

> +descriptor.
> +.PP
> +Multiple programs may be using the fanotify interface at the same time to
> +monitor the same files. 

Insert a paragraph break here. (The idea in the preceding sentence is 
unrelated to the following sentences.)

> +In the current implementation the number of fanotify groups per user is limited

s/implementation/implementation,/

> +to 128.
> +This limit cannot be overridden.
> +.PP
> +Calling
> +.BR fanotify_init()

.BR fanotify_init ()

> +requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +This constraint might be relaxed in future versions of the API.
> +Therefore additional local capability checks have been implemented as indicated

s/additional local/certain specific/

> +below.
> +.PP
> +The
> +.I flags
> +argument contains a multi-bit field defining the usage type of the listening

I'd change all instances of "usage type" to "notification class",
since that's a more distiunctive and meaningful term.

> +application and further single bit fields specifying the behavior of the file
> +descriptor.
> +.PP
> +The usage type indicates, which kind of operations will be executed.

s/,//

"notification class"

Also, "which kind of operations will be executed" sounds odd. What
does it mean? Some clarification is needed.

> +Only one of the following values may be used when calling
> +.BR fanotify_init ().
> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +This value allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files before they
> +contain their final data.
> +This may be used hierarchical storage managers.

s/used/used by/

And it might be better to write:

    This notification class might be used by hierarchical storage 
    managers, for example.

> +.TP
> +.B FAN_CLASS_CONTENT
> +This value allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files when they already
> +contain their final content.
> +This may be used by malware detection programs.

==>

    This notification class might be used by malware-detection 
    programs, for example.

> +.TP
> +.B FAN_CLASS_NOTIF
> +This is the default value.

And so it need not be specified? If so, make that explicit in the text.

> +It only allows the receipt of events notifying that a file has been accessed.
> +Permission decisions before the file is accessed are not possible.
> +.PP
> +Listeners with different values will receive events in the sequence

s/values/notification classes/

==>
If multiple processes are employing fanotify on the same file(es),
then the order in which they will receive events
depends their notification class:
.BR FAN_CLASS_PRE_CONTENT
notifications are delivered first, then
.BR FAN_CLASS_CONTENT ,
and finally
.BR FAN_CLASS_NOTIF .

> +.BR FAN_CLASS_PRE_CONTENT ,
> +.BR FAN_CLASS_CONTENT ,
> +.BR FAN_CLASS_NOTIF .

> +The call sequence among listeners of the same value is undefined.

s/call sequence among/order of notification for/
s/value/notification class/

> +.PP
> +The following bit mask values can be set additionally in
> +.IR flags .

s/\./:/

> +.TP
> +.B FAN_CLOEXEC
> +This flag sets the close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +on the new file descriptor.
> +When calling
> +.BR execve (2)
> +the inherited file descriptor of the child process will be closed.
> +See the description of the
> +.B O_CLOEXEC
> +flag in
> +.BR open (2).
> +.TP
> +.B FAN_NONBLOCK
> +This flag enables the non-blocking flag

s/non-/non/

> +.RB ( O_NONBLOCK )
> +for the file descriptor.
> +Reading from the file descriptor will not block.
> +Instead, if no data is available in a call to
> +.BR read (2)
> +the error
> +.B EAGAIN
> +will occur.
> +.TP
> +.B FAN_UNLIMITED_QUEUE
> +This flag removes the limit of 16384 events on the size of the event queue.
> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.TP
> +.B FAN_UNLIMITED_MARKS
> +This flag removes the limit of 8192 marks on the number of marks.

s/ on the number of marks//

> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.PP
> +The argument
> +.I event_f_flags
> +defines the file flags, with which file descriptors for fanotify events shall

s/,//

> +be created.
> +For explanations of possible values, see argument
> +.I flags
> +of the 
> +.BR open (2)
> +system call.
> +Useful values are:
> +.TP
> +.B O_RDONLY
> +This value allows only read access.
> +.TP
> +.B O_WRONLY
> +This value allows only write access.
> +.TP
> +.B O_RDWR
> +This value allows read and write access.
> +.TP
> +.B O_CLOEXEC
> +This flag enables close-on-exec.

s/close-on-exec/close-on-exec flag for the file descriptor/

> +.TP
> +.B O_LARGEFILE
> +This flag enables support files exceeding 2 GB.

support/support for/

> +Failing to set this flag will result in an
> +.B EOVERFLOW
> +error when trying to open a large file which is monitored by an fanotify group
> +on a 32-bit system.
> +.SH RETURN VALUE
> +On success,
> +.BR fanotify_init ()
> +returns a new file descriptor.
> +In case of an error, \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags .
> +.B FAN_ALL_INIT_FLAGS
> +defines all allowable bits.
> +.TP
> +.B EMFILE
> +The number of fanotify groups of the user exceeds 128.
> +.TP
> +.B ENOMEM
> +The allocation of memory for the notification group failed. 
> +.TP
> +.B EPERM
> +The operation is not permitted because capability
> +.B CAP_SYS_ADMIN
> +is missing.

Better would be:

bcecause the caller lacks the
.B CAP_SYS_ADMIN
capability.

> +.SH VERSIONS
> +.BR fanotify_init ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_mark (2),
> +.BR fanotify (7)
> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
> new file mode 100644
> index 0000000..70e0473
> --- /dev/null
> +++ b/man2/fanotify_mark.2
> @@ -0,0 +1,265 @@
> +.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_MARK 2 2014-04-18 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem
> +object
> +.SH SYNOPSIS
> +.nf
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
> +.BI "                  uint64_t " mask ", int " dirfd ,
> +.BI "                  const char *" pathname );
> +.fi
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_mark (2)
> +adds, removes, or modifies an fanotify mark on a filesystem.
> +.PP
> +Read access is needed for the filesystem object to be marked.

Better would be something like:

    The caller must have read permission on the filesystem 
    object that is to be marked.

> +.PP
> +The
> +.I fanotify_fd
> +argument is the file descriptor returned by

s/the/a
> +.BR fanotify_init (2).
> +.PP
> +.I flags
> +is a bit mask describing the modification to perform.
> +It must include one of the following values:

s/one/exactly one/

> +.TP
> +.B FAN_MARK_ADD
> +The events in argument
> +.I mask
> +will be added to the mark mask (or to the ignore mask).
> +.I mask
> +must be nonempty or the error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_REMOVE
> +The events in paramter

spelling! But, in any case, write "argument" here.

> +.I mask
> +will be removed from the mark mask (or from the ignore mask).
> +.I mask
> +must be nonempty or the error

missing words here.

> +.TP
> +.B FAN_MARK_FLUSH
> +Remove all marks from the whole fanotify group.

s/whole//

(You already said "all", so "whole" seems redundant.)

> +If, if
> +.I mask
> +contains
> +.B FAN_MARK_MOUNT

.BR FAN_MARK_MOUNT ,

> +all marks for mounts are removed from the group.
> +Otherwise all marks for directories and files are removed.

s/Otherwise/Otherwise,/

The above text feels a little unclear. The last two sentences to say 
that you can either remove all mount marks from the group, or all 
non-mount marks, bit not both (in a single call). But the first sentence
simply says "Remove all marks". Something needs to be clarified here.

Also, it looks like any other flags that are specified in 'mask' are
ignored. Is that correct? If so, please note that in the page.

> +.PP
> +If none of the values above is specified, or more than one is specified, the
> +call fails with the error
> +.BR EINVAL .
> +.PP
> +In addition

s/$/,/

> +.I flags
> +may contain zero or more of the following:
> +.TP
> +.B FAN_MARK_DONT_FOLLOW
> +Symbolic links shall not be followed.

I'd be more explicit here:

If
.I pathname
is a symbolic link, mark the the link itself,
rather than the file to which it refers.
(By default,
.BR fanotify_mark ()
dereferences
.I pathname
if it is a symbolic link.)

> +.TP
> +.B FAN_MARK_ONLYDIR
> +If the the filesystem object to be marked is not a directory, the error

s/the the/the/

> +.B ENOTDIR
> +shall be raised.

But, I'd simplify the previous sentence to just:

> +.TP
> +.B FAN_MARK_MOUNT
> +The path indicates a mount point to be marked.
> +If the path is not itself a mount point the mount point containing the path

s/a mount point/a mount point,/

> +will be marked.
> +All directories, subdirectories, and the contained files of the mount point
> +will be monitored.
> +.TP
> +.B FAN_MARK_IGNORED_MASK
> +The events in argument
> +.I mask
> +shall be added to or removed from the ignore mask.
> +.TP
> +.B FAN_MARK_IGNORED_SURV_MODIFY
> +The ignore mask shall survive modify events.
> +If this flag is not set, the ignore mask is cleared, if a modify event occurs

s/, if/ when/

> +for the fanotify group.
> +.PP
> +.I mask
> +defines which events shall be listened to (or which shall be ignored).
> +It is a bit mask composed of the following values:
> +.TP
> +.B FAN_ACCESS
> +Create an event, when a file or directory (see BUGS) is accessed (read).

s/see BUGS/but see BIGS/

s/, when/ when/ 
and in all instances below.

> +.TP
> +.B FAN_MODIFY
> +Create an event, when a file is modified (write).
> +.TP
> +.B FAN_CLOSE_WRITE
> +Create an event, when a writeable file is closed.

s/writeable/writable/

> +.TP
> +.B FAN_CLOSE_NOWRITE
> +Create an event, when a readonly file or directory is closed.

s/readonly/read-only/

> +.TP
> +.B FAN_OPEN
> +Create an event, when a file or directory is opened.
> +.TP
> +.B FAN_OPEN_PERM
> +Create an event, when a permission to open a file or directory is requested.
> +.TP
> +.B FAN_ACCESS_PERM
> +Create an event, when a permission to read a file or directory is requested.
> +.TP
> +.B FAN_ONDIR
> +Events for directories shall be created.

There needs to be more detail here. Describe a case where the presence 
of this flag makes a difference.

> +.TP
> +.B FAN_EVENT_ON_CHILD
> +Events for the immediate children of marked directories shall be created.
> +This does not cover the members of subdirectories.

Better would I think be:

Note that events are not generated for children of the subdirectories
of marked directories.

> +To monitor complete directory trees it is necessary to mark the relevant
> +mount.
> +.PP
> +The following composed value is defined

s/$/:/

> +.TP
> +.B FAN_CLOSE
> +A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The filesystem object to be marked is determined by the file descriptor
> +.I dirfd
> +and the pathname specified in
> +.IR pathname :
> +.IP * 3
> +If 
> +.I pathname
> +is NULL,
> +.I dirfd
> +defines the filesystem object to be marked.
> +.IP *
> +If
> +.I pathname
> +is NULL, and
> +.I dirfd
> +takes the special value
> +.BR AT_FDCWD ,
> +the current working directory is to be marked.

> +.IP *
> +If
> +.I pathname
> +is absolute it defines the filesystem object to be marked, and

s/absolute/absolute,/

> +.I dirfd
> +is ignored.
> +.IP *
> +If
> +.I pathname
> +is relative, it defines a filesystem object relative to the directory
> +indicated by the file descriptor in
> +.I dirfd
> +to be marked.

It would be clearer to say:

If pathname is relative, and dirfd does not have the value AT_FDCWD, then 
the filesystem object to be marked is determined by interpreting pathname
relative the directory referred to by dirfd.

[[
> +.IP *
> +If
> +.I pathname
> +is relative and
> +.I dirfd
> +takes the special value
> +.BR AT_FDCWD ,
> +.I pathname
> +defines a filesystem object relative to the current working directory to be
> +marked.
]]

It would be clearer to say:

If pathname is relative, and dirfd has the value AT_FDCWD, then the 
filesystem object to be marked is determined by interpreting pathname
relative the current working directory.

> +.SH RETURN VALUE
> +On success

s/$/,/

> +.BR fanotify_mark ()
> +returns 0.
> +In case of an error, \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EBADF
> +An invalid file descriptor was passed in
> +.IR fanotify_fd .
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags
> +or
> +.IR mask ,
> +or
> +.I fanotify_fd
> +was not an fanotify file descriptor.
> +.TP
> +.B ENOENT
> +The filesystem object indicated by
> +.IR dirfd
> +and
> +.IR pathname
> +does not exist.
> +This error also occurs when trying to remove a mark from an object which is not
> +marked.
> +.TP
> +.B ENOMEM
> +The necessary memory could not be allocated.
> +.TP
> +.B ENOSPC
> +The number of marks exceeds the limit of 8192 and
> +.B FAN_UNLIMITED_MARKS
> +was not specified in the call to
> +.BR fanotify_init (2).
> +.TP
> +.B ENOTDIR
> +.I flags
> +contains
> +.BR FAN_MARK_ONLYDIR ,
> +and
> +.I dirfd
> +and
> +.I pathname
> +do not specify a directory.
> +.SH VERSIONS
> +.BR fanotify_mark ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH CONFORMING TO
> +This system call is Linux-specific.
> +.SH BUGS
> +Up to Kernel 3.15

s/Kernel 3.15/Linux 3.15,/

> +.I dfd
> +and
> +.I pathname
> +must indicate a valid path, if

s/path, if/filesystem object, even when/

> +.I flags
> +contains
> +.B FAN_MARK_FLUSH.

This last sentence implies that things are changing in Linux 3.15.
If that is so, it should be made explicit. If not then I would
just do

	s/Up to Kernel 3.15/Currently,/

> +This path is not used.

s/path/filesystem object/

> +.PP
> +Up to Kernel 3.15

s/Kernel 3.15/Linux 3.15,/

> +.IR readdir (2)

s/IR/BR/

> +does not result in a
> +.B FAN_ACCESS
> +event.

This last sentence implies that things are changing in Linux 3.15.
If that is so, it should be made explicit. If not then I would
just do

	s/Up to Kernel 3.15/Currently,/

> +.SH SEE ALSO
> +.BR fanotify_init (2),
> +.BR fanotify (7)
> index 0000000..ea8d73b
> diff --git a/man7/inotify.7 b/man7/inotify.7
> index 17462c6..8943604 100644
> --- a/man7/inotify.7
> +++ b/man7/inotify.7
> @@ -753,6 +753,7 @@ instead checked if the most recent event could be coalesced with the
>  .I oldest
>  unread event.
>  .SH SEE ALSO
> +.BR fanotify (7),

Move the above entry to the end of the list.

>  .BR inotifywait (1),
>  .BR inotifywatch (1),
>  .BR inotify_add_watch (2),
> 

Cheers,

Michael



-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/1] fanotify: add manpages
       [not found]                                     ` <53567CC2.6050708-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2014-04-23 17:40                                       ` Heinrich Schuchardt
       [not found]                                         ` <1398274809-6107-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-04-23 17:40 UTC (permalink / raw)
  To: Michael Kerrisk
  Cc: Jan Kara, Eric Paris, linux-man-u79uwXL29TY76Z2rM5mHXA,
	Heinrich Schuchardt

Hello Michael,

I applied all your obvious corrections. For others find my comments
below.

Best regards

Heinrich Schuchardt

== fanotify.7 ==

' * Can only set permission events if FAN_CLASS_PRE_CONTENT or
'   FAN_CLASS_CONTENT (not FAN_CLASS_CONTENT) was used to create
'   FAN fd. (EINVAL)
'
' Did that get addressed. I can't seem to find relevant text
' covering that case in the pages.
Up to now it was only addressed in fanotify_init.2
I have now added this information now in fanotify_mark.

' Now I know that I earlier said that FAN_ONDIR and FAN_EVENT_ON_CHILD
' belong in the input events for fanotify_mark(), not here in the
' returned events. Or at least, as far as I can tell, they can't be
' in the returned events--but can you confirm this please.
Where did you find FAN_ONDIR and FAN_EVENT_ON_CHILD in fanotify.7?

' ' +.I fanotify_event_metadata
' ' +is created, authorization to read and write the file is not checked.
'
' Somehow I think the warning around that last point could be bigger.
' This appears to be a serious security issue, and if so, I'd say
' something about it. Yep, I know you have a patch out to try to
' improve this situation.)
Fixed

' Something is wrong here. There is no shell session log here.
' Add heading
'     .SS Program source
' ' +.in +4n
' Don't indent the program source (but do indent the shell session log).
Fixed. I revovered the lost lines from by git repository.

' The logic here seems to be a little strange. Dispense with 'ret'
The logic you propose is, in case of an error just use exit() and rely on
the operating system to clean up the mess.
I prefer an application to take care of closing the file descriptors
it opened.
The code fragment you provided does not deal with errors occuring while
reading from the fanotify file descriptor in handle_events().

== fanotify_mark.2 ==

' "notification class"
'
' Also, "which kind of operations will be executed" sounds odd. What
' does it mean? Some clarification is needed.
Fixed

' ' +.B FAN_CLASS_NOTIF
' ' +This is the default value.
'
' And so it need not be specified? If so, make that explicit in the text.
Fixed

== fanotify_init.2 ==
' ' +must be nonempty or the error
'
' missing words here.
Fixed

' The above text feels a little unclear. The last two sentences to say
' that you can either remove all mount marks from the group, or all
' non-mount marks, bit not both (in a single call). But the first sentence
' simply says "Remove all marks". Something needs to be clarified here.
'
' Also, it looks like any other flags that are specified in 'mask' are
' ignored. Is that correct? If so, please note that in the page.
Fixed.

' ' +.B ENOTDIR
' ' +shall be raised.
'
' But, I'd simplify the previous sentence to just:
You did not provide a proposal.

' ' +.B FAN_ONDIR
' ' +Events for directories shall be created.
'
' There needs to be more detail here. Describe a case where the presence
' of this flag makes a difference.

Fixed

' This last sentence implies that things are changing in Linux 3.15.
' If that is so, it should be made explicit. If not then I would
' just do
Fixed:
"As of Linux 3.15 the following bugs existed:"

== inotify.7 ==
' '  .SH SEE ALSO
' ' +.BR fanotify (7),
'
' Move the above entry to the end of the list.
Fixed
What is the ruleset you follow? Not alphabetical?

Signed-off-by: Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
---
 man2/fanotify_init.2 | 210 ++++++++++++++++
 man2/fanotify_mark.2 | 303 +++++++++++++++++++++++
 man7/fanotify.7      | 662 +++++++++++++++++++++++++++++++++++++++++++++++++++
 man7/inotify.7       |   3 +-
 4 files changed, 1177 insertions(+), 1 deletion(-)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..f206692
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,210 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_init ()
+initializes a new fanotify group and returns a file descriptor for the event
+queue associated with the group.
+.PP
+The file descriptor is used in calls to
+.BR fanotify_mark (2)
+to specify the files, directories, and mounts for which fanotify events shall
+be created.
+These events are received by reading from the file descriptor.
+Some events are only informative, indicating that a file has been accessed.
+Other events can be used to control if another application may access a file
+or directory.
+Permission to access filesystem objects is granted by writing to the file
+descriptor.
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+.PP
+In the current implementation, the number of fanotify groups per user is
+limited to 128.
+This limit cannot be overridden.
+.PP
+Calling
+.BR fanotify_init ()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Therefore certain specific capability checks have been implemented as indicated
+below.
+.PP
+The
+.I flags
+argument contains a multi-bit field defining the notification class of the
+listening application and further single bit fields specifying the behavior of
+the file descriptor.
+.PP
+If multiple listeners for permission events exist the notification class is
+used to establish the sequence in which the listeners receive the events.
+.PP
+Only one of the following values may be used when calling
+.BR fanotify_init ().
+.TP
+.B FAN_CLASS_PRE_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files before they
+contain their final data.
+This notification class might be used by hierarchical storage managers, for
+example.
+.TP
+.B FAN_CLASS_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files when they already
+contain their final content.
+This notification class might be used by malware detection programs, for
+example.
+.TP
+.B FAN_CLASS_NOTIF
+This is the default value.
+It does not need to be specified.
+This value only allows the receipt of events notifying that a file has been
+accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners with different notification classes will receive events in the
+sequence
+.BR FAN_CLASS_PRE_CONTENT ,
+.BR FAN_CLASS_CONTENT ,
+.BR FAN_CLASS_NOTIF .
+The order of notification for listeners of the same value is undefined.
+.PP
+The following bit mask values can be set additionally in
+.IR flags :
+.TP
+.B FAN_CLOEXEC
+This flag sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+This flag enables the non blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead, if no data is available in a call to
+.BR read (2)
+the error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_UNLIMITED_QUEUE
+This flag removes the limit of 16384 events on the size of the event queue.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+This flag removes the limit of 8192 marks.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+The argument
+.I event_f_flags
+defines the file flags with which file descriptors for fanotify events shall
+be created.
+For explanations of possible values, see argument
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are:
+.TP
+.B O_RDONLY
+This value allows only read access.
+.TP
+.B O_WRONLY
+This value allows only write access.
+.TP
+.B O_RDWR
+This value allows read and write access.
+.TP
+.B O_CLOEXEC
+This flag enables the close-on-exec flag for the file descriptor..
+.TP
+.B O_LARGEFILE
+This flag enables support for files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by an fanotify group
+on a 32-bit system.
+.SH RETURN VALUE
+On success,
+.BR fanotify_init ()
+returns a new file descriptor.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+The number of fanotify groups of the user exceeds 128.
+.TP
+.B ENOMEM
+The allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+The operation is not permitted because the caller lacks the
+.B CAP_SYS_ADMIN
+capability.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..3d82041
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,303 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem
+object
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
+.BI "                  uint64_t " mask ", int " dirfd ,
+.BI "                  const char *" pathname );
+.fi
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_mark (2)
+adds, removes, or modifies an fanotify mark on a filesystem.
+.PP
+The caller must have read permission on the filesystem object that is to be
+marked.
+.PP
+The
+.I fanotify_fd
+argument is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bit mask describing the modification to perform.
+It must include exactly one of the following values:
+.TP
+.B FAN_MARK_ADD
+The events in argument
+.I mask
+will be added to the mark mask (or to the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+The events in argument
+.I mask
+will be removed from the mark mask (or from the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_FLUSH
+Remove either all mount or non mount marks from the fanotify group.
+If
+.I mask
+contains
+.BR FAN_MARK_MOUNT ,
+all marks for mounts are removed from the group.
+Otherwise, all marks for directories and files are removed.
+Other flags than
+.B FAN_MARK_MOUNT
+should not be specified in
+.I mask
+(but see BUGS).
+.PP
+If none of the values above is specified, or more than one is specified, the
+call fails with the error
+.BR EINVAL .
+.PP
+In addition,
+.I flags
+may contain zero or more of the following:
+.TP
+.B FAN_MARK_DONT_FOLLOW
+If
+.I pathname
+is a symbolic link, mark the the link itself, rather than the file to which it
+refers.
+(By default,
+.BR fanotify_mark ()
+dereferences
+.I pathname
+if it is a symbolic link.)
+.TP
+.B FAN_MARK_ONLYDIR
+If the filesystem object to be marked is not a directory, the error
+.B ENOTDIR
+shall be raised.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount point to be marked.
+If the path is not itself a mount point, the mount point containing the path
+will be marked.
+All directories, subdirectories, and the contained files of the mount point
+will be monitored.
+.TP
+.B FAN_MARK_IGNORED_MASK
+The events in argument
+.I mask
+shall be added to or removed from the ignore mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignore mask shall survive modify events.
+If this flag is not set, the ignore mask is cleared when a modify event occurs
+for the fanotify group.
+.PP
+.I mask
+defines which events shall be listened to (or which shall be ignored).
+It is a bit mask composed of the following values:
+.TP
+.B FAN_ACCESS
+Create an event when a file or directory (but see BUGS) is accessed (read).
+.TP
+.B FAN_MODIFY
+Create an event when a file is modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+Create an event when a writeable file is closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+Create an event when a read-only file or directory is closed.
+.TP
+.B FAN_OPEN
+Create an event when a file or directory is opened.
+.TP
+.B FAN_OPEN_PERM
+Create an event when a permission to open a file or directory is requested.
+An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
+FAN_CLASS_CONTENT is required.
+.TP
+.B FAN_ACCESS_PERM
+Create an event when a permission to read a file or directory is requested.
+An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
+FAN_CLASS_CONTENT is required.
+.TP
+.B FAN_ONDIR
+Events for directories shall be created, for example when
+.IR opendir (2),
+.IR readdir (2)
+(but see BUGS), and
+.IR closedir (2)
+are called.
+Without this flag only events for files are created.
+.TP
+.B FAN_EVENT_ON_CHILD
+Events for the immediate children of marked directories shall be created.
+The flag has no effect when marking mounts.
+Note that events are not generated for children of the subdirectories
+of marked directories.
+To monitor complete directory trees it is necessary to mark the relevant
+mount.
+.PP
+The following composed value is defined:
+.TP
+.B FAN_CLOSE
+A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The filesystem object to be marked is determined by the file descriptor
+.I dirfd
+and the pathname specified in
+.IR pathname :
+.IP * 3
+If 
+.I pathname
+is NULL,
+.I dirfd
+defines the filesystem object to be marked.
+.IP *
+If
+.I pathname
+is NULL, and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+the current working directory is to be marked.
+.IP *
+If
+.I pathname
+is absolute, it defines the filesystem object to be marked, and
+.I dirfd
+is ignored.
+.IP *
+If
+.I pathname
+is relative, and dirfd does not have the value
+.BR AT_FDCWD ,
+then the filesystem object to be marked is determined by interpreting
+.I pathname
+relative the directory referred to by
+.IR dirfd.
+.IP *
+If
+.I pathname is relative, and
+.I dirfd
+has the value
+.BR AT_FDCWD,
+then the filesystem object to be marked is determined by interpreting
+.I pathname
+relative the current working directory.
+.SH RETURN VALUE
+On success,
+.BR fanotify_mark ()
+returns 0.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags
+or
+.IR mask ,
+or
+.I fanotify_fd
+was not an fanotify file descriptor.
+.br
+The fanotify file descriptor was opened with FAN_CLASS_NOTIF and mask
+contains a flag for permission events (FAN_OPEN_PERM or FAN_ACCESS_PERM).
+.TP
+.B ENOENT
+The filesystem object indicated by
+.IR dirfd
+and
+.IR pathname
+does not exist.
+This error also occurs when trying to remove a mark from an object which is not
+marked.
+.TP
+.B ENOMEM
+The necessary memory could not be allocated.
+.TP
+.B ENOSPC
+The number of marks exceeds the limit of 8192 and
+.B FAN_UNLIMITED_MARKS
+was not specified in the call to
+.BR fanotify_init (2).
+.TP
+.B ENOTDIR
+.I flags
+contains
+.BR FAN_MARK_ONLYDIR ,
+and
+.I dirfd
+and
+.I pathname
+do not specify a directory.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH CONFORMING TO
+This system call is Linux-specific.
+.SH BUGS
+As of Linux 3.15 the following bugs existed:
+.PP
+.I dfd
+and
+.I pathname
+must indicate a valid path, if
+.I flags
+contains
+.B FAN_MARK_FLUSH.
+This path is not used.
+.PP
+.IR readdir (2)
+does not result in a
+.B FAN_ACCESS
+event.
+.PP
+.I mask
+is not checked if
+.I flag
+is
+.BR FAN_MARK_FLUSH .
+.SH SEE ALSO
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..138d251
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,662 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases include virus scanning and hierarchical storage management.
+Currently, only a limited set of events is supported.
+In particular there is no support for create, delete, and move events.
+
+Additional capabilities compared to the
+.IR inotify (7)
+API are monitoring of complete mounts, access permission decisions, and the
+possibility to read or modify files before access by other applications.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes an fanotify notification group and returns a file
+descriptor referring to it.
+.PP
+An fanotify notification group is an internal object of the kernel which holds
+a list of files, directories, and mount points for which events shall be
+created.
+.PP
+For each entry in an fanotify notification group, two bit masks exist.
+One mask (the mark mask) defines file activities for which an event shall be
+created.
+Another mask (the ignore mask) defines activities for which no event shall be
+generated.
+Having these two types of masks permits a mount point or directory to be
+marked for receiving events, while at the same time ignoring events for
+specific objects under that mount point or directory.
+.PP
+A possible usage of the ignore mask is for a file cache.
+Events of interest for a file cache are modification of a file and closing
+of the same.
+Hence, the cached directory or mount point is to be marked to receive these
+events.
+After receiving the first event informing that a file has been modified, the
+corresponding cache entry will be invalidated.
+No further modification events for this file are of interest until the file is
+closed.
+Hence, the modify event can be added to the ignore mask.
+Upon receiving the closed event, the modify event can be removed from the
+ignore mask and the file cache entry can be updated.
+.PP
+The entries in the fanotify notification groups refer to files and directories
+via their inode number and to mounts via their mount id.
+If files or directories are renamed or moved the respective entries survive.
+If files or directories are deleted or mounts are unmounted, the corresponding
+entries are deleted.
+.PP
+Two types of events exist: notification and permission events.
+Notification events are only informative and require no action to be taken by
+the receiving application except for closing the file descriptor passed in the
+event.
+Permission events are requests to the receiving application to decide whether
+permission for a file access shall be granted.
+For these events, the recipient has to write a response which decides whether
+access is granted or not.
+.PP
+When all file descriptors referring to the fanotify notification group are
+closed, the fanotify group is released and the resources are freed for reuse by
+the kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, directory, or mount to the group and specifies which events
+shall be reported (or ignored), or removes or modifies such an entry.
+.PP
+When an fanotify event occurs, the fanotify file descriptor indicates as
+readable when passed to
+.BR epoll (7),
+.BR poll (2),
+or
+.BR select (2).
+.PP
+All events for an fanotify group are collected in a queue.
+Consecutive events for the same filesystem object and originating from the
+same process may be merged into a single event, with the exception that two
+permission events are never merged into one queue entry.
+Queue entries for notification events are removed when the event has been
+read.
+Queue entries for permission events are removed when the permission
+decision has been taken by writing to the fanotify file descriptor.
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if the flag
+.B FAN_NONBLOCK
+is not specified in the call to
+.BR fanotify_init (2))
+until either a file event occurs or the call is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or \-1 in case of an error.
+In case of success, the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+This is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.IR fanotify_event_metadata .
+Therefore, it is recommended to use a larger buffer size when reading,
+for example 4096 bytes.
+.TP
+.I vers
+This field holds a version number for the structures.
+It must be compared to
+.B FANOTIFY_METADATA_VERSION
+to verify that the structures at runtime match the structures at compile
+time.
+In case of a mismatch, the fanotify file descriptor has to be closed.
+.TP
+.I reserved
+This field is not used.
+.TP
+.I metadata_len
+This is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+No such optional headers exist in the current implementation.
+.TP
+.I mask
+This is a bit mask describing the event.
+.TP
+.I fd
+This is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The file descriptor can be used to access the contents of the monitored file or
+directory.
+It has internal the flag
+.B FMODE_NONOTIFY
+set.
+This flag suppresses fanotify event generation.
+Hence, when the receiver of the fanotify event accesses the notified file or
+directory using this file descriptor, no additional events will be created.
+The reading application is responsible for closing the file descriptor.
+.TP
+.I pid
+This is the ID of the process that caused the event.
+A program listening to fanotify events can compare this PID to the PID returned
+by
+.BR getpid (2),
+to determine whether the event is caused by the listener itself, or is due to a
+file access by another program.
+.PP
+The bit mask in
+.I mask
+signals which events have occurred for a single filesystem object.
+More than one of the following flags can be set at once in the bit mask.
+.TP
+.B FAN_ACCESS
+A file or a directory (but see BUGS) was accessed (read).
+.TP
+.B FAN_OPEN
+A file or a directory was opened.
+.TP
+.B FAN_MODIFY
+A file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+A file that was only opened for reading (
+.B O_RDONLY
+) or a directory was closed.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue exceeded the limit of 16384 entries.
+This limit can be overridden in the call to
+.BR fanotify_init (2)
+by setting flag
+.BR FAN_UNLIMITED_QUEUE .
+.TP
+.B FAN_ACCESS_PERM
+An application wants to read a file or directory, for example using
+.BR read (2)
+or
+.BR readdir (2).
+The reader must write a response that determines whether the permission to
+access the filesystem object shall be granted.
+.TP
+.B FAN_OPEN_PERM
+An application wants to open a file or directory.
+A decision has to be taken, if the permission to open the filesystem object
+shall be granted.
+.PP
+To check for any close event, the following bit mask may be used:
+.TP
+.B FAN_CLOSE
+A file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer with fanotify
+event metadata returned by
+.BR read (2)
+from an fanotify file descriptor.
+.TP
+.B FAN_EVENT_OK(meta, len)
+This macro checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+This macro sets the pointer
+.I meta
+to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.IT len .
+.PP
+For permission events, the application must
+.BR write (2)
+a structure of the following form to the 
+.B fanotify
+file descriptor:
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+This is the file descriptor from the structure
+.IR fanotify_event_metadata .
+.TP
+.I response
+This field indicates whether or not the permission is to be granted.
+Its value must be either
+.B FAN_ALLOW
+to allow the file operation or
+.B FAN_DENY
+to deny the file operation.
+.PP
+If access has been denied, the requesting application call will receive an
+error
+.BR EPERM .
+.PP
+To end listening, it is sufficient to
+.BR close (2)
+the fanotify file descriptor.
+The outstanding permission events will be set to allowed, and all resources
+will be returned to the kernel.
+.PP
+The file 
+.I /proc/<pid>/fdinfo/<fd>
+contains information about fanotify marks for file descriptor
+.I fd
+or process
+.IR pid .
+See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+In addition to the usual errors for
+.BR read (2),
+the following errors can occur when reading from the fanotify file descriptor:
+.TP
+.B EINVAL
+The buffer is too short to hold the event.
+.TP
+.B EMFILE
+The per-process limit on the number of open files has been reached.
+See the description of
+.B RLIMIT_NOFILE
+in
+.BR getrlimit (2).
+.TP
+.B ENFILE
+The system-wide limit on the number of open files has been reached.
+See
+.I /proc/sys/fs/file-max
+in
+.BR proc (5).
+.TP
+.B ETXTBSY
+A write enabled file descriptor shall be created for a file that is executing.
+This occurs if
+.IR fanotify_init (2)
+was called with
+.B O_RDWR
+or
+.B O_WRONLY
+and an event for a monitored file, which is executed, is read.
+.PP
+In addition to the usual errors for
+.BR write (2),
+the following errors can occur when writing to the fanotify file descriptor:
+.TP
+.B EINVAL
+Fanotify access permissions are not enabled in the kernel configuration or the
+value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+The file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The fanotify API was introduced in version 2.6.36 of the Linux kernel and
+enabled in version 2.6.37.
+Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The fanotify API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+The fanotify API is available only if the kernel was built with the 
+.B CONFIG_FANOTIFY
+configuration option enabled.
+In addition, fanotify permission handling is available only if the
+.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+configuration option is enabled.
+.SS Limitations and caveats
+Fanotify reports only events that a user-space program triggers through the
+filesystem API.
+As a result, it does not catch remote events that occur on network filesystems.
+.PP
+The fanotify API does not report file accesses and modifications that
+may occur because of
+.BR mmap (2),
+.BR msync (2),
+and
+.BR munmap (2).
+.PP
+Events for directories are created only if the directory itself is opened,
+read, and closed.
+Adding, removing, or changing children of a marked directory does not create
+events for the monitored directory itself.
+.PP
+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.
+.PP
+The event queue can overflow.
+In this case, events are lost.
+.SH BUGS
+As of Linux 3.15 the following bugs existed:
+.PP
+.IR readdir (2)
+does not create a
+.B FAN_ACCESS
+event.
+.PP
+When the file descriptor
+.I fd
+passed in
+.I fanotify_event_metadata
+is created, authorization to read and write the file is not checked.
+This poses a security risk, when the
+.B CAP_SYS_ADMIN
+capability is set for programs executed by non privileged users.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API.
+It marks the mount passed as argument and waits for events of type
+.B FAN_PERM_OPEN
+and
+.BR FAN_CLOSE_WRITE .
+When a permission event occurs, a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file 
+.IR /home/user/temp/notes .
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occurred.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occurred.
+The example program ended when hitting the enter key.
+.SS Example output
+.in +4n
+.nf
+# ./fanotify_example /home
+Press enter key to terminate.
+Listening for events.
+FAN_OPEN_PERM: File /home/user/temp/notes
+FAN_CLOSE_WRITE: File /home/user/temp/notes
+
+Listening for events stopped.
+.fi
+.in
+.SS Program source
+.nf
+#define _GNU_SOURCE // needed for O_LARGEFILE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+/* Read all available fanotify events from the file descriptor 'fd' */
+
+int
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    ssize_t len;
+    char path[PATH_MAX];
+    ssize_t path_len;
+    char procfd_path[PATH_MAX];
+    struct fanotify_response response;
+
+    /* Loop while events can be read from fanotify file descriptor. */
+
+    for(;;) {
+
+        /* Read some events. */
+
+        len = read(fd, (void *) &buf, sizeof(buf));
+        if (len == \-1 && errno != EAGAIN) {
+            perror("read");
+            return EXIT_FAILURE;
+        }
+
+        /* Check if end of available data reached. */
+
+        if (len <= 0)
+            break;
+
+        /* Point to the first event in the buffer. */
+
+        metadata = (struct fanotify_event_metadata *) buf;
+
+        /* Loop over all events in the buffer. */
+
+        while (FAN_EVENT_OK(metadata, len)) {
+
+            /* Assert that run time and compile time structures
+               match. */
+
+            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
+                fprintf(stderr,
+                        "Mismatch of fanotify metadata version.\\n");
+                return EXIT_FAILURE;
+            }
+
+            /* Check that the event contains a file descriptor. */
+
+            if (metadata\->fd >= 0) {
+
+                /* Handle open permission event. */
+
+                if (metadata\->mask & FAN_OPEN_PERM) {
+                    printf("FAN_OPEN_PERM: ");
+
+                    /* Allow file to be opened. */
+
+                    response.fd = metadata\->fd;
+                    response.response = FAN_ALLOW;
+                    write(fd, &response, sizeof(
+                              struct fanotify_response));
+                }
+
+                /* Handle closing of writable file event. */
+
+                if (metadata\->mask & FAN_CLOSE_WRITE) {
+                    printf("FAN_CLOSE_WRITE: ");
+                }
+
+                /* Determine path of the file accessed. */
+
+                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");
+                    return EXIT_FAILURE;
+                }
+
+                path[path_len] = '\\0';
+                printf("File %s", path);
+
+                /* Close the file descriptor of the event. */
+
+                close(metadata\->fd);
+                printf("\\n");
+            }
+
+            /* Forward pointer to next event. */
+
+            metadata = FAN_EVENT_NEXT(metadata, len);
+        }
+    }
+    return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char *argv[])
+{
+    char buf;
+    int fd, poll_num, ret;
+    nfds_t nfds;
+    struct pollfd fds[2];
+    ret = EXIT_SUCCESS;
+
+    /* Check mount point is supplied. */
+
+    if (argc != 2) {
+        printf("Usage: %s MOUNT\\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("Press enter key to terminate.\\n");
+
+    /* Create the file descriptor for accessing the fanotify API. */
+
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return EXIT_FAILURE;
+    }
+
+    /* Mark the mount for
+       \- permission events before opening files
+       \- notification events after closing a write enabled file descriptor. */
+
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
+                      argv[1]) == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return EXIT_FAILURE;
+    }
+
+    /* Prepare for polling. */
+
+    nfds = 2;
+
+    /* Console input. */
+
+    fds[0].fd = STDIN_FILENO;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+
+    /* Fanotify input. */
+
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    /* This is the loop to wait for incoming events. */
+
+    printf("Listening for events.\\n");
+    while (ret == EXIT_SUCCESS) {
+        poll_num = poll(fds, nfds, \-1);
+        if (poll_num > 0) {
+            if (fds[0].revents & POLLIN) {
+
+                /* Console input is available. Empty stdin and quit. */
+
+                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
+                    continue;
+                break;
+            }
+            if (fds[1].revents & POLLIN) {
+
+                /* Fanotify events are available. */
+
+                ret = handle_events(fd);
+                fds[1].revents = 0;
+            }
+        } else if (poll_num == \-1 && errno != EINTR) {
+            perror("poll");
+            ret = EXIT_FAILURE;
+        }
+    }
+
+    /* Close fanotify file descriptor. */
+
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return ret;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
diff --git a/man7/inotify.7 b/man7/inotify.7
index 17462c6..da76b2a 100644
--- a/man7/inotify.7
+++ b/man7/inotify.7
@@ -760,7 +760,8 @@ unread event.
 .BR inotify_init1 (2),
 .BR inotify_rm_watch (2),
 .BR read (2),
-.BR stat (2)
+.BR stat (2),
+.BR fanotify (7)
 
 .IR Documentation/filesystems/inotify.txt
 in the Linux kernel source tree
-- 
1.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] fanotify: add man pages
       [not found]                                         ` <1398274809-6107-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-04-23 20:24                                           ` Heinrich Schuchardt
       [not found]                                             ` <1398284672-7410-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
  0 siblings, 1 reply; 22+ messages in thread
From: Heinrich Schuchardt @ 2014-04-23 20:24 UTC (permalink / raw)
  To: Michael Kerrisk
  Cc: Jan Kara, Eric Paris, linux-man-u79uwXL29TY76Z2rM5mHXA,
	Heinrich Schuchardt

Hello Michael,

In the last mail I got the section about FAN_MARK_FLUSH in
fanotify_mark wrong. So please, find the update below.

Best regards

Heinrich Schuchardt
---
 man2/fanotify_init.2 | 210 ++++++++++++++++
 man2/fanotify_mark.2 | 303 +++++++++++++++++++++++
 man7/fanotify.7      | 661 +++++++++++++++++++++++++++++++++++++++++++++++++++
 man7/inotify.7       |   3 +-
 4 files changed, 1176 insertions(+), 1 deletion(-)
 create mode 100644 man2/fanotify_init.2
 create mode 100644 man2/fanotify_mark.2
 create mode 100644 man7/fanotify.7

diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
new file mode 100644
index 0000000..f206692
--- /dev/null
+++ b/man2/fanotify_init.2
@@ -0,0 +1,210 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_INIT 2 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_init \- create and initialize fanotify group
+.SH SYNOPSIS
+.B #include <fcntl.h>
+.br
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_init ()
+initializes a new fanotify group and returns a file descriptor for the event
+queue associated with the group.
+.PP
+The file descriptor is used in calls to
+.BR fanotify_mark (2)
+to specify the files, directories, and mounts for which fanotify events shall
+be created.
+These events are received by reading from the file descriptor.
+Some events are only informative, indicating that a file has been accessed.
+Other events can be used to control if another application may access a file
+or directory.
+Permission to access filesystem objects is granted by writing to the file
+descriptor.
+.PP
+Multiple programs may be using the fanotify interface at the same time to
+monitor the same files. 
+.PP
+In the current implementation, the number of fanotify groups per user is
+limited to 128.
+This limit cannot be overridden.
+.PP
+Calling
+.BR fanotify_init ()
+requires the
+.B CAP_SYS_ADMIN
+capability.
+This constraint might be relaxed in future versions of the API.
+Therefore certain specific capability checks have been implemented as indicated
+below.
+.PP
+The
+.I flags
+argument contains a multi-bit field defining the notification class of the
+listening application and further single bit fields specifying the behavior of
+the file descriptor.
+.PP
+If multiple listeners for permission events exist the notification class is
+used to establish the sequence in which the listeners receive the events.
+.PP
+Only one of the following values may be used when calling
+.BR fanotify_init ().
+.TP
+.B FAN_CLASS_PRE_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files before they
+contain their final data.
+This notification class might be used by hierarchical storage managers, for
+example.
+.TP
+.B FAN_CLASS_CONTENT
+This value allows the receipt of events notifying that a file has been
+accessed and events for permission decisions if a file may be accessed.
+It is intended for event listeners that need to access files when they already
+contain their final content.
+This notification class might be used by malware detection programs, for
+example.
+.TP
+.B FAN_CLASS_NOTIF
+This is the default value.
+It does not need to be specified.
+This value only allows the receipt of events notifying that a file has been
+accessed.
+Permission decisions before the file is accessed are not possible.
+.PP
+Listeners with different notification classes will receive events in the
+sequence
+.BR FAN_CLASS_PRE_CONTENT ,
+.BR FAN_CLASS_CONTENT ,
+.BR FAN_CLASS_NOTIF .
+The order of notification for listeners of the same value is undefined.
+.PP
+The following bit mask values can be set additionally in
+.IR flags :
+.TP
+.B FAN_CLOEXEC
+This flag sets the close-on-exec flag
+.RB ( FD_CLOEXEC )
+on the new file descriptor.
+When calling
+.BR execve (2)
+the inherited file descriptor of the child process will be closed.
+See the description of the
+.B O_CLOEXEC
+flag in
+.BR open (2).
+.TP
+.B FAN_NONBLOCK
+This flag enables the non blocking flag
+.RB ( O_NONBLOCK )
+for the file descriptor.
+Reading from the file descriptor will not block.
+Instead, if no data is available in a call to
+.BR read (2)
+the error
+.B EAGAIN
+will occur.
+.TP
+.B FAN_UNLIMITED_QUEUE
+This flag removes the limit of 16384 events on the size of the event queue.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.TP
+.B FAN_UNLIMITED_MARKS
+This flag removes the limit of 8192 marks.
+It requires the
+.B CAP_SYS_ADMIN
+capability.
+.PP
+The argument
+.I event_f_flags
+defines the file flags with which file descriptors for fanotify events shall
+be created.
+For explanations of possible values, see argument
+.I flags
+of the 
+.BR open (2)
+system call.
+Useful values are:
+.TP
+.B O_RDONLY
+This value allows only read access.
+.TP
+.B O_WRONLY
+This value allows only write access.
+.TP
+.B O_RDWR
+This value allows read and write access.
+.TP
+.B O_CLOEXEC
+This flag enables the close-on-exec flag for the file descriptor..
+.TP
+.B O_LARGEFILE
+This flag enables support for files exceeding 2 GB.
+Failing to set this flag will result in an
+.B EOVERFLOW
+error when trying to open a large file which is monitored by an fanotify group
+on a 32-bit system.
+.SH RETURN VALUE
+On success,
+.BR fanotify_init ()
+returns a new file descriptor.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags .
+.B FAN_ALL_INIT_FLAGS
+defines all allowable bits.
+.TP
+.B EMFILE
+The number of fanotify groups of the user exceeds 128.
+.TP
+.B ENOMEM
+The allocation of memory for the notification group failed. 
+.TP
+.B EPERM
+The operation is not permitted because the caller lacks the
+.B CAP_SYS_ADMIN
+capability.
+.SH VERSIONS
+.BR fanotify_init ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH "CONFORMING TO"
+This system call is Linux-specific.
+.SH "SEE ALSO"
+.BR fanotify_mark (2),
+.BR fanotify (7)
diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
new file mode 100644
index 0000000..3d82041
--- /dev/null
+++ b/man2/fanotify_mark.2
@@ -0,0 +1,303 @@
+.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY_MARK 2 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem
+object
+.SH SYNOPSIS
+.nf
+.B #include <sys/fanotify.h>
+.sp
+.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
+.BI "                  uint64_t " mask ", int " dirfd ,
+.BI "                  const char *" pathname );
+.fi
+.SH DESCRIPTION
+For an overview of the fanotify API, see
+.BR fanotify (7).
+.PP
+.BR fanotify_mark (2)
+adds, removes, or modifies an fanotify mark on a filesystem.
+.PP
+The caller must have read permission on the filesystem object that is to be
+marked.
+.PP
+The
+.I fanotify_fd
+argument is the file descriptor returned by
+.BR fanotify_init (2).
+.PP
+.I flags
+is a bit mask describing the modification to perform.
+It must include exactly one of the following values:
+.TP
+.B FAN_MARK_ADD
+The events in argument
+.I mask
+will be added to the mark mask (or to the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_REMOVE
+The events in argument
+.I mask
+will be removed from the mark mask (or from the ignore mask).
+.I mask
+must be nonempty or the error
+.B EINVAL
+will occur.
+.TP
+.B FAN_MARK_FLUSH
+Remove either all mount or non mount marks from the fanotify group.
+If
+.I mask
+contains
+.BR FAN_MARK_MOUNT ,
+all marks for mounts are removed from the group.
+Otherwise, all marks for directories and files are removed.
+Other flags than
+.B FAN_MARK_MOUNT
+should not be specified in
+.I mask
+(but see BUGS).
+.PP
+If none of the values above is specified, or more than one is specified, the
+call fails with the error
+.BR EINVAL .
+.PP
+In addition,
+.I flags
+may contain zero or more of the following:
+.TP
+.B FAN_MARK_DONT_FOLLOW
+If
+.I pathname
+is a symbolic link, mark the the link itself, rather than the file to which it
+refers.
+(By default,
+.BR fanotify_mark ()
+dereferences
+.I pathname
+if it is a symbolic link.)
+.TP
+.B FAN_MARK_ONLYDIR
+If the filesystem object to be marked is not a directory, the error
+.B ENOTDIR
+shall be raised.
+.TP
+.B FAN_MARK_MOUNT
+The path indicates a mount point to be marked.
+If the path is not itself a mount point, the mount point containing the path
+will be marked.
+All directories, subdirectories, and the contained files of the mount point
+will be monitored.
+.TP
+.B FAN_MARK_IGNORED_MASK
+The events in argument
+.I mask
+shall be added to or removed from the ignore mask.
+.TP
+.B FAN_MARK_IGNORED_SURV_MODIFY
+The ignore mask shall survive modify events.
+If this flag is not set, the ignore mask is cleared when a modify event occurs
+for the fanotify group.
+.PP
+.I mask
+defines which events shall be listened to (or which shall be ignored).
+It is a bit mask composed of the following values:
+.TP
+.B FAN_ACCESS
+Create an event when a file or directory (but see BUGS) is accessed (read).
+.TP
+.B FAN_MODIFY
+Create an event when a file is modified (write).
+.TP
+.B FAN_CLOSE_WRITE
+Create an event when a writeable file is closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+Create an event when a read-only file or directory is closed.
+.TP
+.B FAN_OPEN
+Create an event when a file or directory is opened.
+.TP
+.B FAN_OPEN_PERM
+Create an event when a permission to open a file or directory is requested.
+An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
+FAN_CLASS_CONTENT is required.
+.TP
+.B FAN_ACCESS_PERM
+Create an event when a permission to read a file or directory is requested.
+An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
+FAN_CLASS_CONTENT is required.
+.TP
+.B FAN_ONDIR
+Events for directories shall be created, for example when
+.IR opendir (2),
+.IR readdir (2)
+(but see BUGS), and
+.IR closedir (2)
+are called.
+Without this flag only events for files are created.
+.TP
+.B FAN_EVENT_ON_CHILD
+Events for the immediate children of marked directories shall be created.
+The flag has no effect when marking mounts.
+Note that events are not generated for children of the subdirectories
+of marked directories.
+To monitor complete directory trees it is necessary to mark the relevant
+mount.
+.PP
+The following composed value is defined:
+.TP
+.B FAN_CLOSE
+A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The filesystem object to be marked is determined by the file descriptor
+.I dirfd
+and the pathname specified in
+.IR pathname :
+.IP * 3
+If 
+.I pathname
+is NULL,
+.I dirfd
+defines the filesystem object to be marked.
+.IP *
+If
+.I pathname
+is NULL, and
+.I dirfd
+takes the special value
+.BR AT_FDCWD ,
+the current working directory is to be marked.
+.IP *
+If
+.I pathname
+is absolute, it defines the filesystem object to be marked, and
+.I dirfd
+is ignored.
+.IP *
+If
+.I pathname
+is relative, and dirfd does not have the value
+.BR AT_FDCWD ,
+then the filesystem object to be marked is determined by interpreting
+.I pathname
+relative the directory referred to by
+.IR dirfd.
+.IP *
+If
+.I pathname is relative, and
+.I dirfd
+has the value
+.BR AT_FDCWD,
+then the filesystem object to be marked is determined by interpreting
+.I pathname
+relative the current working directory.
+.SH RETURN VALUE
+On success,
+.BR fanotify_mark ()
+returns 0.
+In case of an error, \-1 is returned, and
+.I errno
+is set to indicate the error.
+.SH ERRORS
+.TP
+.B EBADF
+An invalid file descriptor was passed in
+.IR fanotify_fd .
+.TP
+.B EINVAL
+An invalid value was passed in
+.IR flags
+or
+.IR mask ,
+or
+.I fanotify_fd
+was not an fanotify file descriptor.
+.br
+The fanotify file descriptor was opened with FAN_CLASS_NOTIF and mask
+contains a flag for permission events (FAN_OPEN_PERM or FAN_ACCESS_PERM).
+.TP
+.B ENOENT
+The filesystem object indicated by
+.IR dirfd
+and
+.IR pathname
+does not exist.
+This error also occurs when trying to remove a mark from an object which is not
+marked.
+.TP
+.B ENOMEM
+The necessary memory could not be allocated.
+.TP
+.B ENOSPC
+The number of marks exceeds the limit of 8192 and
+.B FAN_UNLIMITED_MARKS
+was not specified in the call to
+.BR fanotify_init (2).
+.TP
+.B ENOTDIR
+.I flags
+contains
+.BR FAN_MARK_ONLYDIR ,
+and
+.I dirfd
+and
+.I pathname
+do not specify a directory.
+.SH VERSIONS
+.BR fanotify_mark ()
+was introduced in version 2.6.36 of the Linux kernel and enabled in version
+2.6.37.
+.SH CONFORMING TO
+This system call is Linux-specific.
+.SH BUGS
+As of Linux 3.15 the following bugs existed:
+.PP
+.I dfd
+and
+.I pathname
+must indicate a valid path, if
+.I flags
+contains
+.B FAN_MARK_FLUSH.
+This path is not used.
+.PP
+.IR readdir (2)
+does not result in a
+.B FAN_ACCESS
+event.
+.PP
+.I mask
+is not checked if
+.I flag
+is
+.BR FAN_MARK_FLUSH .
+.SH SEE ALSO
+.BR fanotify_init (2),
+.BR fanotify (7)
diff --git a/man7/fanotify.7 b/man7/fanotify.7
new file mode 100644
index 0000000..102816a
--- /dev/null
+++ b/man7/fanotify.7
@@ -0,0 +1,661 @@
+.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
+.\" 
+.\" %%%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
+.TH FANOTIFY 7 2014-04-23 "Linux" "Linux Programmer's Manual"
+.SH NAME
+fanotify \- monitoring filesystem events
+.SH DESCRIPTION
+The
+.B fanotify
+API provides notification and interception of filesystem events.
+Use cases include virus scanning and hierarchical storage management.
+Currently, only a limited set of events is supported.
+In particular there is no support for create, delete, and move events.
+
+Additional capabilities compared to the
+.IR inotify (7)
+API are monitoring of complete mounts, access permission decisions, and the
+possibility to read or modify files before access by other applications.
+
+The following system calls are used with this API:
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR poll (2),
+.BR ppoll (2),
+.BR read (2),
+.BR write (2),
+and
+.BR close (2).
+.PP
+.BR fanotify_init (2)
+creates and initializes an fanotify notification group and returns a file
+descriptor referring to it.
+.PP
+An fanotify notification group is an internal object of the kernel which holds
+a list of files, directories, and mount points for which events shall be
+created.
+.PP
+For each entry in an fanotify notification group, two bit masks exist.
+One mask (the mark mask) defines file activities for which an event shall be
+created.
+Another mask (the ignore mask) defines activities for which no event shall be
+generated.
+Having these two types of masks permits a mount point or directory to be
+marked for receiving events, while at the same time ignoring events for
+specific objects under that mount point or directory.
+.PP
+A possible usage of the ignore mask is for a file cache.
+Events of interest for a file cache are modification of a file and closing
+of the same.
+Hence, the cached directory or mount point is to be marked to receive these
+events.
+After receiving the first event informing that a file has been modified, the
+corresponding cache entry will be invalidated.
+No further modification events for this file are of interest until the file is
+closed.
+Hence, the modify event can be added to the ignore mask.
+Upon receiving the closed event, the modify event can be removed from the
+ignore mask and the file cache entry can be updated.
+.PP
+The entries in the fanotify notification groups refer to files and directories
+via their inode number and to mounts via their mount id.
+If files or directories are renamed or moved the respective entries survive.
+If files or directories are deleted or mounts are unmounted, the corresponding
+entries are deleted.
+.PP
+Two types of events exist: notification and permission events.
+Notification events are only informative and require no action to be taken by
+the receiving application except for closing the file descriptor passed in the
+event.
+Permission events are requests to the receiving application to decide whether
+permission for a file access shall be granted.
+For these events, the recipient has to write a response which decides whether
+access is granted or not.
+.PP
+When all file descriptors referring to the fanotify notification group are
+closed, the fanotify group is released and the resources are freed for reuse by
+the kernel.
+.PP
+.BR fanotify_mark (2)
+adds a file, directory, or mount to the group and specifies which events
+shall be reported (or ignored), or removes or modifies such an entry.
+.PP
+When an fanotify event occurs, the fanotify file descriptor indicates as
+readable when passed to
+.BR epoll (7),
+.BR poll (2),
+or
+.BR select (2).
+.PP
+All events for an fanotify group are collected in a queue.
+Consecutive events for the same filesystem object and originating from the
+same process may be merged into a single event, with the exception that two
+permission events are never merged into one queue entry.
+Queue entries for notification events are removed when the event has been
+read.
+Queue entries for permission events are removed when the permission
+decision has been taken by writing to the fanotify file descriptor.
+.PP
+Calling
+.BR read (2)
+for the file descriptor returned by
+.BR fanotify_init (2)
+blocks (if the flag
+.B FAN_NONBLOCK
+is not specified in the call to
+.BR fanotify_init (2))
+until either a file event occurs or the call is interrupted by a signal
+(see
+.BR signal (7)).
+
+The return value of
+.BR read (2)
+is the length of the filled buffer or \-1 in case of an error.
+In case of success, the read buffer contains one or more of the following
+structures:
+
+.in +4n
+.nf
+struct fanotify_event_metadata {
+    __u32 event_len;
+    __u8 vers;
+    __u8 reserved;
+    __u16 metadata_len;
+    __aligned_u64 mask;
+    __s32 fd; 
+    __s32 pid;
+};
+.fi
+.in
+
+.TP 15
+.I event_len
+This is the length of the data for the current event and the offset to the next
+event in the buffer.
+This length might be longer than the size of structure
+.IR fanotify_event_metadata .
+Therefore, it is recommended to use a larger buffer size when reading,
+for example 4096 bytes.
+.TP
+.I vers
+This field holds a version number for the structures.
+It must be compared to
+.B FANOTIFY_METADATA_VERSION
+to verify that the structures at runtime match the structures at compile
+time.
+In case of a mismatch, the fanotify file descriptor has to be closed.
+.TP
+.I reserved
+This field is not used.
+.TP
+.I metadata_len
+This is the length of the structure.
+The field was introduced to facilitate the implementation of optional headers
+per event type.
+No such optional headers exist in the current implementation.
+.TP
+.I mask
+This is a bit mask describing the event.
+.TP
+.I fd
+This is an open file descriptor for the object being accessed or
+.B FAN_NOFD
+if a queue overflow occurred.
+The file descriptor can be used to access the contents of the monitored file or
+directory.
+It has internal the flag
+.B FMODE_NONOTIFY
+set.
+This flag suppresses fanotify event generation.
+Hence, when the receiver of the fanotify event accesses the notified file or
+directory using this file descriptor, no additional events will be created.
+The reading application is responsible for closing the file descriptor.
+.TP
+.I pid
+This is the ID of the process that caused the event.
+A program listening to fanotify events can compare this PID to the PID returned
+by
+.BR getpid (2),
+to determine whether the event is caused by the listener itself, or is due to a
+file access by another program.
+.PP
+The bit mask in
+.I mask
+signals which events have occurred for a single filesystem object.
+More than one of the following flags can be set at once in the bit mask.
+.TP
+.B FAN_ACCESS
+A file or a directory (but see BUGS) was accessed (read).
+.TP
+.B FAN_OPEN
+A file or a directory was opened.
+.TP
+.B FAN_MODIFY
+A file was modified.
+.TP
+.B FAN_CLOSE_WRITE
+A writable file was closed.
+.TP
+.B FAN_CLOSE_NOWRITE
+A file that was only opened for reading (
+.B O_RDONLY
+) or a directory was closed.
+.TP
+.B FAN_Q_OVERFLOW
+The event queue exceeded the limit of 16384 entries.
+This limit can be overridden in the call to
+.BR fanotify_init (2)
+by setting flag
+.BR FAN_UNLIMITED_QUEUE .
+.TP
+.B FAN_ACCESS_PERM
+An application wants to read a file or directory, for example using
+.BR read (2)
+or
+.BR readdir (2).
+The reader must write a response that determines whether the permission to
+access the filesystem object shall be granted.
+.TP
+.B FAN_OPEN_PERM
+An application wants to open a file or directory.
+A decision has to be taken, if the permission to open the filesystem object
+shall be granted.
+.PP
+To check for any close event, the following bit mask may be used:
+.TP
+.B FAN_CLOSE
+A file was closed 
+(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
+.PP
+The following macros are provided to iterate over a buffer with fanotify
+event metadata returned by
+.BR read (2)
+from an fanotify file descriptor.
+.TP
+.B FAN_EVENT_OK(meta, len)
+This macro checks the remaining length
+.I len
+of the buffer
+.I meta
+against the length of the metadata structure and the
+.I event_len
+field of the first metadata structure in the buffer.
+.TP
+.B FAN_EVENT_NEXT(meta, len)
+This macro sets the pointer
+.I meta
+to the next metadata structure using the length indicated in the
+.I event_len
+field of the metadata structure and reduces the remaining length of the
+buffer
+.IT len .
+.PP
+For permission events, the application must
+.BR write (2)
+a structure of the following form to the 
+.B fanotify
+file descriptor:
+
+.in +4n
+.nf
+struct fanotify_response {
+        __s32 fd;
+        __u32 response;
+};
+.fi
+.in
+
+.TP 15
+.I fd
+This is the file descriptor from the structure
+.IR fanotify_event_metadata .
+.TP
+.I response
+This field indicates whether or not the permission is to be granted.
+Its value must be either
+.B FAN_ALLOW
+to allow the file operation or
+.B FAN_DENY
+to deny the file operation.
+.PP
+If access has been denied, the requesting application call will receive an
+error
+.BR EPERM .
+.PP
+To end listening, it is sufficient to
+.BR close (2)
+the fanotify file descriptor.
+The outstanding permission events will be set to allowed, and all resources
+will be returned to the kernel.
+.PP
+The file 
+.I /proc/<pid>/fdinfo/<fd>
+contains information about fanotify marks for file descriptor
+.I fd
+or process
+.IR pid .
+See
+.I Documentation/filesystems/proc.txt
+for details.
+.SH ERRORS
+In addition to the usual errors for
+.BR read (2),
+the following errors can occur when reading from the fanotify file descriptor:
+.TP
+.B EINVAL
+The buffer is too short to hold the event.
+.TP
+.B EMFILE
+The per-process limit on the number of open files has been reached.
+See the description of
+.B RLIMIT_NOFILE
+in
+.BR getrlimit (2).
+.TP
+.B ENFILE
+The system-wide limit on the number of open files has been reached.
+See
+.I /proc/sys/fs/file-max
+in
+.BR proc (5).
+.TP
+.B ETXTBSY
+A write enabled file descriptor shall be created for a file that is executing.
+This occurs if
+.IR fanotify_init (2)
+was called with
+.B O_RDWR
+or
+.B O_WRONLY
+and an event for a monitored file, which is executed, is read.
+.PP
+In addition to the usual errors for
+.BR write (2),
+the following errors can occur when writing to the fanotify file descriptor:
+.TP
+.B EINVAL
+Fanotify access permissions are not enabled in the kernel configuration or the
+value of
+.I response
+in the response structure is not valid.
+.TP
+.B ENOENT
+The file descriptor
+.I fd
+in the response structure is not valid.
+This might occur because the file was already deleted by another thread or
+process.
+.SH VERSIONS
+The fanotify API was introduced in version 2.6.36 of the Linux kernel and
+enabled in version 2.6.37.
+Fdinfo support was added in version 3.8.
+.SH "CONFORMING TO"
+The fanotify API is Linux-specific.
+.SH NOTES
+The notification is based on the kernel filesystem notification system
+.B fsnotify.
+.PP
+The fanotify API is available only if the kernel was built with the 
+.B CONFIG_FANOTIFY
+configuration option enabled.
+In addition, fanotify permission handling is available only if the
+.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+configuration option is enabled.
+.SS Limitations and caveats
+Fanotify reports only events that a user-space program triggers through the
+filesystem API.
+As a result, it does not catch remote events that occur on network filesystems.
+.PP
+The fanotify API does not report file accesses and modifications that
+may occur because of
+.BR mmap (2),
+.BR msync (2),
+and
+.BR munmap (2).
+.PP
+Events for directories are created only if the directory itself is opened,
+read, and closed.
+Adding, removing, or changing children of a marked directory does not create
+events for the monitored directory itself.
+.PP
+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.
+.PP
+The event queue can overflow.
+In this case, events are lost.
+.SH BUGS
+Up to Linux 3.15
+.IR readdir (2)
+does not create a
+.B FAN_ACCESS
+event.
+.PP
+When the file descriptor
+.I fd
+passed in
+.I fanotify_event_metadata
+is created, authorization to read and write the file is not checked.
+This poses a security risk, when the
+.B CAP_SYS_ADMIN
+capability is set for programs executed by non privileged users.
+.SH EXAMPLE
+The following program demonstrates the usage of the
+.B fanotify
+API.
+It marks the mount passed as argument and waits for events of type
+.B FAN_PERM_OPEN
+and
+.BR FAN_CLOSE_WRITE .
+When a permission event occurs, a
+.B FAN_ALLOW
+response is given.
+.PP
+The following output was recorded while editing file 
+.IR /home/user/temp/notes .
+Before the file was opened a
+.B FAN_OPEN_PERM
+event occurred.
+After the file was closed a
+.B FAN_CLOSE_WRITE
+event occurred.
+The example program ended when hitting the enter key.
+.SS Example output
+.in +4n
+.nf
+# ./fanotify_example /home
+Press enter key to terminate.
+Listening for events.
+FAN_OPEN_PERM: File /home/user/temp/notes
+FAN_CLOSE_WRITE: File /home/user/temp/notes
+
+Listening for events stopped.
+.fi
+.in
+.SS Program source
+.nf
+#define _GNU_SOURCE // needed for O_LARGEFILE
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/fanotify.h>
+#include <unistd.h>
+
+/* Read all available fanotify events from the file descriptor 'fd' */
+
+int
+handle_events(int fd)
+{
+    const struct fanotify_event_metadata *metadata;
+    char buf[4096];
+    ssize_t len;
+    char path[PATH_MAX];
+    ssize_t path_len;
+    char procfd_path[PATH_MAX];
+    struct fanotify_response response;
+
+    /* Loop while events can be read from fanotify file descriptor. */
+
+    for(;;) {
+
+        /* Read some events. */
+
+        len = read(fd, (void *) &buf, sizeof(buf));
+        if (len == \-1 && errno != EAGAIN) {
+            perror("read");
+            return EXIT_FAILURE;
+        }
+
+        /* Check if end of available data reached. */
+
+        if (len <= 0)
+            break;
+
+        /* Point to the first event in the buffer. */
+
+        metadata = (struct fanotify_event_metadata *) buf;
+
+        /* Loop over all events in the buffer. */
+
+        while (FAN_EVENT_OK(metadata, len)) {
+
+            /* Assert that run time and compile time structures
+               match. */
+
+            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
+                fprintf(stderr,
+                        "Mismatch of fanotify metadata version.\\n");
+                return EXIT_FAILURE;
+            }
+
+            /* Check that the event contains a file descriptor. */
+
+            if (metadata\->fd >= 0) {
+
+                /* Handle open permission event. */
+
+                if (metadata\->mask & FAN_OPEN_PERM) {
+                    printf("FAN_OPEN_PERM: ");
+
+                    /* Allow file to be opened. */
+
+                    response.fd = metadata\->fd;
+                    response.response = FAN_ALLOW;
+                    write(fd, &response, sizeof(
+                              struct fanotify_response));
+                }
+
+                /* Handle closing of writable file event. */
+
+                if (metadata\->mask & FAN_CLOSE_WRITE) {
+                    printf("FAN_CLOSE_WRITE: ");
+                }
+
+                /* Determine path of the file accessed. */
+
+                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");
+                    return EXIT_FAILURE;
+                }
+
+                path[path_len] = '\\0';
+                printf("File %s", path);
+
+                /* Close the file descriptor of the event. */
+
+                close(metadata\->fd);
+                printf("\\n");
+            }
+
+            /* Forward pointer to next event. */
+
+            metadata = FAN_EVENT_NEXT(metadata, len);
+        }
+    }
+    return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char *argv[])
+{
+    char buf;
+    int fd, poll_num, ret;
+    nfds_t nfds;
+    struct pollfd fds[2];
+    ret = EXIT_SUCCESS;
+
+    /* Check mount point is supplied. */
+
+    if (argc != 2) {
+        printf("Usage: %s MOUNT\\n", argv[0]);
+        return EXIT_FAILURE;
+    }
+
+    printf("Press enter key to terminate.\\n");
+
+    /* Create the file descriptor for accessing the fanotify API. */
+
+    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
+                       O_RDONLY | O_LARGEFILE);
+    if (fd == \-1) {
+        perror("fanotify_init");
+        return EXIT_FAILURE;
+    }
+
+    /* Mark the mount for
+       \- permission events before opening files
+       \- notification events after closing a write enabled file descriptor. */
+
+    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
+                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
+                      argv[1]) == \-1) {
+        perror("fanotify_mark");
+        close(fd);
+        return EXIT_FAILURE;
+    }
+
+    /* Prepare for polling. */
+
+    nfds = 2;
+
+    /* Console input. */
+
+    fds[0].fd = STDIN_FILENO;
+    fds[0].events = POLLIN;
+    fds[0].revents = 0;
+
+    /* Fanotify input. */
+
+    fds[1].fd = fd;
+    fds[1].events = POLLIN;
+    fds[1].revents = 0;
+
+    /* This is the loop to wait for incoming events. */
+
+    printf("Listening for events.\\n");
+    while (ret == EXIT_SUCCESS) {
+        poll_num = poll(fds, nfds, \-1);
+        if (poll_num > 0) {
+            if (fds[0].revents & POLLIN) {
+
+                /* Console input is available. Empty stdin and quit. */
+
+                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
+                    continue;
+                break;
+            }
+            if (fds[1].revents & POLLIN) {
+
+                /* Fanotify events are available. */
+
+                ret = handle_events(fd);
+                fds[1].revents = 0;
+            }
+        } else if (poll_num == \-1 && errno != EINTR) {
+            perror("poll");
+            ret = EXIT_FAILURE;
+        }
+    }
+
+    /* Close fanotify file descriptor. */
+
+    close(fd);
+    printf("Listening for events stopped.\\n");
+    return ret;
+}
+.fi
+.SH "SEE ALSO"
+.ad l
+.BR fanotify_init (2),
+.BR fanotify_mark (2),
+.BR inotify (7)
diff --git a/man7/inotify.7 b/man7/inotify.7
index 17462c6..da76b2a 100644
--- a/man7/inotify.7
+++ b/man7/inotify.7
@@ -760,7 +760,8 @@ unread event.
 .BR inotify_init1 (2),
 .BR inotify_rm_watch (2),
 .BR read (2),
-.BR stat (2)
+.BR stat (2),
+.BR fanotify (7)
 
 .IR Documentation/filesystems/inotify.txt
 in the Linux kernel source tree
-- 
1.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] fanotify: add man pages
       [not found]                                             ` <1398284672-7410-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
@ 2014-04-24 16:25                                               ` Michael Kerrisk (man-pages)
  0 siblings, 0 replies; 22+ messages in thread
From: Michael Kerrisk (man-pages) @ 2014-04-24 16:25 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w, Jan Kara, Eric Paris,
	linux-man-u79uwXL29TY76Z2rM5mHXA

Hello Heinrich,

My Thunderbird client is threading these new mails of yours in 
odd ways, I assume because you are doing a reply all to past 
messages on new submissions of the page. Could I ask you for any 
future versions to:
* Put a version number in the subject line
* Start a fresh mail thread.

Also, your patches often have whitespaces at the end of lines. 
Could you fix that please.

Overall summary: I think we're nearly there. I'd still prefer you 
changed the logic of the example program, but I'll still accept 
the page even if you don't. There are various other minor fixes 
suggested in the comments below. Thanks for your doigged persitence
in the face of a ratehr demanding editor.

On 04/23/2014 10:24 PM, Heinrich Schuchardt wrote:
> Hello Michael,
> 
> In the last mail I got the section about FAN_MARK_FLUSH in
> fanotify_mark wrong. So please, find the update below.

Okay.

I past in this piece from the previous mail:

> I applied all your obvious corrections. For others find my comments
> below.
> 
> Best regards
> 
> Heinrich Schuchardt
> 
> == fanotify.7 ==
> 
> ' * Can only set permission events if FAN_CLASS_PRE_CONTENT or
> '   FAN_CLASS_CONTENT (not FAN_CLASS_CONTENT) was used to create
> '   FAN fd. (EINVAL)
> '
> ' Did that get addressed. I can't seem to find relevant text
> ' covering that case in the pages.
> Up to now it was only addressed in fanotify_init.2
> I have now added this information now in fanotify_mark.

Thanks.

> ' Now I know that I earlier said that FAN_ONDIR and FAN_EVENT_ON_CHILD
> ' belong in the input events for fanotify_mark(), not here in the
> ' returned events. Or at least, as far as I can tell, they can't be
> ' in the returned events--but can you confirm this please.
> Where did you find FAN_ONDIR and FAN_EVENT_ON_CHILD in fanotify.7?

They were in an earlier version in fanotify.7, if I recall correctly.
Anyway, my point is: have you confirmed that FAN_ONDIR and 
FAN_EVENT_ON_CHILD are only input flags, and can't be returned as output
event flags?

> 
> ' ' +.I fanotify_event_metadata
> ' ' +is created, authorization to read and write the file is not checked.
> '
> ' Somehow I think the warning around that last point could be bigger.
> ' This appears to be a serious security issue, and if so, I'd say
> ' something about it. Yep, I know you have a patch out to try to
> ' improve this situation.)
> Fixed

Thanks.

> ' Something is wrong here. There is no shell session log here.
> ' Add heading
> '     .SS Program source
> ' ' +.in +4n
> ' Don't indent the program source (but do indent the shell session log).
> Fixed. I revovered the lost lines from by git repository.
>
Okay.

> ' The logic here seems to be a little strange. Dispense with 'ret'
> The logic you propose is, in case of an error just use exit() and rely on
> the operating system to clean up the mess.
> I prefer an application to take care of closing the file descriptors
> it opened.

I'm not convinced that this is necessary. Process termination closes file 
descriptors. Making sure you do it yourself complicates the logic of the
example considerably.

> The code fragment you provided does not deal with errors occuring while
> reading from the fanotify file descriptor in handle_events().

Okay -- I'll take another look.

> == fanotify_mark.2 ==
> 
> ' "notification class"
> '
> ' Also, "which kind of operations will be executed" sounds odd. What
> ' does it mean? Some clarification is needed.
> Fixed

ok

> ' ' +.B FAN_CLASS_NOTIF
> ' ' +This is the default value.
> '
> ' And so it need not be specified? If so, make that explicit in the text.
> Fixed

ok

> == fanotify_init.2 ==
> ' ' +must be nonempty or the error
> '
> ' missing words here.
> Fixed
> 
> ' The above text feels a little unclear. The last two sentences to say
> ' that you can either remove all mount marks from the group, or all
> ' non-mount marks, bit not both (in a single call). But the first sentence
> ' simply says "Remove all marks". Something needs to be clarified here.
> '
> ' Also, it looks like any other flags that are specified in 'mask' are
> ' ignored. Is that correct? If so, please note that in the page.
> Fixed.

ok

> ' ' +.B ENOTDIR
> ' ' +shall be raised.
> '
> ' But, I'd simplify the previous sentence to just:
> You did not provide a proposal.

Ooops. I'll take another look.

> ' ' +.B FAN_ONDIR
> ' ' +Events for directories shall be created.
> '
> ' There needs to be more detail here. Describe a case where the presence
> ' of this flag makes a difference.
> 
> Fixed
> 
> ' This last sentence implies that things are changing in Linux 3.15.
> ' If that is so, it should be made explicit. If not then I would
> ' just do
> Fixed:
> "As of Linux 3.15 the following bugs existed:"
> 
> == inotify.7 ==
> ' '  .SH SEE ALSO
> ' ' +.BR fanotify (7),
> '
> ' Move the above entry to the end of the list.
> Fixed
> What is the ruleset you follow? Not alphabetical?

See man-pages(7). Key 1 is section number, key 2 is page name.

> Best regards
> 
> Heinrich Schuchardt
> ---
>  man2/fanotify_init.2 | 210 ++++++++++++++++
>  man2/fanotify_mark.2 | 303 +++++++++++++++++++++++
>  man7/fanotify.7      | 661 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  man7/inotify.7       |   3 +-
>  4 files changed, 1176 insertions(+), 1 deletion(-)
>  create mode 100644 man2/fanotify_init.2
>  create mode 100644 man2/fanotify_mark.2
>  create mode 100644 man7/fanotify.7
> 
> diff --git a/man7/fanotify.7 b/man7/fanotify.7
> new file mode 100644
> index 0000000..102816a
> --- /dev/null
> +++ b/man7/fanotify.7
> @@ -0,0 +1,661 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY 7 2014-04-23 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify \- monitoring filesystem events
> +.SH DESCRIPTION
> +The
> +.B fanotify
> +API provides notification and interception of filesystem events.
> +Use cases include virus scanning and hierarchical storage management.
> +Currently, only a limited set of events is supported.
> +In particular there is no support for create, delete, and move events.
> +
> +Additional capabilities compared to the
> +.IR inotify (7)

s/IR/BR/

> +API are monitoring of complete mounts, access permission decisions, and the
> +possibility to read or modify files before access by other applications.
> +
> +The following system calls are used with this API:
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR poll (2),
> +.BR ppoll (2),
> +.BR read (2),
> +.BR write (2),
> +and
> +.BR close (2).
> +.PP
> +.BR fanotify_init (2)
> +creates and initializes an fanotify notification group and returns a file
> +descriptor referring to it.
> +.PP
> +An fanotify notification group is an internal object of the kernel which holds
> +a list of files, directories, and mount points for which events shall be
> +created.
> +.PP
> +For each entry in an fanotify notification group, two bit masks exist.
> +One mask (the mark mask) defines file activities for which an event shall be
> +created.
> +Another mask (the ignore mask) defines activities for which no event shall be
> +generated.
> +Having these two types of masks permits a mount point or directory to be
> +marked for receiving events, while at the same time ignoring events for
> +specific objects under that mount point or directory.
> +.PP
> +A possible usage of the ignore mask is for a file cache.
> +Events of interest for a file cache are modification of a file and closing
> +of the same.
> +Hence, the cached directory or mount point is to be marked to receive these
> +events.
> +After receiving the first event informing that a file has been modified, the
> +corresponding cache entry will be invalidated.
> +No further modification events for this file are of interest until the file is
> +closed.
> +Hence, the modify event can be added to the ignore mask.
> +Upon receiving the closed event, the modify event can be removed from the
> +ignore mask and the file cache entry can be updated.
> +.PP
> +The entries in the fanotify notification groups refer to files and directories
> +via their inode number and to mounts via their mount id.

s/id/ID/

> +If files or directories are renamed or moved the respective entries survive.

s/moved/moved,/

> +If files or directories are deleted or mounts are unmounted, the corresponding
> +entries are deleted.
> +.PP
> +Two types of events exist: notification and permission events.

s/notification/notification events/

> +Notification events are only informative and require no action to be taken by
> +the receiving application except for closing the file descriptor passed in the
> +event.
> +Permission events are requests to the receiving application to decide whether
> +permission for a file access shall be granted.
> +For these events, the recipient has to write a response which decides whether

s/has to/must/
(just a little smoother)

> +access is granted or not.
> +.PP
> +When all file descriptors referring to the fanotify notification group are
> +closed, the fanotify group is released and the resources are freed for reuse by

s/the resources/its resources/

> +the kernel.
> +.PP
> +.BR fanotify_mark (2)
> +adds a file, directory, or mount to the group and specifies which events
> +shall be reported (or ignored), or removes or modifies such an entry.
> +.PP
> +When an fanotify event occurs, the fanotify file descriptor indicates as
> +readable when passed to
> +.BR epoll (7),
> +.BR poll (2),
> +or
> +.BR select (2).
> +.PP
> +All events for an fanotify group are collected in a queue.
> +Consecutive events for the same filesystem object and originating from the
> +same process may be merged into a single event, with the exception that two
> +permission events are never merged into one queue entry.
> +Queue entries for notification events are removed when the event has been
> +read.
> +Queue entries for permission events are removed when the permission
> +decision has been taken by writing to the fanotify file descriptor.
> +.PP
> +Calling
> +.BR read (2)
> +for the file descriptor returned by
> +.BR fanotify_init (2)
> +blocks (if the flag
> +.B FAN_NONBLOCK
> +is not specified in the call to
> +.BR fanotify_init (2))
> +until either a file event occurs or the call is interrupted by a signal
> +(see
> +.BR signal (7)).
> +
> +The return value of
> +.BR read (2)
> +is the length of the filled buffer or \-1 in case of an error.

s/buffer/buffer,/

> +In case of success, the read buffer contains one or more of the following

s/In case of success/After a successful\n.BR read ()/

> +structures:
> +
> +.in +4n
> +.nf
> +struct fanotify_event_metadata {
> +    __u32 event_len;
> +    __u8 vers;
> +    __u8 reserved;
> +    __u16 metadata_len;
> +    __aligned_u64 mask;
> +    __s32 fd; 
> +    __s32 pid;
> +};
> +.fi
> +.in
> +
> +.TP 15
> +.I event_len
> +This is the length of the data for the current event and the offset to the next
> +event in the buffer.
> +This length might be longer than the size of structure
> +.IR fanotify_event_metadata .
> +Therefore, it is recommended to use a larger buffer size when reading,
> +for example 4096 bytes.
> +.TP
> +.I vers
> +This field holds a version number for the structures.
> +It must be compared to
> +.B FANOTIFY_METADATA_VERSION
> +to verify that the structures at runtime match the structures at compile
> +time.
> +In case of a mismatch, the fanotify file descriptor has to be closed.

This last sentence seems to miss the point a little. Should it not say 
something like:

    In case of a mismatch, the application should abandon trying to
    use the fanotify file descriptor.

?

> +.TP
> +.I reserved
> +This field is not used.
> +.TP
> +.I metadata_len
> +This is the length of the structure.
> +The field was introduced to facilitate the implementation of optional headers
> +per event type.
> +No such optional headers exist in the current implementation.
> +.TP
> +.I mask
> +This is a bit mask describing the event.
> +.TP
> +.I fd
> +This is an open file descriptor for the object being accessed or


s/accessed/accessed,/

> +.B FAN_NOFD
> +if a queue overflow occurred.
> +The file descriptor can be used to access the contents of the monitored file or
> +directory.
> +It has internal the flag
> +.B FMODE_NONOTIFY
> +set.
> +This flag suppresses fanotify event generation.
> +Hence, when the receiver of the fanotify event accesses the notified file or
> +directory using this file descriptor, no additional events will be created.
> +The reading application is responsible for closing the file descriptor.
> +.TP
> +.I pid
> +This is the ID of the process that caused the event.
> +A program listening to fanotify events can compare this PID to the PID returned
> +by
> +.BR getpid (2),
> +to determine whether the event is caused by the listener itself, or is due to a
> +file access by another program.
> +.PP
> +The bit mask in
> +.I mask
> +signals which events have occurred for a single filesystem object.
> +More than one of the following flags can be set at once in the bit mask.
> +.TP
> +.B FAN_ACCESS
> +A file or a directory (but see BUGS) was accessed (read).
> +.TP
> +.B FAN_OPEN
> +A file or a directory was opened.
> +.TP
> +.B FAN_MODIFY
> +A file was modified.
> +.TP
> +.B FAN_CLOSE_WRITE
> +A writable file was closed.

Bewtter: A file that was opened for writing was closed.

> +.TP
> +.B FAN_CLOSE_NOWRITE
> +A file that was only opened for reading (
> +.B O_RDONLY
> +) 

The way to format this correctly is

.RB ( O_RDONLY )

> or a directory was closed.
> +.TP
> +.B FAN_Q_OVERFLOW
> +The event queue exceeded the limit of 16384 entries.
> +This limit can be overridden in the call to
> +.BR fanotify_init (2)
> +by setting flag

s/flag/the flag/

> +.BR FAN_UNLIMITED_QUEUE .
> +.TP
> +.B FAN_ACCESS_PERM
> +An application wants to read a file or directory, for example using
> +.BR read (2)
> +or
> +.BR readdir (2).
> +The reader must write a response that determines whether the permission to
> +access the filesystem object shall be granted.
> +.TP
> +.B FAN_OPEN_PERM
> +An application wants to open a file or directory.
> +A decision has to be taken, if the permission to open the filesystem object
> +shall be granted.

Better:

The reader must write a response that determines whether the permission to
open the filesystem object shall be granted.

> +.PP
> +To check for any close event, the following bit mask may be used:
> +.TP
> +.B FAN_CLOSE
> +A file was closed 
> +(FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The following macros are provided to iterate over a buffer with fanotify

s/with/containing/

> +event metadata returned by
> +.BR read (2)
> +from an fanotify file descriptor.
> +.TP
> +.B FAN_EVENT_OK(meta, len)
> +This macro checks the remaining length
> +.I len
> +of the buffer
> +.I meta
> +against the length of the metadata structure and the
> +.I event_len
> +field of the first metadata structure in the buffer.
> +.TP
> +.B FAN_EVENT_NEXT(meta, len)
> +This macro sets the pointer
> +.I meta
> +to the next metadata structure using the length indicated in the
> +.I event_len
> +field of the metadata structure and reduces the remaining length of the
> +buffer
> +.IT len .
> +.PP
> +For permission events, the application must
> +.BR write (2)
> +a structure of the following form to the 
> +.B fanotify
> +file descriptor:
> +
> +.in +4n
> +.nf
> +struct fanotify_response {
> +        __s32 fd;
> +        __u32 response;
> +};

Four-space indents for the structure fields please.

> +.fi
> +.in
> +
> +.TP 15
> +.I fd
> +This is the file descriptor from the structure
> +.IR fanotify_event_metadata .
> +.TP
> +.I response
> +This field indicates whether or not the permission is to be granted.
> +Its value must be either
> +.B FAN_ALLOW
> +to allow the file operation or
> +.B FAN_DENY
> +to deny the file operation.
> +.PP
> +If access has been denied, the requesting application call will receive an
> +error
> +.BR EPERM .
> +.PP
> +To end listening, it is sufficient to
> +.BR close (2)
> +the fanotify file descriptor.
> +The outstanding permission events will be set to allowed, and all resources
> +will be returned to the kernel.
> +.PP
> +The file 
> +.I /proc/<pid>/fdinfo/<fd>
> +contains information about fanotify marks for file descriptor
> +.I fd
> +or process

s/or/of/

> +.IR pid .
> +See
> +.I Documentation/filesystems/proc.txt
> +for details.
> +.SH ERRORS
> +In addition to the usual errors for
> +.BR read (2),
> +the following errors can occur when reading from the fanotify file descriptor:
> +.TP
> +.B EINVAL
> +The buffer is too short to hold the event.
> +.TP
> +.B EMFILE
> +The per-process limit on the number of open files has been reached.
> +See the description of
> +.B RLIMIT_NOFILE
> +in
> +.BR getrlimit (2).
> +.TP
> +.B ENFILE
> +The system-wide limit on the number of open files has been reached.
> +See
> +.I /proc/sys/fs/file-max
> +in
> +.BR proc (5).
> +.TP
> +.B ETXTBSY
> +A write enabled file descriptor shall be created for a file that is executing.
> +This occurs if
> +.IR fanotify_init (2)

s/IR/BR/

> +was called with
> +.B O_RDWR
> +or
> +.B O_WRONLY
> +and an event for a monitored file, which is executed, is read.

The ETXTBSY text reads a little strangely. It implies that a file descriptor
*is* created, but that's not right, is it? Is the story not something
more like this:

[[
.B O_RDWR
or
.B O_WRONLY
was specified in the
.I event_f_flags
argument when calling
.BR fanotify_init (2)
and an event occurred for a monitored file that is currently
being executed.
]]

?

> +.PP
> +In addition to the usual errors for
> +.BR write (2),
> +the following errors can occur when writing to the fanotify file descriptor:
> +.TP
> +.B EINVAL
> +Fanotify access permissions are not enabled in the kernel configuration or the
> +value of
> +.I response
> +in the response structure is not valid.
> +.TP
> +.B ENOENT
> +The file descriptor
> +.I fd
> +in the response structure is not valid.
> +This might occur because the file was already deleted by another thread or
> +process.
> +.SH VERSIONS
> +The fanotify API was introduced in version 2.6.36 of the Linux kernel and
> +enabled in version 2.6.37.
> +Fdinfo support was added in version 3.8.
> +.SH "CONFORMING TO"
> +The fanotify API is Linux-specific.
> +.SH NOTES
> +The notification is based on the kernel filesystem notification system
> +.B fsnotify.


This last sentence is an implementation detail for kernel internal stuff.
I think the sentence probably is not needed for the man page.

> +.PP
> +The fanotify API is available only if the kernel was built with the 
> +.B CONFIG_FANOTIFY
> +configuration option enabled.
> +In addition, fanotify permission handling is available only if the
> +.B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
> +configuration option is enabled.
> +.SS Limitations and caveats
> +Fanotify reports only events that a user-space program triggers through the
> +filesystem API.
> +As a result, it does not catch remote events that occur on network filesystems.
> +.PP
> +The fanotify API does not report file accesses and modifications that
> +may occur because of
> +.BR mmap (2),
> +.BR msync (2),
> +and
> +.BR munmap (2).
> +.PP
> +Events for directories are created only if the directory itself is opened,
> +read, and closed.
> +Adding, removing, or changing children of a marked directory does not create
> +events for the monitored directory itself.
> +.PP
> +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.
> +.PP
> +The event queue can overflow.
> +In this case, events are lost.
> +.SH BUGS
> +Up to Linux 3.15

s/$/,/

Insert the following here:

    .\" FIXME: This may change.

(same also for any of your other pending patches, just so we have a marker
for points in the pages that may need fixing.

> +.IR readdir (2)

s/IR/BR/

> +does not create a
> +.B FAN_ACCESS
> +event.

> +.PP
> +When the file descriptor
> +.I fd
> +passed in
> +.I fanotify_event_metadata
> +is created, authorization to read and write the file is not checked.

Better would be something like:

==> 
When an event is generated,
no check is made to see whether the user ID of the receiving process 
has authorization to read or write the file before passing a file 
descriptor for that file in
.IR fanotify_event_metadata .

> +This poses a security risk, when the
> +.B CAP_SYS_ADMIN
> +capability is set for programs executed by non privileged users.

s/non /un/
> +.SH EXAMPLE
> +The following program demonstrates the usage of the
> +.B fanotify

You haven't formatted "fanotify" elsewhere, so I wouldn't do it here 
either.

> +API.
> +It marks the mount passed as argument and waits for events of type
> +.B FAN_PERM_OPEN
> +and
> +.BR FAN_CLOSE_WRITE .
> +When a permission event occurs, a
> +.B FAN_ALLOW
> +response is given.
> +.PP
> +The following output was recorded while editing file 
> +.IR /home/user/temp/notes .
> +Before the file was opened a

s/opened/opened,/

> +.B FAN_OPEN_PERM
> +event occurred.
> +After the file was closed a

s/closed/closed,/

> +.B FAN_CLOSE_WRITE
> +event occurred.
> +The example program ended when hitting the enter key.

Execution of the program ends when the user presses the ENTER key.

> +.SS Example output
> +.in +4n
> +.nf
> +# ./fanotify_example /home
> +Press enter key to terminate.
> +Listening for events.
> +FAN_OPEN_PERM: File /home/user/temp/notes
> +FAN_CLOSE_WRITE: File /home/user/temp/notes
> +
> +Listening for events stopped.
> +.fi
> +.in
> +.SS Program source
> +.nf
> +#define _GNU_SOURCE // needed for O_LARGEFILE
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <limits.h>
> +#include <poll.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/fanotify.h>
> +#include <unistd.h>
> +
> +/* Read all available fanotify events from the file descriptor 'fd' */
> +
> +int
> +handle_events(int fd)
> +{
> +    const struct fanotify_event_metadata *metadata;
> +    char buf[4096];
> +    ssize_t len;
> +    char path[PATH_MAX];
> +    ssize_t path_len;
> +    char procfd_path[PATH_MAX];
> +    struct fanotify_response response;
> +
> +    /* Loop while events can be read from fanotify file descriptor. */
> +
> +    for(;;) {
> +
> +        /* Read some events. */
> +
> +        len = read(fd, (void *) &buf, sizeof(buf));
> +        if (len == \-1 && errno != EAGAIN) {
> +            perror("read");
> +            return EXIT_FAILURE;

for what it's worth, I think your code would be simpler, and easier 
to understand if handle_events() returned void, and each of the 

    return EXIT_FAILURE

became

     exit(EXIT_FAILURE)

> +        }
> +
> +        /* Check if end of available data reached. */
> +
> +        if (len <= 0)
> +            break;
> +
> +        /* Point to the first event in the buffer. */
> +
> +        metadata = (struct fanotify_event_metadata *) buf;
> +
> +        /* Loop over all events in the buffer. */
> +
> +        while (FAN_EVENT_OK(metadata, len)) {
> +
> +            /* Assert that run time and compile time structures

s/Assert/Check/

> +               match. */
> +
> +            if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
> +                fprintf(stderr,
> +                        "Mismatch of fanotify metadata version.\\n");
> +                return EXIT_FAILURE;

See comment above.

> +            }
> +
> +            /* Check that the event contains a file descriptor. */
> +
> +            if (metadata\->fd >= 0) {
> +
> +                /* Handle open permission event. */
> +
> +                if (metadata\->mask & FAN_OPEN_PERM) {
> +                    printf("FAN_OPEN_PERM: ");
> +
> +                    /* Allow file to be opened. */
> +
> +                    response.fd = metadata\->fd;
> +                    response.response = FAN_ALLOW;
> +                    write(fd, &response, sizeof(
> +                              struct fanotify_response));
> +                }
> +
> +                /* Handle closing of writable file event. */
> +
> +                if (metadata\->mask & FAN_CLOSE_WRITE) {
> +                    printf("FAN_CLOSE_WRITE: ");
> +                }
> +
> +                /* Determine path of the file accessed. */
> +
> +                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");
> +                    return EXIT_FAILURE;

See comment above.


> +                }
> +
> +                path[path_len] = '\\0';
> +                printf("File %s", path);
> +
> +                /* Close the file descriptor of the event. */
> +
> +                close(metadata\->fd);
> +                printf("\\n");
> +            }
> +
> +            /* Forward pointer to next event. */
> +
> +            metadata = FAN_EVENT_NEXT(metadata, len);
> +        }
> +    }
> +    return EXIT_SUCCESS;

And that last line would disappear.

> +}
> +
> +int
> +main(int argc, char *argv[])
> +{
> +    char buf;
> +    int fd, poll_num, ret;
> +    nfds_t nfds;
> +    struct pollfd fds[2];
> +    ret = EXIT_SUCCESS;
> +
> +    /* Check mount point is supplied. */
> +
> +    if (argc != 2) {
> +        printf("Usage: %s MOUNT\\n", argv[0]);
> +        return EXIT_FAILURE;
> +    }
> +
> +    printf("Press enter key to terminate.\\n");
> +
> +    /* Create the file descriptor for accessing the fanotify API. */
> +
> +    fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
> +                       O_RDONLY | O_LARGEFILE);
> +    if (fd == \-1) {
> +        perror("fanotify_init");
> +        return EXIT_FAILURE;
> +    }
> +
> +    /* Mark the mount for
> +       \- permission events before opening files
> +       \- notification events after closing a write enabled file descriptor. */

The previous line renders wider than 80 characters. Please wrap.

> +
> +    if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
> +                      FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1,
> +                      argv[1]) == \-1) {
> +        perror("fanotify_mark");
> +        close(fd);
> +        return EXIT_FAILURE;
> +    }
> +
> +    /* Prepare for polling. */
> +
> +    nfds = 2;
> +
> +    /* Console input. */
> +
> +    fds[0].fd = STDIN_FILENO;
> +    fds[0].events = POLLIN;
> +    fds[0].revents = 0;
> +
> +    /* Fanotify input. */
> +
> +    fds[1].fd = fd;
> +    fds[1].events = POLLIN;
> +    fds[1].revents = 0;
> +
> +    /* This is the loop to wait for incoming events. */
> +
> +    printf("Listening for events.\\n");

I find this that the effort you make to ensure that the program
explicitly closes 'fd' rather than leaving it to the system
on process termination renders this example more complex and
difficult to read than it needs to be. Please consider 
changing it.

> +    while (ret == EXIT_SUCCESS) {
> +        poll_num = poll(fds, nfds, \-1);
> +        if (poll_num > 0) {
> +            if (fds[0].revents & POLLIN) {
> +
> +                /* Console input is available. Empty stdin and quit. */
> +
> +                while(read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')

s/while(/while (/

> +                    continue;
> +                break;
> +            }
> +            if (fds[1].revents & POLLIN) {
> +
> +                /* Fanotify events are available. */
> +
> +                ret = handle_events(fd);
> +                fds[1].revents = 0;

The preceding line is not necessary.

> +            }
> +        } else if (poll_num == \-1 && errno != EINTR) {
> +            perror("poll");
> +            ret = EXIT_FAILURE;
> +        }
> +    }

Making the changes I suggest above for handle_events(), 
dispensing with 'ret' and writing the following does 
seem much simpler (and makes the treatment on EINTR more
explicit):


   printf("Listening for events.\n");
   while (1) {
       poll_num = poll(fds, nfds, \-1);
       if (poll_num == \-1) {
           if (errno == EINTR)
               continue;        /* Restart poll() */

           perror("poll");
           exit(EXITFAILURE);
       }       
       if (fds[0].revents & POLLIN) {

           /* Console input is available. Empty stdin and quit. */

           while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n')
               continue;
           break;  
       }       
       if (fds[1].revents & POLLIN) {

           /* Fanotify events are available. */

           handle_events(fd);
           fds[1].revents = 0;
       }       
   }

   printf("Listening for events stopped.\\n");
   exit(EXIT_SUCCESS);
} 

> +    /* Close fanotify file descriptor. */
> +
> +    close(fd);
> +    printf("Listening for events stopped.\\n");
> +    return ret;
> +}
> +.fi
> +.SH "SEE ALSO"
> +.ad l
> +.BR fanotify_init (2),
> +.BR fanotify_mark (2),
> +.BR inotify (7)
> diff --git a/man7/inotify.7 b/man7/inotify.7
> index 17462c6..da76b2a 100644


> diff --git a/man2/fanotify_init.2 b/man2/fanotify_init.2
> new file mode 100644
> index 0000000..f206692
> --- /dev/null
> +++ b/man2/fanotify_init.2
> @@ -0,0 +1,210 @@
> +.\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_INIT 2 2014-04-23 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_init \- create and initialize fanotify group
> +.SH SYNOPSIS
> +.B #include <fcntl.h>
> +.br
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_init(unsigned int " flags ", unsigned int " event_f_flags );
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_init ()
> +initializes a new fanotify group and returns a file descriptor for the event
> +queue associated with the group.
> +.PP
> +The file descriptor is used in calls to
> +.BR fanotify_mark (2)
> +to specify the files, directories, and mounts for which fanotify events shall
> +be created.
> +These events are received by reading from the file descriptor.
> +Some events are only informative, indicating that a file has been accessed.
> +Other events can be used to control if another application may access a file
> +or directory.
> +Permission to access filesystem objects is granted by writing to the file
> +descriptor.
> +.PP
> +Multiple programs may be using the fanotify interface at the same time to
> +monitor the same files. 
> +.PP
> +In the current implementation, the number of fanotify groups per user is
> +limited to 128.
> +This limit cannot be overridden.
> +.PP
> +Calling
> +.BR fanotify_init ()
> +requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +This constraint might be relaxed in future versions of the API.
> +Therefore certain specific capability checks have been implemented as indicated

On further thought:
s/specific/additional/

> +below.
> +.PP
> +The
> +.I flags
> +argument contains a multi-bit field defining the notification class of the
> +listening application and further single bit fields specifying the behavior of
> +the file descriptor.
> +.PP
> +If multiple listeners for permission events exist the notification class is

s/exist/exist,/

> +used to establish the sequence in which the listeners receive the events.
> +.PP
> +Only one of the following values may be used when calling
> +.BR fanotify_init ().

Better would I think be:

Only one of the following values may be specified in
.BR flags:

> +.TP
> +.B FAN_CLASS_PRE_CONTENT
> +This value allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files before they
> +contain their final data.
> +This notification class might be used by hierarchical storage managers, for
> +example.
> +.TP
> +.B FAN_CLASS_CONTENT
> +This value allows the receipt of events notifying that a file has been
> +accessed and events for permission decisions if a file may be accessed.
> +It is intended for event listeners that need to access files when they already
> +contain their final content.
> +This notification class might be used by malware detection programs, for
> +example.
> +.TP
> +.B FAN_CLASS_NOTIF
> +This is the default value.
> +It does not need to be specified.
> +This value only allows the receipt of events notifying that a file has been
> +accessed.
> +Permission decisions before the file is accessed are not possible.
> +.PP
> +Listeners with different notification classes will receive events in the
> +sequence
> +.BR FAN_CLASS_PRE_CONTENT ,
> +.BR FAN_CLASS_CONTENT ,
> +.BR FAN_CLASS_NOTIF .
> +The order of notification for listeners of the same value is undefined.
> +.PP
> +The following bit mask values can be set additionally in
> +.IR flags :
> +.TP
> +.B FAN_CLOEXEC
> +This flag sets the close-on-exec flag
> +.RB ( FD_CLOEXEC )
> +on the new file descriptor.
> +When calling
> +.BR execve (2)
> +the inherited file descriptor of the child process will be closed.

I think the last sentence probably isn't needed. The details are
covered in open(2).

> +See the description of the
> +.B O_CLOEXEC
> +flag in
> +.BR open (2).
> +.TP
> +.B FAN_NONBLOCK
> +This flag enables the non blocking flag

s/non/non/

> +.RB ( O_NONBLOCK )
> +for the file descriptor.
> +Reading from the file descriptor will not block.
> +Instead, if no data is available in a call to
> +.BR read (2)
> +the error
> +.B EAGAIN
> +will occur.
> +.TP
> +.B FAN_UNLIMITED_QUEUE
> +This flag removes the limit of 16384 events on the size of the event queue.
> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.TP
> +.B FAN_UNLIMITED_MARKS
> +This flag removes the limit of 8192 marks.
> +It requires the
> +.B CAP_SYS_ADMIN
> +capability.
> +.PP
> +The argument
> +.I event_f_flags
> +defines the file flags with which file descriptors for fanotify events shall
> +be created.
> +For explanations of possible values, see argument

s/see/see the/

> +.I flags
> +of the 
> +.BR open (2)
> +system call.
> +Useful values are:
> +.TP
> +.B O_RDONLY
> +This value allows only read access.
> +.TP
> +.B O_WRONLY
> +This value allows only write access.
> +.TP
> +.B O_RDWR
> +This value allows read and write access.
> +.TP
> +.B O_CLOEXEC
> +This flag enables the close-on-exec flag for the file descriptor..

s/.$//

> +.TP
> +.B O_LARGEFILE
> +This flag enables support for files exceeding 2 GB.
> +Failing to set this flag will result in an
> +.B EOVERFLOW
> +error when trying to open a large file which is monitored by an fanotify group
> +on a 32-bit system.
> +.SH RETURN VALUE
> +On success,
> +.BR fanotify_init ()
> +returns a new file descriptor.
> +In case of an error, \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags .
> +.B FAN_ALL_INIT_FLAGS
> +defines all allowable bits.

I think that last sentence could go. FAN_ALL_INIT_FLAGS is non it sys/fanotify.h
(only in the linux/ header file).

> +.TP
> +.B EMFILE
> +The number of fanotify groups of the user exceeds 128.
> +.TP
> +.B ENOMEM
> +The allocation of memory for the notification group failed. 
> +.TP
> +.B EPERM
> +The operation is not permitted because the caller lacks the
> +.B CAP_SYS_ADMIN
> +capability.
> +.SH VERSIONS
> +.BR fanotify_init ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH "CONFORMING TO"
> +This system call is Linux-specific.
> +.SH "SEE ALSO"
> +.BR fanotify_mark (2),
> +.BR fanotify (7)
> diff --git a/man2/fanotify_mark.2 b/man2/fanotify_mark.2
> new file mode 100644
> index 0000000..3d82041
> --- /dev/null
> +++ b/man2/fanotify_mark.2
> @@ -0,0 +1,303 @@
> +.\" Copyright (C) 2013,  Heinrich Schuchardt <xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
> +.\" 
> +.\" %%%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
> +.TH FANOTIFY_MARK 2 2014-04-23 "Linux" "Linux Programmer's Manual"
> +.SH NAME
> +fanotify_mark \- add, remove, or modify an fanotify mark on a filesystem
> +object
> +.SH SYNOPSIS
> +.nf
> +.B #include <sys/fanotify.h>
> +.sp
> +.BI "int fanotify_mark(int " fanotify_fd ", unsigned int " flags ,
> +.BI "                  uint64_t " mask ", int " dirfd ,
> +.BI "                  const char *" pathname );
> +.fi
> +.SH DESCRIPTION
> +For an overview of the fanotify API, see
> +.BR fanotify (7).
> +.PP
> +.BR fanotify_mark (2)
> +adds, removes, or modifies an fanotify mark on a filesystem.
> +.PP
> +The caller must have read permission on the filesystem object that is to be
> +marked.
> +.PP
> +The
> +.I fanotify_fd
> +argument is the file descriptor returned by
> +.BR fanotify_init (2).
> +.PP
> +.I flags
> +is a bit mask describing the modification to perform.
> +It must include exactly one of the following values:
> +.TP
> +.B FAN_MARK_ADD
> +The events in argument

s/argument//

> +.I mask
> +will be added to the mark mask (or to the ignore mask).
> +.I mask
> +must be nonempty or the error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_REMOVE
> +The events in argument
> +.I mask
> +will be removed from the mark mask (or from the ignore mask).
> +.I mask
> +must be nonempty or the error
> +.B EINVAL
> +will occur.
> +.TP
> +.B FAN_MARK_FLUSH
> +Remove either all mount or non mount marks from the fanotify group.

s/non mount/all non-mount/

> +If
> +.I mask
> +contains
> +.BR FAN_MARK_MOUNT ,
> +all marks for mounts are removed from the group.
> +Otherwise, all marks for directories and files are removed.
> +Other flags than

S/Other flags/Flags other/

> +.B FAN_MARK_MOUNT
> +should not be specified in
> +.I mask
> +(but see BUGS).
> +.PP
> +If none of the values above is specified, or more than one is specified, the
> +call fails with the error
> +.BR EINVAL .
> +.PP
> +In addition,
> +.I flags
> +may contain zero or more of the following:
> +.TP
> +.B FAN_MARK_DONT_FOLLOW
> +If
> +.I pathname
> +is a symbolic link, mark the the link itself, rather than the file to which it

sthe the/the/

> +refers.
> +(By default,
> +.BR fanotify_mark ()
> +dereferences
> +.I pathname
> +if it is a symbolic link.)
> +.TP
> +.B FAN_MARK_ONLYDIR
> +If the filesystem object to be marked is not a directory, the error
> +.B ENOTDIR
> +shall be raised.
> +.TP
> +.B FAN_MARK_MOUNT
> +The path indicates a mount point to be marked.

==>
.B pathname
indicates a mount point to be marked.

> +If the path is not itself a mount point, the mount point containing the path
> +will be marked.
> +All directories, subdirectories, and the contained files of the mount point
> +will be monitored.
> +.TP
> +.B FAN_MARK_IGNORED_MASK
> +The events in argument

s/argument//

> +.I mask
> +shall be added to or removed from the ignore mask.
> +.TP
> +.B FAN_MARK_IGNORED_SURV_MODIFY
> +The ignore mask shall survive modify events.
> +If this flag is not set, the ignore mask is cleared when a modify event occurs
> +for the fanotify group.

So, is the ignore mask cleared when a modify event occurs for
*any* monitored object, or only for modify events on this file?
Maybe this could be clarified a little.

> +.PP
> +.I mask
> +defines which events shall be listened to (or which shall be ignored).
> +It is a bit mask composed of the following values:
> +.TP
> +.B FAN_ACCESS
> +Create an event when a file or directory (but see BUGS) is accessed (read).
> +.TP
> +.B FAN_MODIFY
> +Create an event when a file is modified (write).
> +.TP
> +.B FAN_CLOSE_WRITE
> +Create an event when a writeable file is closed.

s/writeable/writable/ 
(I think I said this before.)

> +.TP
> +.B FAN_CLOSE_NOWRITE
> +Create an event when a read-only file or directory is closed.
> +.TP
> +.B FAN_OPEN
> +Create an event when a file or directory is opened.
> +.TP
> +.B FAN_OPEN_PERM
> +Create an event when a permission to open a file or directory is requested.
> +An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
> +FAN_CLASS_CONTENT is required.

Please format the constants with a .B

> +.TP
> +.B FAN_ACCESS_PERM
> +Create an event when a permission to read a file or directory is requested.
> +An fanotify file descriptor created with FAN_CLASS_PRE_CONTENT or
> +FAN_CLASS_CONTENT is required.

Please format the constants with a .B

> +.TP
> +.B FAN_ONDIR
> +Events for directories shall be created, for example when

s/IR/BR? in the next 4 lines.

> +.IR opendir (2),
> +.IR readdir (2)
> +(but see BUGS), and
> +.IR closedir (2)
> +are called.
> +Without this flag only events for files are created.
> +.TP
> +.B FAN_EVENT_ON_CHILD
> +Events for the immediate children of marked directories shall be created.
> +The flag has no effect when marking mounts.
> +Note that events are not generated for children of the subdirectories
> +of marked directories.
> +To monitor complete directory trees it is necessary to mark the relevant
> +mount.
> +.PP
> +The following composed value is defined:
> +.TP
> +.B FAN_CLOSE
> +A file is closed (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE).
> +.PP
> +The filesystem object to be marked is determined by the file descriptor
> +.I dirfd
> +and the pathname specified in
> +.IR pathname :
> +.IP * 3
> +If 
> +.I pathname
> +is NULL,
> +.I dirfd
> +defines the filesystem object to be marked.
> +.IP *
> +If
> +.I pathname
> +is NULL, and
> +.I dirfd
> +takes the special value
> +.BR AT_FDCWD ,
> +the current working directory is to be marked.
> +.IP *
> +If
> +.I pathname
> +is absolute, it defines the filesystem object to be marked, and
> +.I dirfd
> +is ignored.
> +.IP *
> +If
> +.I pathname
> +is relative, and dirfd does not have the value

Format dirfd with .I

> +.BR AT_FDCWD ,
> +then the filesystem object to be marked is determined by interpreting
> +.I pathname
> +relative the directory referred to by
> +.IR dirfd.

s/\./ ./

> +.IP *
> +If
> +.I pathname is relative, and

Formatting problem. Add a line break after 'pathname'

> +.I dirfd
> +has the value
> +.BR AT_FDCWD,
> +then the filesystem object to be marked is determined by interpreting
> +.I pathname
> +relative the current working directory.
> +.SH RETURN VALUE
> +On success,
> +.BR fanotify_mark ()
> +returns 0.
> +In case of an error, \-1 is returned, and
> +.I errno
> +is set to indicate the error.
> +.SH ERRORS
> +.TP
> +.B EBADF
> +An invalid file descriptor was passed in
> +.IR fanotify_fd .
> +.TP
> +.B EINVAL
> +An invalid value was passed in
> +.IR flags
> +or
> +.IR mask ,
> +or
> +.I fanotify_fd
> +was not an fanotify file descriptor.
> +.br

Change the previous line to:

.TP
.B EINVAL

> +The fanotify file descriptor was opened with FAN_CLASS_NOTIF and mask
> +contains a flag for permission events (FAN_OPEN_PERM or FAN_ACCESS_PERM).

Format the three FAN_* constants above the .B

> +.TP
> +.B ENOENT
> +The filesystem object indicated by
> +.IR dirfd
> +and
> +.IR pathname
> +does not exist.
> +This error also occurs when trying to remove a mark from an object which is not
> +marked.
> +.TP
> +.B ENOMEM
> +The necessary memory could not be allocated.
> +.TP
> +.B ENOSPC
> +The number of marks exceeds the limit of 8192 and
> +.B FAN_UNLIMITED_MARKS
> +was not specified in the call to
> +.BR fanotify_init (2).
> +.TP
> +.B ENOTDIR
> +.I flags
> +contains
> +.BR FAN_MARK_ONLYDIR ,
> +and
> +.I dirfd
> +and
> +.I pathname
> +do not specify a directory.
> +.SH VERSIONS
> +.BR fanotify_mark ()
> +was introduced in version 2.6.36 of the Linux kernel and enabled in version
> +2.6.37.
> +.SH CONFORMING TO
> +This system call is Linux-specific.
> +.SH BUGS
> +As of Linux 3.15 the following bugs existed:

s/existed/exist/

For my own information, can you please indicate which of the following
bugs you currently aim to have fixed with patches to the kernel.

> +.PP

Make the preceding line:

.IP * 3

> +.I dfd
> +and
> +.I pathname
> +must indicate a valid path, if
> +.I flags
> +contains
> +.B FAN_MARK_FLUSH.
> +This path is not used.

I'd write this as:

If 
.I flags
specifies
.BR FAN_MARK_FLUSH ,
.I dfd
and
.I pathname
must specify a valid filesystem object, even though that object is not used.

> +.PP

Make the preceding line

.IP *

> +.IR readdir (2)

s/IR/BR

> +does not result in a
> +.B FAN_ACCESS
> +event.
> +.PP

Make the preceding line

.IP *

> +.I mask
> +is not checked if
> +.I flag

flags

> +is
> +.BR FAN_MARK_FLUSH .

I think this could be clearer. Is your point not that when
'flags' is FAN_MARK_FLUSH , then 'mask' is not checked for invalid
flags? I'd word it something like that (if I am correct).


> +.SH SEE ALSO
> +.BR fanotify_init (2),
> +.BR fanotify (7)
> --- a/man7/inotify.7
> +++ b/man7/inotify.7
> @@ -760,7 +760,8 @@ unread event.
>  .BR inotify_init1 (2),
>  .BR inotify_rm_watch (2),
>  .BR read (2),
> -.BR stat (2)
> +.BR stat (2),
> +.BR fanotify (7)
>  
>  .IR Documentation/filesystems/inotify.txt
>  in the Linux kernel source tree

Cheers,

Michael


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2014-04-24 16:25 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-26 19:53 [PATCH 1/1] Man pages for the fanotify API xypron.glpk-Mmb7MZpHnFY
     [not found] ` <1393444390-16012-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-03-14 16:42   ` Michael Kerrisk (man-pages)
     [not found]     ` <53233160.9000106-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-03-16 15:32       ` xypron.glpk-Mmb7MZpHnFY
     [not found]         ` <1394983959-5392-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-03-17 15:45           ` Michael Kerrisk (man-pages)
     [not found]             ` <53271880.4090100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-03-22 16:42               ` xypron.glpk-Mmb7MZpHnFY
     [not found]                 ` <1395506528-10026-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-03-24 21:23                   ` Michael Kerrisk (man-pages)
     [not found]                     ` <5330A257.9080100-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-03-25 15:39                       ` Man pages for the fanotify API: merging of events Heinrich Schuchardt
     [not found]                         ` <5331A343.9070403-Mmb7MZpHnFY@public.gmane.org>
2014-03-25 16:37                           ` Jan Kara
2014-03-26 19:09                       ` [PATCH 1/1] Man pages for the fanotify API Eric Paris
2014-04-06  0:01                       ` [PATCH 0/1] Manpages " xypron.glpk-Mmb7MZpHnFY
     [not found]                         ` <1396742468-4752-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-04-06 12:18                           ` Michael Kerrisk (man-pages)
     [not found]                             ` <5341461A.3090405-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-04-07  8:48                               ` Jan Kara
2014-04-13 14:05                               ` fanotify API: FMODE_NONOTIFY, FMODE_EXEC, FMODE_NOCMTIME Heinrich Schuchardt
2014-04-20 11:56                               ` [PATCH 1/1] Manpages for the fanotify API Heinrich Schuchardt
     [not found]                                 ` <1397994990-9068-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-04-22 14:29                                   ` Michael Kerrisk (man-pages)
     [not found]                                     ` <53567CC2.6050708-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-04-23 17:40                                       ` [PATCH 1/1] fanotify: add manpages Heinrich Schuchardt
     [not found]                                         ` <1398274809-6107-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-04-23 20:24                                           ` [PATCH] fanotify: add man pages Heinrich Schuchardt
     [not found]                                             ` <1398284672-7410-1-git-send-email-xypron.glpk-Mmb7MZpHnFY@public.gmane.org>
2014-04-24 16:25                                               ` Michael Kerrisk (man-pages)
2014-04-07  8:56                           ` [PATCH 0/1] Manpages for the fanotify API Jan Kara
     [not found]                             ` <20140407085624.GB14927-+0h/O2h83AeN3ZZ/Hiejyg@public.gmane.org>
2014-04-07 18:16                               ` [PATCH 0/1] Manpages for the fanotify API: FAN_ACCESS_PERM for readdir Heinrich Schuchardt
     [not found]                                 ` <5342EB7B.4010201-Mmb7MZpHnFY@public.gmane.org>
2014-04-07 20:13                                   ` Jan Kara
2014-04-06  0:01                       ` [PATCH 1/1] Manpages for the fanotify API xypron.glpk-Mmb7MZpHnFY

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.