From: "Rüdiger Sonderfeld" <ruediger@c-plusplus.de>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Leo <sdl.web@gmail.com>, emacs-devel@gnu.org
Subject: [PATCH] Added inotify support.
Date: Mon, 01 Oct 2012 16:09:55 +0200 [thread overview]
Message-ID: <2181827.T3JxG88qQt@descartes> (raw)
In-Reply-To: <jwv391yopa9.fsf-monnier+emacs@gnu.org>
On Monday 01 October 2012 00:38:09 Stefan Monnier wrote:
> If there's a good chance this won't work without breaking compatibility,
> maybe a better option is to provide a low-level API that maps very
> closely to inotify and then an Elisp layer on top which abstracts away
> differences between different systems. In that case we can install the
> inotify support right away while we're still experimenting with the
> higher-level abstraction.
That's probably the best approach here. I changed the patch to provide a low
level inotify interface. However I did not provide an inotify_init(2) like
function and instead initialization and closing of the inotify handle is done
internally. I don't think that this should be exposed to elisp even in the
low level interface.
> But if they're unlikely to be important in practice, then
> I guess the current solution might be acceptable.
I think we are safe. I added that `equal' should be used to compare cookies.
So we can easily change it without breaking the API.
> I think the cleaner option is to define a new object type for it.
> It could be either a new Lisp_Misc type, so you can make them print as
> something like "#<file-watcher NNN>" (take a look at "enum
> Lisp_Misc_Type" and "union Lisp_Misc" in src/lisp.h for starters; adding
> a new type will require adding corresponding branches to the switch
> statements in alloc.c and in print.c).
That sounds like the best option. I haven't implemented it yet. Is it
possible to make the Lisp_Misc_Type comparable with `equal'? Because the
watch-descriptor has to be comparable.
Regards,
Rüdiger
-- >8 --
Inotify is a Linux kernel API to monitor file system events. This
patch adds a basic inotify based API to Emacs:
`inotify-add-watch' is based on inotify_add_watch(2). But uses
callbacks and accepts lisp objects instead of a bit mask.
`inotify-rm-watch' is based on inotify_rm_watch(2).
The creation and destruction of an inotify fd with inotify_init1(2) is
handled internally.
Example:
(let ((wd (inotify-add-watch "foo.txt" t
(lambda (ev) (message "FS Event %s" ev)))))
;; ...
(inotify-rm-watch wd))
Signed-off-by: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
---
configure.ac | 13 ++
lisp/subr.el | 21 ++
src/Makefile.in | 2 +-
src/emacs.c | 4 +
src/inotify.c | 431
+++++++++++++++++++++++++++++++++++++++++
src/keyboard.c | 28 +++
src/lisp.h | 5 +
src/termhooks.h | 5 +
test/automated/inotify-test.el | 60 ++++++
9 files changed, 568 insertions(+), 1 deletion(-)
create mode 100644 src/inotify.c
create mode 100644 test/automated/inotify-test.el
diff --git a/configure.ac b/configure.ac
index 5a3aea7..c1ce23f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -184,6 +184,7 @@ OPTION_DEFAULT_ON([gconf],[don't compile with GConf
support])
OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support])
OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support])
OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
+OPTION_DEFAULT_ON([inotify],[don't compile with inotify (file-watch)
support])
## For the times when you want to build Emacs but don't have
## a suitable makeinfo, and can live without the manuals.
@@ -2101,6 +2102,18 @@ fi
AC_SUBST(LIBGNUTLS_LIBS)
AC_SUBST(LIBGNUTLS_CFLAGS)
+dnl inotify is only available on GNU/Linux.
+HAVE_INOTIFY=no
+if test "${with_inotify}" = "yes"; then
+ AC_CHECK_HEADERS(sys/inotify.h)
+ if test "$ac_cv_header_sys_inotify_h" = yes ; then
+ AC_CHECK_FUNCS(inotify_init1 inotify_add_watch inotify_rm_watch,
HAVE_INOTIFY=yes)
+ fi
+fi
+if test "${HAVE_INOTIFY}" = "yes"; then
+ AC_DEFINE(HAVE_INOTIFY, [1], [Define to 1 to use inotify])
+fi
+
dnl Do not put whitespace before the #include statements below.
dnl Older compilers (eg sunos4 cc) choke on it.
HAVE_XAW3D=no
diff --git a/lisp/subr.el b/lisp/subr.el
index 8dfe78d..134a1dc 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4159,6 +4159,27 @@ convenience wrapper around `make-progress-reporter' and
friends.
nil ,@(cdr (cdr spec)))))
\f
+;;;; Support for watching filesystem events.
+
+(defun inotify-event-p (event)
+ "Check if EVENT is an inotify event."
+ (and (listp event)
+ (>= (length event) 3)
+ (eq (car event) 'inotify-event)))
+
+;;;###autoload
+(defun inotify-handle-event (event)
+ "Handle file system monitoring event.
+If EVENT is a filewatch event then the callback is called. If EVENT is
+not a filewatch event then a `filewatch-error' is signaled."
+ (interactive "e")
+
+ (unless (inotify-event-p event)
+ (signal 'inotify-error (cons "Not a valid inotify event" event)))
+
+ (funcall (nth 2 event) (nth 1 event)))
+
+\f
;;;; Comparing version strings.
(defconst version-separator "."
diff --git a/src/Makefile.in b/src/Makefile.in
index f8da009..1492dc6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -339,7 +339,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o
$(XMENU_OBJ) window.o \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
- doprnt.o intervals.o textprop.o composite.o xml.o \
+ doprnt.o intervals.o textprop.o composite.o xml.o inotify.o \
profiler.o \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(WINDOW_SYSTEM_OBJ)
diff --git a/src/emacs.c b/src/emacs.c
index 05affee..e43fa0e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1411,6 +1411,10 @@ Using an Emacs configured with --with-x-toolkit=lucid
does not have this problem
syms_of_gnutls ();
#endif
+#ifdef HAVE_INOTIFY
+ syms_of_inotify ();
+#endif /* HAVE_INOTIFY */
+
#ifdef HAVE_DBUS
syms_of_dbusbind ();
#endif /* HAVE_DBUS */
diff --git a/src/inotify.c b/src/inotify.c
new file mode 100644
index 0000000..49a45cb
--- /dev/null
+++ b/src/inotify.c
@@ -0,0 +1,431 @@
+/* Inotify support for Emacs
+
+Copyright (C) 2012
+ Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#ifdef HAVE_INOTIFY
+
+#include "lisp.h"
+#include "coding.h"
+#include "process.h"
+#include "keyboard.h"
+#include "character.h"
+#include "frame.h" /* Required for termhooks.h. */
+#include "termhooks.h"
+
+static Lisp_Object Qaccess; /* IN_ACCESS */
+static Lisp_Object Qattrib; /* IN_ATTRIB */
+static Lisp_Object Qclose_write; /* IN_CLOSE_WRITE */
+static Lisp_Object Qclose_nowrite; /* IN_CLOSE_NOWRITE */
+static Lisp_Object Qcreate; /* IN_CREATE */
+static Lisp_Object Qdelete; /* IN_DELETE */
+static Lisp_Object Qdelete_self; /* IN_DELETE_SELF */
+static Lisp_Object Qmodify; /* IN_MODIFY */
+static Lisp_Object Qmove_self; /* IN_MOVE_SELF */
+static Lisp_Object Qmoved_from; /* IN_MOVED_FROM */
+static Lisp_Object Qmoved_to; /* IN_MOVED_TO */
+static Lisp_Object Qopen; /* IN_OPEN */
+
+static Lisp_Object Qall_events; /* IN_ALL_EVENTS */
+static Lisp_Object Qmove; /* IN_MOVE */
+static Lisp_Object Qclose; /* IN_CLOSE */
+
+static Lisp_Object Qdont_follow; /* IN_DONT_FOLLOW */
+static Lisp_Object Qexcl_unlink; /* IN_EXCL_UNLINK */
+static Lisp_Object Qmask_add; /* IN_MASK_ADD */
+static Lisp_Object Qoneshot; /* IN_ONESHOT */
+static Lisp_Object Qonlydir; /* IN_ONLYDIR */
+
+static Lisp_Object Qignored; /* IN_IGNORED */
+static Lisp_Object Qisdir; /* IN_ISDIR */
+static Lisp_Object Qq_overflow; /* IN_Q_OVERFLOW */
+static Lisp_Object Qunmount; /* IN_UNMOUNT */
+
+static Lisp_Object Qinotify_event;
+
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+
+enum { uninitialized = -100 };
+/* File handle for inotify. */
+static int inotifyfd = uninitialized;
+
+/* Assoc list of files being watched.
+ Format:
+ (watch-descriptor . callback)
+ */
+static Lisp_Object watch_list;
+
+static Lisp_Object
+make_watch_descriptor (int wd)
+{
+ /* TODO replace this with a Misc Object! */
+ return make_number (wd);
+}
+
+static Lisp_Object
+mask_to_aspects (uint32_t mask) {
+ Lisp_Object aspects = Qnil;
+ if (mask & IN_ACCESS)
+ aspects = Fcons (Qaccess, aspects);
+ if (mask & IN_ATTRIB)
+ aspects = Fcons (Qattrib, aspects);
+ if (mask & IN_CLOSE_WRITE)
+ aspects = Fcons (Qclose_write, aspects);
+ if (mask & IN_CLOSE_NOWRITE)
+ aspects = Fcons (Qclose_nowrite, aspects);
+ if (mask & IN_CREATE)
+ aspects = Fcons (Qcreate, aspects);
+ if (mask & IN_DELETE)
+ aspects = Fcons (Qdelete, aspects);
+ if (mask & IN_DELETE_SELF)
+ aspects = Fcons (Qdelete_self, aspects);
+ if (mask & IN_MODIFY)
+ aspects = Fcons (Qmodify, aspects);
+ if (mask & IN_MOVE_SELF)
+ aspects = Fcons (Qmove_self, aspects);
+ if (mask & IN_MOVED_FROM)
+ aspects = Fcons (Qmoved_from, aspects);
+ if (mask & IN_MOVED_TO)
+ aspects = Fcons (Qmoved_to, aspects);
+ if (mask & IN_OPEN)
+ aspects = Fcons (Qopen, aspects);
+ if (mask & IN_IGNORED)
+ aspects = Fcons (Qignored, aspects);
+ if (mask & IN_ISDIR)
+ aspects = Fcons (Qisdir, aspects);
+ if (mask & IN_Q_OVERFLOW)
+ aspects = Fcons (Qq_overflow, aspects);
+ if (mask & IN_UNMOUNT)
+ aspects = Fcons (Qunmount, aspects);
+ return aspects;
+}
+
+static Lisp_Object
+inotifyevent_to_event (Lisp_Object watch_object, struct inotify_event const
*ev)
+{
+ Lisp_Object name = Qnil;
+ if (ev->len > 0)
+ {
+ size_t const len = strlen (ev->name);
+ name = make_unibyte_string (ev->name, min (len, ev->len));
+ name = DECODE_FILE (name);
+ }
+
+ return list2 (list4 (make_watch_descriptor (ev->wd),
+ mask_to_aspects (ev->mask),
+ make_number (ev->cookie),
+ name),
+ XCDR (watch_object));
+}
+
+/* This callback is called when the FD is available for read. The inotify
+ events are read from FD and converted into input_events. */
+static void
+inotify_callback (int fd, void *_)
+{
+ struct input_event event;
+ Lisp_Object watch_object;
+ int to_read;
+ char *buffer;
+ ssize_t n;
+ size_t i;
+
+ to_read = 0;
+ if (ioctl (fd, FIONREAD, &to_read) == -1)
+ report_file_error ("Error while trying to retrieve file system events",
+ Qnil);
+ buffer = xmalloc (to_read);
+ n = read (fd, buffer, to_read);
+ if (n < 0)
+ {
+ xfree (buffer);
+ report_file_error ("Error while trying to read file system events",
+ Qnil);
+ }
+
+ EVENT_INIT (event);
+ event.kind = INOTIFY_EVENT;
+ event.arg = Qnil;
+
+ i = 0;
+ while (i < (size_t)n)
+ {
+ struct inotify_event *ev = (struct inotify_event*)&buffer[i];
+
+ watch_object = Fassoc (make_watch_descriptor (ev->wd), watch_list);
+ if (!NILP (watch_object))
+ {
+ event.arg = inotifyevent_to_event (watch_object, ev);
+
+ /* If event was removed automatically: Drop it from watch list. */
+ if (ev->mask & IN_IGNORED)
+ watch_list = Fdelete (watch_object, watch_list);
+ }
+
+ i += sizeof (*ev) + ev->len;
+ }
+
+ if (!NILP (event.arg))
+ kbd_buffer_store_event (&event);
+
+ xfree (buffer);
+}
+
+static uint32_t
+symbol_to_inotifymask (Lisp_Object symb)
+{
+ if (EQ (symb, Qaccess))
+ return IN_ACCESS;
+ else if (EQ (symb, Qattrib))
+ return IN_ATTRIB;
+ else if (EQ (symb, Qclose_write))
+ return IN_CLOSE_WRITE;
+ else if (EQ (symb, Qclose_nowrite))
+ return IN_CLOSE_NOWRITE;
+ else if (EQ (symb, Qcreate))
+ return IN_CREATE;
+ else if (EQ (symb, Qdelete))
+ return IN_DELETE;
+ else if (EQ (symb, Qdelete_self))
+ return IN_DELETE_SELF;
+ else if (EQ (symb, Qmodify))
+ return IN_MODIFY;
+ else if (EQ (symb, Qmove_self))
+ return IN_MOVE_SELF;
+ else if (EQ (symb, Qmoved_from))
+ return IN_MOVED_FROM;
+ else if (EQ (symb, Qmoved_to))
+ return IN_MOVED_TO;
+ else if (EQ (symb, Qopen))
+ return IN_OPEN;
+ else if (EQ (symb, Qmove))
+ return IN_MOVE;
+ else if (EQ (symb, Qclose))
+ return IN_CLOSE;
+
+ else if (EQ (symb, Qdont_follow))
+ return IN_DONT_FOLLOW;
+ else if (EQ (symb, Qexcl_unlink))
+ return IN_EXCL_UNLINK;
+ else if (EQ (symb, Qmask_add))
+ return IN_MASK_ADD;
+ else if (EQ (symb, Qoneshot))
+ return IN_ONESHOT;
+ else if (EQ (symb, Qonlydir))
+ return IN_ONLYDIR;
+
+ else if (EQ (symb, Qt) || EQ (symb, Qall_events))
+ return IN_ALL_EVENTS;
+ else
+ signal_error ("Unknown aspect", symb);
+}
+
+static uint32_t
+aspect_to_inotifymask (Lisp_Object aspect)
+{
+ if (CONSP (aspect))
+ {
+ Lisp_Object x = aspect;
+ uint32_t mask = 0;
+ while (CONSP (x))
+ {
+ mask |= symbol_to_inotifymask (XCAR (x));
+ x = XCDR (x);
+ }
+ return mask;
+ }
+ else
+ return symbol_to_inotifymask (aspect);
+}
+
+DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0,
+ doc: /* Add a watch for FILE-NAME to inotify.
+
+A WATCH-DESCRIPTOR is returned on success. ASPECT might be one of the
following
+symbols or a list of those symbols:
+
+access
+attrib
+close-write
+close-nowrite
+create
+delete
+delete-self
+modify
+move-self
+moved-from
+moved-to
+open
+
+all-events or t
+move
+close
+
+The following symbols can also be added to a list of aspects
+
+dont-follow
+excl-unlink
+mask-add
+oneshot
+onlydir
+
+Watching a directory is not recursive. CALLBACK gets called in case of an
+event. It gets passed a single argument EVENT which contains an event
structure
+of the format
+
+(WATCH-DESCRIPTOR ASPECTS COOKIE NAME)
+
+WATCH-DESCRIPTOR is the same object that was returned by this function. It
can
+be tested for equality using `equal'. ASPECTS describes the event. It is a
+list of ASPECT symbols described above and can also contain one of the
following
+symbols
+
+ignored
+isdir
+q-overflow
+unmount
+
+COOKIE is an object that can be compared using `equal' to identify two
matching
+renames (moved-from and moved-to).
+
+If a directory is watched then NAME is the name of file that caused the
event.
+
+See inotify(7) and inotify_add_watch(2) for further information. The inotify
fd
+is managed internally and there is no corresponding inotify_init. Use
+`inotify-rm-watch' to remove a watch.
+ */)
+ (Lisp_Object file_name, Lisp_Object aspect, Lisp_Object callback)
+{
+ uint32_t mask;
+ Lisp_Object watch_object;
+ Lisp_Object decoded_file_name;
+ Lisp_Object watch_descriptor;
+ int watchdesc = -1;
+
+ CHECK_STRING (file_name);
+
+ if (inotifyfd == uninitialized)
+ {
+ inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC);
+ if (inotifyfd == -1)
+ {
+ inotifyfd = uninitialized;
+ report_file_error ("File watching feature (inotify) is not
available",
+ Qnil);
+ }
+ watch_list = Qnil;
+ add_read_fd (inotifyfd, &inotify_callback, NULL);
+ }
+
+ mask = aspect_to_inotifymask (aspect);
+ decoded_file_name = ENCODE_FILE (file_name);
+ watchdesc = inotify_add_watch (inotifyfd, SSDATA (decoded_file_name),
mask);
+ if (watchdesc == -1)
+ report_file_error ("Could not add watch for file", Fcons (file_name,
Qnil));
+
+ watch_descriptor = make_watch_descriptor (watchdesc);
+
+ /* Delete existing watch object. */
+ watch_object = Fassoc (watch_descriptor, watch_list);
+ if (!NILP (watch_object))
+ watch_list = Fdelete (watch_object, watch_list);
+
+ /* Store watch object in watch list. */
+ watch_object = Fcons (watch_descriptor, callback);
+ watch_list = Fcons (watch_object, watch_list);
+
+ return watch_descriptor;
+}
+
+DEFUN ("inotify-rm-watch", Finotify_rm_watch, Sinotify_rm_watch, 1, 1, 0,
+ doc: /* Remove an existing WATCH-DESCRIPTOR.
+
+WATCH-DESCRIPTOR should be an object returned by `inotify-add-watch'.
+
+See inotify_rm_watch(2) for more information.
+ */)
+ (Lisp_Object watch_descriptor)
+{
+ Lisp_Object watch_object;
+ int wd = XINT (watch_descriptor);
+
+ if (inotify_rm_watch (inotifyfd, wd) == -1)
+ report_file_error ("Could not rm watch", Fcons (watch_descriptor,
+ Qnil));
+
+ /* Remove watch descriptor from watch list. */
+ watch_object = Fassoc (watch_descriptor, watch_list);
+ if (!NILP (watch_object))
+ watch_list = Fdelete (watch_object, watch_list);
+
+ /* Cleanup if no more files are watched. */
+ if (NILP (watch_list))
+ {
+ close (inotifyfd);
+ delete_read_fd (inotifyfd);
+ inotifyfd = uninitialized;
+ }
+
+ return Qt;
+}
+
+void
+syms_of_inotify (void)
+{
+ DEFSYM (Qaccess, "access");
+ DEFSYM (Qattrib, "attrib");
+ DEFSYM (Qclose_write, "close-write");
+ DEFSYM (Qclose_nowrite, "close-nowrite");
+ DEFSYM (Qcreate, "create");
+ DEFSYM (Qdelete, "delete");
+ DEFSYM (Qdelete_self, "delete-self");
+ DEFSYM (Qmodify, "modify");
+ DEFSYM (Qmove_self, "move-self");
+ DEFSYM (Qmoved_from, "moved-from");
+ DEFSYM (Qmoved_to, "moved-to");
+ DEFSYM (Qopen, "open");
+
+ DEFSYM (Qall_events, "all-events");
+ DEFSYM (Qmove, "move");
+ DEFSYM (Qclose, "close");
+
+ DEFSYM (Qdont_follow, "dont-follow");
+ DEFSYM (Qexcl_unlink, "excl-unlink");
+ DEFSYM (Qmask_add, "mask-add");
+ DEFSYM (Qoneshot, "oneshot");
+ DEFSYM (Qonlydir, "onlydir");
+
+ DEFSYM (Qignored, "ignored");
+ DEFSYM (Qisdir, "isdir");
+ DEFSYM (Qq_overflow, "q-overflow");
+ DEFSYM (Qunmount, "unmount");
+
+ DEFSYM (Qinotify_event, "inotify-event");
+
+ defsubr (&Sinotify_add_watch);
+ defsubr (&Sinotify_rm_watch);
+
+ staticpro (&watch_list);
+
+ Fprovide (intern_c_string ("inotify"), Qnil);
+}
+
+#endif /* HAVE_INOTIFY */
diff --git a/src/keyboard.c b/src/keyboard.c
index f3d7df5..02e1473 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -321,6 +321,9 @@ static Lisp_Object Qsave_session;
#ifdef HAVE_DBUS
static Lisp_Object Qdbus_event;
#endif
+#ifdef HAVE_INOTIFY
+static Lisp_Object Qinotify_event;
+#endif /* HAVE_INOTIFY */
static Lisp_Object Qconfig_changed_event;
/* Lisp_Object Qmouse_movement; - also an event header */
@@ -4021,6 +4024,13 @@ kbd_buffer_get_event (KBOARD **kbp,
kbd_fetch_ptr = event + 1;
}
#endif
+#ifdef HAVE_INOTIFY
+ else if (event->kind == INOTIFY_EVENT)
+ {
+ obj = make_lispy_event (event);
+ kbd_fetch_ptr = event + 1;
+ }
+#endif
else if (event->kind == CONFIG_CHANGED_EVENT)
{
obj = make_lispy_event (event);
@@ -5938,6 +5948,13 @@ make_lispy_event (struct input_event *event)
}
#endif /* HAVE_DBUS */
+#ifdef HAVE_INOTIFY
+ case INOTIFY_EVENT:
+ {
+ return Fcons (Qinotify_event, event->arg);
+ }
+#endif /* HAVE_INOTIFY */
+
case CONFIG_CHANGED_EVENT:
return Fcons (Qconfig_changed_event,
Fcons (event->arg,
@@ -11408,6 +11425,10 @@ syms_of_keyboard (void)
DEFSYM (Qdbus_event, "dbus-event");
#endif
+#ifdef HAVE_INOTIFY
+ DEFSYM (Qinotify_event, "inotify-event");
+#endif /* HAVE_INOTIFY */
+
DEFSYM (QCenable, ":enable");
DEFSYM (QCvisible, ":visible");
DEFSYM (QChelp, ":help");
@@ -12168,6 +12189,13 @@ keys_of_keyboard (void)
"dbus-handle-event");
#endif
+#ifdef HAVE_INOTIFY
+ /* Define a special event which is raised for inotify callback
+ functions. */
+ initial_define_lispy_key (Vspecial_event_map, "inotify-event",
+ "inotify-handle-event");
+#endif /* HAVE_INOTIFY */
+
initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
"ignore");
#if defined (WINDOWSNT)
diff --git a/src/lisp.h b/src/lisp.h
index c3cabe0..02bfa08 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3497,6 +3497,11 @@ extern void syms_of_fontset (void);
extern Lisp_Object Qfont_param;
#endif
+/* Defined in inotify.c */
+#ifdef HAVE_INOTIFY
+extern void syms_of_inotify (void);
+#endif
+
/* Defined in xfaces.c. */
extern Lisp_Object Qdefault, Qtool_bar, Qfringe;
extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
diff --git a/src/termhooks.h b/src/termhooks.h
index f35bd92..5890d10 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -211,6 +211,11 @@ enum event_kind
, NS_NONKEY_EVENT
#endif
+#ifdef HAVE_INOTIFY
+ /* File or directory was changed. */
+ , INOTIFY_EVENT
+#endif
+
};
/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT
diff --git a/test/automated/inotify-test.el b/test/automated/inotify-test.el
new file mode 100644
index 0000000..edda7ef
--- /dev/null
+++ b/test/automated/inotify-test.el
@@ -0,0 +1,60 @@
+;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 Free Software Foundation, Inc.
+
+;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+;; Keywords: internal
+;; Human-Keywords: internal
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+
+(when (featurep 'inotify)
+
+ ;; (ert-deftest filewatch-file-watch-aspects-check ()
+ ;; "Test whether `file-watch' properly checks the aspects."
+ ;; (let ((temp-file (make-temp-file "filewatch-aspects")))
+ ;; (should (stringp temp-file))
+ ;; (should-error (file-watch temp-file 'wrong nil)
+ ;; :type 'error)
+ ;; (should-error (file-watch temp-file '(modify t) nil)
+ ;; :type 'error)
+ ;; (should-error (file-watch temp-file '(modify all-modify) nil)
+ ;; :type 'error)
+ ;; (should-error (file-watch temp-file '(access wrong modify) nil)
+ ;; :type 'error)))
+
+ (ert-deftest inotify-file-watch-simple ()
+ "Test if watching a normal file works."
+ (let ((temp-file (make-temp-file "inotify-simple"))
+ (events 0))
+ (let ((wd
+ (inotify-add-watch temp-file t (lambda (ev)
+ (setq events (1+ events))))))
+ (unwind-protect
+ (progn
+ (with-temp-file temp-file
+ (insert "Foo\n"))
+ (sit-for 5) ;; Hacky. Wait for 5s until events are processed
+ (should (> events 0)))
+ (inotify-rm-watch wd)))))
+)
+
+(provide 'inotify-tests)
+;;; inotify-tests.el ends here.
--
1.7.11.3
next prev parent reply other threads:[~2012-10-01 14:09 UTC|newest]
Thread overview: 148+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-03 22:34 [PATCH] Support for filesystem watching (inotify) Rüdiger Sonderfeld
2011-06-04 8:52 ` joakim
2011-06-04 16:40 ` Rüdiger Sonderfeld
2011-06-04 10:43 ` Jan Djärv
2011-06-04 23:36 ` [PATCH update2] " Rüdiger Sonderfeld
2011-06-05 5:45 ` Eli Zaretskii
2011-06-05 9:48 ` [PATCH update3] " Rüdiger Sonderfeld
2011-06-05 7:48 ` [PATCH update2] " Jan Djärv
2011-06-05 7:54 ` Andreas Schwab
2011-06-05 9:49 ` Rüdiger Sonderfeld
2011-06-05 15:59 ` John Yates
2011-06-05 16:14 ` Rüdiger Sonderfeld
2011-06-05 16:58 ` Eli Zaretskii
2011-06-06 18:56 ` Rüdiger Sonderfeld
2011-06-06 19:57 ` Eli Zaretskii
2011-06-04 11:30 ` [PATCH] " Eli Zaretskii
2011-06-04 17:13 ` [PATCH updated] " Rüdiger Sonderfeld
2011-06-04 19:15 ` Eli Zaretskii
2011-06-04 20:10 ` Thien-Thi Nguyen
2011-06-04 23:43 ` Rüdiger Sonderfeld
2011-06-05 2:15 ` Thien-Thi Nguyen
2011-06-05 9:22 ` Štěpán Němec
2011-06-15 20:53 ` Johan Bockgård
2011-06-16 8:52 ` Inlined cl functions -- how to learn about them Štěpán Němec
2011-06-06 15:21 ` [PATCH updated] Support for filesystem watching (inotify) Stefan Monnier
2011-06-06 16:25 ` Rüdiger Sonderfeld
2011-06-06 17:11 ` Stefan Monnier
2011-06-06 20:16 ` Ted Zlatanov
2011-06-07 14:42 ` Stefan Monnier
2011-06-07 16:46 ` Ted Zlatanov
2011-06-07 18:06 ` Stefan Monnier
2011-06-07 18:26 ` Ted Zlatanov
2011-06-24 0:50 ` Rüdiger Sonderfeld
2011-06-24 10:19 ` Ted Zlatanov
2011-06-24 12:18 ` Ted Zlatanov
2011-07-06 13:36 ` Stefan Monnier
2011-07-06 15:54 ` Paul Eggert
2011-07-06 18:30 ` Stefan Monnier
2011-07-06 20:39 ` Paul Eggert
2011-07-06 19:14 ` wide-int crash [was Re: [PATCH updated] Support for filesystem watching (inotify)] Glenn Morris
2011-07-06 22:31 ` bug#8884: " Paul Eggert
2011-07-06 22:31 ` Paul Eggert
2011-10-07 7:30 ` bug#8884: wide-int crash Glenn Morris
2011-06-17 17:50 ` bug#8884: 24.0.50; temacs crashes and dumps core when configured --with-wide-int Peter Dyballa
2011-06-17 20:07 ` Peter Dyballa
[not found] ` <handler.8884.D8884.131797266119606.notifdone@debbugs.gnu.org>
2011-10-08 13:35 ` bug#8884: closed (Re: bug#8884: wide-int crash) Peter Dyballa
2011-10-17 22:24 ` Peter Dyballa
2011-10-18 5:42 ` Paul Eggert
2011-10-18 9:14 ` Peter Dyballa
2011-10-18 10:55 ` Eli Zaretskii
2011-10-18 13:33 ` Stefan Monnier
2011-10-18 15:38 ` Paul Eggert
2011-10-18 15:45 ` Andreas Schwab
2011-10-18 15:57 ` Paul Eggert
2011-10-18 21:41 ` Peter Dyballa
2011-10-19 1:47 ` Paul Eggert
2011-10-19 22:46 ` Peter Dyballa
2011-10-19 3:43 ` Stefan Monnier
2011-10-19 13:59 ` Peter Dyballa
2011-10-19 14:44 ` Stefan Monnier
2011-10-19 14:59 ` Peter Dyballa
2011-10-19 18:00 ` Stefan Monnier
2011-10-19 21:59 ` Peter Dyballa
2011-10-20 0:32 ` Stefan Monnier
2011-07-07 19:43 ` [PATCH updated] Support for filesystem watching (inotify) Stefan Monnier
2012-09-28 13:06 ` [PATCH] Added basic file system watching support Rüdiger Sonderfeld
2012-09-28 14:13 ` Stefan Monnier
2012-09-28 16:27 ` Rüdiger Sonderfeld
2012-10-01 4:38 ` Stefan Monnier
2012-10-01 7:24 ` Eli Zaretskii
2012-10-01 14:09 ` Rüdiger Sonderfeld [this message]
2012-10-01 16:27 ` [PATCH] Added inotify support Stefan Monnier
2012-10-02 21:28 ` Eli Zaretskii
2012-10-02 23:46 ` Óscar Fuentes
2012-10-03 2:10 ` Stefan Monnier
2012-10-03 3:54 ` Eli Zaretskii
2012-10-03 12:46 ` Stefan Monnier
2012-10-03 18:34 ` Eli Zaretskii
2012-10-03 18:47 ` Stefan Monnier
2012-10-03 19:08 ` Eli Zaretskii
2012-10-03 20:59 ` Stefan Monnier
2012-10-12 13:54 ` Eli Zaretskii
2012-10-14 14:55 ` Eli Zaretskii
2012-10-03 19:33 ` Óscar Fuentes
2012-10-05 7:40 ` Eli Zaretskii
2012-10-05 13:07 ` Óscar Fuentes
2012-10-05 15:19 ` Eli Zaretskii
2012-10-05 16:55 ` Nix
2012-10-05 17:15 ` Eli Zaretskii
2012-10-05 17:46 ` Nix
2012-10-05 18:22 ` Stefan Monnier
2012-10-05 18:30 ` Óscar Fuentes
2012-10-06 16:39 ` Nix
2012-10-06 17:01 ` Stefan Monnier
2012-10-06 18:51 ` Nix
2012-10-06 21:26 ` Stefan Monnier
2012-10-06 21:28 ` Nix
2012-10-07 7:38 ` Achim Gratz
2012-10-07 13:58 ` Stefan Monnier
2012-10-07 14:54 ` Achim Gratz
2012-10-07 8:24 ` Stephen J. Turnbull
2012-10-07 14:00 ` Stefan Monnier
2012-10-07 14:28 ` Óscar Fuentes
2012-10-07 14:38 ` Stefan Monnier
2012-10-08 7:07 ` Stephen J. Turnbull
2012-10-08 8:06 ` Eli Zaretskii
2012-10-14 15:52 ` Jim Meyering
2012-10-06 7:04 ` Stephen J. Turnbull
2012-10-06 7:23 ` Andreas Schwab
2012-10-06 16:41 ` Nix
2012-10-07 8:09 ` Stephen J. Turnbull
2012-10-07 14:08 ` Stefan Monnier
2012-10-03 3:57 ` Eli Zaretskii
2012-12-02 20:08 ` Eli Zaretskii
2012-12-03 17:18 ` Stefan Monnier
2012-12-10 14:16 ` Eli Zaretskii
2012-12-10 14:47 ` Stefan Monnier
2012-12-10 11:52 ` Eli Zaretskii
2012-12-10 12:11 ` Rüdiger Sonderfeld
2012-12-11 7:43 ` Michael Albinus
2012-12-11 8:20 ` Eli Zaretskii
2012-12-11 16:36 ` Michael Albinus
2012-12-11 16:46 ` Rüdiger Sonderfeld
2012-12-11 20:17 ` Michael Albinus
2012-12-11 7:54 ` [PATCH] Added basic file system watching support Michael Albinus
2012-12-11 8:12 ` Eli Zaretskii
2012-12-11 8:19 ` Michael Albinus
2012-12-11 8:29 ` Eli Zaretskii
2012-12-11 8:44 ` Michael Albinus
2012-12-11 9:39 ` Eli Zaretskii
2012-12-11 10:15 ` Eli Zaretskii
2012-12-11 10:38 ` Michael Albinus
2012-12-11 10:24 ` Michael Albinus
2012-12-11 12:51 ` Eli Zaretskii
2012-12-11 13:17 ` Michael Albinus
2012-12-11 13:23 ` Eli Zaretskii
2012-12-12 1:09 ` Leo
2012-12-12 3:57 ` Eli Zaretskii
2013-01-07 11:33 ` Michael Albinus
2013-01-07 15:57 ` Eli Zaretskii
2013-01-07 16:00 ` Michael Albinus
2013-01-07 20:26 ` Stefan Monnier
2013-01-08 7:44 ` Michael Albinus
2011-06-06 15:14 ` [PATCH updated] Support for filesystem watching (inotify) Stefan Monnier
2011-06-06 16:21 ` Rüdiger Sonderfeld
2012-09-18 11:50 ` [PATCH] " Leo
2012-09-26 12:15 ` Rüdiger Sonderfeld
2012-09-26 17:52 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2181827.T3JxG88qQt@descartes \
--to=ruediger@c-plusplus.de \
--cc=emacs-devel@gnu.org \
--cc=monnier@iro.umontreal.ca \
--cc=sdl.web@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.