diff options
| author | Michael Albinus | 2015-11-18 13:47:25 +0000 |
|---|---|---|
| committer | Michael Albinus | 2015-11-25 15:07:11 +0100 |
| commit | 65ba5a98d47f4305f95f960efdf424684754a11d (patch) | |
| tree | 644b229abb093a6024446bf4655d1aa0b460b453 /src | |
| parent | 13f3508443e4f5c48d40e4dbb11eaf875a5b2042 (diff) | |
| download | emacs-65ba5a98d47f4305f95f960efdf424684754a11d.tar.gz emacs-65ba5a98d47f4305f95f960efdf424684754a11d.zip | |
Further fixes for kqueue.
* lisp/filenotify.el (file-notify-callback): Raise also event if
directory name matches.
(file-notify-add-watch): Add `create' to the flags for `kqueue'.
* src/kqueue.c (kqueue_generate_event): Use watch_object as
argument instead of ident. Remove callback argument. Adapt
callees. Check actions whether they are monitored flags.
* test/automated/file-notify-tests.el (file-notify--test-library):
New defun.
(file-notify-test00-availability, file-notify-test02-events)
(file-notify-test04-file-validity)
(file-notify-test05-dir-validity): Use it.
(file-notify-test02-events, file-notify-test04-file-validity): Add
`read-event' calls between different file actions, in order to
give the backends a chance to rais an event. Needed especially
for kqueue. In case of deleting a directory, there are two
`deleted' events.
Diffstat (limited to 'src')
| -rw-r--r-- | src/kqueue.c | 81 |
1 files changed, 44 insertions, 37 deletions
diff --git a/src/kqueue.c b/src/kqueue.c index 5caef67b92a..e2c9dabcb20 100644 --- a/src/kqueue.c +++ b/src/kqueue.c | |||
| @@ -67,21 +67,39 @@ kqueue_directory_listing (Lisp_Object directory_files) | |||
| 67 | /* Generate a file notification event. */ | 67 | /* Generate a file notification event. */ |
| 68 | static void | 68 | static void |
| 69 | kqueue_generate_event | 69 | kqueue_generate_event |
| 70 | (Lisp_Object ident, Lisp_Object actions, Lisp_Object file, Lisp_Object file1, | 70 | (Lisp_Object watch_object, Lisp_Object actions, |
| 71 | Lisp_Object callback) | 71 | Lisp_Object file, Lisp_Object file1) |
| 72 | { | 72 | { |
| 73 | Lisp_Object flags, action, entry; | ||
| 73 | struct input_event event; | 74 | struct input_event event; |
| 74 | EVENT_INIT (event); | 75 | |
| 75 | event.kind = FILE_NOTIFY_EVENT; | 76 | /* Check, whether all actions shall be monitored. */ |
| 76 | event.frame_or_window = Qnil; | 77 | flags = Fnth (make_number (2), watch_object); |
| 77 | event.arg = list2 (Fcons (ident, Fcons (actions, | 78 | action = actions; |
| 78 | NILP (file1) | 79 | do { |
| 79 | ? Fcons (file, Qnil) | 80 | if (NILP (action)) |
| 80 | : list2 (file, file1))), | 81 | break; |
| 81 | callback); | 82 | entry = XCAR (action); |
| 83 | if (NILP (Fmember (entry, flags))) { | ||
| 84 | action = XCDR (action); | ||
| 85 | actions = Fdelq (entry, actions); | ||
| 86 | } else | ||
| 87 | action = XCDR (action); | ||
| 88 | } while (1); | ||
| 82 | 89 | ||
| 83 | /* Store it into the input event queue. */ | 90 | /* Store it into the input event queue. */ |
| 84 | kbd_buffer_store_event (&event); | 91 | if (! NILP (actions)) { |
| 92 | EVENT_INIT (event); | ||
| 93 | event.kind = FILE_NOTIFY_EVENT; | ||
| 94 | event.frame_or_window = Qnil; | ||
| 95 | event.arg = list2 (Fcons (XCAR (watch_object), | ||
| 96 | Fcons (actions, | ||
| 97 | NILP (file1) | ||
| 98 | ? Fcons (file, Qnil) | ||
| 99 | : list2 (file, file1))), | ||
| 100 | Fnth (make_number (3), watch_object)); | ||
| 101 | kbd_buffer_store_event (&event); | ||
| 102 | } | ||
| 85 | } | 103 | } |
| 86 | 104 | ||
| 87 | /* This compares two directory listings in case of a `write' event for | 105 | /* This compares two directory listings in case of a `write' event for |
| @@ -93,19 +111,16 @@ static void | |||
| 93 | kqueue_compare_dir_list | 111 | kqueue_compare_dir_list |
| 94 | (Lisp_Object watch_object) | 112 | (Lisp_Object watch_object) |
| 95 | { | 113 | { |
| 96 | Lisp_Object dir, callback; | 114 | Lisp_Object dir, old_directory_files, old_dl, new_directory_files, new_dl, dl; |
| 97 | Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl; | ||
| 98 | 115 | ||
| 99 | dir = XCAR (XCDR (watch_object)); | 116 | dir = XCAR (XCDR (watch_object)); |
| 100 | callback = Fnth (make_number (3), watch_object); | ||
| 101 | 117 | ||
| 102 | old_directory_files = Fnth (make_number (4), watch_object); | 118 | old_directory_files = Fnth (make_number (4), watch_object); |
| 103 | old_dl = kqueue_directory_listing (old_directory_files); | 119 | old_dl = kqueue_directory_listing (old_directory_files); |
| 104 | 120 | ||
| 105 | /* When the directory is not accessible anymore, it has been deleted. */ | 121 | /* When the directory is not accessible anymore, it has been deleted. */ |
| 106 | if (NILP (Ffile_directory_p (dir))) { | 122 | if (NILP (Ffile_directory_p (dir))) { |
| 107 | kqueue_generate_event | 123 | kqueue_generate_event (watch_object, Fcons (Qdelete, Qnil), dir, Qnil); |
| 108 | (XCAR (watch_object), Fcons (Qdelete, Qnil), dir, Qnil, callback); | ||
| 109 | return; | 124 | return; |
| 110 | } | 125 | } |
| 111 | new_directory_files = | 126 | new_directory_files = |
| @@ -137,21 +152,20 @@ kqueue_compare_dir_list | |||
| 137 | if (NILP (Fequal (Fnth (make_number (2), old_entry), | 152 | if (NILP (Fequal (Fnth (make_number (2), old_entry), |
| 138 | Fnth (make_number (2), new_entry)))) | 153 | Fnth (make_number (2), new_entry)))) |
| 139 | kqueue_generate_event | 154 | kqueue_generate_event |
| 140 | (XCAR (watch_object), Fcons (Qwrite, Qnil), | 155 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (old_entry)), Qnil); |
| 141 | XCAR (XCDR (old_entry)), Qnil, callback); | ||
| 142 | /* Status change time has been changed, the file attributes | 156 | /* Status change time has been changed, the file attributes |
| 143 | have changed. */ | 157 | have changed. */ |
| 144 | if (NILP (Fequal (Fnth (make_number (3), old_entry), | 158 | if (NILP (Fequal (Fnth (make_number (3), old_entry), |
| 145 | Fnth (make_number (3), new_entry)))) | 159 | Fnth (make_number (3), new_entry)))) |
| 146 | kqueue_generate_event | 160 | kqueue_generate_event |
| 147 | (XCAR (watch_object), Fcons (Qattrib, Qnil), | 161 | (watch_object, Fcons (Qattrib, Qnil), |
| 148 | XCAR (XCDR (old_entry)), Qnil, callback); | 162 | XCAR (XCDR (old_entry)), Qnil); |
| 149 | 163 | ||
| 150 | } else { | 164 | } else { |
| 151 | /* The file has been renamed. */ | 165 | /* The file has been renamed. */ |
| 152 | kqueue_generate_event | 166 | kqueue_generate_event |
| 153 | (XCAR (watch_object), Fcons (Qrename, Qnil), | 167 | (watch_object, Fcons (Qrename, Qnil), |
| 154 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry)), callback); | 168 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); |
| 155 | } | 169 | } |
| 156 | new_dl = Fdelq (new_entry, new_dl); | 170 | new_dl = Fdelq (new_entry, new_dl); |
| 157 | goto the_end; | 171 | goto the_end; |
| @@ -164,8 +178,7 @@ kqueue_compare_dir_list | |||
| 164 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), | 178 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), |
| 165 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { | 179 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { |
| 166 | kqueue_generate_event | 180 | kqueue_generate_event |
| 167 | (XCAR (watch_object), Fcons (Qwrite, Qnil), | 181 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (old_entry)), Qnil); |
| 168 | XCAR (XCDR (old_entry)), Qnil, callback); | ||
| 169 | new_dl = Fdelq (new_entry, new_dl); | 182 | new_dl = Fdelq (new_entry, new_dl); |
| 170 | goto the_end; | 183 | goto the_end; |
| 171 | } | 184 | } |
| @@ -173,8 +186,7 @@ kqueue_compare_dir_list | |||
| 173 | 186 | ||
| 174 | /* The file has been deleted. */ | 187 | /* The file has been deleted. */ |
| 175 | kqueue_generate_event | 188 | kqueue_generate_event |
| 176 | (XCAR (watch_object), Fcons (Qdelete, Qnil), | 189 | (watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil); |
| 177 | XCAR (XCDR (old_entry)), Qnil, callback); | ||
| 178 | 190 | ||
| 179 | the_end: | 191 | the_end: |
| 180 | dl = XCDR (dl); | 192 | dl = XCDR (dl); |
| @@ -191,15 +203,13 @@ kqueue_compare_dir_list | |||
| 191 | /* A new file has appeared. */ | 203 | /* A new file has appeared. */ |
| 192 | new_entry = XCAR (dl); | 204 | new_entry = XCAR (dl); |
| 193 | kqueue_generate_event | 205 | kqueue_generate_event |
| 194 | (XCAR (watch_object), Fcons (Qcreate, Qnil), | 206 | (watch_object, Fcons (Qcreate, Qnil), XCAR (XCDR (new_entry)), Qnil); |
| 195 | XCAR (XCDR (new_entry)), Qnil, callback); | ||
| 196 | 207 | ||
| 197 | /* Check size of that file. */ | 208 | /* Check size of that file. */ |
| 198 | Lisp_Object size = Fnth (make_number (4), new_entry); | 209 | Lisp_Object size = Fnth (make_number (4), new_entry); |
| 199 | if (FLOATP (size) || (XINT (size) > 0)) | 210 | if (FLOATP (size) || (XINT (size) > 0)) |
| 200 | kqueue_generate_event | 211 | kqueue_generate_event |
| 201 | (XCAR (watch_object), Fcons (Qwrite, Qnil), | 212 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (new_entry)), Qnil); |
| 202 | XCAR (XCDR (new_entry)), Qnil, callback); | ||
| 203 | 213 | ||
| 204 | dl = XCDR (dl); | 214 | dl = XCDR (dl); |
| 205 | new_dl = Fdelq (new_entry, new_dl); | 215 | new_dl = Fdelq (new_entry, new_dl); |
| @@ -226,7 +236,7 @@ kqueue_callback (int fd, void *data) | |||
| 226 | for (;;) { | 236 | for (;;) { |
| 227 | struct kevent kev; | 237 | struct kevent kev; |
| 228 | static const struct timespec nullts = { 0, 0 }; | 238 | static const struct timespec nullts = { 0, 0 }; |
| 229 | Lisp_Object descriptor, watch_object, file, callback, actions; | 239 | Lisp_Object descriptor, watch_object, file, actions; |
| 230 | 240 | ||
| 231 | /* Read one event. */ | 241 | /* Read one event. */ |
| 232 | int ret = kevent (kqueuefd, NULL, 0, &kev, 1, &nullts); | 242 | int ret = kevent (kqueuefd, NULL, 0, &kev, 1, &nullts); |
| @@ -235,14 +245,11 @@ kqueue_callback (int fd, void *data) | |||
| 235 | return; | 245 | return; |
| 236 | } | 246 | } |
| 237 | 247 | ||
| 238 | /* Determine descriptor, file name and callback function. */ | 248 | /* Determine descriptor and file name. */ |
| 239 | descriptor = make_number (kev.ident); | 249 | descriptor = make_number (kev.ident); |
| 240 | watch_object = assq_no_quit (descriptor, watch_list); | 250 | watch_object = assq_no_quit (descriptor, watch_list); |
| 241 | 251 | if (CONSP (watch_object)) | |
| 242 | if (CONSP (watch_object)) { | ||
| 243 | file = XCAR (XCDR (watch_object)); | 252 | file = XCAR (XCDR (watch_object)); |
| 244 | callback = Fnth (make_number (3), watch_object); | ||
| 245 | } | ||
| 246 | else | 253 | else |
| 247 | continue; | 254 | continue; |
| 248 | 255 | ||
| @@ -271,7 +278,7 @@ kqueue_callback (int fd, void *data) | |||
| 271 | 278 | ||
| 272 | /* Create the event. */ | 279 | /* Create the event. */ |
| 273 | if (! NILP (actions)) | 280 | if (! NILP (actions)) |
| 274 | kqueue_generate_event (descriptor, actions, file, Qnil, callback); | 281 | kqueue_generate_event (watch_object, actions, file, Qnil); |
| 275 | 282 | ||
| 276 | /* Cancel monitor if file or directory is deleted or renamed. */ | 283 | /* Cancel monitor if file or directory is deleted or renamed. */ |
| 277 | if (kev.fflags & (NOTE_DELETE | NOTE_RENAME)) | 284 | if (kev.fflags & (NOTE_DELETE | NOTE_RENAME)) |