File Index
Files and directories
Sign in
FILE

fs-monitor.c

File preview with syntax highlighting.

linux-6.19.14/samples/fanotify/fs-monitor.c C
  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
 23struct 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
 38static 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
 58static 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		}
114next_event:
115		printf("---\n\n");
116	}
117}
118
119int 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}
~/ Read-only file preview.