2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
11 #include <sys/types.h>
14 #include "ecore_file_private.h"
19 * - Listen to these events:
20 * IN_ACCESS, IN_ATTRIB, IN_CLOSE_WRITE, IN_CLOSE_NOWRITE, IN_OPEN
21 * - Read all events first, then call the callbacks. This will prevent several
22 * callbacks with the typic save cycle (delete file, new file)
27 #ifdef HAVE_SYS_INOTIFY
28 # include <sys/inotify.h>
30 # include <asm/unistd.h>
31 # include <linux/inotify.h>
34 #ifndef HAVE_SYS_INOTIFY
35 static inline int inotify_init(void);
36 static inline int inotify_add_watch(int fd, const char *name, __u32 mask);
37 static inline int inotify_rm_watch(int fd, __u32 wd);
41 typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify;
43 #define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x))
45 struct _Ecore_File_Monitor_Inotify
47 Ecore_File_Monitor monitor;
51 static Ecore_Fd_Handler *_fdh = NULL;
52 static Ecore_File_Monitor *_monitors = NULL;
54 static int _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh);
55 static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd);
56 static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask);
57 static int _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path);
59 static void _ecore_file_monitor_inotify_print(char *file, int mask);
63 ecore_file_monitor_inotify_init(void)
71 _fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler,
83 ecore_file_monitor_inotify_shutdown(void)
88 ecore_file_monitor_inotify_del(_monitors);
92 fd = ecore_main_fd_handler_fd_get(_fdh);
93 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 em = calloc(1, sizeof(Ecore_File_Monitor_Inotify));
110 if (!em) return NULL;
115 em->path = strdup(path);
116 len = strlen(em->path);
117 if (em->path[len - 1] == '/' && strcmp(em->path, "/"))
118 em->path[len - 1] = 0;
120 _monitors = ECORE_FILE_MONITOR(eina_inlist_append(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
122 if (ecore_file_exists(em->path))
124 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
129 ecore_file_monitor_inotify_del(em);
137 ecore_file_monitor_inotify_del(Ecore_File_Monitor *em)
141 _monitors = ECORE_FILE_MONITOR(eina_inlist_remove(EINA_INLIST_GET(_monitors), EINA_INLIST_GET(em)));
143 fd = ecore_main_fd_handler_fd_get(_fdh);
144 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd)
145 inotify_rm_watch(fd, ECORE_FILE_MONITOR_INOTIFY(em)->wd);
151 _ecore_file_monitor_inotify_handler(void *data __UNUSED__, Ecore_Fd_Handler *fdh)
153 Ecore_File_Monitor *em;
155 struct inotify_event *event;
160 size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer));
163 event = (struct inotify_event *)&buffer[i];
164 event_size = sizeof(struct inotify_event) + event->len;
167 em = _ecore_file_monitor_inotify_monitor_find(event->wd);
170 _ecore_file_monitor_inotify_events(em, (event->len ? event->name : NULL), event->mask);
176 static Ecore_File_Monitor *
177 _ecore_file_monitor_inotify_monitor_find(int wd)
179 Ecore_File_Monitor *l;
181 EINA_INLIST_FOREACH(_monitors, l)
183 if (ECORE_FILE_MONITOR_INOTIFY(l)->wd == wd)
190 _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask)
195 if ((file) && (file[0]))
196 snprintf(buf, sizeof(buf), "%s/%s", em->path, file);
198 strcpy(buf, em->path);
199 isdir = mask & IN_ISDIR;
202 _ecore_file_monitor_inotify_print(file, mask);
205 if (mask & IN_MODIFY)
208 em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf);
210 if (mask & IN_MOVED_FROM)
213 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
215 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
217 if (mask & IN_MOVED_TO)
220 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
222 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
224 if (mask & IN_DELETE)
227 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf);
229 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf);
231 if (mask & IN_CREATE)
234 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf);
236 em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf);
238 if (mask & IN_DELETE_SELF)
240 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
242 if (mask & IN_MOVE_SELF)
244 /* We just call delete. The dir is gone... */
245 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
247 if (mask & IN_UNMOUNT)
249 /* We just call delete. The dir is gone... */
250 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
252 if (mask & IN_IGNORED)
254 /* The watch is removed. If the file name still exists monitor the new one,
256 if (ecore_file_exists(em->path))
258 if (!_ecore_file_monitor_inotify_monitor(em, em->path))
259 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
262 em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path);
267 _ecore_file_monitor_inotify_monitor(Ecore_File_Monitor *em, const char *path)
271 IN_MOVED_FROM|IN_MOVED_TO|
273 IN_DELETE_SELF|IN_MOVE_SELF|
275 ECORE_FILE_MONITOR_INOTIFY(em)->wd = inotify_add_watch(ecore_main_fd_handler_fd_get(_fdh),
277 if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0)
279 ERR("inotify_add_watch error");
280 ecore_file_monitor_inotify_del(em);
286 #ifndef HAVE_SYS_INOTIFY
290 return syscall(__NR_inotify_init);
294 inotify_add_watch(int fd, const char *name, __u32 mask)
296 return syscall(__NR_inotify_add_watch, fd, name, mask);
300 inotify_rm_watch(int fd, __u32 wd)
302 return syscall(__NR_inotify_rm_watch, fd, wd);
308 _ecore_file_monitor_inotify_print(char *file, int mask)
317 if (mask & IN_MODIFY)
319 WRN("Inotify modified %s: %s", type, file);
321 if (mask & IN_MOVED_FROM)
323 WRN("Inotify moved from %s: %s", type, file);
325 if (mask & IN_MOVED_TO)
327 WRN("Inotify moved to %s: %s", type, file);
329 if (mask & IN_DELETE)
331 WRN("Inotify delete %s: %s", type, file);
333 if (mask & IN_CREATE)
335 WRN("Inotify create %s: %s", type, file);
337 if (mask & IN_DELETE_SELF)
339 WRN("Inotify delete self %s: %s", type, file);
341 if (mask & IN_MOVE_SELF)
343 WRN("Inotify move self %s: %s", type, file);
345 if (mask & IN_UNMOUNT)
347 WRN("Inotify unmount %s: %s", type, file);
351 #endif /* HAVE_INOTIFY */