aboutsummaryrefslogtreecommitdiffstats
path: root/src/kqueue.c
diff options
context:
space:
mode:
authorMichael Albinus2015-11-18 13:47:25 +0000
committerMichael Albinus2015-11-25 15:07:11 +0100
commit65ba5a98d47f4305f95f960efdf424684754a11d (patch)
tree644b229abb093a6024446bf4655d1aa0b460b453 /src/kqueue.c
parent13f3508443e4f5c48d40e4dbb11eaf875a5b2042 (diff)
downloademacs-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/kqueue.c')
-rw-r--r--src/kqueue.c81
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. */
68static void 68static void
69kqueue_generate_event 69kqueue_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
93kqueue_compare_dir_list 111kqueue_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))