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)
23 #ifdef HAVE_SYS_INOTIFY
24 # include <sys/inotify.h>
26 # include <asm/unistd.h>
27 # include <linux/inotify.h>
30 #ifndef HAVE_SYS_INOTIFY
31 static inline int inotify_init(void);
32 static inline int inotify_add_watch(int fd, const char *name, __u32 mask);
33 static inline int inotify_rm_watch(int fd, __u32 wd);
37 typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
39 #define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
41 struct _Ecore_File_Monitor_Inotify
43 Ecore_File_Monitor monitor;
47 static Ecore_Fd_Handler *_fdh = NULL;
48 static Ecore_File_Monitor *_monitors = NULL;
50 static Eina_Bool _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
51 static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
52 static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask);
53 static int _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path);
55 static void _ecore_file_monitor_inotify_print(char *file, int mask);
59 ecore_file_monitor_inotify_init(void)
67 _fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler,
79 ecore_file_monitor_inotify_shutdown(void)
84 ecore_file_monitor_inotify_del(_monitors);
88 fd = ecore_main_fd_handler_fd_get(_fdh);
89 ecore_main_fd_handler_del(_fdh);
96 ecore_file_monitor_inotify_add(const char *path,
97 void (*func) (void *data, Ecore_File_Monitor *em,
98 Ecore_File_Event event,
102 Ecore_File_Monitor *em;
105 em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
106 if (!em) return NULL;
111 em->path = strdup(path);
112 len = strlen(em->path);
113 if (em->path[len - 1] == '/' && strcmp(em->path, "/"))
114 em->path[len - 1] = 0;
116 _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
118 if (ecore_file_exists(em->path))
120 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
125 ecore_file_monitor_inotify_del(em);
133 ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
137 _monitors = ECORE_FILE_MONITOR(eina_inlist_remove(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
139 fd = ecore_main_fd_handler_fd_get(_fdh);
140 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd)
141 inotify_rm_watch(fd, ECORE_FILE_MONITOR_INOTIFY(em)->wd);
147 _ecore_file_monitor_inotify_handler(void *data __UNUSED__, Ecore_Fd_Handler *fdh)
149 Ecore_File_Monitor *em;
151 struct inotify_event *event;
156 size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
159 event = (struct inotify_event *)&buffer[i];
160 event_size = sizeof(struct inotify_event) + event->len;
163 em = _ecore_file_monitor_inotify_monitor_find(event->wd);
166 _ecore_file_monitor_inotify_events(em, (event->len ? event->name : NULL), event->mask);
169 return ECORE_CALLBACK_RENEW;
172 static Ecore_File_Monitor *
173 _ecore_file_monitor_inotify_monitor_find(int wd)
175 Ecore_File_Monitor *l;
177 EINA_INLIST_FOREACH(_monitors, l)
179 if (ECORE_FILE_MONITOR_INOTIFY(l)->wd == wd)
186 _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask)
191 if ((file) && (file[0]))
192 snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
194 strcpy(buf, em->path);
195 isdir = mask & IN_ISDIR;
198 _ecore_file_monitor_inotify_print(file, mask);
201 if (mask & IN_MODIFY)
204 em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
206 if (mask & IN_MOVED_FROM)
209 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
211 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
213 if (mask & IN_MOVED_TO)
216 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
218 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
220 if (mask & IN_DELETE)
223 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
225 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
227 if (mask & IN_CREATE)
230 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
232 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
234 if (mask & IN_DELETE_SELF)
236 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
238 if (mask & IN_MOVE_SELF)
240 /* We just call delete. The dir is gone... */
241 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
243 if (mask & IN_UNMOUNT)
245 /* We just call delete. The dir is gone... */
246 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
248 if (mask & IN_IGNORED)
250 /* The watch is removed. If the file name still exists monitor the new one,
252 if (ecore_file_exists(em->path))
254 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
255 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
258 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
263 _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path)
267 IN_MOVED_FROM|IN_MOVED_TO|
269 IN_DELETE_SELF|IN_MOVE_SELF|
271 ECORE_FILE_MONITOR_INOTIFY(em)->wd = inotify_add_watch(ecore_main_fd_handler_fd_get(_fdh),
273 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0)
275 ERR("inotify_add_watch error");
276 ecore_file_monitor_inotify_del(em);
282 #ifndef HAVE_SYS_INOTIFY
286 return syscall(__NR_inotify_init);
290 inotify_add_watch(int fd, const char *name, __u32 mask)
292 return syscall(__NR_inotify_add_watch, fd, name, mask);
296 inotify_rm_watch(int fd, __u32 wd)
298 return syscall(__NR_inotify_rm_watch, fd, wd);
304 _ecore_file_monitor_inotify_print(char *file, int mask)
313 if (mask & IN_MODIFY)
315 WRN("Inotify modified %s: %s", type, file);
317 if (mask & IN_MOVED_FROM)
319 WRN("Inotify moved from %s: %s", type, file);
321 if (mask & IN_MOVED_TO)
323 WRN("Inotify moved to %s: %s", type, file);
325 if (mask & IN_DELETE)
327 WRN("Inotify delete %s: %s", type, file);
329 if (mask & IN_CREATE)
331 WRN("Inotify create %s: %s", type, file);
333 if (mask & IN_DELETE_SELF)
335 WRN("Inotify delete self %s: %s", type, file);
337 if (mask & IN_MOVE_SELF)
339 WRN("Inotify move self %s: %s", type, file);
341 if (mask & IN_UNMOUNT)
343 WRN("Inotify unmount %s: %s", type, file);
347 #endif /* HAVE_INOTIFY */