]>
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 | |
1c612526 | 25 | .TH FANOTIFY 7 2014-05-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. | |
94 | If files or directories are renamed or moved, | |
95 | the respective entries survive. | |
96 | If files or directories are deleted or mounts are unmounted, | |
97 | 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) | |
312 | This macro sets the pointer | |
313 | .I meta | |
314 | to the next metadata structure using the length indicated in the | |
315 | .I event_len | |
316 | field of the metadata structure and reduces the remaining length of the | |
317 | buffer | |
7ea227bd | 318 | .IR len . |
488cdd81 MK |
319 | .SS Monitoring an fanotify file descriptor for events |
320 | When an fanotify event occurs, the fanotify file descriptor indicates as | |
321 | readable when passed to | |
322 | .BR epoll (7), | |
323 | .BR poll (2), | |
324 | or | |
325 | .BR select (2). | |
88145b29 | 326 | .SS Dealing with permission events |
597aaea2 HS |
327 | For permission events, the application must |
328 | .BR write (2) | |
329 | a structure of the following form to the | |
d3471a46 | 330 | fanotify file descriptor: |
597aaea2 HS |
331 | |
332 | .in +4n | |
333 | .nf | |
334 | struct fanotify_response { | |
335 | __s32 fd; | |
336 | __u32 response; | |
337 | }; | |
338 | .fi | |
339 | .in | |
d7d24d40 MK |
340 | .PP |
341 | The fields of this structure are as follows: | |
9d76d630 | 342 | .TP |
597aaea2 HS |
343 | .I fd |
344 | This is the file descriptor from the structure | |
345 | .IR fanotify_event_metadata . | |
346 | .TP | |
347 | .I response | |
348 | This field indicates whether or not the permission is to be granted. | |
349 | Its value must be either | |
350 | .B FAN_ALLOW | |
351 | to allow the file operation or | |
352 | .B FAN_DENY | |
353 | to deny the file operation. | |
354 | .PP | |
49894a5a MK |
355 | If access is denied, the requesting application call will receive an |
356 | .BR EPERM | |
357 | error. | |
88145b29 | 358 | .SS Closing the fanotify file descriptor |
be8ba5d8 MK |
359 | .PP |
360 | When all file descriptors referring to the fanotify notification group are | |
361 | closed, the fanotify group is released and its resources | |
362 | are freed for reuse by the kernel. | |
363 | Upon | |
364 | .BR close (2), | |
365 | outstanding permission events will be set to allowed. | |
c00ff2dc | 366 | .SS /proc/[pid]/fdinfo |
597aaea2 | 367 | The file |
3d4433fe | 368 | .I /proc/[pid]/fdinfo/[fd] |
597aaea2 HS |
369 | contains information about fanotify marks for file descriptor |
370 | .I fd | |
371 | of process | |
372 | .IR pid . | |
72b9aa96 | 373 | See the kernel source file |
597aaea2 HS |
374 | .I Documentation/filesystems/proc.txt |
375 | for details. | |
376 | .SH ERRORS | |
377 | In addition to the usual errors for | |
378 | .BR read (2), | |
1b24e2ee MK |
379 | the following errors can occur when reading from the |
380 | fanotify file descriptor: | |
597aaea2 HS |
381 | .TP |
382 | .B EINVAL | |
4a57583f | 383 | The buffer is too small to hold the event. |
597aaea2 HS |
384 | .TP |
385 | .B EMFILE | |
386 | The per-process limit on the number of open files has been reached. | |
387 | See the description of | |
388 | .B RLIMIT_NOFILE | |
389 | in | |
390 | .BR getrlimit (2). | |
391 | .TP | |
392 | .B ENFILE | |
393 | The system-wide limit on the number of open files has been reached. | |
394 | See | |
395 | .I /proc/sys/fs/file-max | |
396 | in | |
397 | .BR proc (5). | |
398 | .TP | |
399 | .B ETXTBSY | |
597aaea2 | 400 | This error is returned by |
68bcc008 | 401 | .BR read (2) |
597aaea2 HS |
402 | if |
403 | .B O_RDWR | |
404 | or | |
405 | .B O_WRONLY | |
406 | was specified in the | |
407 | .I event_f_flags | |
408 | argument when calling | |
409 | .BR fanotify_init (2) | |
68bcc008 | 410 | and an event occurred for a monitored file that is currently being executed. |
597aaea2 HS |
411 | .PP |
412 | In addition to the usual errors for | |
413 | .BR write (2), | |
414 | the following errors can occur when writing to the fanotify file descriptor: | |
415 | .TP | |
416 | .B EINVAL | |
1b24e2ee MK |
417 | Fanotify access permissions are not enabled in the kernel configuration |
418 | or the value of | |
597aaea2 HS |
419 | .I response |
420 | in the response structure is not valid. | |
421 | .TP | |
422 | .B ENOENT | |
423 | The file descriptor | |
424 | .I fd | |
425 | in the response structure is not valid. | |
33022419 MK |
426 | This may occur when a response for the permission event has already been |
427 | written. | |
597aaea2 HS |
428 | .SH VERSIONS |
429 | The fanotify API was introduced in version 2.6.36 of the Linux kernel and | |
430 | enabled in version 2.6.37. | |
431 | Fdinfo support was added in version 3.8. | |
432 | .SH "CONFORMING TO" | |
433 | The fanotify API is Linux-specific. | |
434 | .SH NOTES | |
435 | The fanotify API is available only if the kernel was built with the | |
436 | .B CONFIG_FANOTIFY | |
437 | configuration option enabled. | |
438 | In addition, fanotify permission handling is available only if the | |
439 | .B CONFIG_FANOTIFY_ACCESS_PERMISSIONS | |
440 | configuration option is enabled. | |
441 | .SS Limitations and caveats | |
442 | Fanotify reports only events that a user-space program triggers through the | |
443 | filesystem API. | |
1b24e2ee MK |
444 | As a result, |
445 | it does not catch remote events that occur on network filesystems. | |
597aaea2 HS |
446 | .PP |
447 | The fanotify API does not report file accesses and modifications that | |
448 | may occur because of | |
449 | .BR mmap (2), | |
450 | .BR msync (2), | |
451 | and | |
452 | .BR munmap (2). | |
453 | .PP | |
454 | Events for directories are created only if the directory itself is opened, | |
455 | read, and closed. | |
456 | Adding, removing, or changing children of a marked directory does not create | |
457 | events for the monitored directory itself. | |
458 | .PP | |
1b24e2ee MK |
459 | Fanotify monitoring of directories is not recursive: |
460 | to monitor subdirectories under a directory, | |
461 | additional marks must be created. | |
3d1ee497 | 462 | (But note that the fanotify API provides no way of detecting when a |
1b24e2ee MK |
463 | subdirectory has been created under a marked directory, |
464 | which makes recursive monitoring difficult.) | |
597aaea2 HS |
465 | Monitoring mounts offers the capability to monitor a whole directory tree. |
466 | .PP | |
467 | The event queue can overflow. | |
468 | In this case, events are lost. | |
469 | .SH BUGS | |
470 | As of Linux 3.15, | |
f96adfdc | 471 | the following bugs exists: |
597aaea2 | 472 | .IP * 3 |
597aaea2 | 473 | .\" FIXME: A patch was proposed. |
1b24e2ee MK |
474 | When an event is generated, |
475 | no check is made to see whether the user ID of the | |
476 | receiving process has authorization to read or write the file | |
477 | before passing a file descriptor for that file. | |
597aaea2 HS |
478 | This poses a security risk, when the |
479 | .B CAP_SYS_ADMIN | |
480 | capability is set for programs executed by unprivileged users. | |
f96adfdc HS |
481 | .IP * |
482 | If a call to | |
1c612526 | 483 | .BR read (2) |
e1001916 MK |
484 | processes multiple events from the fanotify queue and an error occurs, |
485 | the return value will be the total length of the events successfully | |
486 | copied to the user-space buffer before the error occurred. | |
487 | The return value will not be \-1, and | |
f96adfdc HS |
488 | .I errno |
489 | will not be set. | |
e1001916 | 490 | Thus, the reading application has no way to detect the error. |
597aaea2 HS |
491 | .SH EXAMPLE |
492 | The following program demonstrates the usage of the fanotify API. | |
4a57583f | 493 | It marks the mount point passed as a command-line argument |
ddb112c2 | 494 | and waits for events of type |
597aaea2 HS |
495 | .B FAN_PERM_OPEN |
496 | and | |
497 | .BR FAN_CLOSE_WRITE . | |
498 | When a permission event occurs, a | |
499 | .B FAN_ALLOW | |
500 | response is given. | |
501 | .PP | |
ddb112c2 | 502 | The following output was recorded while editing the file |
597aaea2 HS |
503 | .IR /home/user/temp/notes . |
504 | Before the file was opened, a | |
505 | .B FAN_OPEN_PERM | |
506 | event occurred. | |
507 | After the file was closed, a | |
508 | .B FAN_CLOSE_WRITE | |
509 | event occurred. | |
510 | Execution of the program ends when the user presses the ENTER key. | |
511 | .SS Example output | |
512 | .in +4n | |
513 | .nf | |
514 | # ./fanotify_example /home | |
515 | Press enter key to terminate. | |
516 | Listening for events. | |
517 | FAN_OPEN_PERM: File /home/user/temp/notes | |
518 | FAN_CLOSE_WRITE: File /home/user/temp/notes | |
519 | ||
520 | Listening for events stopped. | |
521 | .fi | |
522 | .in | |
523 | .SS Program source | |
524 | .nf | |
616fce49 | 525 | #define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */ |
597aaea2 HS |
526 | #include <errno.h> |
527 | #include <fcntl.h> | |
528 | #include <limits.h> | |
529 | #include <poll.h> | |
530 | #include <stdio.h> | |
531 | #include <stdlib.h> | |
532 | #include <sys/fanotify.h> | |
533 | #include <unistd.h> | |
534 | ||
535 | /* Read all available fanotify events from the file descriptor 'fd' */ | |
536 | ||
815df19b | 537 | static void |
597aaea2 HS |
538 | handle_events(int fd) |
539 | { | |
540 | const struct fanotify_event_metadata *metadata; | |
541 | char buf[4096]; | |
542 | ssize_t len; | |
543 | char path[PATH_MAX]; | |
544 | ssize_t path_len; | |
545 | char procfd_path[PATH_MAX]; | |
546 | struct fanotify_response response; | |
547 | ||
f7767949 | 548 | /* Loop while events can be read from fanotify file descriptor */ |
597aaea2 HS |
549 | |
550 | for(;;) { | |
551 | ||
f7767949 | 552 | /* Read some events */ |
597aaea2 HS |
553 | |
554 | len = read(fd, (void *) &buf, sizeof(buf)); | |
555 | if (len == \-1 && errno != EAGAIN) { | |
556 | perror("read"); | |
557 | exit(EXIT_FAILURE); | |
558 | } | |
559 | ||
f7767949 | 560 | /* Check if end of available data reached */ |
597aaea2 HS |
561 | |
562 | if (len <= 0) | |
563 | break; | |
564 | ||
f7767949 | 565 | /* Point to the first event in the buffer */ |
597aaea2 HS |
566 | |
567 | metadata = (struct fanotify_event_metadata *) buf; | |
568 | ||
f7767949 | 569 | /* Loop over all events in the buffer */ |
597aaea2 HS |
570 | |
571 | while (FAN_EVENT_OK(metadata, len)) { | |
572 | ||
f7767949 | 573 | /* Check that run\-time and compile\-time structures match */ |
597aaea2 HS |
574 | |
575 | if (metadata\->vers != FANOTIFY_METADATA_VERSION) { | |
576 | fprintf(stderr, | |
577 | "Mismatch of fanotify metadata version.\\n"); | |
578 | exit(EXIT_FAILURE); | |
579 | } | |
580 | ||
bfff73cb MK |
581 | /* metadata\->fd contains either FAN_NOFD, indicating a |
582 | queue overflow, or a file descriptor (a nonnegative | |
583 | integer). Here, we simply ignore queue overflow. */ | |
0554d3f7 | 584 | |
597aaea2 HS |
585 | if (metadata\->fd >= 0) { |
586 | ||
f7767949 | 587 | /* Handle open permission event */ |
597aaea2 HS |
588 | |
589 | if (metadata\->mask & FAN_OPEN_PERM) { | |
590 | printf("FAN_OPEN_PERM: "); | |
591 | ||
f7767949 | 592 | /* Allow file to be opened */ |
597aaea2 HS |
593 | |
594 | response.fd = metadata\->fd; | |
595 | response.response = FAN_ALLOW; | |
f7767949 | 596 | write(fd, &response, |
616fce49 | 597 | sizeof(struct fanotify_response)); |
597aaea2 HS |
598 | } |
599 | ||
f7767949 | 600 | /* Handle closing of writable file event */ |
597aaea2 | 601 | |
f7767949 | 602 | if (metadata\->mask & FAN_CLOSE_WRITE) |
597aaea2 | 603 | printf("FAN_CLOSE_WRITE: "); |
597aaea2 | 604 | |
b34cbc45 | 605 | /* Retrieve and print pathname of the accessed file */ |
597aaea2 HS |
606 | |
607 | snprintf(procfd_path, sizeof(procfd_path), | |
608 | "/proc/self/fd/%d", metadata\->fd); | |
609 | path_len = readlink(procfd_path, path, | |
610 | sizeof(path) \- 1); | |
611 | if (path_len == \-1) { | |
612 | perror("readlink"); | |
613 | exit(EXIT_FAILURE); | |
614 | } | |
615 | ||
616 | path[path_len] = '\\0'; | |
def5c668 | 617 | printf("File %s\\n", path); |
597aaea2 | 618 | |
f7767949 | 619 | /* Close the file descriptor of the event */ |
597aaea2 HS |
620 | |
621 | close(metadata\->fd); | |
597aaea2 HS |
622 | } |
623 | ||
48fd9fe0 | 624 | /* Advance to next event */ |
597aaea2 HS |
625 | |
626 | metadata = FAN_EVENT_NEXT(metadata, len); | |
627 | } | |
628 | } | |
629 | } | |
630 | ||
631 | int | |
632 | main(int argc, char *argv[]) | |
633 | { | |
634 | char buf; | |
635 | int fd, poll_num; | |
636 | nfds_t nfds; | |
637 | struct pollfd fds[2]; | |
638 | ||
f7767949 | 639 | /* Check mount point is supplied */ |
597aaea2 HS |
640 | |
641 | if (argc != 2) { | |
f7767949 | 642 | fprintf(stderr, "Usage: %s MOUNT\\n", argv[0]); |
597aaea2 HS |
643 | exit(EXIT_FAILURE); |
644 | } | |
645 | ||
646 | printf("Press enter key to terminate.\\n"); | |
647 | ||
f7767949 | 648 | /* Create the file descriptor for accessing the fanotify API */ |
597aaea2 HS |
649 | |
650 | fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK, | |
651 | O_RDONLY | O_LARGEFILE); | |
652 | if (fd == \-1) { | |
653 | perror("fanotify_init"); | |
654 | exit(EXIT_FAILURE); | |
655 | } | |
656 | ||
f7767949 | 657 | /* Mark the mount for: |
597aaea2 | 658 | \- permission events before opening files |
f7767949 MK |
659 | \- notification events after closing a write\-enabled |
660 | file descriptor */ | |
597aaea2 HS |
661 | |
662 | if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, | |
663 | FAN_OPEN_PERM | FAN_CLOSE_WRITE, \-1, | |
664 | argv[1]) == \-1) { | |
665 | perror("fanotify_mark"); | |
597aaea2 HS |
666 | exit(EXIT_FAILURE); |
667 | } | |
668 | ||
f7767949 | 669 | /* Prepare for polling */ |
597aaea2 HS |
670 | |
671 | nfds = 2; | |
672 | ||
f7767949 | 673 | /* Console input */ |
597aaea2 HS |
674 | |
675 | fds[0].fd = STDIN_FILENO; | |
676 | fds[0].events = POLLIN; | |
677 | ||
f7767949 | 678 | /* Fanotify input */ |
597aaea2 HS |
679 | |
680 | fds[1].fd = fd; | |
681 | fds[1].events = POLLIN; | |
682 | ||
f7767949 | 683 | /* This is the loop to wait for incoming events */ |
597aaea2 HS |
684 | |
685 | printf("Listening for events.\\n"); | |
370359a7 | 686 | |
597aaea2 HS |
687 | while (1) { |
688 | poll_num = poll(fds, nfds, \-1); | |
689 | if (poll_num == \-1) { | |
e1ca5880 MK |
690 | if (errno == EINTR) /* Interrupted by a signal */ |
691 | continue; /* Restart poll() */ | |
692 | ||
693 | perror("poll"); /* Unexpected error */ | |
597aaea2 HS |
694 | exit(EXIT_FAILURE); |
695 | } | |
370359a7 | 696 | |
597aaea2 HS |
697 | if (poll_num > 0) { |
698 | if (fds[0].revents & POLLIN) { | |
699 | ||
f7767949 | 700 | /* Console input is available: empty stdin and quit */ |
597aaea2 HS |
701 | |
702 | while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\\n') | |
703 | continue; | |
704 | break; | |
705 | } | |
370359a7 | 706 | |
597aaea2 HS |
707 | if (fds[1].revents & POLLIN) { |
708 | ||
f7767949 | 709 | /* Fanotify events are available */ |
597aaea2 HS |
710 | |
711 | handle_events(fd); | |
712 | } | |
713 | } | |
714 | } | |
715 | ||
597aaea2 | 716 | printf("Listening for events stopped.\\n"); |
f7767949 | 717 | exit(EXIT_SUCCESS); |
597aaea2 HS |
718 | } |
719 | .fi | |
720 | .SH "SEE ALSO" | |
721 | .ad l | |
722 | .BR fanotify_init (2), | |
723 | .BR fanotify_mark (2), | |
724 | .BR inotify (7) |