10 #include "ecore_file_private.h"
15 * - Listen to these events:
16 * IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN
17 * - Read all events first, then call the callbacks. This will prevent several
18 * callbacks with the typic save cycle (delete file, new file)
19 * - Listen to IN_IGNORED, emitted when the watch is removed
24 #ifdef HAVE_SYS_INOTIFY
25 # include <sys/inotify.h>
27 # include <asm/unistd.h>
28 # include <linux/inotify.h>
31 #ifndef HAVE_SYS_INOTIFY
32 static inline int inotify_init(void);
33 static inline int inotify_add_watch(int fd, const char *name, __u32 mask);
34 static inline int inotify_rm_watch(int fd, __u32 wd);
38 typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
40 #define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
42 struct _Ecore_File_Monitor_Inotify
44 Ecore_File_Monitor monitor;
48 static Ecore_Fd_Handler *_fdh = NULL;
49 static Ecore_File_Monitor *_monitors = NULL;
50 static pid_t _inotify_fd_pid = -1;
52 static Eina_Bool _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
53 static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
54 static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask);
55 static int _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path);
57 static void _ecore_file_monitor_inotify_print(char *file, int mask);
61 ecore_file_monitor_inotify_init(void)
69 _fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler,
77 _inotify_fd_pid = getpid();
82 ecore_file_monitor_inotify_shutdown(void)
87 ecore_file_monitor_inotify_del(_monitors);
91 fd = ecore_main_fd_handler_fd_get(_fdh);
92 ecore_main_fd_handler_del(_fdh);
100 ecore_file_monitor_inotify_add(const char *path,
101 void (*func) (void *data, Ecore_File_Monitor *em,
102 Ecore_File_Event event,
106 Ecore_File_Monitor *em;
109 if (_inotify_fd_pid == -1) return NULL;
111 if (_inotify_fd_pid != getpid())
113 ecore_file_monitor_inotify_shutdown();
114 ecore_file_monitor_inotify_init();
117 em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
118 if (!em) return NULL;
123 em->path = strdup(path);
124 len = strlen(em->path);
125 if (em->path[len - 1] == '/' && strcmp(em->path, "/"))
126 em->path[len - 1] = 0;
128 _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
130 if (ecore_file_exists(em->path))
132 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
137 ecore_file_monitor_inotify_del(em);
145 ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
150 _monitors = ECORE_FILE_MONITOR(eina_inlist_remove(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
152 fd = ecore_main_fd_handler_fd_get(_fdh);
153 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd)
154 inotify_rm_watch(fd, ECORE_FILE_MONITOR_INOTIFY(em)->wd);
160 _ecore_file_monitor_inotify_handler(void *data __UNUSED__, Ecore_Fd_Handler *fdh)
162 Ecore_File_Monitor *em;
164 struct inotify_event *event;
169 size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
172 event = (struct inotify_event *)&buffer[i];
173 event_size = sizeof(struct inotify_event) + event->len;
176 em = _ecore_file_monitor_inotify_monitor_find(event->wd);
179 _ecore_file_monitor_inotify_events(em, (event->len ? event->name : NULL), event->mask);
182 return ECORE_CALLBACK_RENEW;
185 static Ecore_File_Monitor *
186 _ecore_file_monitor_inotify_monitor_find(int wd)
188 Ecore_File_Monitor *l;
190 EINA_INLIST_FOREACH(_monitors, l)
192 if (ECORE_FILE_MONITOR_INOTIFY(l)->wd == wd)
199 _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask)
204 if ((file) && (file[0]))
205 snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
207 strcpy(buf, em->path);
208 isdir = mask & IN_ISDIR;
211 _ecore_file_monitor_inotify_print(buf, mask);
214 if (mask & IN_ATTRIB)
216 em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
218 if (mask & IN_CLOSE_WRITE)
221 em->func(em->data, em, ECORE_FILE_EVENT_CLOSED, buf);
223 if (mask & IN_MODIFY)
226 em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
228 if (mask & IN_MOVED_FROM)
231 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
233 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
235 if (mask & IN_MOVED_TO)
238 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
240 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
242 if (mask & IN_DELETE)
245 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
247 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
249 if (mask & IN_CREATE)
252 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
254 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
256 if (mask & IN_DELETE_SELF)
258 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
260 if (mask & IN_MOVE_SELF)
262 /* We just call delete. The dir is gone... */
263 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
265 if (mask & IN_UNMOUNT)
267 /* We just call delete. The dir is gone... */
268 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
270 if (mask & IN_IGNORED)
272 /* The watch is removed. If the file name still exists monitor the new one,
274 if (ecore_file_exists(em->path))
276 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
277 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
280 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
285 _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path)
299 ECORE_FILE_MONITOR_INOTIFY(em)->wd =
300 inotify_add_watch(ecore_main_fd_handler_fd_get(_fdh), path, mask);
301 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0)
303 ERR("inotify_add_watch error");
304 ecore_file_monitor_inotify_del(em);
310 #ifndef HAVE_SYS_INOTIFY
314 return syscall(__NR_inotify_init);
318 inotify_add_watch(int fd, const char *name, __u32 mask)
320 return syscall(__NR_inotify_add_watch, fd, name, mask);
324 inotify_rm_watch(int fd, __u32 wd)
326 return syscall(__NR_inotify_rm_watch, fd, wd);
332 _ecore_file_monitor_inotify_print(char *file, int mask)
341 if (mask & IN_ACCESS)
342 INF("Inotify accessed %s: %s", type, file);
343 if (mask & IN_MODIFY)
344 INF("Inotify modified %s: %s", type, file);
345 if (mask & IN_ATTRIB)
346 INF("Inotify attributes %s: %s", type, file);
347 if (mask & IN_CLOSE_WRITE)
348 INF("Inotify close write %s: %s", type, file);
349 if (mask & IN_CLOSE_NOWRITE)
350 INF("Inotify close write %s: %s", type, file);
352 INF("Inotify open %s: %s", type, file);
353 if (mask & IN_MOVED_FROM)
354 INF("Inotify moved from %s: %s", type, file);
355 if (mask & IN_MOVED_TO)
356 INF("Inotify moved to %s: %s", type, file);
357 if (mask & IN_DELETE)
358 INF("Inotify delete %s: %s", type, file);
359 if (mask & IN_CREATE)
360 INF("Inotify create %s: %s", type, file);
361 if (mask & IN_DELETE_SELF)
362 INF("Inotify delete self %s: %s", type, file);
363 if (mask & IN_MOVE_SELF)
364 INF("Inotify move self %s: %s", type, file);
365 if (mask & IN_UNMOUNT)
366 INF("Inotify unmount %s: %s", type, file);
369 #endif /* HAVE_INOTIFY */