]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man7/fanotify.7
044e3f44fdedfe46f67d57498ba08b3f9c20deca
[thirdparty/man-pages.git] / man7 / fanotify.7
1 .\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de>
2 .\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
8 .\"
9 .\" Permission is granted to copy and distribute modified versions of
10 .\" this manual under the conditions for verbatim copying, provided that
11 .\" the entire resulting derived work is distributed under the terms of
12 .\" a permission notice identical to this one.
13 .\"
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date. The author(s) assume.
16 .\" no responsibility for errors or omissions, or for damages resulting.
17 .\" from the use of the information contained herein. The author(s) may.
18 .\" not have taken the same level of care in the production of this.
19 .\" manual, which is licensed free of charge, as they might when working.
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .TH FANOTIFY 7 2019-03-06 "Linux" "Linux Programmer's Manual"
26 .SH NAME
27 fanotify \- monitoring filesystem events
28 .SH DESCRIPTION
29 The fanotify API provides notification and interception of
30 filesystem events.
31 Use cases include virus scanning and hierarchical storage management.
32 Currently, only a limited set of events is supported.
33 In particular, there is no support for create, delete, and move events.
34 (See
35 .BR inotify (7)
36 for details of an API that does notify those events.)
37 .PP
38 Additional capabilities compared to the
39 .BR inotify (7)
40 API include the ability to monitor all of the objects
41 in a mounted filesystem,
42 the ability to make access permission decisions, and the
43 possibility to read or modify files before access by other applications.
44 .PP
45 The following system calls are used with this API:
46 .BR fanotify_init (2),
47 .BR fanotify_mark (2),
48 .BR read (2),
49 .BR write (2),
50 and
51 .BR close (2).
52 .SS fanotify_init(), fanotify_mark(), and notification groups
53 The
54 .BR fanotify_init (2)
55 system call creates and initializes an fanotify notification group
56 and returns a file descriptor referring to it.
57 .PP
58 An fanotify notification group is a kernel-internal object that holds
59 a list of files, directories, filesystems, and mount points for which
60 events shall be created.
61 .PP
62 For each entry in an fanotify notification group, two bit masks exist: the
63 .I mark
64 mask and the
65 .I ignore
66 mask.
67 The mark mask defines file activities for which an event shall be created.
68 The ignore mask defines activities for which no event shall be generated.
69 Having these two types of masks permits a filesystem, mount point, or
70 directory to be marked for receiving events, while at the same time
71 ignoring events for specific objects under a mount point or directory.
72 .PP
73 The
74 .BR fanotify_mark (2)
75 system call adds a file, directory, filesystem or mount point to a
76 notification group and specifies which events
77 shall be reported (or ignored), or removes or modifies such an entry.
78 .PP
79 A possible usage of the ignore mask is for a file cache.
80 Events of interest for a file cache are modification of a file and closing
81 of the same.
82 Hence, the cached directory or mount point is to be marked to receive these
83 events.
84 After receiving the first event informing that a file has been modified,
85 the corresponding cache entry will be invalidated.
86 No further modification events for this file are of interest until the file
87 is closed.
88 Hence, the modify event can be added to the ignore mask.
89 Upon receiving the close event, the modify event can be removed from the
90 ignore mask and the file cache entry can be updated.
91 .PP
92 The entries in the fanotify notification groups refer to files and
93 directories via their inode number and to mounts via their mount ID.
94 If files or directories are renamed or moved within the same mount,
95 the respective entries survive.
96 If files or directories are deleted or moved to another mount or if
97 filesystems or mounts are unmounted, the corresponding entries are deleted.
98 .SS The event queue
99 As events occur on the filesystem objects monitored by a notification group,
100 the fanotify system generates events that are collected in a queue.
101 These events can then be read (using
102 .BR read (2)
103 or similar)
104 from the fanotify file descriptor
105 returned by
106 .BR fanotify_init (2).
107 .PP
108 Two types of events are generated:
109 .I notification
110 events and
111 .I permission
112 events.
113 Notification events are merely informative
114 and require no action to be taken by
115 the receiving application with the exception being that the file
116 descriptor provided within a generic event must be closed.
117 The closing of file descriptors for each event applies only to
118 applications that have initialized fanotify without using
119 .BR FAN_REPORT_FID
120 (see below).
121 Permission events are requests to the receiving application to decide
122 whether permission for a file access shall be granted.
123 For these events, the recipient must write a response which decides whether
124 access is granted or not.
125 .PP
126 An event is removed from the event queue of the fanotify group
127 when it has been read.
128 Permission events that have been read are kept in an internal list of the
129 fanotify group until either a permission decision has been taken by
130 writing to the fanotify file descriptor or the fanotify file descriptor
131 is closed.
132 .SS Reading fanotify events
133 Calling
134 .BR read (2)
135 for the file descriptor returned by
136 .BR fanotify_init (2)
137 blocks (if the flag
138 .B FAN_NONBLOCK
139 is not specified in the call to
140 .BR fanotify_init (2))
141 until either a file event occurs or the call is interrupted by a signal
142 (see
143 .BR signal (7)).
144 .PP
145 Depending on whether
146 .BR FAN_REPORT_FID
147 is supplied as one of the flags when calling
148 .BR fanotify_init (2)
149 determines what structure(s) are returned for an event within the read
150 buffer.
151 After a successful
152 .BR read (2),
153 the read buffer contains one or more of the following structures:
154 .PP
155 .in +4n
156 .EX
157 struct fanotify_event_metadata {
158 __u32 event_len;
159 __u8 vers;
160 __u8 reserved;
161 __u16 metadata_len;
162 __aligned_u64 mask;
163 __s32 fd;
164 __s32 pid;
165 };
166 .EE
167 .in
168 .PP
169 In the case where
170 .BR FAN_REPORT_FID
171 is supplied as one of the flags to
172 .BR fanotify_init (2),
173 you should also expect to receive the structure detailed below following
174 the generic
175 .I fanotify_event_metadata
176 structure within the read buffer:
177 .PP
178 .in +4n
179 .EX
180 struct fanotify_event_info_fid {
181 struct fanotify_event_info_header hdr;
182 __kernel_fsid_t fsid;
183 unsigned char file_handle[0];
184 };
185 .EE
186 .in
187 .PP
188 For performance reasons, it is recommended to use a large
189 buffer size (for example, 4096 bytes),
190 so that multiple events can be retrieved by a single
191 .BR read (2).
192 .PP
193 The return value of
194 .BR read (2)
195 is the number of bytes placed in the buffer,
196 or \-1 in case of an error (but see BUGS).
197 .PP
198 The fields of the
199 .I fanotify_event_metadata
200 structure are as follows:
201 .TP
202 .I event_len
203 This is the length of the data for the current event and the offset
204 to the next event in the buffer.
205 Without
206 .BR FAN_REPORT_FID ,
207 the value of
208 .I event_len
209 is always
210 .BR FAN_EVENT_METADATA_LEN .
211 With
212 .BR FAN_REPORT_FID ,
213 .I event_len
214 also includes the variable length file identifier.
215 .TP
216 .I vers
217 This field holds a version number for the structure.
218 It must be compared to
219 .B FANOTIFY_METADATA_VERSION
220 to verify that the structures returned at run time match
221 the structures defined at compile time.
222 In case of a mismatch, the application should abandon trying to use the
223 fanotify file descriptor.
224 .TP
225 .I reserved
226 This field is not used.
227 .TP
228 .I metadata_len
229 This is the length of the structure.
230 The field was introduced to facilitate the implementation of
231 optional headers per event type.
232 No such optional headers exist in the current implementation.
233 .TP
234 .I mask
235 This is a bit mask describing the event (see below).
236 .TP
237 .I fd
238 This is an open file descriptor for the object being accessed, or
239 .B FAN_NOFD
240 if a queue overflow occurred.
241 If the fanotify file descriptor has been initialized using
242 .BR FAN_REPORT_FID ,
243 applications should expect this value to be set to
244 .B FAN_NOFD
245 for each event that is received.
246 The file descriptor can be used to access the contents
247 of the monitored file or directory.
248 The reading application is responsible for closing this file descriptor.
249 .IP
250 When calling
251 .BR fanotify_init (2),
252 the caller may specify (via the
253 .I event_f_flags
254 argument) various file status flags that are to be set
255 on the open file description that corresponds to this file descriptor.
256 In addition, the (kernel-internal)
257 .B FMODE_NONOTIFY
258 file status flag is set on the open file description.
259 This flag suppresses fanotify event generation.
260 Hence, when the receiver of the fanotify event accesses the notified file or
261 directory using this file descriptor, no additional events will be created.
262 .TP
263 .I pid
264 If flag
265 .B FAN_REPORT_TID
266 was set in
267 .BR fanotify_init (2),
268 this is the TID of the thread that caused the event.
269 Otherwise, this the PID of the process that caused the event.
270 .PP
271 A program listening to fanotify events can compare this PID
272 to the PID returned by
273 .BR getpid (2),
274 to determine whether the event is caused by the listener itself,
275 or is due to a file access by another process.
276 .PP
277 The bit mask in
278 .I mask
279 indicates which events have occurred for a single filesystem object.
280 Multiple bits may be set in this mask,
281 if more than one event occurred for the monitored filesystem object.
282 In particular,
283 consecutive events for the same filesystem object and originating from the
284 same process may be merged into a single event, with the exception that two
285 permission events are never merged into one queue entry.
286 .PP
287 The bits that may appear in
288 .I mask
289 are as follows:
290 .TP
291 .B FAN_ACCESS
292 A file or a directory (but see BUGS) was accessed (read).
293 .TP
294 .B FAN_OPEN
295 A file or a directory was opened.
296 .TP
297 .B FAN_OPEN_EXEC
298 A file was opened with the intent to be executed.
299 See NOTES in
300 .BR fanotify_mark (2)
301 for additional details.
302 .TP
303 .B FAN_ATTRIB
304 A file or directory metadata was changed.
305 .TP
306 .B FAN_CREATE
307 A child file or directory was created in a watched parent.
308 .TP
309 .B FAN_DELETE
310 A child file or directory was deleted in a watched parent.
311 .TP
312 .B FAN_DELETE_SELF
313 A watched file or directory was deleted.
314 .TP
315 .B FAN_MOVED_FROM
316 A file or directory has been moved from a watched parent directory.
317 .TP
318 .B FAN_MOVED_TO
319 A file or directory has been moved to a watched parent directory.
320 .TP
321 .B FAN_MOVE_SELF
322 A watched file or directory was moved.
323 .TP
324 .B FAN_MODIFY
325 A file was modified.
326 .TP
327 .B FAN_CLOSE_WRITE
328 A file that was opened for writing
329 .RB ( O_WRONLY
330 or
331 .BR O_RDWR )
332 was closed.
333 .TP
334 .B FAN_CLOSE_NOWRITE
335 A file or directory that was opened read-only
336 .RB ( O_RDONLY )
337 was closed.
338 .TP
339 .B FAN_Q_OVERFLOW
340 The event queue exceeded the limit of 16384 entries.
341 This limit can be overridden by specifying the
342 .BR FAN_UNLIMITED_QUEUE
343 flag when calling
344 .BR fanotify_init (2).
345 .TP
346 .B FAN_ACCESS_PERM
347 An application wants to read a file or directory, for example using
348 .BR read (2)
349 or
350 .BR readdir (2).
351 The reader must write a response (as described below)
352 that determines whether the permission to
353 access the filesystem object shall be granted.
354 .TP
355 .B FAN_OPEN_PERM
356 An application wants to open a file or directory.
357 The reader must write a response that determines whether the permission to
358 open the filesystem object shall be granted.
359 .TP
360 .B FAN_OPEN_EXEC_PERM
361 An application wants to open a file for execution.
362 The reader must write a response that determines whether the permission to
363 open the filesystem object for execution shall be granted.
364 See NOTES in
365 .BR fanotify_mark (2)
366 for additional details.
367 .PP
368 To check for any close event, the following bit mask may be used:
369 .TP
370 .B FAN_CLOSE
371 A file was closed.
372 This is a synonym for:
373 .IP
374 FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
375 .PP
376 To check for any move event, the following bit mask may be used:
377 .TP
378 .B FAN_MOVE
379 A file or directory was moved.
380 This is a synonym for:
381 .IP
382 FAN_MOVED_FROM | FAN_MOVED_TO
383 .PP
384 The fields of the
385 .I fanotify_event_info_fid
386 structure are as follows:
387 .TP
388 .I hdr
389 This is a structure of type
390 .IR fanotify_event_info_header .
391 It is a generic header that contains information used to describe
392 additional information attached to the event.
393 For example, when an fanotify file descriptor is created using
394 .BR FAN_REPORT_FID ,
395 the
396 .I info_type
397 field of this header is set to
398 .BR FAN_EVENT_INFO_TYPE_FID .
399 Event listeners can use this field to check that the additional
400 information received for an event is of the correct type.
401 Additionally, the
402 .I fanotify_event_info_header
403 also contains a
404 .I len
405 field.
406 In the current implementation, the value of
407 .I len
408 is always (event_len - FAN_EVENT_METADATA_LEN).
409 .TP
410 .I fsid
411 This is a unique identifier of the filesystem containing the object
412 associated with the event.
413 It is a structure of type
414 .I __kernel_fsid_t
415 and contains the same value as
416 .I f_fsid
417 when calling
418 .BR statfs (2).
419 .TP
420 .I file_handle
421 This is a variable length structure of type
422 .IR file_handle .
423 It is an opaque handle that corresponds to a specified object on a
424 filesystem as returned by
425 .BR name_to_handle_at (2).
426 It can be used to uniquely identify a file on a filesystem and can be
427 passed as an argument to
428 .BR open_by_handle_at (2).
429 Note that for directory entry events, such as
430 .BR FAN_CREATE ,
431 .BR FAN_DELETE ,
432 and
433 .BR FAN_MOVE ,
434 the
435 .IR file_handle
436 describes the modified directory and not the created/deleted/moved child
437 object.
438 The events
439 .BR FAN_ATTRIB ,
440 .BR FAN_DELETE_SELF ,
441 and
442 .BR FAN_MOVE_SELF
443 will carry the
444 .IR file_handle
445 information for the child object if the child object is being watched.
446 .PP
447 The following macros are provided to iterate over a buffer containing
448 fanotify event metadata returned by a
449 .BR read (2)
450 from an fanotify file descriptor:
451 .TP
452 .B FAN_EVENT_OK(meta, len)
453 This macro checks the remaining length
454 .I len
455 of the buffer
456 .I meta
457 against the length of the metadata structure and the
458 .I event_len
459 field of the first metadata structure in the buffer.
460 .TP
461 .B FAN_EVENT_NEXT(meta, len)
462 This macro uses the length indicated in the
463 .I event_len
464 field of the metadata structure pointed to by
465 .IR meta
466 to calculate the address of the next metadata structure that follows
467 .IR meta .
468 .I len
469 is the number of bytes of metadata that currently remain in the buffer.
470 The macro returns a pointer to the next metadata structure that follows
471 .IR meta ,
472 and reduces
473 .I len
474 by the number of bytes in the metadata structure that
475 has been skipped over (i.e., it subtracts
476 .IR meta\->event_len
477 from
478 .IR len ).
479 .PP
480 In addition, there is:
481 .TP
482 .B FAN_EVENT_METADATA_LEN
483 This macro returns the size (in bytes) of the structure
484 .IR fanotify_event_metadata .
485 This is the minimum size (and currently the only size) of any event metadata.
486 .\"
487 .SS Monitoring an fanotify file descriptor for events
488 When an fanotify event occurs, the fanotify file descriptor indicates as
489 readable when passed to
490 .BR epoll (7),
491 .BR poll (2),
492 or
493 .BR select (2).
494 .SS Dealing with permission events
495 For permission events, the application must
496 .BR write (2)
497 a structure of the following form to the
498 fanotify file descriptor:
499 .PP
500 .in +4n
501 .EX
502 struct fanotify_response {
503 __s32 fd;
504 __u32 response;
505 };
506 .EE
507 .in
508 .PP
509 The fields of this structure are as follows:
510 .TP
511 .I fd
512 This is the file descriptor from the structure
513 .IR fanotify_event_metadata .
514 .TP
515 .I response
516 This field indicates whether or not the permission is to be granted.
517 Its value must be either
518 .B FAN_ALLOW
519 to allow the file operation or
520 .B FAN_DENY
521 to deny the file operation.
522 .PP
523 If access is denied, the requesting application call will receive an
524 .BR EPERM
525 error.
526 .SS Closing the fanotify file descriptor
527 .PP
528 When all file descriptors referring to the fanotify notification group are
529 closed, the fanotify group is released and its resources
530 are freed for reuse by the kernel.
531 Upon
532 .BR close (2),
533 outstanding permission events will be set to allowed.
534 .SS /proc/[pid]/fdinfo
535 The file
536 .I /proc/[pid]/fdinfo/[fd]
537 contains information about fanotify marks for file descriptor
538 .I fd
539 of process
540 .IR pid .
541 See
542 .BR proc (5)
543 for details.
544 .SH ERRORS
545 In addition to the usual errors for
546 .BR read (2),
547 the following errors can occur when reading from the
548 fanotify file descriptor:
549 .TP
550 .B EINVAL
551 The buffer is too small to hold the event.
552 .TP
553 .B EMFILE
554 The per-process limit on the number of open files has been reached.
555 See the description of
556 .B RLIMIT_NOFILE
557 in
558 .BR getrlimit (2).
559 .TP
560 .B ENFILE
561 The system-wide limit on the total number of open files has been reached.
562 See
563 .I /proc/sys/fs/file\-max
564 in
565 .BR proc (5).
566 .TP
567 .B ETXTBSY
568 This error is returned by
569 .BR read (2)
570 if
571 .B O_RDWR
572 or
573 .B O_WRONLY
574 was specified in the
575 .I event_f_flags
576 argument when calling
577 .BR fanotify_init (2)
578 and an event occurred for a monitored file that is currently being executed.
579 .PP
580 In addition to the usual errors for
581 .BR write (2),
582 the following errors can occur when writing to the fanotify file descriptor:
583 .TP
584 .B EINVAL
585 Fanotify access permissions are not enabled in the kernel configuration
586 or the value of
587 .I response
588 in the response structure is not valid.
589 .TP
590 .B ENOENT
591 The file descriptor
592 .I fd
593 in the response structure is not valid.
594 This may occur when a response for the permission event has already been
595 written.
596 .SH VERSIONS
597 The fanotify API was introduced in version 2.6.36 of the Linux kernel and
598 enabled in version 2.6.37.
599 Fdinfo support was added in version 3.8.
600 .SH CONFORMING TO
601 The fanotify API is Linux-specific.
602 .SH NOTES
603 The fanotify API is available only if the kernel was built with the
604 .B CONFIG_FANOTIFY
605 configuration option enabled.
606 In addition, fanotify permission handling is available only if the
607 .B CONFIG_FANOTIFY_ACCESS_PERMISSIONS
608 configuration option is enabled.
609 .SS Limitations and caveats
610 Fanotify reports only events that a user-space program triggers through the
611 filesystem API.
612 As a result,
613 it does not catch remote events that occur on network filesystems.
614 .PP
615 The fanotify API does not report file accesses and modifications that
616 may occur because of
617 .BR mmap (2),
618 .BR msync (2),
619 and
620 .BR munmap (2).
621 .PP
622 Events for directories are created only if the directory itself is opened,
623 read, and closed.
624 Adding, removing, or changing children of a marked directory does not create
625 events for the monitored directory itself.
626 .PP
627 Fanotify monitoring of directories is not recursive:
628 to monitor subdirectories under a directory,
629 additional marks must be created.
630 (But note that the fanotify API provides no way of detecting when a
631 subdirectory has been created under a marked directory,
632 which makes recursive monitoring difficult.)
633 Monitoring mounts offers the capability to monitor a whole directory tree.
634 Monitoring filesystems offers the capability to monitor changes made from
635 any mount of a filesystem instance.
636 .PP
637 The event queue can overflow.
638 In this case, events are lost.
639 .SH BUGS
640 Before Linux 3.19,
641 .BR fallocate (2)
642 did not generate fanotify events.
643 Since Linux 3.19,
644 .\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35
645 calls to
646 .BR fallocate (2)
647 generate
648 .B FAN_MODIFY
649 events.
650 .PP
651 As of Linux 3.17,
652 the following bugs exist:
653 .IP * 3
654 On Linux, a filesystem object may be accessible through multiple paths,
655 for example, a part of a filesystem may be remounted using the
656 .IR \-\-bind
657 option of
658 .BR mount (8).
659 A listener that marked a mount will be notified only of events that were
660 triggered for a filesystem object using the same mount.
661 Any other event will pass unnoticed.
662 .IP *
663 .\" FIXME . A patch was proposed.
664 When an event is generated,
665 no check is made to see whether the user ID of the
666 receiving process has authorization to read or write the file
667 before passing a file descriptor for that file.
668 This poses a security risk, when the
669 .B CAP_SYS_ADMIN
670 capability is set for programs executed by unprivileged users.
671 .IP *
672 If a call to
673 .BR read (2)
674 processes multiple events from the fanotify queue and an error occurs,
675 the return value will be the total length of the events successfully
676 copied to the user-space buffer before the error occurred.
677 The return value will not be \-1, and
678 .I errno
679 will not be set.
680 Thus, the reading application has no way to detect the error.
681 .SH EXAMPLE
682 The two example programs below demonstrate the usage of the fanotify API.
683 The first program (fanotify_example.c) is an example of fanotify being
684 used with its event object information passed in the form of a file
685 descriptor.
686 It marks the mount point passed as a command-line argument and waits for
687 events of type
688 .B FAN_OPEN_PERM
689 and
690 .BR FAN_CLOSE_WRITE .
691 When a permission event occurs, a
692 .B FAN_ALLOW
693 response is given.
694 .PP
695 The second program (fanotify_fid.c) is an example of fanotify being used
696 with
697 .B FAN_REPORT_FID
698 enabled.
699 It attempts to mark the filesystem object that is passed as
700 a command-line argument
701 and waits until an event of type
702 .B FAN_CREATE
703 has occurred.
704 Depending on whether a file or directory is created depends on what mask
705 is returned in the event mask.
706 Once all events have been read from the buffer and processed accordingly,
707 the program simply terminates.
708 .PP
709 The first example program output was captured from fanotify_example.
710 This session involved editing the file
711 .IR /home/user/temp/notes .
712 Before the file was opened, a
713 .B FAN_OPEN_PERM
714 event occurred.
715 After the file was closed, a
716 .B FAN_CLOSE_WRITE
717 event occurred.
718 Execution of the program ends when the user presses the ENTER key.
719 .PP
720 The second example program output was captured from fanotify_fid.
721 There are two discrete invocations of this program, with each invocation
722 accommodating a different action performed on a watched object.
723 This first session shows a mark being placed on
724 .IR /home/user .
725 This is followed by a subsequent regular file
726 .IR /home/user/testfile.txt
727 being created.
728 This results in a
729 .B FAN_CREATE
730 event being created and reported against the file's parent watched
731 directory object.
732 Program execution ends once all events captured within the buffer have
733 been processed.
734 The second session shows a mark being placed on
735 .IR /home/user .
736 This is followed by a directory
737 .IR /home/user/testdir
738 being created.
739 This specific action results in the program producing a
740 .B FAN_CREATE
741 and
742 .B FAN_ONDIR
743 event.
744 Program execution ends once all events captured within the buffer are
745 processed.
746 .SS Example output (fanotify_example.c)
747 .in +4n
748 .EX
749 # ./fanotify_example /home
750 Press enter key to terminate.
751 Listening for events.
752 FAN_OPEN_PERM: File /home/user/temp/notes
753 FAN_CLOSE_WRITE: File /home/user/temp/notes
754
755 Listening for events stopped.
756 .EE
757 .SS Example output (fanotify_fid.c)
758 .in +4n
759 .EX
760 # ./fanotify_fid /home/user
761 Listening for events.
762 FAN_CREATE (file created): Directory /home/user has been modified.
763 All events processed successfully. Program exiting.
764
765 $ touch /home/user/testing
766
767 ---
768
769 # ./fanotify_fid /home/user
770 Listening for events.
771 FAN_CREATE | FAN_ONDIR (subdirectory created): Directory /home/user has been modified.
772 All events processed successfully. Program exiting.
773
774 $ mkdir -p /home/user/testing
775 .EE
776 .in
777 .SS Program source: fanotify_example.c
778 \&
779 .EX
780 #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */
781 #include <errno.h>
782 #include <fcntl.h>
783 #include <limits.h>
784 #include <poll.h>
785 #include <stdio.h>
786 #include <stdlib.h>
787 #include <sys/fanotify.h>
788 #include <unistd.h>
789
790 /* Read all available fanotify events from the file descriptor 'fd' */
791
792 static void
793 handle_events(int fd)
794 {
795 const struct fanotify_event_metadata *metadata;
796 struct fanotify_event_metadata buf[200];
797 ssize_t len;
798 char path[PATH_MAX];
799 ssize_t path_len;
800 char procfd_path[PATH_MAX];
801 struct fanotify_response response;
802
803 /* Loop while events can be read from fanotify file descriptor */
804
805 for(;;) {
806
807 /* Read some events */
808
809 len = read(fd, (void *) &buf, sizeof(buf));
810 if (len == \-1 && errno != EAGAIN) {
811 perror("read");
812 exit(EXIT_FAILURE);
813 }
814
815 /* Check if end of available data reached */
816
817 if (len <= 0)
818 break;
819
820 /* Point to the first event in the buffer */
821
822 metadata = buf;
823
824 /* Loop over all events in the buffer */
825
826 while (FAN_EVENT_OK(metadata, len)) {
827
828 /* Check that run\-time and compile\-time structures match */
829
830 if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
831 fprintf(stderr,
832 "Mismatch of fanotify metadata version.\en");
833 exit(EXIT_FAILURE);
834 }
835
836 /* metadata\->fd contains either FAN_NOFD, indicating a
837 queue overflow, or a file descriptor (a nonnegative
838 integer). Here, we simply ignore queue overflow. */
839
840 if (metadata\->fd >= 0) {
841
842 /* Handle open permission event */
843
844 if (metadata\->mask & FAN_OPEN_PERM) {
845 printf("FAN_OPEN_PERM: ");
846
847 /* Allow file to be opened */
848
849 response.fd = metadata\->fd;
850 response.response = FAN_ALLOW;
851 write(fd, &response,
852 sizeof(struct fanotify_response));
853 }
854
855 /* Handle closing of writable file event */
856
857 if (metadata\->mask & FAN_CLOSE_WRITE)
858 printf("FAN_CLOSE_WRITE: ");
859
860 /* Retrieve and print pathname of the accessed file */
861
862 snprintf(procfd_path, sizeof(procfd_path),
863 "/proc/self/fd/%d", metadata\->fd);
864 path_len = readlink(procfd_path, path,
865 sizeof(path) \- 1);
866 if (path_len == \-1) {
867 perror("readlink");
868 exit(EXIT_FAILURE);
869 }
870
871 path[path_len] = '\e0';
872 printf("File %s\en", path);
873
874 /* Close the file descriptor of the event */
875
876 close(metadata\->fd);
877 }
878
879 /* Advance to next event */
880
881 metadata = FAN_EVENT_NEXT(metadata, len);
882 }
883 }
884 }
885
886 int
887 main(int argc, char *argv[])
888 {
889 char buf;
890 int fd, poll_num;
891 nfds_t nfds;
892 struct pollfd fds[2];
893
894 /* Check mount point is supplied */
895
896 if (argc != 2) {
897 fprintf(stderr, "Usage: %s MOUNT\en", argv[0]);
898 exit(EXIT_FAILURE);
899 }
900
901 printf("Press enter key to terminate.\en");
902
903 /* Create the file descriptor for accessing the fanotify API */
904
905 fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
906 O_RDONLY | O_LARGEFILE);
907 if (fd == \-1) {
908 perror("fanotify_init");
909 exit(EXIT_FAILURE);
910 }
911
912 /* Mark the mount for:
913 \- permission events before opening files
914 \- notification events after closing a write\-enabled
915 file descriptor */
916
917 if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
918 FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
919 argv[1]) == \-1) {
920 perror("fanotify_mark");
921 exit(EXIT_FAILURE);
922 }
923
924 /* Prepare for polling */
925
926 nfds = 2;
927
928 /* Console input */
929
930 fds[0].fd = STDIN_FILENO;
931 fds[0].events = POLLIN;
932
933 /* Fanotify input */
934
935 fds[1].fd = fd;
936 fds[1].events = POLLIN;
937
938 /* This is the loop to wait for incoming events */
939
940 printf("Listening for events.\en");
941
942 while (1) {
943 poll_num = poll(fds, nfds, \-1);
944 if (poll_num == \-1) {
945 if (errno == EINTR) /* Interrupted by a signal */
946 continue; /* Restart poll() */
947
948 perror("poll"); /* Unexpected error */
949 exit(EXIT_FAILURE);
950 }
951
952 if (poll_num > 0) {
953 if (fds[0].revents & POLLIN) {
954
955 /* Console input is available: empty stdin and quit */
956
957 while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\en')
958 continue;
959 break;
960 }
961
962 if (fds[1].revents & POLLIN) {
963
964 /* Fanotify events are available */
965
966 handle_events(fd);
967 }
968 }
969 }
970
971 printf("Listening for events stopped.\en");
972 exit(EXIT_SUCCESS);
973 }
974 .EE
975 .in
976 .SS Program source: fanotify_fid.c
977 \&
978 .EX
979 #define _GNU_SOURCE
980 #include <errno.h>
981 #include <fcntl.h>
982 #include <limits.h>
983 #include <stdio.h>
984 #include <stdlib.h>
985 #include <sys/types.h>
986 #include <sys/stat.h>
987 #include <sys/fanotify.h>
988 #include <unistd.h>
989
990 #define BUF_SIZE 256
991
992 int main(int argc, char **argv)
993 {
994 int fd, ret, event_fd;
995 ssize_t len, path_len;
996 char path[PATH_MAX];
997 char procfd_path[PATH_MAX];
998 char events_buf[BUF_SIZE];
999
1000 struct file_handle *file_handle;
1001 struct fanotify_event_metadata *metadata;
1002 struct fanotify_event_info_fid *fid;
1003
1004 if (argc != 2) {
1005 fprintf(stderr, "Invalid number of command line arguments.\\n");
1006 exit(EXIT_FAILURE);
1007 }
1008
1009 /* Create an fanotify file descriptor with FAN_REPORT_FID as a flag
1010 so that program can receive fid events. */
1011
1012 fd = fanotify_init(FAN_CLASS_NOTIF | FAN_REPORT_FID, 0);
1013 if (fd == -1) {
1014 perror("fanotify_init");
1015 exit(EXIT_FAILURE);
1016 }
1017
1018 /* Place a mark on the filesystem object supplied in argv[1]. */
1019
1020 ret = fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_ONLYDIR,
1021 FAN_CREATE | FAN_ONDIR,
1022 AT_FDCWD, argv[1]);
1023 if (ret == -1) {
1024 perror("fanotify_mark");
1025 exit(EXIT_FAILURE);
1026 }
1027
1028 printf("Listening for events.\\n");
1029
1030 /* Read events from the event queue into a buffer */
1031
1032 len = read(fd, (void *) &events_buf, sizeof(events_buf));
1033 if (len == -1 && errno != EAGAIN) {
1034 perror("read");
1035 exit(EXIT_FAILURE);
1036 }
1037
1038 /* Process all events within the buffer */
1039
1040 for (metadata = (struct fanotify_event_metadata *) events_buf;
1041 FAN_EVENT_OK(metadata, len);
1042 metadata = FAN_EVENT_NEXT(metadata, len)) {
1043 fid = (struct fanotify_event_info_fid *) (metadata + 1);
1044 file_handle = (struct file_handle *) fid->handle;
1045
1046 /* Ensure that the event info is of the correct type */
1047
1048 if (fid->hdr.info_type != FAN_EVENT_INFO_TYPE_FID) {
1049 fprintf(stderr, "Received unexpected event info type.\\n");
1050 exit(EXIT_FAILURE);
1051 }
1052
1053 if (metadata->mask == FAN_CREATE)
1054 printf("FAN_CREATE (file created): ");
1055
1056 if (metadata->mask == FAN_CREATE | FAN_ONDIR)
1057 printf("FAN_CREATE | FAN_ONDIR (subdirectory created): ");
1058
1059 /* metadata->fd is set to FAN_NOFD when FAN_REPORT_FID is enabled.
1060 To obtain a file descriptor for the file object corresponding to
1061 an event you can use the struct file_handle that's provided
1062 within the fanotify_event_info_fid in conjunction with the
1063 open_by_handle_at(2) system call. A check for -ESTALE is done
1064 to accommodate for the situation where the file handle was
1065 deleted for the object prior to this system call. */
1066
1067 event_fd = open_by_handle_at(AT_FDCWD, file_handle, O_RDONLY);
1068 if (ret == -1 && errno == ESTALE) {
1069 printf("File handle is no longer valid. File has been deleted\\n");
1070 continue;
1071 } else if (ret == -1) {
1072 perror("open_by_handle_at");
1073 exit(EXIT_FAILURE);
1074 }
1075
1076 snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", event_fd);
1077
1078 /* Retrieve and print the path of the modified dentry */
1079
1080 path_len = readlink(procfd_path, path, sizeof(path) - 1);
1081 if (path_len == -1) {
1082 perror("readlink");
1083 exit(EXIT_FAILURE);
1084 }
1085
1086 path[path_len] = '\\0';
1087 printf("Directory '%s' has been modified.\\n", path);
1088
1089 /* Close associated file descriptor for this event */
1090 close(event_fd);
1091 }
1092
1093 printf("All events processed successfully. Program exiting.\\n");
1094 exit(EXIT_SUCCESS);
1095 }
1096 .EE
1097 .SH SEE ALSO
1098 .ad l
1099 .BR fanotify_init (2),
1100 .BR fanotify_mark (2),
1101 .BR inotify (7)