X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/86dfb7a8155ba4705f6bdc8e9be3a38388ad207e..8afaa1321f8088bfb877fe4b6676e8517adb0bb7:/src/inotify.c diff --git a/src/inotify.c b/src/inotify.c index 01fb34a5c4..d1a80bbad1 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -1,6 +1,6 @@ /* Inotify support for Emacs -Copyright (C) 2012-2013 Free Software Foundation, Inc. +Copyright (C) 2012-2015 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -25,38 +25,9 @@ along with GNU Emacs. If not, see . */ #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 */ - +#include #include #include @@ -71,9 +42,8 @@ static Lisp_Object Qunmount; /* IN_UNMOUNT */ # define IN_ONLYDIR 0 #endif -enum { uninitialized = -100 }; /* File handle for inotify. */ -static int inotifyfd = uninitialized; +static int inotifyfd = -1; /* Assoc list of files being watched. Format: @@ -158,17 +128,14 @@ inotify_callback (int fd, void *_) to_read = 0; if (ioctl (fd, FIONREAD, &to_read) == -1) - xsignal1 - (Qfile_notify_error, - build_string ("Error while trying to retrieve file system events")); + report_file_notify_error ("Error while retrieving file system events", + Qnil); buffer = xmalloc (to_read); n = read (fd, buffer, to_read); if (n < 0) { xfree (buffer); - xsignal1 - (Qfile_notify_error, - build_string ("Error while trying to read file system events")); + report_file_notify_error ("Error while reading file system events", Qnil); } EVENT_INIT (event); @@ -244,7 +211,10 @@ symbol_to_inotifymask (Lisp_Object symb) else if (EQ (symb, Qt) || EQ (symb, Qall_events)) return IN_ALL_EVENTS; else - xsignal2 (Qfile_notify_error, build_string ("Unknown aspect"), symb); + { + errno = EINVAL; + report_file_notify_error ("Unknown aspect", symb); + } } static uint32_t @@ -268,8 +238,10 @@ aspect_to_inotifymask (Lisp_Object 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: +Return a watch descriptor. The watch will look for ASPECT events and +invoke CALLBACK when an event occurs. + +ASPECT might be one of the following symbols or a list of those symbols: access attrib @@ -288,7 +260,7 @@ all-events or t move close -The following symbols can also be added to a list of aspects +The following symbols can also be added to a list of aspects: dont-follow excl-unlink @@ -296,9 +268,8 @@ 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 +Watching a directory is not recursive. CALLBACK is passed a single argument +EVENT which contains an event structure of the format (WATCH-DESCRIPTOR ASPECTS NAME COOKIE) @@ -331,16 +302,11 @@ is managed internally and there is no corresponding inotify_init. Use CHECK_STRING (file_name); - if (inotifyfd == uninitialized) + if (inotifyfd < 0) { inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC); - if (inotifyfd == -1) - { - inotifyfd = uninitialized; - xsignal1 - (Qfile_notify_error, - build_string ("File watching feature (inotify) is not available")); - } + if (inotifyfd < 0) + report_file_notify_error ("File watching is not available", Qnil); watch_list = Qnil; add_read_fd (inotifyfd, &inotify_callback, NULL); } @@ -349,17 +315,16 @@ is managed internally and there is no corresponding inotify_init. Use encoded_file_name = ENCODE_FILE (file_name); watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask); if (watchdesc == -1) - xsignal2 (Qfile_notify_error, - build_string ("Could not add watch for file"), file_name); + report_file_notify_error ("Could not add watch for file", file_name); watch_descriptor = make_watch_descriptor (watchdesc); - /* Delete existing watch object. */ + /* 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. */ + /* Store watch object in watch list. */ watch_object = Fcons (watch_descriptor, callback); watch_list = Fcons (watch_object, watch_list); @@ -379,58 +344,74 @@ See inotify_rm_watch(2) for more information. int wd = XINT (watch_descriptor); if (inotify_rm_watch (inotifyfd, wd) == -1) - xsignal2 (Qfile_notify_error, - build_string ("Could not rm watch"), watch_descriptor); + report_file_notify_error ("Could not rm watch", watch_descriptor); - /* Remove watch descriptor from watch list. */ + /* 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. */ + /* Cleanup if no more files are watched. */ if (NILP (watch_list)) { - close (inotifyfd); + emacs_close (inotifyfd); delete_read_fd (inotifyfd); - inotifyfd = uninitialized; + inotifyfd = -1; } return Qt; } +DEFUN ("inotify-valid-p", Finotify_valid_p, Sinotify_valid_p, 1, 1, 0, + doc: /* "Check a watch specified by its WATCH-DESCRIPTOR. + +WATCH-DESCRIPTOR should be an object returned by `inotify-add-watch'. + +A watch can become invalid if the file or directory it watches is +deleted, or if the watcher thread exits abnormally for any other +reason. Removing the watch by calling `inotify-rm-watch' also makes +it invalid. */) + (Lisp_Object watch_descriptor) +{ + Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list); + return NILP (watch_object) ? Qnil : Qt; +} + void syms_of_inotify (void) { - DEFSYM (Qaccess, "access"); - DEFSYM (Qattrib, "attrib"); - DEFSYM (Qclose_write, "close-write"); + DEFSYM (Qaccess, "access"); /* IN_ACCESS */ + DEFSYM (Qattrib, "attrib"); /* IN_ATTRIB */ + DEFSYM (Qclose_write, "close-write"); /* IN_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"); + /* IN_CLOSE_NOWRITE */ + DEFSYM (Qcreate, "create"); /* IN_CREATE */ + DEFSYM (Qdelete, "delete"); /* IN_DELETE */ + DEFSYM (Qdelete_self, "delete-self"); /* IN_DELETE_SELF */ + DEFSYM (Qmodify, "modify"); /* IN_MODIFY */ + DEFSYM (Qmove_self, "move-self"); /* IN_MOVE_SELF */ + DEFSYM (Qmoved_from, "moved-from"); /* IN_MOVED_FROM */ + DEFSYM (Qmoved_to, "moved-to"); /* IN_MOVED_TO */ + DEFSYM (Qopen, "open"); /* IN_OPEN */ + + DEFSYM (Qall_events, "all-events"); /* IN_ALL_EVENTS */ + DEFSYM (Qmove, "move"); /* IN_MOVE */ + DEFSYM (Qclose, "close"); /* IN_CLOSE */ + + DEFSYM (Qdont_follow, "dont-follow"); /* IN_DONT_FOLLOW */ + DEFSYM (Qexcl_unlink, "excl-unlink"); /* IN_EXCL_UNLINK */ + DEFSYM (Qmask_add, "mask-add"); /* IN_MASK_ADD */ + DEFSYM (Qoneshot, "oneshot"); /* IN_ONESHOT */ + DEFSYM (Qonlydir, "onlydir"); /* IN_ONLYDIR */ + + DEFSYM (Qignored, "ignored"); /* IN_IGNORED */ + DEFSYM (Qisdir, "isdir"); /* IN_ISDIR */ + DEFSYM (Qq_overflow, "q-overflow"); /* IN_Q_OVERFLOW */ + DEFSYM (Qunmount, "unmount"); /* IN_UNMOUNT */ defsubr (&Sinotify_add_watch); defsubr (&Sinotify_rm_watch); + defsubr (&Sinotify_valid_p); staticpro (&watch_list);