INOTIFY(2)
๐ INOTIFY(2) โ the manual page, but make it make sense
okay bestie, so this is the inotify page from section 2 of the manual (the system calls one, iykyk). it's the whole inotify_init family and fr fr it's giving "monitor literally everything happening on your filesystem" energy. let's go ๐ฆ
โจ NAME โจ
inotify_init, inotify_init1, inotify_add_watch, inotify_add_watch_at, inotify_rm_watch โ monitor file system events ๐
๐ LIBRARY ๐
Standard C Library (libc, -lc). the classic. the icon. ๐ซถ
๐ธ SYNOPSIS ๐ธ
#include <sys/inotify.h>
int
inotify_init();
int
inotify_init1(int flags);
int
inotify_add_watch(int fd, const char *pathname, uint32_t mask);
int
inotify_add_watch_at(int fd, int dfd, const char *pathname,
uint32_t mask);
int
inotify_rm_watch(int fd, uint32_t wd);
struct inotify_event {
int wd; /* Watch descriptor */
uint32_t mask; /* Event and flags */
uint32_t cookie; /* Unique ID which links rename events */
uint32_t len; /* Name field size, including nul bytes */
char name[0]; /* Filename (nul-terminated) */
};
that struct is literally the main character of every read you're gonna do, so likeโฆ look at it. memorize it. ๐
๐ DESCRIPTION ๐
So the inotify system calls give you an interface to monitor file system events, no cap. They aim to be compatible with the Linux inotify interface โ so if you're coming from Linux, hey bestie, welcome. The functionality they hand you is similar to the EVFILT_VNODE filter of the kevent(2) system call, but it goes further: it lets you monitor a directory without needing to open each object in that directory. Which, lowkey, is a huge slay โ it avoids races and cuts down the number of file descriptors you need to monitor a large file hierarchy. ๐ฅ
inotify lets one or more file system objects โ generally files or directories โ be watched for events, like a file open or close. Watched objects are associated with a file descriptor returned by inotify_init() or inotify_init1(). When an event happens, a record describing the event becomes available for reading from the inotify file descriptor. So each inotify descriptor is basically referring to a queue of events just waiting to be read. ๐ฌ
Also important, bestie: inotify descriptors are inherited across fork(2) calls and may be passed to other processes via unix(4) sockets. family heirloom behavior fr fr. ๐
The inotify_init1() system call accepts two flags:
IN_NONBLOCKโ causes the inotify descriptor to be opened in non-blocking mode, such thatread(2)calls will not block if no records are available to consume, and will instead returnEWOULDBLOCK. (so like, no waiting around, she's busy ๐ )IN_CLOEXECโ causes the inotify descriptor to be closed automatically whenexecve(2)is called. clean exits only.
To watch a file or directory, you gotta use the inotify_add_watch() or inotify_add_watch_at() system calls. They take a path and a mask of events to watch for, and return a "watch descriptor" โ a non-negative integer which uniquely identifies the watched object within the inotify descriptor. it's giving ID card. ๐ชช
The inotify_rm_watch() system call removes a watch from an inotify descriptor. bye bestie ๐
When you're watching a directory, objects within the directory are monitored for events as well as the directory itself. A record describing an inotify event consists of a struct inotify_event followed by the name of the object in the directory being watched. If the watched object itself generates an event, no name is present. Extra nul bytes may follow the file name in order to provide alignment for a subsequent record. (alignment padding, the unglamorous but necessary backup dancer ๐)
โญ the events (yes, all of them) โญ
IN_ACCESSโ a file's contents were accessed, e.g., byread(2),copy_file_range(2),sendfile(2), orgetdirentries(2).IN_ATTRIBโ a file's metadata was changed, e.g., bychmod(2)orunlink(2).IN_CLOSE_WRITEโ a file that was previously opened for writing was closed.IN_CLOSE_NOWRITEโ a file that was previously opened read-only was closed.IN_CREATEโ a file within a watched directory was created, e.g., byopen(2),mkdir(2),symlink(2),mknod(2), orbind(2).IN_DELETEโ a file or directory within a watched directory was removed.IN_DELETE_SELFโ the watched file or directory itself was deleted. This event is generated only when the link count of the file drops to zero.IN_MODIFYโ a file's contents were modified, e.g., bywrite(2)orcopy_file_range(2).IN_MOVE_SELFโ the watched file or directory itself was renamed.IN_MOVED_FROMโ a file or directory was moved from a watched directory.IN_MOVED_TOโ a file or directory was moved into a watched directory. Arename(2)call thus may generate two events, one for the old name and one for the new name. These are linked together by thecookiefield in the inotify record, which can be compared to link the two records to the same event. ๐ช (yes that's literally why it's called cookie, obsessed)IN_OPENโ a file was opened.
๐ฆ some extra flags that can show up in event records ๐ฆ
IN_IGNOREDโ when a watch is removed from a file โ for example because it was created with theIN_ONESHOTflag, the file was deleted, or the watch was explicitly removed withinotify_rm_watch(2)โ an event with this mask is generated to indicate that the watch will not generate any more events. Once this event is generated, the watch is automatically removed, and in particular should not be removed manually withinotify_rm_watch(2). like, do not do that. ๐IN_ISDIRโ when the subject of an event is a directory, this flag is set in the mask.IN_Q_OVERFLOWโ one or more events were dropped, for example because of a kernel memory allocation failure or because the event queue size hit a limit. ๐ญIN_UNMOUNTโ the filesystem containing the watched object was unmounted.
๐ and the flags you can pass in the mask ๐
A number of flags may also be specified in the mask given to inotify_add_watch() and inotify_add_watch_at():
IN_DONT_FOLLOWโ if pathname is a symbolic link, do not follow it.IN_EXCL_UNLINKโ this currently has no effect, see the "BUGS" section. When adding a watch to an object, and that object is already watched by the same inotify descriptor, by default the mask of the existing watch is overwritten.IN_MASK_ADDโ when specified, the mask of the existing watch is instead logically ORed with the new mask.IN_MASK_CREATEโ wheninotify_add(watch)is used to add a watch to an object,IN_MASK_CREATEis specified, and that object is already watched by the same inotify descriptor, return an error instead of updating the existing watch.IN_ONESHOTโ monitor the object for a single event, after which the watch is automatically removed. As part of removal, aIN_IGNOREDevent is generated.IN_ONLYDIRโ when creating a watch, fail withENOTDIRif the path does not refer to a directory.
๐ง SYSCTL VARIABLES ๐ง
The following variables are available as both sysctl(8) variables and loader(8) tunables:
vfs.inotify.max_eventsโ the maximum number of inotify records that can be queued for a single inotify descriptor. Records in excess of this limit are discarded, and a single event with mask equal toIN_Q_OVERFLOWwill be present in the queue. (girl, you missed some ๐)vfs.inotify.max_user_instancesโ the maximum number of inotify descriptors that can be created by a single user.vfs.inotify.max_user_watchesโ the maximum number of inotify watches per user.
๐ EXAMPLES ๐
See the example program in /usr/share/examples/inotify/inotify.c. go look at it, it ate. โจ
๐ ERRORS ๐
The inotify_init() and inotify_init1() functions will fail if:
[ENFILE]โ the system limit on the total number of open files has been reached.[EMFILE]โ a per-process limit on the number of open files has been reached.[EMFILE]โ the system limit on the number of inotify descriptors has been reached.[EINVAL]โ an unrecognized flag was passed toinotify_init1().
The inotify_add_watch() and inotify_add_watch_at() system calls will fail if:
[EBADF]โ the fd parameter is not a valid file descriptor.[EINVAL]โ the fd parameter is not an inotify descriptor.[EINVAL]โ the mask parameter does not specify an event, or theIN_MASK_CREATEandIN_MASK_ADDflags are both set, or an unrecognized flag was passed.[ENOTDIR]โ the pathname parameter refers to a file that is not a directory, and theIN_ONLYDIRflag was specified.[ENOSPC]โ the per-user limit on the total number of inotify watches has been reached.[ECAPMODE]โ the process is in capability mode andinotify_add_watch()was called, orinotify_add_watch_at()was called withAT_FDCWDas the directory file descriptor dfd.[ENOTCAPABLE]โ the process is in capability mode and pathname contains a..component leading to a directory outside the directory hierarchy specified by dfd.
The inotify_rm_watch() system call will fail if:
[EBADF]โ the fd parameter is not a valid file descriptor.[EINVAL]โ the fd parameter is not an inotify descriptor.[EINVAL]โ the wd parameter is not a valid watch descriptor.
๐ฅ SEE ALSO ๐ฅ
๐ STANDARDS ๐
The inotify_init interface originates from Linux and is non-standard. This implementation aims to be compatible with that of Linux and is based on the documentation available at https://man7.org/linux/man-pages/man7/inotify.7.html. cross-platform bestie behavior ๐ซถ
๐ธ HISTORY ๐ธ
The inotify system calls first appeared in FreeBSD 15.0. baby's first release!! ๐
๐ญ BUGS ๐ญ
okay so, the caveats. pay attention, these are real:
- If a file in a watched directory has multiple hard links, an access via any hard link for that file will generate an event, even if the accessed link belongs to an unwatched directory. This is not the case for the Linux implementation, where only accesses via the hard link in the watched directory will generate an event. ๐
- If a watched directory contains multiple hard links of a file, an event on one of the hard links will generate an inotify record for each link in the directory. (so many records. so many. ๐)
- When a file is unlinked, no more events will be generated for that file, even if it continues to be accessed. By default, the Linux implementation will continue to generate events in this case. Thus, the FreeBSD implementation behaves as though
IN_EXCL_UNLINKis always set. not her doing the most at all times ๐
<div>so yeah, that's the whole page โจ this one came from the Debian build of the manual, dated May 19, 2025 โ mwah, ty for the docs, now go watch some files ๐ฆ๐</div>
๐ฆ where this page comes from
- freebsd 15.1: base 15.1
- ๐ the page's license: BSD-2-Clause
- Copyright (c) 2025 Klara, Inc
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms