1.\" 2.\" SPDX-License-Identifier: BSD-2-Clause 3.\" 4.\" Copyright (c) 2025 Klara, Inc. 5.\" 6.Dd May 19, 2025 7.Dt INOTIFY 2 8.Os 9.Sh NAME 10.Nm inotify_init , 11.Nm inotify_init1 , 12.Nm inotify_add_watch , 13.Nm inotify_add_watch_at , 14.Nm inotify_rm_watch 15.Nd monitor file system events 16.Sh LIBRARY 17.Lb libc 18.Sh SYNOPSIS 19.In sys/inotify.h 20.Ft int 21.Fo inotify_init 22.Fc 23.Ft int 24.Fo inotify_init1 25.Fa "int flags" 26.Fc 27.Ft int 28.Fo inotify_add_watch 29.Fa "int fd" 30.Fa "const char *pathname" 31.Fa "uint32_t mask" 32.Fc 33.Ft int 34.Fo inotify_add_watch_at 35.Fa "int fd" 36.Fa "int dfd" 37.Fa "const char *pathname" 38.Fa "uint32_t mask" 39.Fc 40.Ft int 41.Fo inotify_rm_watch 42.Fa "int fd" 43.Fa "uint32_t wd" 44.Fc 45.Bd -literal 46struct inotify_event { 47 int wd; /* Watch descriptor */ 48 uint32_t mask; /* Event and flags */ 49 uint32_t cookie; /* Unique ID which links rename events */ 50 uint32_t len; /* Name field size, including nul bytes */ 51 char name[0]; /* Filename (nul-terminated) */ 52}; 53.Ed 54.Sh DESCRIPTION 55The inotify system calls provide an interface to monitor file system events. 56They aim to be compatible with the Linux inotify interface. 57The provided functionality is similar to the 58.Dv EVFILT_VNODE 59filter of the 60.Xr kevent 2 61system call, but further allows monitoring of a directory without needing to 62open each object in that directory. 63This avoids races and reduces the number of file descriptors needed to monitor 64a large file hierarchy. 65.Pp 66inotify allows one or more file system objects, generally files or directories, 67to be watched for events, such as file open or close. 68Watched objects are associated with a file descriptor returned 69by 70.Fn inotify_init 71or 72.Fn inotify_init1 . 73When an event occurs, a record describing the event becomes available for 74reading from the inotify file descriptor. 75Each inotify descriptor thus refers to a queue of events waiting to be read. 76inotify descriptors are inherited across 77.Xr fork 2 78calls and may be passed to other processes via 79.Xr unix 4 80sockets. 81.Pp 82The 83.Fn inotify_init1 84system call accepts two flags. 85The 86.Dv IN_NONBLOCK 87flag causes the inotify descriptor to be opened in non-blocking mode, such that 88.Xr read 2 89calls will not block if no records are available to consume, and will instead 90return 91.Er EWOULDBLOCK . 92The 93.Dv IN_CLOEXEC 94flag causes the inotify descriptor to be closed automatically when 95.Xr execve 2 96is called. 97.Pp 98To watch a file or directory, the 99.Fn inotify_add_watch 100or 101.Fn inotify_add_watch_at 102system calls must be used. 103They take a path and a mask of events to watch for, and return a 104.Dq watch descriptor , 105a non-negative integer which uniquely identifies the watched object within the 106inotify descriptor. 107.Pp 108The 109.Fn inotify_rm_watch 110system call removes a watch from an inotify descriptor. 111.Pp 112When watching a directory, objects within the directory are monitored for events 113as well as the directory itself. 114A record describing an inotify event consists of a 115.Dq struct inotify_event 116followed by the name of the object in the directory being watched. 117If the watched object itself generates an event, no name is present. 118Extra nul bytes may follow the file name in order to provide alignment for a 119subsequent record. 120.Pp 121The following events are defined: 122.Bl -tag -width IN_CLOSE_NOWRITE 123.It Dv IN_ACCESS 124A file's contents were accessed, e.g., by 125.Xr read 2 126.Xr copy_file_range 2 , 127.Xr sendfile 2 , 128or 129.Xr getdirentries 2 . 130.It Dv IN_ATTRIB 131A file's metadata was changed, e.g., by 132.Xr chmod 2 133or 134.Xr unlink 2 . 135.It Dv IN_CLOSE_WRITE 136A file that was previously opened for writing was closed. 137.It Dv IN_CLOSE_NOWRITE 138A file that was previously opened read-only was closed. 139.It Dv IN_CREATE 140A file within a watched directory was created, e.g., by 141.Xr open 2 , 142.Xr mkdir 2 , 143.Xr symlink 2 , 144.Xr mknod 2 , 145or 146.Xr bind 2 . 147.It Dv IN_DELETE 148A file or directory within a watched directory was removed. 149.It Dv IN_DELETE_SELF 150The watched file or directory itself was deleted. 151This event is generated only when the link count of the file drops 152to zero. 153.It Dv IN_MODIFY 154A file's contents were modified, e.g., by 155.Xr write 2 156or 157.Xr copy_file_range 2 . 158.It Dv IN_MOVE_SELF 159The watched file or directory itself was renamed. 160.It Dv IN_MOVED_FROM 161A file or directory was moved from a watched directory. 162.It Dv IN_MOVED_TO 163A file or directory was moved into a watched directory. 164A 165.Xr rename 2 166call thus may generate two events, one for the old name and one for the new 167name. 168These are linked together by the 169.Ar cookie 170field in the inotify record, which can be compared to link the two records 171to the same event. 172.It Dv IN_OPEN 173A file was opened. 174.El 175.Pp 176Some additional flags may be set in inotify event records: 177.Bl -tag -width IN_Q_OVERFLOW 178.It Dv IN_IGNORED 179When a watch is removed from a file, for example because it was created with the 180.Dv IN_ONESHOT 181flag, the file was deleted, or the watch was explicitly removed with 182.Xr inotify_rm_watch 2 , 183an event with this mask is generated to indicate that the watch will not 184generate any more events. 185Once this event is generated, the watch is automatically removed, and in 186particular should not be removed manually with 187.Xr inotify_rm_watch 2 . 188.It Dv IN_ISDIR 189When the subject of an event is a directory, this flag is set in the 190.Ar mask 191.It Dv IN_Q_OVERFLOW 192One or more events were dropped, for example because of a kernel memory allocation 193failure or because the event queue size hit a limit. 194.It Dv IN_UNMOUNT 195The filesystem containing the watched object was unmounted. 196.El 197.Pp 198A number of flags may also be specified in the 199.Ar mask 200given to 201.Fn inotify_add_watch 202and 203.Fn inotify_add_watch_at : 204.Bl -tag -width IN_DONT_FOLLOW 205.It Dv IN_DONT_FOLLOW 206If 207.Ar pathname 208is a symbolic link, do not follow it. 209.It Dv IN_EXCL_UNLINK 210This currently has no effect, see the 211.Sx BUGS 212section. 213.In Dv IN_MASK_ADD 214When adding a watch to an object, and that object is already watched by the 215same inotify descriptor, by default the mask of the existing watch is 216overwritten. 217When 218.Dv IN_MASK_ADD 219is specified, the mask of the existing watch is instead logically ORed with 220the new mask. 221.In Dv IN_MASK_CREATE 222When 223.Fn inotify_add watch 224is used to add a watch to an object, 225.Dv IN_MASK_CREATE 226is specified, and that object is already watched by the same inotify descriptor, 227return an error instead of updating the existing watch. 228.In Dv IN_ONESHOT 229Monitor the object for a single event, after which the watch is automatically 230removed. 231As part of removal, a 232.Dv IN_IGNORED 233event is generated. 234.In Dv IN_ONLYDIR 235When creating a watch, fail with 236.Er ENOTDIR 237if the path does not refer to a directory. 238.El 239.Sh SYSCTL VARIABLES 240The following variables are available as both 241.Xr sysctl 8 242variables and 243.Xr loader 8 244tunables: 245.Bl -tag -width 15 246.It Va vfs.inotify.max_events 247The maximum number of inotify records that can be queued for a single 248inotify descriptor. 249Records in excess of this limit are discarded, and a single event with 250mask equal to 251.Dv IN_Q_OVERFLOW 252will be present in the queue. 253.It Va vfs.inotify.max_user_instances 254The maximum number of inotify descriptors that can be created by a single 255user. 256.It Va vfs.inotify.max_user_watches 257The maximum number of inotify watches per user. 258.El 259.Sh EXAMPLES 260See the example program in 261.Pa /usr/share/examples/inotify/inotify.c . 262.Sh ERRORS 263The 264.Fn inotify_init 265and 266.Fn inotify_init1 267functions will fail if: 268.Bl -tag -width Er 269.It Bq Er ENFILE 270The system limit on the total number of open files has been reached. 271.It Bq Er EMFILE 272A per-process limit on the number of open files has been reached. 273.It Bq Er EMFILE 274The system limit on the number of inotify descriptors has been reached. 275.It Bq Er EINVAL 276An unrecognized flag was passed to 277.Fn inotify_init1 . 278.El 279.Pp 280The 281.Fn inotify_add_watch 282and 283.Fn inotify_add_watch_at 284system calls will fail if: 285.Bl -tag -width Er 286.It Bq Er EBADF 287The 288.Ar fd 289parameter is not a valid file descriptor. 290.It Bq Er EINVAL 291The 292.Ar fd 293parameter is not an inotify descriptor. 294.It Bq Er EINVAL 295The 296.Ar mask 297parameter does not specify an event, or 298the 299.Dv IN_MASK_CREATE 300and 301.Dv IN_MASK_ADD 302flags are both set, or an unrecognized flag was passed. 303.It Bq Er ENOTDIR 304The 305.Ar pathname 306parameter refers to a file that is not a directory, and the 307.Dv IN_ONLYDIR 308flag was specified. 309.It Bq Er ENOSPC 310The per-user limit on the total number of inotify watches has been reached. 311.It Bq Er ECAPMODE 312The process is in capability mode and 313.Fn inotify_add_watch 314was called, or 315.Fn inotify_add_watch_at 316was called with 317.Dv AT_FDCWD 318as the directory file descriptor 319.Ar dfd . 320.It Bq Er ENOTCAPABLE 321The process is in capability mode and 322.Ar pathname 323contains a 324.Dq .. 325component leading to a directory outside the directory hierarchy specified 326by 327.Ar dfd . 328.El 329.Pp 330The 331.Fn inotify_rm_watch 332system call will fail if: 333.Bl -tag -width Er 334.It Bq Er EBADF 335The 336.Ar fd 337parameter is not a valid file descriptor. 338.It Bq Er EINVAL 339The 340.Ar fd 341parameter is not an inotify descriptor. 342.It Bq Er EINVAL 343The 344.Ar wd 345parameter is not a valid watch descriptor. 346.El 347.Sh SEE ALSO 348.Xr kevent 2 , 349.Xr capsicum 4 350.Sh STANDARDS 351The 352.Nm 353interface originates from Linux and is non-standard. 354This implementation aims to be compatible with that of Linux and is based 355on the documentation available at 356.Pa https://man7.org/linux/man-pages/man7/inotify.7.html . 357.Sh HISTORY 358The inotify system calls first appeared in 359.Fx 15.0 . 360.Sh BUGS 361If a file in a watched directory has multiple hard links, 362an access via any hard link for that file will generate an event, even 363if the accessed link belongs to an unwatched directory. 364This is not the case for the Linux implementation, where only accesses 365via the hard link in the watched directory will generate an event. 366.Pp 367If a watched directory contains multiple hard links of a file, an event 368on one of the hard links will generate an inotify record for each link 369in the directory. 370.Pp 371When a file is unlinked, no more events will be generated for that file, 372even if it continues to be accessed. 373By default, the Linux implementation will continue to generate events in 374this case. 375Thus, the 376.Fx 377implementation behaves as though 378.Dv IN_EXCL_UNLINK 379is always set. 380