brintos

brintos / linux-shallow public Read only

0
0
Text · 3.0 KiB · 608db24 Raw
143 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright 2021, Collabora Ltd.4 */5 6#define _GNU_SOURCE7#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 16#ifndef FAN_FS_ERROR17#define FAN_FS_ERROR		0x0000800018#define FAN_EVENT_INFO_TYPE_ERROR	519 20struct fanotify_event_info_error {21	struct fanotify_event_info_header hdr;22	__s32 error;23	__u32 error_count;24};25#endif26 27#ifndef FILEID_INO32_GEN28#define FILEID_INO32_GEN	129#endif30 31#ifndef FILEID_INVALID32#define	FILEID_INVALID		0xff33#endif34 35static void print_fh(struct file_handle *fh)36{37	int i;38	uint32_t *h = (uint32_t *) fh->f_handle;39 40	printf("\tfh: ");41	for (i = 0; i < fh->handle_bytes; i++)42		printf("%hhx", fh->f_handle[i]);43	printf("\n");44 45	printf("\tdecoded fh: ");46	if (fh->handle_type == FILEID_INO32_GEN)47		printf("inode=%u gen=%u\n", h[0], h[1]);48	else if (fh->handle_type == FILEID_INVALID && !fh->handle_bytes)49		printf("Type %d (Superblock error)\n", fh->handle_type);50	else51		printf("Type %d (Unknown)\n", fh->handle_type);52 53}54 55static void handle_notifications(char *buffer, int len)56{57	struct fanotify_event_metadata *event =58		(struct fanotify_event_metadata *) buffer;59	struct fanotify_event_info_header *info;60	struct fanotify_event_info_error *err;61	struct fanotify_event_info_fid *fid;62	int off;63 64	for (; FAN_EVENT_OK(event, len); event = FAN_EVENT_NEXT(event, len)) {65 66		if (event->mask != FAN_FS_ERROR) {67			printf("unexpected FAN MARK: %llx\n",68							(unsigned long long)event->mask);69			goto next_event;70		}71 72		if (event->fd != FAN_NOFD) {73			printf("Unexpected fd (!= FAN_NOFD)\n");74			goto next_event;75		}76 77		printf("FAN_FS_ERROR (len=%d)\n", event->event_len);78 79		for (off = sizeof(*event) ; off < event->event_len;80		     off += info->len) {81			info = (struct fanotify_event_info_header *)82				((char *) event + off);83 84			switch (info->info_type) {85			case FAN_EVENT_INFO_TYPE_ERROR:86				err = (struct fanotify_event_info_error *) info;87 88				printf("\tGeneric Error Record: len=%d\n",89				       err->hdr.len);90				printf("\terror: %d\n", err->error);91				printf("\terror_count: %d\n", err->error_count);92				break;93 94			case FAN_EVENT_INFO_TYPE_FID:95				fid = (struct fanotify_event_info_fid *) info;96 97				printf("\tfsid: %x%x\n",98				       fid->fsid.val[0], fid->fsid.val[1]);99				print_fh((struct file_handle *) &fid->handle);100				break;101 102			default:103				printf("\tUnknown info type=%d len=%d:\n",104				       info->info_type, info->len);105			}106		}107next_event:108		printf("---\n\n");109	}110}111 112int main(int argc, char **argv)113{114	int fd;115 116	char buffer[BUFSIZ];117 118	if (argc < 2) {119		printf("Missing path argument\n");120		return 1;121	}122 123	fd = fanotify_init(FAN_CLASS_NOTIF|FAN_REPORT_FID, O_RDONLY);124	if (fd < 0)125		errx(1, "fanotify_init");126 127	if (fanotify_mark(fd, FAN_MARK_ADD|FAN_MARK_FILESYSTEM,128			  FAN_FS_ERROR, AT_FDCWD, argv[1])) {129		errx(1, "fanotify_mark");130	}131 132	while (1) {133		int n = read(fd, buffer, BUFSIZ);134 135		if (n < 0)136			errx(1, "read");137 138		handle_notifications(buffer, n);139	}140 141	return 0;142}143