Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/fanotify/fs-monitor.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright 2021, Collabora Ltd.
4
*/
5
6
#define _GNU_SOURCE
7
#include <errno.h>
8
#include <err.h>
9
#include <stdlib.h>
10
#include <stdio.h>
11
#include <fcntl.h>
12
#include <sys/fanotify.h>
13
#include <sys/types.h>
14
#include <unistd.h>
15
#ifndef __GLIBC__
16
#include <asm-generic/int-ll64.h>
17
#endif
18
19
#ifndef FAN_FS_ERROR
20
#define FAN_FS_ERROR 0x00008000
21
#define FAN_EVENT_INFO_TYPE_ERROR 5
22
23
struct fanotify_event_info_error {
24
struct fanotify_event_info_header hdr;
25
__s32 error;
26
__u32 error_count;
27
};
28
#endif
29
30
#ifndef FILEID_INO32_GEN
31
#define FILEID_INO32_GEN 1
32
#endif
33
34
#ifndef FILEID_INVALID
35
#define FILEID_INVALID 0xff
36
#endif
37
38
static void print_fh(struct file_handle *fh)
39
{
40
int i;
41
uint32_t *h = (uint32_t *) fh->f_handle;
42
43
printf("\tfh: ");
44
for (i = 0; i < fh->handle_bytes; i++)
45
printf("%hhx", fh->f_handle[i]);
46
printf("\n");
47
48
printf("\tdecoded fh: ");
49
if (fh->handle_type == FILEID_INO32_GEN)
50
printf("inode=%u gen=%u\n", h[0], h[1]);
51
else if (fh->handle_type == FILEID_INVALID && !fh->handle_bytes)
52
printf("Type %d (Superblock error)\n", fh->handle_type);
53
else
54
printf("Type %d (Unknown)\n", fh->handle_type);
55
56
}
57
58
static void handle_notifications(char *buffer, int len)
59
{
60
struct fanotify_event_metadata *event =
61
(struct fanotify_event_metadata *) buffer;
62
struct fanotify_event_info_header *info;
63
struct fanotify_event_info_error *err;
64
struct fanotify_event_info_fid *fid;
65
int off;
66
67
for (; FAN_EVENT_OK(event, len); event = FAN_EVENT_NEXT(event, len)) {
68
69
if (event->mask != FAN_FS_ERROR) {
70
printf("unexpected FAN MARK: %llx\n",
71
(unsigned long long)event->mask);
72
goto next_event;
73
}
74
75
if (event->fd != FAN_NOFD) {
76
printf("Unexpected fd (!= FAN_NOFD)\n");
77
goto next_event;
78
}
79
80
printf("FAN_FS_ERROR (len=%d)\n", event->event_len);
81
82
for (off = sizeof(*event) ; off < event->event_len;
83
off += info->len) {
84
info = (struct fanotify_event_info_header *)
85
((char *) event + off);
86
87
switch (info->info_type) {
88
case FAN_EVENT_INFO_TYPE_ERROR:
89
err = (struct fanotify_event_info_error *) info;
90
91
printf("\tGeneric Error Record: len=%d\n",
92
err->hdr.len);
93
printf("\terror: %d\n", err->error);
94
printf("\terror_count: %d\n", err->error_count);
95
break;
96
97
case FAN_EVENT_INFO_TYPE_FID:
98
fid = (struct fanotify_event_info_fid *) info;
99
100
printf("\tfsid: %x%x\n",
101
#if defined(__GLIBC__)
102
fid->fsid.val[0], fid->fsid.val[1]);
103
#else
104
fid->fsid.__val[0], fid->fsid.__val[1]);
105
#endif
106
print_fh((struct file_handle *) &fid->handle);
107
break;
108
109
default:
110
printf("\tUnknown info type=%d len=%d:\n",
111
info->info_type, info->len);
112
}
113
}
114
next_event:
115
printf("---\n\n");
116
}
117
}
118
119
int main(int argc, char **argv)
120
{
121
int fd;
122
123
char buffer[BUFSIZ];
124
125
if (argc < 2) {
126
printf("Missing path argument\n");
127
return 1;
128
}
129
130
fd = fanotify_init(FAN_CLASS_NOTIF|FAN_REPORT_FID, O_RDONLY);
131
if (fd < 0)
132
errx(1, "fanotify_init");
133
134
if (fanotify_mark(fd, FAN_MARK_ADD|FAN_MARK_FILESYSTEM,
135
FAN_FS_ERROR, AT_FDCWD, argv[1])) {
136
errx(1, "fanotify_mark");
137
}
138
139
while (1) {
140
int n = read(fd, buffer, BUFSIZ);
141
142
if (n < 0)
143
errx(1, "read");
144
145
handle_notifications(buffer, n);
146
}
147
148
return 0;
149
}
150
151