revert code that did not affect memory
[gitlive] / fanotify / fanotify-helper.c
1 #define _GNU_SOURCE     /* Needed to get O_LARGEFILE definition */
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <limits.h>
5 #include <poll.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/fanotify.h>
9 #include <unistd.h>
10 #include <sys/stat.h>
11
12 /* Read all available fanotify events from the file descriptor 'fd'. */
13
14 #define BUF_SIZE  1024
15
16 void fanotify_read(int fd)
17 {
18      int  ret, event_fd, mount_fd;
19     ssize_t len, path_len;
20     char path[PATH_MAX];
21     char procfd_path[PATH_MAX];
22     char events_buf[BUF_SIZE];
23     struct file_handle *file_handle;
24     struct fanotify_event_metadata *metadata;
25     struct fanotify_event_info_fid *fid;
26     const char *file_name;
27     struct stat sb;
28     
29      mount_fd = open("/", O_DIRECTORY | O_RDONLY);
30       if (mount_fd == -1) {
31                perror("cant open mount");
32                exit(EXIT_FAILURE);
33            }
34  
35     printf("Listening for events.\n");
36     
37     /* Read events from the event queue into a buffer. */
38     
39     len = read(fd, events_buf, sizeof(events_buf));
40     if (len == -1 && errno != EAGAIN) {
41         perror("read");
42         exit(EXIT_FAILURE);
43     }
44     
45     /* Process all events within the buffer. */
46     
47     for (metadata = (struct fanotify_event_metadata *) events_buf;
48             FAN_EVENT_OK(metadata, len);
49             metadata = FAN_EVENT_NEXT(metadata, len)) {
50         
51         
52         fid = (struct fanotify_event_info_fid *) (metadata + 1);
53         
54         
55         
56         file_handle = (struct file_handle *) fid->handle;
57     
58         // Ensure that the event info is of the correct type. 
59     
60         if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_FID ||
61             fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID) {
62             printf("Got FID or DFID.\n");
63             file_name = NULL;
64         } else if (fid->hdr.info_type == FAN_EVENT_INFO_TYPE_DFID_NAME) {
65             file_name = file_handle->f_handle +
66                         file_handle->handle_bytes;
67             printf("Got DFID_NAME %s.\n",file_name);                        
68         } else {
69             fprintf(stderr, "Received unexpected event info type.\n");
70             exit(EXIT_FAILURE);
71         }
72     
73         if (metadata->mask == FAN_CREATE)
74             printf("FAN_CREATE (file created):\n");
75     
76         if (metadata->mask == (FAN_CREATE | FAN_ONDIR))
77             printf("FAN_CREATE | FAN_ONDIR (subdirectory created):\n");
78     
79     
80     
81         // what is fsid??
82         /* - from
83          *
84          https://github.com/GNOME/tracker-miners/blob/38596491ead21b1ee6db99f2623ac6f127b6da34/src/miners/fs/tracker-monitor-fanotify.c#L356
85          
86          seems to create a hashtable for all monitored files?
87          
88          *handle = (HandleData *) &fid->fsid;
89                 fid_bytes = create_bytes_for_handle (handle);
90                 data = g_hash_table_lookup (monitor->handles, fid_bytes);
91                 g_bytes_unref (fid_bytes);
92                 *
93         
94      /* metadata->fd is set to FAN_NOFD when the group identifies
95         objects by file handles.  To obtain a file descriptor for
96         the file object corresponding to an event you can use the
97         struct file_handle that's provided within the
98         fanotify_event_info_fid in conjunction with the
99         open_by_handle_at(2) system call.  A check for ESTALE is
100         done to accommodate for the situation where the file handle
101         for the object was deleted prior to this system call. */
102      
103
104         event_fd = open_by_handle_at(mount_fd, file_handle, O_RDONLY);
105         if (event_fd == -1) {
106             if (errno == ESTALE) {
107                 printf("File handle is no longer valid. "
108                         "File has been deleted\n");
109                 continue;
110             } else {
111                 perror("open_by_handle_at");
112                 exit(EXIT_FAILURE);
113             }
114         }
115     
116         snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d",
117                 event_fd);
118     
119         /* Retrieve and print the path of the modified dentry. */
120     
121         path_len = readlink(procfd_path, path, sizeof(path) - 1);
122         if (path_len == -1) {
123             perror("readlink");
124             exit(EXIT_FAILURE);
125         }
126     
127         path[path_len] = '\0';
128         printf("\tDirectory '%s' has been modified.\n", path);
129     
130         if (file_name) {
131             ret = fstatat(event_fd, file_name, &sb, 0);
132             if (ret == -1) {
133                 if (errno != ENOENT) {
134                     perror("fstatat");
135                     exit(EXIT_FAILURE);
136                 }
137                 printf("\tEntry '%s' does not exist.\n", file_name);
138             } else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
139                 printf("\tEntry '%s' is a subdirectory.\n", file_name);
140             } else {
141                 printf("\tEntry '%s' is not a subdirectory.\n",
142                         file_name);
143             }
144         }
145     
146         /* Close associated file descriptor for this event. */
147     
148         close(event_fd);
149     }
150     
151     printf("All events processed successfully. Program exiting.\n");
152     exit(EXIT_SUCCESS);
153 }