summaryrefslogtreecommitdiff
path: root/legacy/eio
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-09-06 06:30:29 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-09-06 06:30:29 +0000
commited4a4d5fdc5844f3e4eae4d5bbcca041ee24aa33 (patch)
treef6f432b32b87cd562ac86b456f0b1d98cce442f7 /legacy/eio
parent816c904dc83f3269ba14ce613b4afa91a12ec30d (diff)
Eio: improve path monitoring on Windows
Not perfect but i'm fed up with that Windows stuff. I need to work on something else SVN revision: 76215
Diffstat (limited to 'legacy/eio')
-rw-r--r--legacy/eio/ChangeLog4
-rw-r--r--legacy/eio/NEWS3
-rw-r--r--legacy/eio/TODO1
-rw-r--r--legacy/eio/src/lib/Eio.h4
-rw-r--r--legacy/eio/src/lib/eio_monitor.c6
-rw-r--r--legacy/eio/src/lib/eio_monitor_win32.c233
6 files changed, 177 insertions, 74 deletions
diff --git a/legacy/eio/ChangeLog b/legacy/eio/ChangeLog
index cb58e900e8..0dc04a1cbc 100644
--- a/legacy/eio/ChangeLog
+++ b/legacy/eio/ChangeLog
@@ -35,3 +35,7 @@
352012-08-30 Carsten Haitzler (The Rasterman) 352012-08-30 Carsten Haitzler (The Rasterman)
36 36
37 1.7.0 release 37 1.7.0 release
38
392012-09-06 Vincent Torri
40
41 * Improve file monitoring on Windows to mimic more inotify behavior.
diff --git a/legacy/eio/NEWS b/legacy/eio/NEWS
index 5da27bd815..aedcbee570 100644
--- a/legacy/eio/NEWS
+++ b/legacy/eio/NEWS
@@ -14,6 +14,7 @@ Fixes:
14 - Fix memory leak when using file_associate. 14 - Fix memory leak when using file_associate.
15 15
16Improvements: 16Improvements:
17 - Add log debuggong macros 17 - Add log debugging macros.
18 - path monitoring on Windows.
18 19
19Removal: 20Removal:
diff --git a/legacy/eio/TODO b/legacy/eio/TODO
new file mode 100644
index 0000000000..01c6f05a5c
--- /dev/null
+++ b/legacy/eio/TODO
@@ -0,0 +1 @@
* Fix file monitoring on Windows when we pass a file and not just a directory \ No newline at end of file
diff --git a/legacy/eio/src/lib/Eio.h b/legacy/eio/src/lib/Eio.h
index 07d1e1f84b..e21a269f5d 100644
--- a/legacy/eio/src/lib/Eio.h
+++ b/legacy/eio/src/lib/Eio.h
@@ -1107,11 +1107,11 @@ EAPI Eio_File *eio_eet_write_cipher(Eet_File *ef,
1107EAPI extern int EIO_MONITOR_FILE_CREATED; /**< A new file was created in a watched directory */ 1107EAPI extern int EIO_MONITOR_FILE_CREATED; /**< A new file was created in a watched directory */
1108EAPI extern int EIO_MONITOR_FILE_DELETED; /**< A watched file was deleted, or a file in a watched directory was deleted */ 1108EAPI extern int EIO_MONITOR_FILE_DELETED; /**< A watched file was deleted, or a file in a watched directory was deleted */
1109EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< A file was modified in a watched directory */ 1109EAPI extern int EIO_MONITOR_FILE_MODIFIED; /**< A file was modified in a watched directory */
1110EAPI extern int EIO_MONITOR_FILE_CLOSED; /**< A file was closed in a watched directory */ 1110EAPI extern int EIO_MONITOR_FILE_CLOSED; /**< A file was closed in a watched directory. This event is never sent on Windows */
1111EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< A new directory was created in a watched directory */ 1111EAPI extern int EIO_MONITOR_DIRECTORY_CREATED; /**< A new directory was created in a watched directory */
1112EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< A directory has been deleted: this can be either a watched directory or one of its subdirectories */ 1112EAPI extern int EIO_MONITOR_DIRECTORY_DELETED; /**< A directory has been deleted: this can be either a watched directory or one of its subdirectories */
1113EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< A directory has been modified in a watched directory */ 1113EAPI extern int EIO_MONITOR_DIRECTORY_MODIFIED; /**< A directory has been modified in a watched directory */
1114EAPI extern int EIO_MONITOR_DIRECTORY_CLOSED; /**< A directory has been closed in a watched directory */ 1114EAPI extern int EIO_MONITOR_DIRECTORY_CLOSED; /**< A directory has been closed in a watched directory. This event is never sent on Windows */
1115EAPI extern int EIO_MONITOR_SELF_RENAME; /**< The monitored path has been renamed, an error could happen just after if the renamed path doesn't exist */ 1115EAPI extern int EIO_MONITOR_SELF_RENAME; /**< The monitored path has been renamed, an error could happen just after if the renamed path doesn't exist */
1116EAPI extern int EIO_MONITOR_SELF_DELETED; /**< The monitored path has been removed */ 1116EAPI extern int EIO_MONITOR_SELF_DELETED; /**< The monitored path has been removed */
1117EAPI extern int EIO_MONITOR_ERROR; /**< During operation the monitor failed and will no longer work. eio_monitor_del must be called on it. */ 1117EAPI extern int EIO_MONITOR_ERROR; /**< During operation the monitor failed and will no longer work. eio_monitor_del must be called on it. */
diff --git a/legacy/eio/src/lib/eio_monitor.c b/legacy/eio/src/lib/eio_monitor.c
index 50d9ef4dca..c21b1f49ca 100644
--- a/legacy/eio/src/lib/eio_monitor.c
+++ b/legacy/eio/src/lib/eio_monitor.c
@@ -273,7 +273,11 @@ eio_monitor_stringshared_add(const char *path)
273 eio_monitor_init(); 273 eio_monitor_init();
274 } 274 }
275 275
276 if (stat(path, &st) != 0) return NULL; 276 if (stat(path, &st) != 0)
277 {
278 INF("monitored path not found");
279 return NULL;
280 }
277 281
278 monitor = eina_hash_find(_eio_monitors, path); 282 monitor = eina_hash_find(_eio_monitors, path);
279 283
diff --git a/legacy/eio/src/lib/eio_monitor_win32.c b/legacy/eio/src/lib/eio_monitor_win32.c
index 676ba2f4ac..16dbaa7fdd 100644
--- a/legacy/eio/src/lib/eio_monitor_win32.c
+++ b/legacy/eio/src/lib/eio_monitor_win32.c
@@ -41,16 +41,19 @@ struct _Eio_Monitor_Win32_Watcher
41 HANDLE event; 41 HANDLE event;
42 Eio_Monitor *monitor; 42 Eio_Monitor *monitor;
43 Ecore_Win32_Handler *h; 43 Ecore_Win32_Handler *h;
44 char *current;
45 char *file;
44 DWORD buf_length; 46 DWORD buf_length;
45 int is_dir; 47 Eina_Bool monitor_file : 1;
48 Eina_Bool monitor_parent : 1;
46}; 49};
47 50
48struct _Eio_Monitor_Backend 51struct _Eio_Monitor_Backend
49{ 52{
50 Eio_Monitor *parent; 53 Eio_Monitor *parent;
51 54 Eio_Monitor_Win32_Watcher *watcher_file;
52 Eio_Monitor_Win32_Watcher *file; 55 Eio_Monitor_Win32_Watcher *watcher_dir;
53 Eio_Monitor_Win32_Watcher *dir; 56 Eio_Monitor_Win32_Watcher *watcher_parent;
54}; 57};
55 58
56static Eina_Bool _eio_monitor_win32_native = EINA_FALSE; 59static Eina_Bool _eio_monitor_win32_native = EINA_FALSE;
@@ -58,7 +61,6 @@ static Eina_Bool _eio_monitor_win32_native = EINA_FALSE;
58static Eina_Bool 61static Eina_Bool
59_eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__) 62_eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
60{ 63{
61 char filename[PATH_MAX];
62 PFILE_NOTIFY_INFORMATION fni; 64 PFILE_NOTIFY_INFORMATION fni;
63 Eio_Monitor_Win32_Watcher *w; 65 Eio_Monitor_Win32_Watcher *w;
64 wchar_t *wname; 66 wchar_t *wname;
@@ -66,7 +68,7 @@ _eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
66 DWORD filter; 68 DWORD filter;
67 DWORD offset; 69 DWORD offset;
68 DWORD buf_length; 70 DWORD buf_length;
69 int event = EIO_MONITOR_ERROR; 71 int event;
70 72
71 w = (Eio_Monitor_Win32_Watcher *)data; 73 w = (Eio_Monitor_Win32_Watcher *)data;
72 74
@@ -79,76 +81,99 @@ _eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
79 break; 81 break;
80 offset = fni->NextEntryOffset; 82 offset = fni->NextEntryOffset;
81 83
82 wname = (wchar_t *)malloc(sizeof(wchar_t) * (fni->FileNameLength + 1)); 84 wname = (wchar_t *)malloc(fni->FileNameLength + sizeof(wchar_t));
83 if (!wname) 85 if (!wname)
84 return 0; 86 return 0;
85 87
86 memcpy(wname, fni->FileName, fni->FileNameLength); 88 memcpy(wname, fni->FileName, fni->FileNameLength);
87 wname[fni->FileNameLength]='\0'; 89 wname[fni->FileNameLength / sizeof(wchar_t)] = 0;
88 name = evil_wchar_to_char(wname); 90 name = evil_wchar_to_char(wname);
89 free(wname); 91 free(wname);
90 if (!name) 92 if (!name)
91 return ECORE_CALLBACK_CANCEL; 93 return ECORE_CALLBACK_CANCEL;
92 94
93 _snprintf(filename, PATH_MAX, "%s\\%s", w->monitor->path, name); 95 event = -1;
94 free(name);
95
96 name = filename;
97 while (*name)
98 {
99 if (*name == '/') *name = '\\';
100 name++;
101 }
102
103 switch (fni->Action) 96 switch (fni->Action)
104 { 97 {
105 case FILE_ACTION_ADDED: 98 case FILE_ACTION_ADDED:
106 if (w->is_dir) 99 if (!w->monitor_parent)
107 event = EIO_MONITOR_DIRECTORY_CREATED; 100 {
108 else 101 if (w->monitor_file)
109 event = EIO_MONITOR_FILE_CREATED; 102 event = EIO_MONITOR_FILE_CREATED;
103 else
104 event = EIO_MONITOR_DIRECTORY_CREATED;
105 }
110 break; 106 break;
111 case FILE_ACTION_REMOVED: 107 case FILE_ACTION_REMOVED:
112 if (w->is_dir) 108 if (w->monitor_parent)
113 event = EIO_MONITOR_DIRECTORY_DELETED; 109 {
110 char path[MAX_PATH];
111 char *res;
112
113 res = _fullpath(path, name, MAX_PATH);
114 if (res && (strcmp(res, w->current) == 0))
115 event = EIO_MONITOR_SELF_DELETED;
116 }
114 else 117 else
115 event = EIO_MONITOR_FILE_DELETED; 118 {
119 if (w->monitor_file)
120 event = EIO_MONITOR_FILE_DELETED;
121 else
122 event = EIO_MONITOR_DIRECTORY_DELETED;
123 }
116 break; 124 break;
117 case FILE_ACTION_MODIFIED: 125 case FILE_ACTION_MODIFIED:
118 if (!w->is_dir) 126 if (!w->monitor_parent)
119 event = EIO_MONITOR_FILE_MODIFIED; 127 {
128 if (w->monitor_file)
129 event = EIO_MONITOR_FILE_MODIFIED;
130 else
131 event = EIO_MONITOR_DIRECTORY_MODIFIED;
132 }
120 break; 133 break;
121 case FILE_ACTION_RENAMED_OLD_NAME: 134 case FILE_ACTION_RENAMED_OLD_NAME:
122 if (w->is_dir) 135 if (!w->monitor_parent)
123 event = EIO_MONITOR_DIRECTORY_DELETED; 136 {
124 else 137 if (w->monitor_file)
125 event = EIO_MONITOR_FILE_DELETED; 138 event = EIO_MONITOR_FILE_DELETED;
139 else
140 event = EIO_MONITOR_DIRECTORY_DELETED;
141 }
126 break; 142 break;
127 case FILE_ACTION_RENAMED_NEW_NAME: 143 case FILE_ACTION_RENAMED_NEW_NAME:
128 if (w->is_dir) 144 if (!w->monitor_parent)
129 event = EIO_MONITOR_DIRECTORY_CREATED; 145 {
130 else 146 if (w->monitor_file)
131 event = EIO_MONITOR_FILE_CREATED; 147 event = EIO_MONITOR_FILE_CREATED;
148 else
149 event = EIO_MONITOR_DIRECTORY_CREATED;
150 }
132 break; 151 break;
133 default: 152 default:
134 fprintf(stderr, "unknown event\n"); 153 ERR("unknown event");
135 event = EIO_MONITOR_ERROR; 154 event = EIO_MONITOR_ERROR;
136 break; 155 break;
137 } 156 }
138 if (event != EIO_MONITOR_ERROR) 157
139 _eio_monitor_send(w->monitor, filename, event); 158 if (event >= 0)
159 _eio_monitor_send(w->monitor, name, event);
160
161 free(name);
140 162
141 fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset); 163 fni = (PFILE_NOTIFY_INFORMATION)((LPBYTE)fni + offset);
142 } while (offset); 164 } while (offset);
143 165
144 filter = (w->is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME; 166 filter =
145 filter |=
146 FILE_NOTIFY_CHANGE_ATTRIBUTES | 167 FILE_NOTIFY_CHANGE_ATTRIBUTES |
147 FILE_NOTIFY_CHANGE_SIZE | 168 FILE_NOTIFY_CHANGE_SIZE |
148 FILE_NOTIFY_CHANGE_LAST_WRITE | 169 FILE_NOTIFY_CHANGE_LAST_WRITE |
149 FILE_NOTIFY_CHANGE_LAST_ACCESS | 170 FILE_NOTIFY_CHANGE_LAST_ACCESS |
150 FILE_NOTIFY_CHANGE_CREATION | 171 FILE_NOTIFY_CHANGE_CREATION |
151 FILE_NOTIFY_CHANGE_SECURITY; 172 FILE_NOTIFY_CHANGE_SECURITY;
173 if (w->monitor_file)
174 filter |= FILE_NOTIFY_CHANGE_FILE_NAME;
175 else
176 filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
152 177
153 ReadDirectoryChangesW(w->handle, 178 ReadDirectoryChangesW(w->handle,
154 (LPVOID)w->buffer, 179 (LPVOID)w->buffer,
@@ -163,17 +188,32 @@ _eio_monitor_win32_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
163} 188}
164 189
165static Eio_Monitor_Win32_Watcher * 190static Eio_Monitor_Win32_Watcher *
166_eio_monitor_win32_watcher_new(Eio_Monitor *monitor, unsigned char is_dir) 191_eio_monitor_win32_watcher_new(Eio_Monitor *monitor,
192 char *current,
193 char *file,
194 Eina_Bool monitor_file,
195 Eina_Bool monitor_parent)
167{ 196{
168 char path[PATH_MAX];
169 Eio_Monitor_Win32_Watcher *w; 197 Eio_Monitor_Win32_Watcher *w;
198 char *monitored;
170 DWORD filter; 199 DWORD filter;
171 200
172 w = (Eio_Monitor_Win32_Watcher *)calloc(1, sizeof(Eio_Monitor_Win32_Watcher)); 201 w = (Eio_Monitor_Win32_Watcher *)calloc(1, sizeof(Eio_Monitor_Win32_Watcher));
173 if (!w) return NULL; 202 if (!w) return NULL;
174 203
175 realpath(monitor->path, path); 204 if (!monitor_parent)
176 w->handle = CreateFile(path, 205 monitored = current;
206 else
207 {
208 char *tmp;
209
210 tmp = strrchr(current, '\\');
211 monitored = (char *)alloca((tmp - current) + 1);
212 memcpy(monitored, current, tmp - current);
213 monitored[tmp - current] = '\0';
214 }
215
216 w->handle = CreateFile(monitored,
177 FILE_LIST_DIRECTORY, 217 FILE_LIST_DIRECTORY,
178 FILE_SHARE_READ | 218 FILE_SHARE_READ |
179 FILE_SHARE_WRITE, 219 FILE_SHARE_WRITE,
@@ -192,14 +232,17 @@ _eio_monitor_win32_watcher_new(Eio_Monitor *monitor, unsigned char is_dir)
192 ZeroMemory (&w->overlapped, sizeof(w->overlapped)); 232 ZeroMemory (&w->overlapped, sizeof(w->overlapped));
193 w->overlapped.hEvent = w->event; 233 w->overlapped.hEvent = w->event;
194 234
195 filter = (is_dir == 0) ? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME; 235 filter =
196 filter |=
197 FILE_NOTIFY_CHANGE_ATTRIBUTES | 236 FILE_NOTIFY_CHANGE_ATTRIBUTES |
198 FILE_NOTIFY_CHANGE_SIZE | 237 FILE_NOTIFY_CHANGE_SIZE |
199 FILE_NOTIFY_CHANGE_LAST_WRITE | 238 FILE_NOTIFY_CHANGE_LAST_WRITE |
200 FILE_NOTIFY_CHANGE_LAST_ACCESS | 239 FILE_NOTIFY_CHANGE_LAST_ACCESS |
201 FILE_NOTIFY_CHANGE_CREATION | 240 FILE_NOTIFY_CHANGE_CREATION |
202 FILE_NOTIFY_CHANGE_SECURITY; 241 FILE_NOTIFY_CHANGE_SECURITY;
242 if (monitor_file)
243 filter |= FILE_NOTIFY_CHANGE_FILE_NAME;
244 else
245 filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
203 246
204 if (!ReadDirectoryChangesW(w->handle, 247 if (!ReadDirectoryChangesW(w->handle,
205 (LPVOID)w->buffer, 248 (LPVOID)w->buffer,
@@ -228,7 +271,10 @@ _eio_monitor_win32_watcher_new(Eio_Monitor *monitor, unsigned char is_dir)
228 goto close_event; 271 goto close_event;
229 272
230 w->monitor = monitor; 273 w->monitor = monitor;
231 w->is_dir = is_dir; 274 w->monitor_file = monitor_file;
275 w->monitor_parent = monitor_parent;
276 w->file = file;
277 w->current = current;
232 278
233 return w; 279 return w;
234 280
@@ -247,6 +293,9 @@ _eio_monitor_win32_watcher_free(Eio_Monitor_Win32_Watcher *w)
247{ 293{
248 if (!w) return; 294 if (!w) return;
249 295
296 if (w->file)
297 free(w->file);
298 free(w->current);
250 CloseHandle(w->event); 299 CloseHandle(w->event);
251 CloseHandle (w->handle); 300 CloseHandle (w->handle);
252 free (w); 301 free (w);
@@ -274,37 +323,80 @@ void eio_monitor_backend_shutdown(void)
274 323
275void eio_monitor_backend_add(Eio_Monitor *monitor) 324void eio_monitor_backend_add(Eio_Monitor *monitor)
276{ 325{
326 char path[PATH_MAX];
327 struct _stat s;
328 char *res;
329 char *current;
330 char *file = NULL;
277 Eio_Monitor_Backend *backend; 331 Eio_Monitor_Backend *backend;
332 int ret;
278 333
279 backend = calloc(1, sizeof (Eio_Monitor_Backend)); 334 res = _fullpath(path, monitor->path, MAX_PATH);
280 if (!backend) 335 if (!res)
281 { 336 goto fallback;
282 eio_monitor_fallback_add(monitor);
283 return;
284 }
285 337
286 backend->parent = monitor; 338 ret = _stat(res, &s);
287 backend->file = _eio_monitor_win32_watcher_new(monitor, 0); 339 if (ret != 0)
288 if (!backend->file) 340 goto fallback;
341
342 if (_S_IFDIR & s.st_mode)
289 { 343 {
290 INF("falling back to poll monitoring"); 344 current = strdup(path);
291 free(backend); 345 if (!current)
292 eio_monitor_fallback_add(monitor); 346 goto fallback;
293 return;
294 } 347 }
295 348 else if (_S_IFREG & s.st_mode)
296 backend->dir = _eio_monitor_win32_watcher_new(monitor, 1);
297 if (!backend->dir)
298 { 349 {
299 INF("falling back to poll monitoring"); 350 char *tmp;
300 _eio_monitor_win32_watcher_free(backend->file); 351
301 free(backend); 352 tmp = strrchr(path, '\\');
302 eio_monitor_fallback_add(monitor); 353 file = strdup(tmp + 1);
303 return; 354 if (!file)
355 goto fallback;
356
357 *tmp = '\0';
358 current = strdup(path);
359 if (!current)
360 {
361 free(file);
362 goto fallback;
363 }
304 } 364 }
365 else
366 goto fallback;
367
368 backend = calloc(1, sizeof (Eio_Monitor_Backend));
369 if (!backend)
370 goto fallback;
371
372 backend->parent = monitor;
373
374 backend->watcher_file = _eio_monitor_win32_watcher_new(monitor, current, file, EINA_TRUE, EINA_FALSE);
375 if (!backend->watcher_file)
376 goto free_backend;
377
378 backend->watcher_dir = _eio_monitor_win32_watcher_new(monitor, current, file, EINA_FALSE, EINA_FALSE);
379 if (!backend->watcher_dir)
380 goto free_backend_file;
381
382 backend->watcher_parent = _eio_monitor_win32_watcher_new(monitor, current, file, EINA_FALSE, EINA_TRUE);
383 if (!backend->watcher_parent)
384 goto free_backend_dir;
305 385
306 _eio_monitor_win32_native = EINA_TRUE; 386 _eio_monitor_win32_native = EINA_TRUE;
307 monitor->backend = backend; 387 monitor->backend = backend;
388
389 return;
390
391 free_backend_dir:
392 _eio_monitor_win32_watcher_free(backend->watcher_dir);
393 free_backend_file:
394 _eio_monitor_win32_watcher_free(backend->watcher_file);
395 free_backend:
396 free(backend);
397 fallback:
398 INF("falling back to poll monitoring");
399 eio_monitor_fallback_add(monitor);
308} 400}
309 401
310void eio_monitor_backend_del(Eio_Monitor *monitor) 402void eio_monitor_backend_del(Eio_Monitor *monitor)
@@ -315,8 +407,9 @@ void eio_monitor_backend_del(Eio_Monitor *monitor)
315 return ; 407 return ;
316 } 408 }
317 409
318 _eio_monitor_win32_watcher_free(monitor->backend->file); 410 _eio_monitor_win32_watcher_free(monitor->backend->watcher_parent);
319 _eio_monitor_win32_watcher_free(monitor->backend->dir); 411 _eio_monitor_win32_watcher_free(monitor->backend->watcher_dir);
412 _eio_monitor_win32_watcher_free(monitor->backend->watcher_file);
320 free(monitor->backend); 413 free(monitor->backend);
321 monitor->backend = NULL; 414 monitor->backend = NULL;
322} 415}