Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright 2021, Collabora Ltd.
0004  */
0005 
0006 #define _GNU_SOURCE
0007 #include <errno.h>
0008 #include <err.h>
0009 #include <stdlib.h>
0010 #include <stdio.h>
0011 #include <fcntl.h>
0012 #include <sys/fanotify.h>
0013 #include <sys/types.h>
0014 #include <unistd.h>
0015 
0016 #ifndef FAN_FS_ERROR
0017 #define FAN_FS_ERROR        0x00008000
0018 #define FAN_EVENT_INFO_TYPE_ERROR   5
0019 
0020 struct fanotify_event_info_error {
0021     struct fanotify_event_info_header hdr;
0022     __s32 error;
0023     __u32 error_count;
0024 };
0025 #endif
0026 
0027 #ifndef FILEID_INO32_GEN
0028 #define FILEID_INO32_GEN    1
0029 #endif
0030 
0031 #ifndef FILEID_INVALID
0032 #define FILEID_INVALID      0xff
0033 #endif
0034 
0035 static void print_fh(struct file_handle *fh)
0036 {
0037     int i;
0038     uint32_t *h = (uint32_t *) fh->f_handle;
0039 
0040     printf("\tfh: ");
0041     for (i = 0; i < fh->handle_bytes; i++)
0042         printf("%hhx", fh->f_handle[i]);
0043     printf("\n");
0044 
0045     printf("\tdecoded fh: ");
0046     if (fh->handle_type == FILEID_INO32_GEN)
0047         printf("inode=%u gen=%u\n", h[0], h[1]);
0048     else if (fh->handle_type == FILEID_INVALID && !fh->handle_bytes)
0049         printf("Type %d (Superblock error)\n", fh->handle_type);
0050     else
0051         printf("Type %d (Unknown)\n", fh->handle_type);
0052 
0053 }
0054 
0055 static void handle_notifications(char *buffer, int len)
0056 {
0057     struct fanotify_event_metadata *event =
0058         (struct fanotify_event_metadata *) buffer;
0059     struct fanotify_event_info_header *info;
0060     struct fanotify_event_info_error *err;
0061     struct fanotify_event_info_fid *fid;
0062     int off;
0063 
0064     for (; FAN_EVENT_OK(event, len); event = FAN_EVENT_NEXT(event, len)) {
0065 
0066         if (event->mask != FAN_FS_ERROR) {
0067             printf("unexpected FAN MARK: %llx\n",
0068                             (unsigned long long)event->mask);
0069             goto next_event;
0070         }
0071 
0072         if (event->fd != FAN_NOFD) {
0073             printf("Unexpected fd (!= FAN_NOFD)\n");
0074             goto next_event;
0075         }
0076 
0077         printf("FAN_FS_ERROR (len=%d)\n", event->event_len);
0078 
0079         for (off = sizeof(*event) ; off < event->event_len;
0080              off += info->len) {
0081             info = (struct fanotify_event_info_header *)
0082                 ((char *) event + off);
0083 
0084             switch (info->info_type) {
0085             case FAN_EVENT_INFO_TYPE_ERROR:
0086                 err = (struct fanotify_event_info_error *) info;
0087 
0088                 printf("\tGeneric Error Record: len=%d\n",
0089                        err->hdr.len);
0090                 printf("\terror: %d\n", err->error);
0091                 printf("\terror_count: %d\n", err->error_count);
0092                 break;
0093 
0094             case FAN_EVENT_INFO_TYPE_FID:
0095                 fid = (struct fanotify_event_info_fid *) info;
0096 
0097                 printf("\tfsid: %x%x\n",
0098                        fid->fsid.val[0], fid->fsid.val[1]);
0099                 print_fh((struct file_handle *) &fid->handle);
0100                 break;
0101 
0102             default:
0103                 printf("\tUnknown info type=%d len=%d:\n",
0104                        info->info_type, info->len);
0105             }
0106         }
0107 next_event:
0108         printf("---\n\n");
0109     }
0110 }
0111 
0112 int main(int argc, char **argv)
0113 {
0114     int fd;
0115 
0116     char buffer[BUFSIZ];
0117 
0118     if (argc < 2) {
0119         printf("Missing path argument\n");
0120         return 1;
0121     }
0122 
0123     fd = fanotify_init(FAN_CLASS_NOTIF|FAN_REPORT_FID, O_RDONLY);
0124     if (fd < 0)
0125         errx(1, "fanotify_init");
0126 
0127     if (fanotify_mark(fd, FAN_MARK_ADD|FAN_MARK_FILESYSTEM,
0128               FAN_FS_ERROR, AT_FDCWD, argv[1])) {
0129         errx(1, "fanotify_mark");
0130     }
0131 
0132     while (1) {
0133         int n = read(fd, buffer, BUFSIZ);
0134 
0135         if (n < 0)
0136             errx(1, "read");
0137 
0138         handle_notifications(buffer, n);
0139     }
0140 
0141     return 0;
0142 }