[PATCH 1/1] Man pages for the fanotify API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Heinrich Schuchardt <xypron.glpk@xxxxxx>

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@xxxxxx>
---
 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@xxxxxx>
+.\" 
+.\" %%%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@xxxxxx>
+.\" 
+.\" %%%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@xxxxxx>
+.\" 
+.\" %%%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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux