diff options
| author | Michael Albinus | 2015-11-09 20:26:10 +0100 |
|---|---|---|
| committer | Michael Albinus | 2015-11-11 12:10:48 +0100 |
| commit | 0198c3066e8866d464690a9a7924d42e9c2663bf (patch) | |
| tree | f0b6e7771a4372da7a6476984e0d401974c9c3ca | |
| parent | 662ee733257d573deaadd2e217894b70265fb5fe (diff) | |
| download | emacs-0198c3066e8866d464690a9a7924d42e9c2663bf.tar.gz emacs-0198c3066e8866d464690a9a7924d42e9c2663bf.zip | |
Work on kqueue
* lisp/filenotify.el (file-notify--library)
(file-notify-descriptors, file-notify-callback)
(file-notify-add-watch, file-notify-rm-watch)
(file-notify-valid-p): Add kqueue support.
* src/keyboard.c (make_lispy_event): Check also for HAVE_KQUEUE.
| -rw-r--r-- | lisp/filenotify.el | 40 | ||||
| -rw-r--r-- | src/keyboard.c | 4 | ||||
| -rw-r--r-- | src/kqueue.c | 270 |
3 files changed, 125 insertions, 189 deletions
diff --git a/lisp/filenotify.el b/lisp/filenotify.el index 4c5d43fb44e..f7c97569825 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el | |||
| @@ -22,15 +22,16 @@ | |||
| 22 | ;;; Commentary | 22 | ;;; Commentary |
| 23 | 23 | ||
| 24 | ;; This package is an abstraction layer from the different low-level | 24 | ;; This package is an abstraction layer from the different low-level |
| 25 | ;; file notification packages `gfilenotify', `inotify' and | 25 | ;; file notification packages `inotify', `kqueue', `gfilenotify' and |
| 26 | ;; `w32notify'. | 26 | ;; `w32notify'. |
| 27 | 27 | ||
| 28 | ;;; Code: | 28 | ;;; Code: |
| 29 | 29 | ||
| 30 | (defconst file-notify--library | 30 | (defconst file-notify--library |
| 31 | (cond | 31 | (cond |
| 32 | ((featurep 'gfilenotify) 'gfilenotify) | ||
| 33 | ((featurep 'inotify) 'inotify) | 32 | ((featurep 'inotify) 'inotify) |
| 33 | ((featurep 'kqueue) 'kqueue) | ||
| 34 | ((featurep 'gfilenotify) 'gfilenotify) | ||
| 34 | ((featurep 'w32notify) 'w32notify)) | 35 | ((featurep 'w32notify) 'w32notify)) |
| 35 | "Non-nil when Emacs has been compiled with file notification support. | 36 | "Non-nil when Emacs has been compiled with file notification support. |
| 36 | The value is the name of the low-level file notification package | 37 | The value is the name of the low-level file notification package |
| @@ -40,8 +41,8 @@ could use another implementation.") | |||
| 40 | (defvar file-notify-descriptors (make-hash-table :test 'equal) | 41 | (defvar file-notify-descriptors (make-hash-table :test 'equal) |
| 41 | "Hash table for registered file notification descriptors. | 42 | "Hash table for registered file notification descriptors. |
| 42 | A key in this hash table is the descriptor as returned from | 43 | A key in this hash table is the descriptor as returned from |
| 43 | `gfilenotify', `inotify', `w32notify' or a file name handler. | 44 | `inotify', `kqueue', `gfilenotify', `w32notify' or a file name |
| 44 | The value in the hash table is a list | 45 | handler. The value in the hash table is a list |
| 45 | 46 | ||
| 46 | (DIR (FILE . CALLBACK) (FILE . CALLBACK) ...) | 47 | (DIR (FILE . CALLBACK) (FILE . CALLBACK) ...) |
| 47 | 48 | ||
| @@ -76,7 +77,8 @@ WHAT is a file or directory name to be removed, needed just for `inotify'." | |||
| 76 | (remhash desc file-notify-descriptors) | 77 | (remhash desc file-notify-descriptors) |
| 77 | (puthash desc registered file-notify-descriptors)))))) | 78 | (puthash desc registered file-notify-descriptors)))))) |
| 78 | 79 | ||
| 79 | ;; This function is used by `gfilenotify', `inotify' and `w32notify' events. | 80 | ;; This function is used by `inotify', `kqueue', `gfilenotify' and |
| 81 | ;; `w32notify' events. | ||
| 80 | ;;;###autoload | 82 | ;;;###autoload |
| 81 | (defun file-notify-handle-event (event) | 83 | (defun file-notify-handle-event (event) |
| 82 | "Handle file system monitoring event. | 84 | "Handle file system monitoring event. |
| @@ -159,7 +161,7 @@ EVENT is the cadr of the event in `file-notify-handle-event' | |||
| 159 | (setq actions nil)) | 161 | (setq actions nil)) |
| 160 | 162 | ||
| 161 | ;; Loop over actions. In fact, more than one action happens only | 163 | ;; Loop over actions. In fact, more than one action happens only |
| 162 | ;; for `inotify'. | 164 | ;; for `inotify' and `kqueue'. |
| 163 | (dolist (action actions) | 165 | (dolist (action actions) |
| 164 | 166 | ||
| 165 | ;; Send pending event, if it doesn't match. | 167 | ;; Send pending event, if it doesn't match. |
| @@ -184,19 +186,17 @@ EVENT is the cadr of the event in `file-notify-handle-event' | |||
| 184 | ;; Map action. We ignore all events which cannot be mapped. | 186 | ;; Map action. We ignore all events which cannot be mapped. |
| 185 | (setq action | 187 | (setq action |
| 186 | (cond | 188 | (cond |
| 187 | ;; gfilenotify. | 189 | ((memq action |
| 188 | ((memq action '(attribute-changed changed created deleted)) | 190 | '(attribute-changed changed created deleted renamed)) |
| 189 | action) | 191 | action) |
| 190 | ((eq action 'moved) | 192 | ((eq action 'moved) |
| 191 | (setq file1 (file-notify--event-file1-name event)) | 193 | (setq file1 (file-notify--event-file1-name event)) |
| 192 | 'renamed) | 194 | 'renamed) |
| 193 | |||
| 194 | ;; inotify, w32notify. | ||
| 195 | ((eq action 'ignored) | 195 | ((eq action 'ignored) |
| 196 | (setq stopped t actions nil)) | 196 | (setq stopped t actions nil)) |
| 197 | ((eq action 'attrib) 'attribute-changed) | 197 | ((memq action '(attrib link)) 'attribute-changed) |
| 198 | ((memq action '(create added)) 'created) | 198 | ((memq action '(create added)) 'created) |
| 199 | ((memq action '(modify modified)) 'changed) | 199 | ((memq action '(modify modified write)) 'changed) |
| 200 | ((memq action '(delete delete-self move-self removed)) 'deleted) | 200 | ((memq action '(delete delete-self move-self removed)) 'deleted) |
| 201 | ;; Make the event pending. | 201 | ;; Make the event pending. |
| 202 | ((memq action '(moved-from renamed-from)) | 202 | ((memq action '(moved-from renamed-from)) |
| @@ -275,8 +275,8 @@ EVENT is the cadr of the event in `file-notify-handle-event' | |||
| 275 | (file-notify--rm-descriptor | 275 | (file-notify--rm-descriptor |
| 276 | (file-notify--descriptor desc file) file))))) | 276 | (file-notify--descriptor desc file) file))))) |
| 277 | 277 | ||
| 278 | ;; `gfilenotify' and `w32notify' return a unique descriptor for every | 278 | ;; `kqueue', `gfilenotify' and `w32notify' return a unique descriptor |
| 279 | ;; `file-notify-add-watch', while `inotify' returns a unique | 279 | ;; for every `file-notify-add-watch', while `inotify' returns a unique |
| 280 | ;; descriptor per inode only. | 280 | ;; descriptor per inode only. |
| 281 | (defun file-notify-add-watch (file flags callback) | 281 | (defun file-notify-add-watch (file flags callback) |
| 282 | "Add a watch for filesystem events pertaining to FILE. | 282 | "Add a watch for filesystem events pertaining to FILE. |
| @@ -349,8 +349,9 @@ FILE is the name of the file whose event is being reported." | |||
| 349 | ;; Determine low-level function to be called. | 349 | ;; Determine low-level function to be called. |
| 350 | (setq func | 350 | (setq func |
| 351 | (cond | 351 | (cond |
| 352 | ((eq file-notify--library 'gfilenotify) 'gfile-add-watch) | ||
| 353 | ((eq file-notify--library 'inotify) 'inotify-add-watch) | 352 | ((eq file-notify--library 'inotify) 'inotify-add-watch) |
| 353 | ((eq file-notify--library 'kqueue) 'kqueue-add-watch) | ||
| 354 | ((eq file-notify--library 'gfilenotify) 'gfile-add-watch) | ||
| 354 | ((eq file-notify--library 'w32notify) 'w32notify-add-watch))) | 355 | ((eq file-notify--library 'w32notify) 'w32notify-add-watch))) |
| 355 | 356 | ||
| 356 | ;; Determine respective flags. | 357 | ;; Determine respective flags. |
| @@ -362,11 +363,14 @@ FILE is the name of the file whose event is being reported." | |||
| 362 | (cond | 363 | (cond |
| 363 | ((eq file-notify--library 'inotify) | 364 | ((eq file-notify--library 'inotify) |
| 364 | '(create delete delete-self modify move-self move)) | 365 | '(create delete delete-self modify move-self move)) |
| 366 | ((eq file-notify--library 'kqueue) | ||
| 367 | '(delete write extend rename)) | ||
| 365 | ((eq file-notify--library 'w32notify) | 368 | ((eq file-notify--library 'w32notify) |
| 366 | '(file-name directory-name size last-write-time))))) | 369 | '(file-name directory-name size last-write-time))))) |
| 367 | (when (memq 'attribute-change flags) | 370 | (when (memq 'attribute-change flags) |
| 368 | (push (cond | 371 | (push (cond |
| 369 | ((eq file-notify--library 'inotify) 'attrib) | 372 | ((eq file-notify--library 'inotify) 'attrib) |
| 373 | ((eq file-notify--library 'kqueue) 'attrib) | ||
| 370 | ((eq file-notify--library 'w32notify) 'attributes)) | 374 | ((eq file-notify--library 'w32notify) 'attributes)) |
| 371 | l-flags))) | 375 | l-flags))) |
| 372 | 376 | ||
| @@ -410,8 +414,9 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." | |||
| 410 | 414 | ||
| 411 | (funcall | 415 | (funcall |
| 412 | (cond | 416 | (cond |
| 413 | ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) | ||
| 414 | ((eq file-notify--library 'inotify) 'inotify-rm-watch) | 417 | ((eq file-notify--library 'inotify) 'inotify-rm-watch) |
| 418 | ((eq file-notify--library 'kqueue) 'kqueue-rm-watch) | ||
| 419 | ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) | ||
| 415 | ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) | 420 | ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) |
| 416 | desc)) | 421 | desc)) |
| 417 | (file-notify-error nil))) | 422 | (file-notify-error nil))) |
| @@ -441,8 +446,9 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." | |||
| 441 | (funcall handler 'file-notify-valid-p descriptor) | 446 | (funcall handler 'file-notify-valid-p descriptor) |
| 442 | (funcall | 447 | (funcall |
| 443 | (cond | 448 | (cond |
| 444 | ((eq file-notify--library 'gfilenotify) 'gfile-valid-p) | ||
| 445 | ((eq file-notify--library 'inotify) 'inotify-valid-p) | 449 | ((eq file-notify--library 'inotify) 'inotify-valid-p) |
| 450 | ((eq file-notify--library 'kqueue) 'kqueue-valid-p) | ||
| 451 | ((eq file-notify--library 'gfilenotify) 'gfile-valid-p) | ||
| 446 | ((eq file-notify--library 'w32notify) 'w32notify-valid-p)) | 452 | ((eq file-notify--library 'w32notify) 'w32notify-valid-p)) |
| 447 | desc)) | 453 | desc)) |
| 448 | t)))) | 454 | t)))) |
diff --git a/src/keyboard.c b/src/keyboard.c index 851207874db..a6ada2106fb 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -5951,12 +5951,12 @@ make_lispy_event (struct input_event *event) | |||
| 5951 | } | 5951 | } |
| 5952 | #endif /* HAVE_DBUS */ | 5952 | #endif /* HAVE_DBUS */ |
| 5953 | 5953 | ||
| 5954 | #if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY | 5954 | #if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY |
| 5955 | case FILE_NOTIFY_EVENT: | 5955 | case FILE_NOTIFY_EVENT: |
| 5956 | { | 5956 | { |
| 5957 | return Fcons (Qfile_notify, event->arg); | 5957 | return Fcons (Qfile_notify, event->arg); |
| 5958 | } | 5958 | } |
| 5959 | #endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY */ | 5959 | #endif /* HAVE_INOTIFY || HAVE_KQUEUE || HAVE_GFILENOTIFY */ |
| 5960 | 5960 | ||
| 5961 | case CONFIG_CHANGED_EVENT: | 5961 | case CONFIG_CHANGED_EVENT: |
| 5962 | return list3 (Qconfig_changed_event, | 5962 | return list3 (Qconfig_changed_event, |
diff --git a/src/kqueue.c b/src/kqueue.c index 69bf5f61080..a4c3892e9f2 100644 --- a/src/kqueue.c +++ b/src/kqueue.c | |||
| @@ -21,10 +21,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 21 | #ifdef HAVE_KQUEUE | 21 | #ifdef HAVE_KQUEUE |
| 22 | #include <stdio.h> | 22 | #include <stdio.h> |
| 23 | #include <sys/event.h> | 23 | #include <sys/event.h> |
| 24 | #include <sys/file.h> | ||
| 24 | #include "lisp.h" | 25 | #include "lisp.h" |
| 25 | #include "coding.h" | ||
| 26 | #include "termhooks.h" | ||
| 27 | #include "keyboard.h" | 26 | #include "keyboard.h" |
| 27 | #include "process.h" | ||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* File handle for kqueue. */ | 30 | /* File handle for kqueue. */ |
| @@ -33,149 +33,103 @@ static int kqueuefd = -1; | |||
| 33 | /* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */ | 33 | /* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */ |
| 34 | static Lisp_Object watch_list; | 34 | static Lisp_Object watch_list; |
| 35 | 35 | ||
| 36 | #if 0 | 36 | /* This is the callback function for arriving input on kqueuefd. It |
| 37 | /* This is the callback function for arriving signals from | 37 | shall create a Lisp event, and put it into Emacs input queue. */ |
| 38 | g_file_monitor. It shall create a Lisp event, and put it into | 38 | static void |
| 39 | Emacs input queue. */ | 39 | kqueue_callback (int fd, void *data) |
| 40 | static gboolean | ||
| 41 | dir_monitor_callback (GFileMonitor *monitor, | ||
| 42 | GFile *file, | ||
| 43 | GFile *other_file, | ||
| 44 | GFileMonitorEvent event_type, | ||
| 45 | gpointer user_data) | ||
| 46 | { | 40 | { |
| 47 | Lisp_Object symbol, monitor_object, watch_object, flags; | 41 | for (;;) { |
| 48 | char *name = g_file_get_parse_name (file); | 42 | struct kevent kev; |
| 49 | char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; | 43 | struct input_event event; |
| 50 | 44 | Lisp_Object monitor_object, watch_object, name, callback, actions; | |
| 51 | /* Determine event symbol. */ | 45 | |
| 52 | switch (event_type) | 46 | static const struct timespec nullts = { 0, 0 }; |
| 53 | { | 47 | int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL); |
| 54 | case G_FILE_MONITOR_EVENT_CHANGED: | 48 | if (ret < 1) { |
| 55 | symbol = Qchanged; | 49 | /* All events read. */ |
| 56 | break; | 50 | return; |
| 57 | case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: | ||
| 58 | symbol = Qchanges_done_hint; | ||
| 59 | break; | ||
| 60 | case G_FILE_MONITOR_EVENT_DELETED: | ||
| 61 | symbol = Qdeleted; | ||
| 62 | break; | ||
| 63 | case G_FILE_MONITOR_EVENT_CREATED: | ||
| 64 | symbol = Qcreated; | ||
| 65 | break; | ||
| 66 | case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: | ||
| 67 | symbol = Qattribute_changed; | ||
| 68 | break; | ||
| 69 | case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: | ||
| 70 | symbol = Qpre_unmount; | ||
| 71 | break; | ||
| 72 | case G_FILE_MONITOR_EVENT_UNMOUNTED: | ||
| 73 | symbol = Qunmounted; | ||
| 74 | break; | ||
| 75 | case G_FILE_MONITOR_EVENT_MOVED: | ||
| 76 | symbol = Qmoved; | ||
| 77 | break; | ||
| 78 | default: | ||
| 79 | goto cleanup; | ||
| 80 | } | 51 | } |
| 81 | 52 | ||
| 82 | /* Determine callback function. */ | 53 | /* Determine file name and callback function. */ |
| 83 | monitor_object = make_pointer_integer (monitor); | 54 | monitor_object = make_number (kev.ident); |
| 84 | eassert (INTEGERP (monitor_object)); | 55 | watch_object = assq_no_quit (monitor_object, watch_list); |
| 85 | watch_object = assq_no_quit (monitor_object, watch_list); | ||
| 86 | 56 | ||
| 87 | if (CONSP (watch_object)) | 57 | if (CONSP (watch_object)) { |
| 88 | { | 58 | name = XCAR (XCDR (watch_object)); |
| 89 | struct input_event event; | 59 | callback = XCAR (XCDR (XCDR (XCDR (watch_object)))); |
| 90 | Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil; | 60 | } |
| 91 | 61 | else | |
| 92 | /* Check, whether event_type is expected. */ | 62 | continue; |
| 93 | flags = XCAR (XCDR (XCDR (watch_object))); | 63 | |
| 94 | if ((!NILP (Fmember (Qchange, flags)) && | 64 | /* Determine event actions. */ |
| 95 | !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint, | 65 | actions = Qnil; |
| 96 | Qdeleted, Qcreated, Qmoved)))) || | 66 | if (kev.fflags & NOTE_DELETE) |
| 97 | (!NILP (Fmember (Qattribute_change, flags)) && | 67 | actions = Fcons (Qdelete, actions); |
| 98 | ((EQ (symbol, Qattribute_changed))))) | 68 | if (kev.fflags & NOTE_WRITE) |
| 99 | { | 69 | actions = Fcons (Qwrite, actions); |
| 100 | /* Construct an event. */ | 70 | if (kev.fflags & NOTE_EXTEND) |
| 101 | EVENT_INIT (event); | 71 | actions = Fcons (Qextend, actions); |
| 102 | event.kind = FILE_NOTIFY_EVENT; | 72 | if (kev.fflags & NOTE_ATTRIB) |
| 103 | event.frame_or_window = Qnil; | 73 | actions = Fcons (Qattrib, actions); |
| 104 | event.arg = list2 (Fcons (monitor_object, | 74 | if (kev.fflags & NOTE_LINK) |
| 105 | Fcons (symbol, | 75 | actions = Fcons (Qlink, actions); |
| 106 | Fcons (build_string (name), | 76 | if (kev.fflags & NOTE_RENAME) |
| 107 | otail))), | 77 | actions = Fcons (Qrename, actions); |
| 108 | XCAR (XCDR (XCDR (XCDR (watch_object))))); | 78 | |
| 109 | 79 | if (!NILP (actions)) { | |
| 110 | /* Store it into the input event queue. */ | 80 | /* Construct an event. */ |
| 111 | kbd_buffer_store_event (&event); | 81 | EVENT_INIT (event); |
| 112 | // XD_DEBUG_MESSAGE ("%s", XD_OBJECT_TO_STRING (event.arg)); | 82 | event.kind = FILE_NOTIFY_EVENT; |
| 113 | } | 83 | event.frame_or_window = Qnil; |
| 114 | 84 | event.arg = list2 (Fcons (monitor_object, | |
| 115 | /* Cancel monitor if file or directory is deleted. */ | 85 | Fcons (actions, Fcons (name, Qnil))), |
| 116 | if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved))) && | 86 | callback); |
| 117 | (strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0) && | 87 | |
| 118 | !g_file_monitor_is_cancelled (monitor)) | 88 | /* Store it into the input event queue. */ |
| 119 | g_file_monitor_cancel (monitor); | 89 | kbd_buffer_store_event (&event); |
| 120 | } | 90 | } |
| 121 | 91 | ||
| 122 | /* Cleanup. */ | 92 | /* Cancel monitor if file or directory is deleted. */ |
| 123 | cleanup: | 93 | /* TODO: Implement it. */ |
| 124 | g_free (name); | 94 | } |
| 125 | g_free (oname); | 95 | return; |
| 126 | |||
| 127 | return TRUE; | ||
| 128 | } | 96 | } |
| 129 | #endif /* 0 */ | ||
| 130 | 97 | ||
| 131 | DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0, | 98 | DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0, |
| 132 | doc: /* Add a watch for filesystem events pertaining to FILE. | 99 | doc: /* Add a watch for filesystem events pertaining to FILE. |
| 133 | 100 | ||
| 134 | This arranges for filesystem events pertaining to FILE to be reported | 101 | This arranges for filesystem events pertaining to FILE to be reported |
| 135 | to Emacs. Use `gfile-rm-watch' to cancel the watch. | 102 | to Emacs. Use `kqueue-rm-watch' to cancel the watch. |
| 136 | 103 | ||
| 137 | Value is a descriptor for the added watch. If the file cannot be | 104 | Value is a descriptor for the added watch. If the file cannot be |
| 138 | watched for some reason, this function signals a `file-notify-error' error. | 105 | watched for some reason, this function signals a `file-notify-error' error. |
| 139 | 106 | ||
| 140 | FLAGS is a list of conditions to set what will be watched for. It can | 107 | FLAGS is a list of events to be watched for. It can include the |
| 141 | include the following symbols: | 108 | following symbols: |
| 142 | 109 | ||
| 143 | `change' -- watch for file changes | 110 | `delete' -- FILE was deleted |
| 144 | `attribute-change' -- watch for file attributes changes, like | 111 | `write' -- FILE has changed |
| 145 | permissions or modification time | 112 | `extend' -- FILE was extended |
| 146 | `watch-mounts' -- watch for mount events | 113 | `attrib' -- a FILE attribute was changed |
| 147 | `send-moved' -- pair `deleted' and `created' events caused by | 114 | `link' -- a FILE's link count was changed |
| 148 | file renames and send a single `renamed' event | 115 | `rename' -- FILE was moved to FILE1 |
| 149 | instead | ||
| 150 | 116 | ||
| 151 | When any event happens, Emacs will call the CALLBACK function passing | 117 | When any event happens, Emacs will call the CALLBACK function passing |
| 152 | it a single argument EVENT, which is of the form | 118 | it a single argument EVENT, which is of the form |
| 153 | 119 | ||
| 154 | (DESCRIPTOR ACTION FILE [FILE1]) | 120 | (DESCRIPTOR ACTIONS FILE [FILE1]) |
| 155 | 121 | ||
| 156 | DESCRIPTOR is the same object as the one returned by this function. | 122 | DESCRIPTOR is the same object as the one returned by this function. |
| 157 | ACTION is the description of the event. It could be any one of the | 123 | ACTIONS is a list of events. |
| 158 | following: | ||
| 159 | |||
| 160 | `changed' -- FILE has changed | ||
| 161 | `changes-done-hint' -- a hint that this was probably the last change | ||
| 162 | in a set of changes | ||
| 163 | `deleted' -- FILE was deleted | ||
| 164 | `created' -- FILE was created | ||
| 165 | `attribute-changed' -- a FILE attribute was changed | ||
| 166 | `pre-unmount' -- the FILE location will soon be unmounted | ||
| 167 | `unmounted' -- the FILE location was unmounted | ||
| 168 | `moved' -- FILE was moved to FILE1 | ||
| 169 | 124 | ||
| 170 | FILE is the name of the file whose event is being reported. FILE1 | 125 | FILE is the name of the file whose event is being reported. FILE1 |
| 171 | will be reported only in case of the `moved' event. */) | 126 | will be reported only in case of the `rename' event. */) |
| 172 | (Lisp_Object file, Lisp_Object flags, Lisp_Object callback) | 127 | (Lisp_Object file, Lisp_Object flags, Lisp_Object callback) |
| 173 | { | 128 | { |
| 174 | Lisp_Object watch_object; | 129 | Lisp_Object watch_object; |
| 175 | GFile *gfile; | 130 | int fd; |
| 176 | GFileMonitor *monitor; | 131 | u_short fflags = 0; |
| 177 | GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; | 132 | struct kevent ev; |
| 178 | GError *gerror = NULL; | ||
| 179 | 133 | ||
| 180 | /* Check parameters. */ | 134 | /* Check parameters. */ |
| 181 | CHECK_STRING (file); | 135 | CHECK_STRING (file); |
| @@ -183,80 +137,62 @@ will be reported only in case of the `moved' event. */) | |||
| 183 | if (NILP (Ffile_exists_p (file))) | 137 | if (NILP (Ffile_exists_p (file))) |
| 184 | report_file_error ("File does not exist", file); | 138 | report_file_error ("File does not exist", file); |
| 185 | 139 | ||
| 140 | /* TODO: Directories shall be supported as well. */ | ||
| 141 | if (!NILP (Ffile_directory_p (file))) | ||
| 142 | report_file_error ("Directory watching is not supported (yet)", file); | ||
| 143 | |||
| 186 | CHECK_LIST (flags); | 144 | CHECK_LIST (flags); |
| 187 | 145 | ||
| 188 | if (!FUNCTIONP (callback)) | 146 | if (!FUNCTIONP (callback)) |
| 189 | wrong_type_argument (Qinvalid_function, callback); | 147 | wrong_type_argument (Qinvalid_function, callback); |
| 190 | 148 | ||
| 191 | /* Create GFile name. */ | ||
| 192 | // gfile = g_file_new_for_path (SSDATA (ENCODE_FILE (file))); | ||
| 193 | |||
| 194 | /* Assemble flags. */ | ||
| 195 | // if (!NILP (Fmember (Qwatch_mounts, flags))) | ||
| 196 | // gflags |= G_FILE_MONITOR_WATCH_MOUNTS; | ||
| 197 | // if (!NILP (Fmember (Qsend_moved, flags))) | ||
| 198 | // gflags |= G_FILE_MONITOR_SEND_MOVED; | ||
| 199 | |||
| 200 | if (kqueuefd < 0) | 149 | if (kqueuefd < 0) |
| 201 | { | 150 | { |
| 151 | /* Create kqueue descriptor. */ | ||
| 202 | kqueuefd = kqueue (); | 152 | kqueuefd = kqueue (); |
| 203 | if (kqueuefd < 0) | 153 | if (kqueuefd < 0) |
| 204 | report_file_notify_error ("File watching is not available", Qnil); | 154 | report_file_notify_error ("File watching is not available", Qnil); |
| 205 | watch_list = Qnil; | ||
| 206 | // add_read_fd (inotifyfd, &inotify_callback, NULL); | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | } | ||
| 211 | #if 0 | ||
| 212 | 155 | ||
| 213 | mask = aspect_to_inotifymask (aspect); | 156 | /* Start monitoring for possible I/O. */ |
| 214 | encoded_file_name = ENCODE_FILE (file_name); | 157 | add_read_fd (kqueuefd, kqueue_callback, NULL); //data); |
| 215 | watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask); | ||
| 216 | if (watchdesc == -1) | ||
| 217 | report_file_notify_error ("Could not add watch for file", file_name); | ||
| 218 | 158 | ||
| 219 | /* Enable watch. */ | 159 | watch_list = Qnil; |
| 220 | monitor = g_file_monitor (gfile, gflags, NULL, &gerror); | ||
| 221 | g_object_unref (gfile); | ||
| 222 | if (gerror) | ||
| 223 | { | ||
| 224 | char msg[1024]; | ||
| 225 | strcpy (msg, gerror->message); | ||
| 226 | g_error_free (gerror); | ||
| 227 | xsignal1 (Qfile_notify_error, build_string (msg)); | ||
| 228 | } | 160 | } |
| 229 | if (! monitor) | ||
| 230 | xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file); | ||
| 231 | 161 | ||
| 232 | Lisp_Object watch_descriptor = make_pointer_integer (monitor); | 162 | /* Open file. */ |
| 163 | file = ENCODE_FILE (file); | ||
| 164 | fd = emacs_open (SSDATA (file), O_NONBLOCK | O_BINARY | O_RDONLY, 0); | ||
| 165 | if (fd == -1) | ||
| 166 | report_file_error ("File cannot be opened", file); | ||
| 233 | 167 | ||
| 234 | /* Check the dicey assumption that make_pointer_integer is safe. */ | 168 | /* Assemble filter flags */ |
| 235 | if (! INTEGERP (watch_descriptor)) | 169 | if (!NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE; |
| 236 | { | 170 | if (!NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE; |
| 237 | g_object_unref (monitor); | 171 | if (!NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND; |
| 238 | xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"), | 172 | if (!NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB; |
| 239 | file); | 173 | if (!NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK; |
| 240 | } | 174 | if (!NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME; |
| 241 | 175 | ||
| 242 | /* The default rate limit is 800 msec. We adapt this. */ | 176 | /* Register event. */ |
| 243 | g_file_monitor_set_rate_limit (monitor, 100); | 177 | EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, |
| 178 | fflags, 0, NULL); | ||
| 244 | 179 | ||
| 245 | /* Subscribe to the "changed" signal. */ | 180 | if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0) |
| 246 | g_signal_connect (monitor, "changed", | 181 | report_file_error ("Cannot watch file", file); |
| 247 | (GCallback) dir_monitor_callback, NULL); | ||
| 248 | 182 | ||
| 249 | /* Store watch object in watch list. */ | 183 | /* Store watch object in watch list. */ |
| 184 | Lisp_Object watch_descriptor = make_number (fd); | ||
| 250 | watch_object = list4 (watch_descriptor, file, flags, callback); | 185 | watch_object = list4 (watch_descriptor, file, flags, callback); |
| 251 | watch_list = Fcons (watch_object, watch_list); | 186 | watch_list = Fcons (watch_object, watch_list); |
| 252 | 187 | ||
| 253 | return watch_descriptor; | 188 | return watch_descriptor; |
| 254 | } | 189 | } |
| 255 | 190 | ||
| 256 | DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, | 191 | #if 0 |
| 192 | DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0, | ||
| 257 | doc: /* Remove an existing WATCH-DESCRIPTOR. | 193 | doc: /* Remove an existing WATCH-DESCRIPTOR. |
| 258 | 194 | ||
| 259 | WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) | 195 | WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'. */) |
| 260 | (Lisp_Object watch_descriptor) | 196 | (Lisp_Object watch_descriptor) |
| 261 | { | 197 | { |
| 262 | Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); | 198 | Lisp_Object watch_object = assq_no_quit (watch_descriptor, watch_list); |
| @@ -317,12 +253,6 @@ syms_of_kqueue (void) | |||
| 317 | // defsubr (&Skqueue_rm_watch); | 253 | // defsubr (&Skqueue_rm_watch); |
| 318 | // defsubr (&Skqueue_valid_p); | 254 | // defsubr (&Skqueue_valid_p); |
| 319 | 255 | ||
| 320 | /* Filter objects. */ | ||
| 321 | DEFSYM (Qchange, "change"); | ||
| 322 | DEFSYM (Qattribute_change, "attribute-change"); | ||
| 323 | DEFSYM (Qwatch_mounts, "watch-mounts"); /* G_FILE_MONITOR_WATCH_MOUNTS */ | ||
| 324 | DEFSYM (Qsend_moved, "send-moved"); /* G_FILE_MONITOR_SEND_MOVED */ | ||
| 325 | |||
| 326 | /* Event types. */ | 256 | /* Event types. */ |
| 327 | DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */ | 257 | DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */ |
| 328 | DEFSYM (Qwrite, "write"); /* NOTE_WRITE */ | 258 | DEFSYM (Qwrite, "write"); /* NOTE_WRITE */ |