]>
Commit | Line | Data |
---|---|---|
597aaea2 | 1 | .\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de> |
89613d50 | 2 | .\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com> |
597aaea2 HS |
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 | |
97986708 | 25 | .TH FANOTIFY 7 2016-03-15 "Linux" "Linux Programmer's Manual" |
597aaea2 HS |
26 | .SH NAME |
27 | fanotify \- monitoring filesystem events | |
28 | .SH DESCRIPTION | |
1b24e2ee MK |
29 | The fanotify API provides notification and interception of |
30 | filesystem events. | |
597aaea2 HS |
31 | Use cases include virus scanning and hierarchical storage management. |
32 | Currently, only a limited set of events is supported. | |
7ea227bd | 33 | In particular, there is no support for create, delete, and move events. |
d9b086d6 MK |
34 | (See |
35 | .BR inotify (7) | |
36 | for details of an API that does notify those events.) | |
597aaea2 HS |
37 | |
38 | Additional capabilities compared to the | |
39 | .BR inotify (7) | |
4a57583f MK |
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 | |
597aaea2 HS |
43 | possibility to read or modify files before access by other applications. |
44 | ||
45 | The following system calls are used with this API: | |
46 | .BR fanotify_init (2), | |
47 | .BR fanotify_mark (2), | |
597aaea2 HS |
48 | .BR read (2), |
49 | .BR write (2), | |
50 | and | |
51 | .BR close (2). | |
6c693f6d | 52 | .SS fanotify_init(), fanotify_mark(), and notification groups |
397ff1fd | 53 | The |
597aaea2 | 54 | .BR fanotify_init (2) |
397ff1fd MK |
55 | system call creates and initializes an fanotify notification group |
56 | and returns a file descriptor referring to it. | |
597aaea2 | 57 | .PP |
7ea227bd | 58 | An fanotify notification group is a kernel-internal object that holds |
597aaea2 HS |
59 | a list of files, directories, and mount points for which events shall be |
60 | created. | |
61 | .PP | |
7ea227bd MK |
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. | |
597aaea2 HS |
69 | Having these two types of masks permits a mount point or directory to be |
70 | marked for receiving events, while at the same time ignoring events for | |
71 | specific objects under that mount point or directory. | |
72 | .PP | |
ffb30e75 | 73 | The |
6c693f6d MK |
74 | .BR fanotify_mark (2) |
75 | system call adds a file, directory, or mount to a notification group | |
76 | and specifies which events | |
77 | shall be reported (or ignored), or removes or modifies such an entry. | |
78 | .PP | |
597aaea2 HS |
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. | |
1b24e2ee MK |
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. | |
597aaea2 | 88 | Hence, the modify event can be added to the ignore mask. |
5e443a5f | 89 | Upon receiving the close event, the modify event can be removed from the |
597aaea2 HS |
90 | ignore mask and the file cache entry can be updated. |
91 | .PP | |
1b24e2ee MK |
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. | |
7d3c593b | 94 | If files or directories are renamed or moved within the same mount, |
1b24e2ee | 95 | the respective entries survive. |
7d3c593b HS |
96 | If files or directories are deleted or moved to another mount or if mounts are |
97 | unmounted, the corresponding entries are deleted. | |
ad02dd1f | 98 | .SS The event queue |
77bba7b5 | 99 | As events occur on the filesystem objects monitored by a notification group, |
c9120323 MK |
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 | ||
108 | Two types of events are generated: | |
4a57583f MK |
109 | .I notification |
110 | events and | |
111 | .I permission | |
112 | events. | |
c9120323 MK |
113 | Notification events are merely informative |
114 | and require no action to be taken by | |
1b24e2ee | 115 | the receiving application except for closing the file descriptor passed |
4a57583f | 116 | in the event (see below). |
1b24e2ee MK |
117 | Permission events are requests to the receiving application to decide |
118 | whether permission for a file access shall be granted. | |
597aaea2 HS |
119 | For these events, the recipient must write a response which decides whether |
120 | access is granted or not. | |
c9120323 | 121 | |
33022419 MK |
122 | An event is removed from the event queue of the fanotify group |
123 | when it has been read. | |
a6625006 | 124 | Permission events that have been read are kept in an internal list of the |
33022419 MK |
125 | fanotify group until either a permission decision has been taken by |
126 | writing to the fanotify file descriptor or the fanotify file descriptor | |
127 | is closed. | |
ad02dd1f | 128 | .SS Reading fanotify events |
597aaea2 HS |
129 | Calling |
130 | .BR read (2) | |
131 | for the file descriptor returned by | |
132 | .BR fanotify_init (2) | |
133 | blocks (if the flag | |
134 | .B FAN_NONBLOCK | |
135 | is not specified in the call to | |
136 | .BR fanotify_init (2)) | |
137 | until either a file event occurs or the call is interrupted by a signal | |
138 | (see | |
139 | .BR signal (7)). | |
140 | ||
597aaea2 | 141 | After a successful |
7ea227bd | 142 | .BR read (2), |
597aaea2 HS |
143 | the read buffer contains one or more of the following structures: |
144 | ||
145 | .in +4n | |
146 | .nf | |
147 | struct fanotify_event_metadata { | |
148 | __u32 event_len; | |
149 | __u8 vers; | |
150 | __u8 reserved; | |
151 | __u16 metadata_len; | |
152 | __aligned_u64 mask; | |
153 | __s32 fd; | |
154 | __s32 pid; | |
155 | }; | |
156 | .fi | |
157 | .in | |
f2ac23e7 | 158 | .PP |
3253bbc3 MK |
159 | For performance reasons, it is recommended to use a large |
160 | buffer size (for example, 4096 bytes), | |
161 | so that multiple events can be retrieved by a single | |
162 | .BR read (2). | |
163 | ||
164 | The return value of | |
165 | .BR read (2) | |
166 | is the number of bytes placed in the buffer, | |
f96adfdc | 167 | or \-1 in case of an error (but see BUGS). |
3253bbc3 | 168 | |
4a57583f MK |
169 | The fields of the |
170 | .I fanotify_event_metadata | |
171 | structure are as follows: | |
9d76d630 | 172 | .TP |
597aaea2 | 173 | .I event_len |
1b24e2ee MK |
174 | This is the length of the data for the current event and the offset |
175 | to the next event in the buffer. | |
7ea227bd | 176 | In the current implementation, the value of |
597aaea2 HS |
177 | .I event_len |
178 | is always | |
179 | .BR FAN_EVENT_METADATA_LEN . | |
3253bbc3 MK |
180 | However, the API is designed to allow |
181 | variable-length structures to be returned in the future. | |
597aaea2 HS |
182 | .TP |
183 | .I vers | |
6d8c5d01 | 184 | This field holds a version number for the structure. |
597aaea2 HS |
185 | It must be compared to |
186 | .B FANOTIFY_METADATA_VERSION | |
6d8c5d01 MK |
187 | to verify that the structures returned at runtime match |
188 | the structures defined at compile time. | |
597aaea2 HS |
189 | In case of a mismatch, the application should abandon trying to use the |
190 | fanotify file descriptor. | |
191 | .TP | |
192 | .I reserved | |
193 | This field is not used. | |
194 | .TP | |
195 | .I metadata_len | |
196 | This is the length of the structure. | |
1b24e2ee MK |
197 | The field was introduced to facilitate the implementation of |
198 | optional headers per event type. | |
597aaea2 HS |
199 | No such optional headers exist in the current implementation. |
200 | .TP | |
201 | .I mask | |
4a57583f | 202 | This is a bit mask describing the event (see below). |
597aaea2 HS |
203 | .TP |
204 | .I fd | |
205 | This is an open file descriptor for the object being accessed, or | |
206 | .B FAN_NOFD | |
207 | if a queue overflow occurred. | |
1b24e2ee MK |
208 | The file descriptor can be used to access the contents |
209 | of the monitored file or directory. | |
4a57583f MK |
210 | The reading application is responsible for closing this file descriptor. |
211 | .IP | |
a4cd12a9 | 212 | When calling |
ce87be97 | 213 | .BR fanotify_init (2), |
a4cd12a9 MK |
214 | the caller may specify (via the |
215 | .I event_f_flags | |
216 | argument) various file status flags that are to be set | |
217 | on the open file description that corresponds to this file descriptor. | |
218 | In addition, the (kernel-internal) | |
597aaea2 | 219 | .B FMODE_NONOTIFY |
a4cd12a9 | 220 | file status flag is set on the open file description. |
597aaea2 HS |
221 | This flag suppresses fanotify event generation. |
222 | Hence, when the receiver of the fanotify event accesses the notified file or | |
223 | directory using this file descriptor, no additional events will be created. | |
597aaea2 HS |
224 | .TP |
225 | .I pid | |
226 | This is the ID of the process that caused the event. | |
1b24e2ee MK |
227 | A program listening to fanotify events can compare this PID |
228 | to the PID returned by | |
597aaea2 | 229 | .BR getpid (2), |
1b24e2ee | 230 | to determine whether the event is caused by the listener itself, |
4a57583f | 231 | or is due to a file access by another process. |
597aaea2 HS |
232 | .PP |
233 | The bit mask in | |
234 | .I mask | |
4a57583f | 235 | indicates which events have occurred for a single filesystem object. |
29325644 | 236 | Multiple bits may be set in this mask, |
77bba7b5 | 237 | if more than one event occurred for the monitored filesystem object. |
75c3e3bd MK |
238 | In particular, |
239 | consecutive events for the same filesystem object and originating from the | |
240 | same process may be merged into a single event, with the exception that two | |
241 | permission events are never merged into one queue entry. | |
242 | .PP | |
29325644 MK |
243 | The bits that may appear in |
244 | .I mask | |
245 | are as follows: | |
597aaea2 HS |
246 | .TP |
247 | .B FAN_ACCESS | |
248 | A file or a directory (but see BUGS) was accessed (read). | |
249 | .TP | |
250 | .B FAN_OPEN | |
251 | A file or a directory was opened. | |
252 | .TP | |
253 | .B FAN_MODIFY | |
254 | A file was modified. | |
255 | .TP | |
256 | .B FAN_CLOSE_WRITE | |
257 | A file that was opened for writing | |
258 | .RB ( O_WRONLY | |
259 | or | |
260 | .BR O_RDWR ) | |
261 | was closed. | |
262 | .TP | |
263 | .B FAN_CLOSE_NOWRITE | |
02a18e0f | 264 | A file or directory that was opened read-only |
597aaea2 | 265 | .RB ( O_RDONLY ) |
02a18e0f | 266 | was closed. |
597aaea2 HS |
267 | .TP |
268 | .B FAN_Q_OVERFLOW | |
269 | The event queue exceeded the limit of 16384 entries. | |
4a57583f MK |
270 | This limit can be overridden by specifying the |
271 | .BR FAN_UNLIMITED_QUEUE | |
272 | flag when calling | |
273 | .BR fanotify_init (2). | |
597aaea2 HS |
274 | .TP |
275 | .B FAN_ACCESS_PERM | |
276 | An application wants to read a file or directory, for example using | |
277 | .BR read (2) | |
278 | or | |
279 | .BR readdir (2). | |
4a57583f MK |
280 | The reader must write a response (as described below) |
281 | that determines whether the permission to | |
597aaea2 HS |
282 | access the filesystem object shall be granted. |
283 | .TP | |
284 | .B FAN_OPEN_PERM | |
285 | An application wants to open a file or directory. | |
286 | The reader must write a response that determines whether the permission to | |
287 | open the filesystem object shall be granted. | |
288 | .PP | |
289 | To check for any close event, the following bit mask may be used: | |
290 | .TP | |
291 | .B FAN_CLOSE | |
f897ec11 | 292 | A file was closed. |
4a57583f | 293 | This is a synonym for: |
f897ec11 MK |
294 | |
295 | FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE | |
597aaea2 | 296 | .PP |
1b24e2ee | 297 | The following macros are provided to iterate over a buffer containing |
4a57583f | 298 | fanotify event metadata returned by a |
597aaea2 | 299 | .BR read (2) |
4a57583f | 300 | from an fanotify file descriptor: |
597aaea2 HS |
301 | .TP |
302 | .B FAN_EVENT_OK(meta, len) | |
303 | This macro checks the remaining length | |
304 | .I len | |
305 | of the buffer | |
306 | .I meta | |
307 | against the length of the metadata structure and the | |
308 | .I event_len | |
309 | field of the first metadata structure in the buffer. | |
310 | .TP | |
311 | .B FAN_EVENT_NEXT(meta, len) | |
98f7d53c | 312 | This macro uses the length indicated in the |
597aaea2 | 313 | .I event_len |
98f7d53c MK |
314 | field of the metadata structure pointed to by |
315 | .IR meta | |
316 | to calculate the address of the next metadata structure that follows | |
317 | .IR meta . | |
318 | .I len | |
319 | is the number of bytes of metadata that currently remain in the buffer. | |
320 | The macro returns a pointer to the next metadata structure that follows | |
321 | .IR meta , | |
322 | and reduces | |
323 | .I len | |
d721b5aa | 324 | by the number of bytes in the metadata structure that |
98f7d53c MK |
325 | has been skipped over (i.e., it subtracts |
326 | .IR meta\->event_len | |
327 | from | |
328 | .IR len ). | |
3c36e635 HS |
329 | .PP |
330 | In addition, there is: | |
331 | .TP | |
332 | .B FAN_EVENT_METADATA_LEN | |
7c0f0ce0 MK |
333 | This macro returns the size (in bytes) of the structure |
334 | .IR fanotify_event_metadata . | |
3c36e635 | 335 | This is the minimum size (and currently the only size) of any event metadata. |
98f7d53c | 336 | .\" |
488cdd81 MK |
337 | .SS Monitoring an fanotify file descriptor for events |
338 | When an fanotify event occurs, the fanotify file descriptor indicates as | |
339 | readable when passed to | |
340 | .BR epoll (7), | |
341 | .BR poll (2), | |
342 | or | |
343 | .BR select (2). | |
88145b29 | 344 | .SS Dealing with permission events |
597aaea2 HS |
345 | For permission events, the application must |
346 | .BR write (2) | |
347 | a structure of the following form to the | |
d3471a46 | 348 | fanotify file descriptor: |
597aaea2 HS |
349 | |
350 | .in +4n | |
351 | .nf | |
352 | struct fanotify_response { | |
353 | __s32 fd; | |
354 | __u32 response; | |
355 | }; | |
356 | .fi | |
357 | .in | |
d7d24d40 MK |
358 | .PP |
359 | The fields of this structure are as follows: | |
9d76d630 | 360 | .TP |
597aaea2 HS |
361 | .I fd |
362 | This is the file descriptor from the structure | |
363 | .IR fanotify_event_metadata . | |
364 | .TP | |
365 | .I response | |
366 | This field indicates whether or not the permission is to be granted. | |
367 | Its value must be either | |
368 | .B FAN_ALLOW | |
369 | to allow the file operation or | |
370 | .B FAN_DENY | |
371 | to deny the file operation. | |
372 | .PP | |
49894a5a MK |
373 | If access is denied, the requesting application call will receive an |
374 | .BR EPERM | |
375 | error. | |
88145b29 | 376 | .SS Closing the fanotify file descriptor |
be8ba5d8 MK |
377 | .PP |
378 | When all file descriptors referring to the fanotify notification group are | |
379 | closed, the fanotify group is released and its resources | |
380 | are freed for reuse by the kernel. | |
381 | Upon | |
382 | .BR close (2), | |
383 | outstanding permission events will be set to allowed. | |
c00ff2dc | 384 | .SS /proc/[pid]/fdinfo |
597aaea2 | 385 | The file |
3d4433fe | 386 | .I /proc/[pid]/fdinfo/[fd] |
597aaea2 HS |
387 | contains information about fanotify marks for file descriptor |
388 | .I fd | |
389 | of process | |
390 | .IR pid . | |
75f8598a MK |
391 | See |
392 | .BR proc (5) | |
597aaea2 HS |
393 | for details. |
394 | .SH ERRORS | |
395 | In addition to the usual errors for | |
396 | .BR read (2), | |
1b24e2ee MK |
397 | the following errors can occur when reading from the |
398 | fanotify file descriptor: | |
597aaea2 HS |
399 | .TP |
400 | .B EINVAL | |
4a57583f | 401 | The buffer is too small to hold the event. |
597aaea2 HS |
402 | .TP |
403 | .B EMFILE | |
404 | The per-process limit on the number of open files has been reached. | |
405 | See the description of | |
406 | .B RLIMIT_NOFILE | |
407 | in | |
408 | .BR getrlimit (2). | |
409 | .TP | |
410 | .B ENFILE | |
e258766b | 411 | The system-wide limit on the total number of open files has been reached. |
597aaea2 HS |
412 | See |
413 | .I /proc/sys/fs/file-max | |
414 | in | |
415 | .BR proc (5). | |
416 | .TP | |
417 | .B ETXTBSY | |
597aaea2 | 418 | This error is returned by |
68bcc008 | 419 | .BR read (2) |
597aaea2 HS |
420 | if |
421 | .B O_RDWR | |
422 | or | |
423 | .B O_WRONLY | |
424 | was specified in the | |
425 | .I event_f_flags | |
426 | argument when calling | |
427 | .BR fanotify_init (2) | |
68bcc008 | 428 | and an event occurred for a monitored file that is currently being executed. |
597aaea2 HS |
429 | .PP |
430 | In addition to the usual errors for | |
431 | .BR write (2), | |
432 | the following errors can occur when writing to the fanotify file descriptor: | |
433 | .TP | |
434 | .B EINVAL | |
1b24e2ee MK |
435 | Fanotify access permissions are not enabled in the kernel configuration |
436 | or the value of | |
597aaea2 HS |
437 | .I response |
438 | in the response structure is not valid. | |
439 | .TP | |
440 | .B ENOENT | |
441 | The file descriptor | |
442 | .I fd | |
443 | in the response structure is not valid. | |
33022419 MK |
444 | This may occur when a response for the permission event has already been |
445 | written. | |
597aaea2 HS |
446 | .SH VERSIONS |
447 | The fanotify API was introduced in version 2.6.36 of the Linux kernel and | |
448 | enabled in version 2.6.37. | |
449 | Fdinfo support was added in version 3.8. | |
d282bb24 | 450 | .SH CONFORMING TO |
597aaea2 HS |
451 | The fanotify API is Linux-specific. |
452 | .SH NOTES | |
453 | The fanotify API is available only if the kernel was built with the | |
454 | .B CONFIG_FANOTIFY | |
455 | configuration option enabled. | |
456 | In addition, fanotify permission handling is available only if the | |
457 | .B CONFIG_FANOTIFY_ACCESS_PERMISSIONS | |
458 | configuration option is enabled. | |
459 | .SS Limitations and caveats | |
460 | Fanotify reports only events that a user-space program triggers through the | |
461 | filesystem API. | |
1b24e2ee MK |
462 | As a result, |
463 | it does not catch remote events that occur on network filesystems. | |
597aaea2 HS |
464 | .PP |
465 | The fanotify API does not report file accesses and modifications that | |
466 | may occur because of | |
467 | .BR mmap (2), | |
468 | .BR msync (2), | |
469 | and | |
470 | .BR munmap (2). | |
471 | .PP | |
472 | Events for directories are created only if the directory itself is opened, | |
473 | read, and closed. | |
474 | Adding, removing, or changing children of a marked directory does not create | |
475 | events for the monitored directory itself. | |
476 | .PP | |
1b24e2ee MK |
477 | Fanotify monitoring of directories is not recursive: |
478 | to monitor subdirectories under a directory, | |
479 | additional marks must be created. | |
3d1ee497 | 480 | (But note that the fanotify API provides no way of detecting when a |
1b24e2ee MK |
481 | subdirectory has been created under a marked directory, |
482 | which makes recursive monitoring difficult.) | |
597aaea2 HS |
483 | Monitoring mounts offers the capability to monitor a whole directory tree. |
484 | .PP | |
485 | The event queue can overflow. | |
486 | In this case, events are lost. | |
487 | .SH BUGS | |
707914e9 MK |
488 | Before Linux 3.19, |
489 | .BR fallocate (2) | |
490 | did not generate fanotify events. | |
491 | Since Linux 3.19, | |
492 | .\" commit 820c12d5d6c0890bc93dd63893924a13041fdc35 | |
493 | calls to | |
494 | .BR fallocate (2) | |
495 | generate | |
496 | .B FAN_MODIFY | |
497 | events. | |
498 | ||
d5b26a69 | 499 | As of Linux 3.17, |
1aa556ab | 500 | the following bugs exist: |
597aaea2 | 501 | .IP * 3 |
c5a00024 | 502 | On Linux, a filesystem object may be accessible through multiple paths, |
8e38f6d3 | 503 | for example, a part of a filesystem may be remounted using the |
c5a00024 MK |
504 | .IR \-\-bind |
505 | option of | |
506 | .BR mount (8). | |
507 | A listener that marked a mount will be notified only of events that were | |
508 | triggered for a filesystem object using the same mount. | |
a4b394f2 HS |
509 | Any other event will pass unnoticed. |
510 | .IP * | |
bea08fec | 511 | .\" FIXME . A patch was proposed. |
1b24e2ee MK |
512 | When an event is generated, |
513 | no check is made to see whether the user ID of the | |
514 | receiving process has authorization to read or write the file | |
515 | before passing a file descriptor for that file. | |
597aaea2 HS |
516 | This poses a security risk, when the |
517 | .B CAP_SYS_ADMIN | |
518 | capability is set for programs executed by unprivileged users. | |
f96adfdc HS |
519 | .IP * |
520 | If a call to | |
1c612526 | 521 | .BR read (2) |
e1001916 MK |
522 | processes multiple events from the fanotify queue and an error occurs, |
523 | the return value will be the total length of the events successfully | |
524 | copied to the user-space buffer before the error occurred. | |
525 | The return value will not be \-1, and | |
f96adfdc HS |
526 | .I errno |
527 | will not be set. | |
e1001916 | 528 | Thus, the reading application has no way to detect the error. |
597aaea2 HS |
529 | .SH EXAMPLE |
530 | The following program demonstrates the usage of the fanotify API. | |
4a57583f | 531 | It marks the mount point passed as a command-line argument |
ddb112c2 | 532 | and waits for events of type |
597aaea2 HS |
533 | .B FAN_PERM_OPEN |
534 | and | |
535 | .BR FAN_CLOSE_WRITE . | |
536 | When a permission event occurs, a | |
537 | .B FAN_ALLOW | |
538 | response is given. | |
539 | .PP | |
ddb112c2 | 540 | The following output was recorded while editing the file |
597aaea2 HS |
541 | .IR /home/user/temp/notes . |
542 | Before the file was opened, a | |
543 | .B FAN_OPEN_PERM | |
544 | event occurred. | |
545 | After the file was closed, a | |
546 | .B FAN_CLOSE_WRITE | |
547 | event occurred. | |
548 | Execution of the program ends when the user presses the ENTER key. | |
549 | .SS Example output | |
550 | .in +4n | |
551 | .nf | |
552 | # ./fanotify_example /home | |
553 | Press enter key to terminate. | |
554 | Listening for events. | |
555 | FAN_OPEN_PERM: File /home/user/temp/notes | |
556 | FAN_CLOSE_WRITE: File /home/user/temp/notes | |
557 | ||
558 | Listening for events stopped. | |
559 | .fi | |
560 | .in | |
561 | .SS Program source | |
562 | .nf | |
616fce49 | 563 | #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */ |
597aaea2 HS |
564 | #include <errno.h> |
565 | #include <fcntl.h> | |
566 | #include <limits.h> | |
567 | #include <poll.h> | |
568 | #include <stdio.h> | |
569 | #include <stdlib.h> | |
570 | #include <sys/fanotify.h> | |
571 | #include <unistd.h> | |
572 | ||
573 | /* Read all available fanotify events from the file descriptor 'fd' */ | |
574 | ||
815df19b | 575 | static void |
597aaea2 HS |
576 | handle_events(int fd) |
577 | { | |
578 | const struct fanotify_event_metadata *metadata; | |
864eccb9 | 579 | struct fanotify_event_metadata buf[200]; |
597aaea2 HS |
580 | ssize_t len; |
581 | char path[PATH_MAX]; | |
582 | ssize_t path_len; | |
583 | char procfd_path[PATH_MAX]; | |
584 | struct fanotify_response response; | |
585 | ||
f7767949 | 586 | /* Loop while events can be read from fanotify file descriptor */ |
597aaea2 HS |
587 | |
588 | for(;;) { | |
589 | ||
f7767949 | 590 | /* Read some events */ |
597aaea2 HS |
591 | |
592 | len = read(fd, (void *) &buf, sizeof(buf)); | |
593 | if (len == \-1 && errno != EAGAIN) { | |
594 | perror("read"); | |
595 | exit(EXIT_FAILURE); | |
596 | } | |
597 | ||
f7767949 | 598 | /* Check if end of available data reached */ |
597aaea2 HS |
599 | |
600 | if (len <= 0) | |
601 | break; | |
602 | ||
f7767949 | 603 | /* Point to the first event in the buffer */ |
597aaea2 | 604 | |
864eccb9 | 605 | metadata = buf; |
597aaea2 | 606 | |
f7767949 | 607 | /* Loop over all events in the buffer */ |
597aaea2 HS |
608 | |
609 | while (FAN_EVENT_OK(metadata, len)) { | |
610 | ||
f7767949 | 611 | /* Check that run\-time and compile\-time structures match */ |
597aaea2 HS |
612 | |
613 | if (metadata\->vers != FANOTIFY_METADATA_VERSION) { | |
614 | fprintf(stderr, | |
615 | "Mismatch of fanotify metadata version.\\n"); | |
616 | exit(EXIT_FAILURE); | |
617 | } | |
618 | ||
bfff73cb MK |
619 | /* metadata\->fd contains either FAN_NOFD, indicating a |
620 | queue overflow, or a file descriptor (a nonnegative | |
621 | integer). Here, we simply ignore queue overflow. */ | |
0554d3f7 | 622 | |
597aaea2 HS |
623 | if (metadata\->fd >= 0) { |
624 | ||
f7767949 | 625 | /* Handle open permission event */ |
597aaea2 HS |
626 | |
627 | if (metadata\->mask & FAN_OPEN_PERM) { | |
628 | printf("FAN_OPEN_PERM: "); | |
629 | ||
f7767949 | 630 | /* Allow file to be opened */ |
597aaea2 HS |
631 | |
632 | response.fd = metadata\->fd; | |
633 | response.response = FAN_ALLOW; | |
f7767949 | 634 | write(fd, &response, |
864eccb9 | 635 | sizeof(struct fanotify_response)); |
597aaea2 HS |
636 | } |
637 | ||
f7767949 | 638 | /* Handle closing of writable file event */ |
597aaea2 | 639 | |
f7767949 | 640 | if (metadata\->mask & FAN_CLOSE_WRITE) |
597aaea2 | 641 | printf("FAN_CLOSE_WRITE: "); |
597aaea2 | 642 | |
b34cbc45 | 643 | /* Retrieve and print pathname of the accessed file */ |
597aaea2 HS |
644 | |
645 | snprintf(procfd_path, sizeof(procfd_path), | |
646 | "/proc/self/fd/%d", metadata\->fd); | |
647 | path_len = readlink(procfd_path, path, | |
648 | sizeof(path) \- 1); | |
649 | if (path_len == \-1) { | |
650 | perror("readlink"); | |
651 | exit(EXIT_FAILURE); | |
652 | } | |
653 | ||
654 | path[path_len] = '\\0'; | |
def5c668 | 655 | printf("File %s\\n", path); |
597aaea2 | 656 | |
f7767949 | 657 | /* Close the file descriptor of the event */ |
597aaea2 HS |
658 | |
659 | close(metadata\->fd); | |
597aaea2 HS |
660 | } |
661 | ||
48fd9fe0 | 662 | /* Advance to next event */ |
597aaea2 HS |
663 | |
664 | metadata = FAN_EVENT_NEXT(metadata, len); | |
665 | } | |
666 | } | |
667 | } | |
668 | ||
669 | int | |
670 | main(int argc, char *argv[]) | |
671 | { | |
672 | char buf; | |
673 | int fd, poll_num; | |
674 | nfds_t nfds; | |
675 | struct pollfd fds[2]; | |
676 | ||
f7767949 | 677 | /* Check mount point is supplied */ |
597aaea2 HS |
678 | |
679 | if (argc != 2) { | |
f7767949 | 680 | fprintf(stderr, "Usage: %s MOUNT\\n", argv[0]); |
597aaea2 HS |
681 | exit(EXIT_FAILURE); |
682 | } | |
683 | ||
684 | printf("Press enter key to terminate.\\n"); | |
685 | ||
f7767949 | 686 | /* Create the file descriptor for accessing the fanotify API */ |
597aaea2 HS |
687 | |
688 | fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK, | |
689 | O_RDONLY | O_LARGEFILE); | |
690 | if (fd == \-1) { | |
691 | perror("fanotify_init"); | |
692 | exit(EXIT_FAILURE); | |
693 | } | |
694 | ||
f7767949 | 695 | /* Mark the mount for: |
597aaea2 | 696 | \- permission events before opening files |
f7767949 MK |
697 | \- notification events after closing a write\-enabled |
698 | file descriptor */ | |
597aaea2 HS |
699 | |
700 | if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, | |
943c52b7 | 701 | FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD, |
597aaea2 HS |
702 | argv[1]) == \-1) { |
703 | perror("fanotify_mark"); | |
597aaea2 HS |
704 | exit(EXIT_FAILURE); |
705 | } | |
706 | ||
f7767949 | 707 | /* Prepare for polling */ |
597aaea2 HS |
708 | |
709 | nfds = 2; | |
710 | ||
f7767949 | 711 | /* Console input */ |
597aaea2 HS |
712 | |
713 | fds[0].fd = STDIN_FILENO; | |
714 | fds[0].events = POLLIN; | |
715 | ||
f7767949 | 716 | /* Fanotify input */ |
597aaea2 HS |
717 | |
718 | fds[1].fd = fd; | |
719 | fds[1].events = POLLIN; | |
720 | ||
f7767949 | 721 | /* This is the loop to wait for incoming events */ |
597aaea2 HS |
722 | |
723 | printf("Listening for events.\\n"); | |
370359a7 | 724 | |
597aaea2 HS |
725 | while (1) { |
726 | poll_num = poll(fds, nfds, \-1); | |
727 | if (poll_num == \-1) { | |
e1ca5880 MK |
728 | if (errno == EINTR) /* Interrupted by a signal */ |
729 | continue; /* Restart poll() */ | |
730 | ||
731 | perror("poll"); /* Unexpected error */ | |
597aaea2 HS |
732 | exit(EXIT_FAILURE); |
733 | } | |
370359a7 | 734 | |
597aaea2 HS |
735 | if (poll_num > 0) { |
736 | if (fds[0].revents & POLLIN) { | |
737 | ||
f7767949 | 738 | /* Console input is available: empty stdin and quit */ |
597aaea2 HS |
739 | |
740 | while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n') | |
741 | continue; | |
742 | break; | |
743 | } | |
370359a7 | 744 | |
597aaea2 HS |
745 | if (fds[1].revents & POLLIN) { |
746 | ||
f7767949 | 747 | /* Fanotify events are available */ |
597aaea2 HS |
748 | |
749 | handle_events(fd); | |
750 | } | |
751 | } | |
752 | } | |
753 | ||
597aaea2 | 754 | printf("Listening for events stopped.\\n"); |
f7767949 | 755 | exit(EXIT_SUCCESS); |
597aaea2 HS |
756 | } |
757 | .fi | |
d282bb24 | 758 | .SH SEE ALSO |
597aaea2 HS |
759 | .ad l |
760 | .BR fanotify_init (2), | |
761 | .BR fanotify_mark (2), | |
762 | .BR inotify (7) |