| .\" Copyright (C) 2006, 2014 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" Copyright (C) 2014 Heinrich Schuchardt <xypron.glpk@gmx.de> |
| .\" |
| .\" %%%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 INOTIFY 7 2021-03-22 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| inotify \- monitoring filesystem events |
| .SH DESCRIPTION |
| The |
| .I inotify |
| API provides a mechanism for monitoring filesystem events. |
| Inotify can be used to monitor individual files, |
| or to monitor directories. |
| When a directory is monitored, inotify will return events |
| for the directory itself, and for files inside the directory. |
| .PP |
| The following system calls are used with this API: |
| .IP * 3 |
| .BR inotify_init (2) |
| creates an inotify instance and returns a file descriptor |
| referring to the inotify instance. |
| The more recent |
| .BR inotify_init1 (2) |
| is like |
| .BR inotify_init (2), |
| but has a |
| .IR flags |
| argument that provides access to some extra functionality. |
| .IP * |
| .BR inotify_add_watch (2) |
| manipulates the "watch list" associated with an inotify instance. |
| Each item ("watch") in the watch list specifies the pathname of |
| a file or directory, |
| along with some set of events that the kernel should monitor for the |
| file referred to by that pathname. |
| .BR inotify_add_watch (2) |
| either creates a new watch item, or modifies an existing watch. |
| Each watch has a unique "watch descriptor", an integer |
| returned by |
| .BR inotify_add_watch (2) |
| when the watch is created. |
| .IP * |
| When events occur for monitored files and directories, |
| those events are made available to the application as structured data that |
| can be read from the inotify file descriptor using |
| .BR read (2) |
| (see below). |
| .IP * |
| .BR inotify_rm_watch (2) |
| removes an item from an inotify watch list. |
| .IP * |
| When all file descriptors referring to an inotify |
| instance have been closed (using |
| .BR close (2)), |
| the underlying object and its resources are |
| freed for reuse by the kernel; |
| all associated watches are automatically freed. |
| .PP |
| With careful programming, |
| an application can use inotify to efficiently monitor and cache |
| the state of a set of filesystem objects. |
| However, robust applications should allow for the fact that bugs |
| in the monitoring logic or races of the kind described below |
| may leave the cache inconsistent with the filesystem state. |
| It is probably wise to do some consistency checking, |
| and rebuild the cache when inconsistencies are detected. |
| .SS Reading events from an inotify file descriptor |
| To determine what events have occurred, an application |
| .BR read (2)s |
| from the inotify file descriptor. |
| If no events have so far occurred, then, |
| assuming a blocking file descriptor, |
| .BR read (2) |
| will block until at least one event occurs |
| (unless interrupted by a signal, |
| in which case the call fails with the error |
| .BR EINTR ; |
| see |
| .BR signal (7)). |
| .PP |
| Each successful |
| .BR read (2) |
| returns a buffer containing one or more of the following structures: |
| .PP |
| .in +4n |
| .EX |
| struct inotify_event { |
| int wd; /* Watch descriptor */ |
| .\" FIXME . The type of the 'wd' field should probably be "int32_t". |
| .\" I submitted a patch to fix this. See the LKML thread |
| .\" "[patch] Fix type errors in inotify interfaces", 18 Nov 2008 |
| .\" Glibc bug filed: http://sources.redhat.com/bugzilla/show_bug.cgi?id=7040 |
| uint32_t mask; /* Mask describing event */ |
| uint32_t cookie; /* Unique cookie associating related |
| events (for rename(2)) */ |
| uint32_t len; /* Size of \fIname\fP field */ |
| char name[]; /* Optional null\-terminated name */ |
| }; |
| .EE |
| .in |
| .PP |
| .I wd |
| identifies the watch for which this event occurs. |
| It is one of the watch descriptors returned by a previous call to |
| .BR inotify_add_watch (2). |
| .PP |
| .I mask |
| contains bits that describe the event that occurred (see below). |
| .PP |
| .I cookie |
| is a unique integer that connects related events. |
| Currently, this is used only for rename events, and |
| allows the resulting pair of |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| events to be connected by the application. |
| For all other event types, |
| .I cookie |
| is set to 0. |
| .PP |
| The |
| .I name |
| field is present only when an event is returned |
| for a file inside a watched directory; |
| it identifies the filename within the watched directory. |
| This filename is null-terminated, |
| and may include further null bytes (\(aq\e0\(aq) to align subsequent reads to a |
| suitable address boundary. |
| .PP |
| The |
| .I len |
| field counts all of the bytes in |
| .IR name , |
| including the null bytes; |
| the length of each |
| .I inotify_event |
| structure is thus |
| .IR "sizeof(struct inotify_event)+len" . |
| .PP |
| The behavior when the buffer given to |
| .BR read (2) |
| is too small to return information about the next event depends |
| on the kernel version: in kernels before 2.6.21, |
| .BR read (2) |
| returns 0; since kernel 2.6.21, |
| .BR read (2) |
| fails with the error |
| .BR EINVAL . |
| Specifying a buffer of size |
| .PP |
| sizeof(struct inotify_event) + NAME_MAX + 1 |
| .PP |
| will be sufficient to read at least one event. |
| .SS inotify events |
| The |
| .BR inotify_add_watch (2) |
| .I mask |
| argument and the |
| .I mask |
| field of the |
| .I inotify_event |
| structure returned when |
| .BR read (2)ing |
| an inotify file descriptor are both bit masks identifying |
| inotify events. |
| The following bits can be specified in |
| .I mask |
| when calling |
| .BR inotify_add_watch (2) |
| and may be returned in the |
| .I mask |
| field returned by |
| .BR read (2): |
| .RS 4 |
| .TP |
| .BR IN_ACCESS " (+)" |
| File was accessed (e.g., |
| .BR read (2), |
| .BR execve (2)). |
| .TP |
| .BR IN_ATTRIB " (*)" |
| Metadata changed\(emfor example, permissions (e.g., |
| .BR chmod (2)), |
| timestamps (e.g., |
| .BR utimensat (2)), |
| extended attributes |
| .RB ( setxattr (2)), |
| link count (since Linux 2.6.25; e.g., |
| .\" FIXME . |
| .\" Events do not occur for link count changes on a file inside a monitored |
| .\" directory. This differs from other metadata changes for files inside |
| .\" a monitored directory. |
| for the target of |
| .BR link (2) |
| and for |
| .BR unlink (2)), |
| and user/group ID (e.g., |
| .BR chown (2)). |
| .TP |
| .BR IN_CLOSE_WRITE " (+)" |
| File opened for writing was closed. |
| .TP |
| .BR IN_CLOSE_NOWRITE " (*)" |
| File or directory not opened for writing was closed. |
| .TP |
| .BR IN_CREATE " (+)" |
| File/directory created in watched directory (e.g., |
| .BR open (2) |
| .BR O_CREAT , |
| .BR mkdir (2), |
| .BR link (2), |
| .BR symlink (2), |
| .BR bind (2) |
| on a UNIX domain socket). |
| .TP |
| .BR IN_DELETE " (+)" |
| File/directory deleted from watched directory. |
| .TP |
| .B IN_DELETE_SELF |
| Watched file/directory was itself deleted. |
| (This event also occurs if an object is moved to another filesystem, |
| since |
| .BR mv (1) |
| in effect copies the file to the other filesystem and |
| then deletes it from the original filesystem.) |
| In addition, an |
| .B IN_IGNORED |
| event will subsequently be generated for the watch descriptor. |
| .TP |
| .BR IN_MODIFY " (+)" |
| File was modified (e.g., |
| .BR write (2), |
| .BR truncate (2)). |
| .TP |
| .B IN_MOVE_SELF |
| Watched file/directory was itself moved. |
| .TP |
| .BR IN_MOVED_FROM " (+)" |
| Generated for the directory containing the old filename |
| when a file is renamed. |
| .TP |
| .BR IN_MOVED_TO " (+)" |
| Generated for the directory containing the new filename |
| when a file is renamed. |
| .TP |
| .BR IN_OPEN " (*)" |
| File or directory was opened. |
| .RE |
| .PP |
| Inotify monitoring is inode-based: when monitoring a file |
| (but not when monitoring the directory containing a file), |
| an event can be generated for activity on any link to the file |
| (in the same or a different directory). |
| .PP |
| When monitoring a directory: |
| .IP * 3 |
| the events marked above with an asterisk (*) can occur both |
| for the directory itself and for objects inside the directory; and |
| .IP * |
| the events marked with a plus sign (+) occur only for objects |
| inside the directory (not for the directory itself). |
| .PP |
| .IR Note : |
| when monitoring a directory, |
| events are not generated for the files inside the directory |
| when the events are performed via a pathname (i.e., a link) |
| that lies outside the monitored directory. |
| .PP |
| When events are generated for objects inside a watched directory, the |
| .I name |
| field in the returned |
| .I inotify_event |
| structure identifies the name of the file within the directory. |
| .PP |
| The |
| .B IN_ALL_EVENTS |
| macro is defined as a bit mask of all of the above events. |
| This macro can be used as the |
| .I mask |
| argument when calling |
| .BR inotify_add_watch (2). |
| .PP |
| Two additional convenience macros are defined: |
| .RS 4 |
| .TP |
| .BR IN_MOVE |
| Equates to |
| .BR "IN_MOVED_FROM | IN_MOVED_TO" . |
| .TP |
| .BR IN_CLOSE |
| Equates to |
| .BR "IN_CLOSE_WRITE | IN_CLOSE_NOWRITE" . |
| .RE |
| .PP |
| The following further bits can be specified in |
| .I mask |
| when calling |
| .BR inotify_add_watch (2): |
| .RS 4 |
| .TP |
| .BR IN_DONT_FOLLOW " (since Linux 2.6.15)" |
| Don't dereference |
| .I pathname |
| if it is a symbolic link. |
| .TP |
| .BR IN_EXCL_UNLINK " (since Linux 2.6.36)" |
| .\" commit 8c1934c8d70b22ca8333b216aec6c7d09fdbd6a6 |
| By default, when watching events on the children of a directory, |
| events are generated for children even after they have been unlinked |
| from the directory. |
| This can result in large numbers of uninteresting events for |
| some applications (e.g., if watching |
| .IR /tmp , |
| in which many applications create temporary files whose |
| names are immediately unlinked). |
| Specifying |
| .B IN_EXCL_UNLINK |
| changes the default behavior, |
| so that events are not generated for children after |
| they have been unlinked from the watched directory. |
| .TP |
| .B IN_MASK_ADD |
| If a watch instance already exists for the filesystem object corresponding to |
| .IR pathname , |
| add (OR) the events in |
| .I mask |
| to the watch mask (instead of replacing the mask); |
| the error |
| .B EINVAL |
| results if |
| .B IN_MASK_CREATE |
| is also specified. |
| .TP |
| .B IN_ONESHOT |
| Monitor the filesystem object corresponding to |
| .I pathname |
| for one event, then remove from |
| watch list. |
| .TP |
| .BR IN_ONLYDIR " (since Linux 2.6.15)" |
| Watch |
| .I pathname |
| only if it is a directory; |
| the error |
| .B ENOTDIR |
| results if |
| .I pathname |
| is not a directory. |
| Using this flag provides an application with a race-free way of |
| ensuring that the monitored object is a directory. |
| .TP |
| .BR IN_MASK_CREATE " (since Linux 4.18)" |
| Watch |
| .I pathname |
| only if it does not already have a watch associated with it; |
| the error |
| .B EEXIST |
| results if |
| .I pathname |
| is already being watched. |
| .IP |
| Using this flag provides an application with a way of ensuring |
| that new watches do not modify existing ones. |
| This is useful because multiple paths may refer to the same inode, |
| and multiple calls to |
| .BR inotify_add_watch (2) |
| without this flag may clobber existing watch masks. |
| .RE |
| .PP |
| The following bits may be set in the |
| .I mask |
| field returned by |
| .BR read (2): |
| .RS 4 |
| .TP |
| .B IN_IGNORED |
| Watch was removed explicitly |
| .RB ( inotify_rm_watch (2)) |
| or automatically (file was deleted, or filesystem was unmounted). |
| See also BUGS. |
| .TP |
| .B IN_ISDIR |
| Subject of this event is a directory. |
| .TP |
| .B IN_Q_OVERFLOW |
| Event queue overflowed |
| .RI ( wd |
| is \-1 for this event). |
| .TP |
| .B IN_UNMOUNT |
| Filesystem containing watched object was unmounted. |
| In addition, an |
| .B IN_IGNORED |
| event will subsequently be generated for the watch descriptor. |
| .RE |
| .SS Examples |
| Suppose an application is watching the directory |
| .I dir |
| and the file |
| .IR dir/myfile |
| for all events. |
| The examples below show some events that will be generated |
| for these two objects. |
| .RS 4 |
| .TP |
| fd = open("dir/myfile", O_RDWR); |
| Generates |
| .B IN_OPEN |
| events for both |
| .I dir |
| and |
| .IR dir/myfile . |
| .TP |
| read(fd, buf, count); |
| Generates |
| .B IN_ACCESS |
| events for both |
| .I dir |
| and |
| .IR dir/myfile . |
| .TP |
| write(fd, buf, count); |
| Generates |
| .B IN_MODIFY |
| events for both |
| .I dir |
| and |
| .IR dir/myfile . |
| .TP |
| fchmod(fd, mode); |
| Generates |
| .B IN_ATTRIB |
| events for both |
| .I dir |
| and |
| .IR dir/myfile . |
| .TP |
| close(fd); |
| Generates |
| .B IN_CLOSE_WRITE |
| events for both |
| .I dir |
| and |
| .IR dir/myfile . |
| .RE |
| .PP |
| Suppose an application is watching the directories |
| .I dir1 |
| and |
| .IR dir2 , |
| and the file |
| .IR dir1/myfile . |
| The following examples show some events that may be generated. |
| .RS 4 |
| .TP |
| link("dir1/myfile", "dir2/new"); |
| Generates an |
| .B IN_ATTRIB |
| event for |
| .IR myfile |
| and an |
| .B IN_CREATE |
| event for |
| .IR dir2 . |
| .TP |
| rename("dir1/myfile", "dir2/myfile"); |
| Generates an |
| .B IN_MOVED_FROM |
| event for |
| .IR dir1 , |
| an |
| .B IN_MOVED_TO |
| event for |
| .IR dir2 , |
| and an |
| .B IN_MOVE_SELF |
| event for |
| .IR myfile . |
| The |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| events will have the same |
| .I cookie |
| value. |
| .RE |
| .PP |
| Suppose that |
| .IR dir1/xx |
| and |
| .IR dir2/yy |
| are (the only) links to the same file, and an application is watching |
| .IR dir1 , |
| .IR dir2 , |
| .IR dir1/xx , |
| and |
| .IR dir2/yy . |
| Executing the following calls in the order given below will generate |
| the following events: |
| .RS 4 |
| .TP |
| unlink("dir2/yy"); |
| Generates an |
| .BR IN_ATTRIB |
| event for |
| .IR xx |
| (because its link count changes) |
| and an |
| .B IN_DELETE |
| event for |
| .IR dir2 . |
| .TP |
| unlink("dir1/xx"); |
| Generates |
| .BR IN_ATTRIB , |
| .BR IN_DELETE_SELF , |
| and |
| .BR IN_IGNORED |
| events for |
| .IR xx , |
| and an |
| .BR IN_DELETE |
| event for |
| .IR dir1 . |
| .RE |
| .PP |
| Suppose an application is watching the directory |
| .IR dir |
| and (the empty) directory |
| .IR dir/subdir . |
| The following examples show some events that may be generated. |
| .RS 4 |
| .TP |
| mkdir("dir/new", mode); |
| Generates an |
| .B "IN_CREATE | IN_ISDIR" |
| event for |
| .IR dir . |
| .TP |
| rmdir("dir/subdir"); |
| Generates |
| .B IN_DELETE_SELF |
| and |
| .B IN_IGNORED |
| events for |
| .IR subdir , |
| and an |
| .B "IN_DELETE | IN_ISDIR" |
| event for |
| .IR dir . |
| .RE |
| .SS /proc interfaces |
| The following interfaces can be used to limit the amount of |
| kernel memory consumed by inotify: |
| .TP |
| .I /proc/sys/fs/inotify/max_queued_events |
| The value in this file is used when an application calls |
| .BR inotify_init (2) |
| to set an upper limit on the number of events that can be |
| queued to the corresponding inotify instance. |
| Events in excess of this limit are dropped, but an |
| .B IN_Q_OVERFLOW |
| event is always generated. |
| .TP |
| .I /proc/sys/fs/inotify/max_user_instances |
| This specifies an upper limit on the number of inotify instances |
| that can be created per real user ID. |
| .TP |
| .I /proc/sys/fs/inotify/max_user_watches |
| This specifies an upper limit on the number of watches |
| that can be created per real user ID. |
| .SH VERSIONS |
| Inotify was merged into the 2.6.13 Linux kernel. |
| The required library interfaces were added to glibc in version 2.4. |
| .RB ( IN_DONT_FOLLOW , |
| .BR IN_MASK_ADD , |
| and |
| .B IN_ONLYDIR |
| were added in glibc version 2.5.) |
| .SH CONFORMING TO |
| The inotify API is Linux-specific. |
| .SH NOTES |
| Inotify file descriptors can be monitored using |
| .BR select (2), |
| .BR poll (2), |
| and |
| .BR epoll (7). |
| When an event is available, the file descriptor indicates as readable. |
| .PP |
| Since Linux 2.6.25, |
| signal-driven I/O notification is available for inotify file descriptors; |
| see the discussion of |
| .B F_SETFL |
| (for setting the |
| .B O_ASYNC |
| flag), |
| .BR F_SETOWN , |
| and |
| .B F_SETSIG |
| in |
| .BR fcntl (2). |
| The |
| .I siginfo_t |
| structure (described in |
| .BR sigaction (2)) |
| that is passed to the signal handler has the following fields set: |
| .IR si_fd |
| is set to the inotify file descriptor number; |
| .IR si_signo |
| is set to the signal number; |
| .IR si_code |
| is set to |
| .BR POLL_IN ; |
| and |
| .B POLLIN |
| is set in |
| .IR si_band . |
| .PP |
| If successive output inotify events produced on the |
| inotify file descriptor are identical (same |
| .IR wd , |
| .IR mask , |
| .IR cookie , |
| and |
| .IR name ), |
| then they are coalesced into a single event if the |
| older event has not yet been read (but see BUGS). |
| This reduces the amount of kernel memory required for the event queue, |
| but also means that an application can't use inotify to reliably count |
| file events. |
| .PP |
| The events returned by reading from an inotify file descriptor |
| form an ordered queue. |
| Thus, for example, it is guaranteed that when renaming from |
| one directory to another, events will be produced in the |
| correct order on the inotify file descriptor. |
| .PP |
| The set of watch descriptors that is being monitored via |
| an inotify file descriptor can be viewed via the entry for |
| the inotify file descriptor in the process's |
| .IR /proc/[pid]/fdinfo |
| directory. |
| See |
| .BR proc (5) |
| for further details. |
| The |
| .B FIONREAD |
| .BR ioctl (2) |
| returns the number of bytes available to read from an |
| inotify file descriptor. |
| .SS Limitations and caveats |
| The inotify API provides no information about the user or process that |
| triggered the inotify event. |
| In particular, there is no easy |
| way for a process that is monitoring events via inotify |
| to distinguish events that it triggers |
| itself from those that are triggered by other processes. |
| .PP |
| 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. |
| (Applications must fall back to polling the filesystem |
| to catch such events.) |
| Furthermore, various pseudo-filesystems such as |
| .IR /proc , |
| .IR /sys , |
| and |
| .IR /dev/pts |
| are not monitorable with inotify. |
| .PP |
| The inotify API does not report file accesses and modifications that |
| may occur because of |
| .BR mmap (2), |
| .BR msync (2), |
| and |
| .BR munmap (2). |
| .PP |
| The inotify API identifies affected files by filename. |
| However, by the time an application processes an inotify event, |
| the filename may already have been deleted or renamed. |
| .PP |
| The inotify API identifies events via watch descriptors. |
| It is the application's responsibility to cache a mapping |
| (if one is needed) between watch descriptors and pathnames. |
| Be aware that directory renamings may affect multiple cached pathnames. |
| .PP |
| Inotify monitoring of directories is not recursive: |
| to monitor subdirectories under a directory, |
| additional watches must be created. |
| This can take a significant amount time for large directory trees. |
| .PP |
| If monitoring an entire directory subtree, |
| and a new subdirectory is created in that tree or an existing directory |
| is renamed into that tree, |
| be aware that by the time you create a watch for the new subdirectory, |
| new files (and subdirectories) may already exist inside the subdirectory. |
| Therefore, you may want to scan the contents of the subdirectory |
| immediately after adding the watch (and, if desired, |
| recursively add watches for any subdirectories that it contains). |
| .PP |
| Note that the event queue can overflow. |
| In this case, events are lost. |
| Robust applications should handle the possibility of |
| lost events gracefully. |
| For example, it may be necessary to rebuild part or all of |
| the application cache. |
| (One simple, but possibly expensive, |
| approach is to close the inotify file descriptor, empty the cache, |
| create a new inotify file descriptor, |
| and then re-create watches and cache entries |
| for the objects to be monitored.) |
| .PP |
| If a filesystem is mounted on top of a monitored directory, |
| no event is generated, and no events are generated |
| for objects immediately under the new mount point. |
| If the filesystem is subsequently unmounted, |
| events will subsequently be generated for the directory and |
| the objects it contains. |
| .\" |
| .SS Dealing with rename() events |
| As noted above, the |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| event pair that is generated by |
| .BR rename (2) |
| can be matched up via their shared cookie value. |
| However, the task of matching has some challenges. |
| .PP |
| These two events are usually consecutive in the event stream available |
| when reading from the inotify file descriptor. |
| However, this is not guaranteed. |
| If multiple processes are triggering events for monitored objects, |
| then (on rare occasions) an arbitrary number of |
| other events may appear between the |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| events. |
| Furthermore, it is not guaranteed that the event pair is atomically |
| inserted into the queue: there may be a brief interval where the |
| .B IN_MOVED_FROM |
| has appeared, but the |
| .B IN_MOVED_TO |
| has not. |
| .PP |
| Matching up the |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| event pair generated by |
| .BR rename (2) |
| is thus inherently racy. |
| (Don't forget that if an object is renamed outside of a monitored directory, |
| there may not even be an |
| .BR IN_MOVED_TO |
| event.) |
| Heuristic approaches (e.g., assume the events are always consecutive) |
| can be used to ensure a match in most cases, |
| but will inevitably miss some cases, |
| causing the application to perceive the |
| .B IN_MOVED_FROM |
| and |
| .B IN_MOVED_TO |
| events as being unrelated. |
| If watch descriptors are destroyed and re-created as a result, |
| then those watch descriptors will be inconsistent with |
| the watch descriptors in any pending events. |
| (Re-creating the inotify file descriptor and rebuilding the cache may |
| be useful to deal with this scenario.) |
| .PP |
| Applications should also allow for the possibility that the |
| .B IN_MOVED_FROM |
| event was the last event that could fit in the buffer |
| returned by the current call to |
| .BR read (2), |
| and the accompanying |
| .B IN_MOVED_TO |
| event might be fetched only on the next |
| .BR read (2), |
| which should be done with a (small) timeout to allow for the fact that |
| insertion of the |
| .BR IN_MOVED_FROM + IN_MOVED_TO |
| event pair is not atomic, |
| and also the possibility that there may not be any |
| .B IN_MOVED_TO |
| event. |
| .SH BUGS |
| Before Linux 3.19, |
| .BR fallocate (2) |
| did not create any inotify events. |
| Since Linux 3.19, |
| .\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35 |
| calls to |
| .BR fallocate (2) |
| generate |
| .B IN_MODIFY |
| events. |
| .PP |
| .\" FIXME . kernel commit 611da04f7a31b2208e838be55a42c7a1310ae321 |
| .\" implies that unmount events were buggy 2.6.11 to 2.6.36 |
| .\" |
| In kernels before 2.6.16, the |
| .B IN_ONESHOT |
| .I mask |
| flag does not work. |
| .PP |
| As originally designed and implemented, the |
| .B IN_ONESHOT |
| flag did not cause an |
| .B IN_IGNORED |
| event to be generated when the watch was dropped after one event. |
| However, as an unintended effect of other changes, |
| since Linux 2.6.36, an |
| .B IN_IGNORED |
| event is generated in this case. |
| .PP |
| Before kernel 2.6.25, |
| .\" commit 1c17d18e3775485bf1e0ce79575eb637a94494a2 |
| the kernel code that was intended to coalesce successive identical events |
| (i.e., the two most recent events could potentially be coalesced |
| if the older had not yet been read) |
| instead checked if the most recent event could be coalesced with the |
| .I oldest |
| unread event. |
| .PP |
| When a watch descriptor is removed by calling |
| .BR inotify_rm_watch (2) |
| (or because a watch file is deleted or the filesystem |
| that contains it is unmounted), |
| any pending unread events for that watch descriptor remain available to read. |
| As watch descriptors are subsequently allocated with |
| .BR inotify_add_watch (2), |
| the kernel cycles through the range of possible watch descriptors (0 to |
| .BR INT_MAX ) |
| incrementally. |
| When allocating a free watch descriptor, no check is made to see whether that |
| watch descriptor number has any pending unread events in the inotify queue. |
| Thus, it can happen that a watch descriptor is reallocated even |
| when pending unread events exist for a previous incarnation of |
| that watch descriptor number, with the result that the application |
| might then read those events and interpret them as belonging to |
| the file associated with the newly recycled watch descriptor. |
| In practice, the likelihood of hitting this bug may be extremely low, |
| since it requires that an application cycle through |
| .B INT_MAX |
| watch descriptors, |
| release a watch descriptor while leaving unread events for that |
| watch descriptor in the queue, |
| and then recycle that watch descriptor. |
| For this reason, and because there have been no reports |
| of the bug occurring in real-world applications, |
| as of Linux 3.15, |
| .\" FIXME . https://bugzilla.kernel.org/show_bug.cgi?id=77111 |
| no kernel changes have yet been made to eliminate this possible bug. |
| .SH EXAMPLES |
| The following program demonstrates the usage of the inotify API. |
| It marks the directories passed as a command-line arguments |
| and waits for events of type |
| .BR IN_OPEN , |
| .BR IN_CLOSE_NOWRITE , |
| and |
| .BR IN_CLOSE_WRITE . |
| .PP |
| The following output was recorded while editing the file |
| .I /home/user/temp/foo |
| and listing directory |
| .IR /tmp . |
| Before the file and the directory were opened, |
| .B IN_OPEN |
| events occurred. |
| After the file was closed, an |
| .B IN_CLOSE_WRITE |
| event occurred. |
| After the directory was closed, an |
| .B IN_CLOSE_NOWRITE |
| event occurred. |
| Execution of the program ended when the user pressed the ENTER key. |
| .SS Example output |
| .in +4n |
| .EX |
| $ \fB./a.out /tmp /home/user/temp\fP |
| Press enter key to terminate. |
| Listening for events. |
| IN_OPEN: /home/user/temp/foo [file] |
| IN_CLOSE_WRITE: /home/user/temp/foo [file] |
| IN_OPEN: /tmp/ [directory] |
| IN_CLOSE_NOWRITE: /tmp/ [directory] |
| |
| Listening for events stopped. |
| .EE |
| .in |
| .SS Program source |
| \& |
| .EX |
| #include <errno.h> |
| #include <poll.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/inotify.h> |
| #include <unistd.h> |
| #include <string.h> |
| |
| /* Read all available inotify events from the file descriptor \(aqfd\(aq. |
| wd is the table of watch descriptors for the directories in argv. |
| argc is the length of wd and argv. |
| argv is the list of watched directories. |
| Entry 0 of wd and argv is unused. */ |
| |
| static void |
| handle_events(int fd, int *wd, int argc, char* argv[]) |
| { |
| /* Some systems cannot read integer variables if they are not |
| properly aligned. On other systems, incorrect alignment may |
| decrease performance. Hence, the buffer used for reading from |
| the inotify file descriptor should have the same alignment as |
| struct inotify_event. */ |
| |
| char buf[4096] |
| __attribute__ ((aligned(__alignof__(struct inotify_event)))); |
| const struct inotify_event *event; |
| ssize_t len; |
| |
| /* Loop while events can be read from inotify file descriptor. */ |
| |
| for (;;) { |
| |
| /* Read some events. */ |
| |
| len = read(fd, buf, sizeof(buf)); |
| if (len == \-1 && errno != EAGAIN) { |
| perror("read"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* If the nonblocking read() found no events to read, then |
| it returns \-1 with errno set to EAGAIN. In that case, |
| we exit the loop. */ |
| |
| if (len <= 0) |
| break; |
| |
| /* Loop over all events in the buffer. */ |
| |
| for (char *ptr = buf; ptr < buf + len; |
| ptr += sizeof(struct inotify_event) + event\->len) { |
| |
| event = (const struct inotify_event *) ptr; |
| |
| /* Print event type. */ |
| |
| if (event\->mask & IN_OPEN) |
| printf("IN_OPEN: "); |
| if (event\->mask & IN_CLOSE_NOWRITE) |
| printf("IN_CLOSE_NOWRITE: "); |
| if (event\->mask & IN_CLOSE_WRITE) |
| printf("IN_CLOSE_WRITE: "); |
| |
| /* Print the name of the watched directory. */ |
| |
| for (int i = 1; i < argc; ++i) { |
| if (wd[i] == event\->wd) { |
| printf("%s/", argv[i]); |
| break; |
| } |
| } |
| |
| /* Print the name of the file. */ |
| |
| if (event\->len) |
| printf("%s", event\->name); |
| |
| /* Print type of filesystem object. */ |
| |
| if (event\->mask & IN_ISDIR) |
| printf(" [directory]\en"); |
| else |
| printf(" [file]\en"); |
| } |
| } |
| } |
| |
| int |
| main(int argc, char* argv[]) |
| { |
| char buf; |
| int fd, i, poll_num; |
| int *wd; |
| nfds_t nfds; |
| struct pollfd fds[2]; |
| |
| if (argc < 2) { |
| printf("Usage: %s PATH [PATH ...]\en", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Press ENTER key to terminate.\en"); |
| |
| /* Create the file descriptor for accessing the inotify API. */ |
| |
| fd = inotify_init1(IN_NONBLOCK); |
| if (fd == \-1) { |
| perror("inotify_init1"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Allocate memory for watch descriptors. */ |
| |
| wd = calloc(argc, sizeof(int)); |
| if (wd == NULL) { |
| perror("calloc"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Mark directories for events |
| \- file was opened |
| \- file was closed */ |
| |
| for (i = 1; i < argc; i++) { |
| wd[i] = inotify_add_watch(fd, argv[i], |
| IN_OPEN | IN_CLOSE); |
| if (wd[i] == \-1) { |
| fprintf(stderr, "Cannot watch \(aq%s\(aq: %s\en", |
| argv[i], strerror(errno)); |
| exit(EXIT_FAILURE); |
| } |
| } |
| |
| /* Prepare for polling. */ |
| |
| nfds = 2; |
| |
| fds[0].fd = STDIN_FILENO; /* Console input */ |
| fds[0].events = POLLIN; |
| |
| fds[1].fd = fd; /* Inotify input */ |
| fds[1].events = POLLIN; |
| |
| /* Wait for events and/or terminal input. */ |
| |
| printf("Listening for events.\en"); |
| while (1) { |
| poll_num = poll(fds, nfds, \-1); |
| if (poll_num == \-1) { |
| if (errno == EINTR) |
| continue; |
| perror("poll"); |
| exit(EXIT_FAILURE); |
| } |
| |
| 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 != \(aq\en\(aq) |
| continue; |
| break; |
| } |
| |
| if (fds[1].revents & POLLIN) { |
| |
| /* Inotify events are available. */ |
| |
| handle_events(fd, wd, argc, argv); |
| } |
| } |
| } |
| |
| printf("Listening for events stopped.\en"); |
| |
| /* Close inotify file descriptor. */ |
| |
| close(fd); |
| |
| free(wd); |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR inotifywait (1), |
| .BR inotifywatch (1), |
| .BR inotify_add_watch (2), |
| .BR inotify_init (2), |
| .BR inotify_init1 (2), |
| .BR inotify_rm_watch (2), |
| .BR read (2), |
| .BR stat (2), |
| .BR fanotify (7) |
| .PP |
| .IR Documentation/filesystems/inotify.txt |
| in the Linux kernel source tree |