diff --git a/Makefile.am b/Makefile.am index 8ab6a4b..a583a9b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,16 +2,16 @@ AUTOMAKE_OPTIONS = foreign CFLAGS += -Wall $(LUA_CFLAGS) bin_PROGRAMS = lsyncd lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua -#if INOTIFY +if INOTIFY lsyncd_SOURCES += inotify.c -#endif -#if FANOTIFY -#lsyncd_SOURCES += fanotify.c -#endif +endif +if FANOTIFY +lsyncd_SOURCES += fanotify.c +endif -#if FSEVENTS -#lsyncd_SOURCES += fsevents.c -#endif +if FSEVENTS +lsyncd_SOURCES += fsevents.c +endif lsyncd_LDADD = $(LUA_LIBS) exampledir = $(datarootdir)/doc/@PACKAGE@ diff --git a/configure.ac b/configure.ac index 2435926..969b25e 100644 --- a/configure.ac +++ b/configure.ac @@ -41,44 +41,44 @@ AM_CONDITIONAL([RUNNER], [test x${with_runner} != x]) ## With this release Lsyncd can yet only do with inotify. ## enabling fsevents and disabling inotify is thus commented out. -#### -## --without-inotify option -#AC_ARG_WITH([inotify], -#[ --without-inotify Do not use Linux inotify event interface. On by default.]) -#if test "x${with_inotify}" == xno; then -# echo "compiling without inotify" -#else - echo "compiling with inotify" - AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr") -#fi +### +# --without-inotify option +AC_ARG_WITH([inotify], +[ --without-inotify Do not use Linux inotify event interface. On by default.]) +if test "x${with_inotify}" == xno; then + echo "compiling without inotify" +else + echo "compiling with inotify" + AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr") +fi AM_CONDITIONAL([INOTIFY], [test x${with_inotify} != xno]) -#### -## --with-fanotify option -## -#AC_ARG_WITH([fanotify], -#[ --with-fanotify Uses Linux new fanotify event interface. EXPERIMENTAL! -# Off by default.]) -##if test "x${with_fanotify}" == xno; then -# echo "compiling without fanotify" -#else -# echo "compiling with fanotify - WARNING experimental!" -# AC_DEFINE(LSYNCD_WITH_FANOTIFY,,"descr") -##fi +### +# --with-fanotify option +# +AC_ARG_WITH([fanotify], +[ --with-fanotify Uses Linux new fanotify event interface. EXPERIMENTAL! + Off by default.]) +if test "x${with_fanotify}" == x || test "x${with_fanotify}no" == xno; then + echo "compiling without fanotify" +else + echo "compiling with fanotify - WARNING experimental!" + AC_DEFINE(LSYNCD_WITH_FANOTIFY,,"descr") +fi AM_CONDITIONAL([FANOTIFY], [test x${with_fanotify} != x -a x${with_fanotify} != xno]) -#### -## --with-fsevents -#AC_ARG_WITH([fsevents], -#[ --with-fsevents Uses MacOS (10.5) /dev/fsevents. EXPERIMENTAL! -# Off by default.]) -#if test "x${with_fsevents}" != x; then -# echo "compiling with fsevents. WARNING experimental!" -# AC_DEFINE(LSYNCD_WITH_FSEVENTS,,"descr") -#else -# echo "compiling without fsevents" -#fi +### +# --with-fsevents +AC_ARG_WITH([fsevents], +[ --with-fsevents Uses MacOS (10.5) /dev/fsevents. EXPERIMENTAL! + Off by default.]) +if test "x${with_fsevents}" != x; then + echo "compiling with fsevents. WARNING experimental!" + AC_DEFINE(LSYNCD_WITH_FSEVENTS,,"descr") +else + echo "compiling without fsevents" +fi AM_CONDITIONAL([FSEVENTS], [test x${with_fsevents} != x -a xno${with_fsevents} != xno]) diff --git a/fsevents.c b/fsevents.c index 434c444..7650ffd 100644 --- a/fsevents.c +++ b/fsevents.c @@ -25,9 +25,6 @@ * including Spotlight. Consequently, Spotlight may need to look at the entire * volume to determine "what changed". */ - -#error "This code is not yet finished." - #include "lsyncd.h" #include @@ -90,7 +87,8 @@ struct kfs_event { pid_t pid; /* event arguments */ - struct kfs_event_arg args[KFS_NUM_ARGS]; + struct kfs_event_arg args[]; + /* struct kfs_event_arg args[KFS_NUM_ARGS]; */ }; /** @@ -102,7 +100,7 @@ static const luaL_reg lfseventslib[] = { {NULL, NULL} }; -// event names +/* event names */ static const char *eventNames[FSE_MAX_EVENTS] = { "CREATE_FILE", "DELETE", @@ -117,9 +115,111 @@ static const char *eventNames[FSE_MAX_EVENTS] = { "XATTR_REMOVED", }; +/* argument names*/ +static const char *argNames[] = { + "UNKNOWN", + "VNODE", + "STRING", + "PATH", + "INT32", + "INT64", + "RAW", + "INO", + "UID", + "DEV", + "MODE", + "GID", + "FINFO", +}; + +/** + * The read buffer + */ static size_t const readbuf_size = 131072; static char * readbuf = NULL; +/** + * Handles one fsevents event + * @returns the size of the event + */ +static ssize_t +handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) +{ + /* the len of the event */ + ssize_t len = sizeof(int32_t) + sizeof(pid_t); + + bool want_path = false; + const char *path = NULL; + + if (event->type == FSE_EVENTS_DROPPED) { + logstring("Fsevents", "Events dropped!"); + load_runner_func(L, "overflow"); + if (lua_pcall(L, 0, 0, -2)) { + exit(-1); // ERRNO + } + lua_pop(L, 1); + hup = 1; + len += sizeof(u_int16_t); + return len; + } + { + int32_t atype = event->type & FSE_TYPE_MASK; + uint32_t aflags = FSE_GET_FLAGS(event->type); + + if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) { + printlogf(L, "Fsevents", "got event %s", eventNames[atype]); + if (aflags & FSE_COMBINED_EVENTS) { + logstring("Fsevents", "combined events"); + } + if (aflags & FSE_CONTAINS_DROPPED_EVENTS) { + logstring("Fsevents", "contains dropped events"); + } + } else { + printlogf(L, "Error", "unknown event(%d) in fsevents.", + atype); + exit(-1); // ERRNO + } + + switch(atype) { + case FSE_CREATE_FILE : + want_path = true; + break; + } + } + + { + struct kfs_event_arg *arg = event->args; + while (len < mlen) { + int eoff; + if (arg->type == FSE_ARG_DONE) { + logstring("Fsevents", "argdone"); + len += sizeof(u_int16_t); + break; + } + + switch (arg->type) { + case FSE_ARG_STRING : + if (want_path && !path) { + path = arg->data.str; + } + break; + } + + eoff = sizeof(arg->type) + sizeof(arg->len) + arg->len; + len += eoff; + printlogf(L, "Fsevents", "arg:%s:%d", + argNames[arg->type > FSE_MAX_ARGS ? 0 : arg->type], + arg->len); + arg = (struct kfs_event_arg *) ((char *) arg + eoff); + } + } + + if (path) { +// printlogf(L, "path=%s", path); + } + return len; +} + /** * Called when fsevents has something to read */ @@ -141,7 +241,7 @@ fsevents_ready(lua_State *L, struct observance *obs) } if (len < 0) { if (err == EAGAIN) { - /* nothing more inotify */ + /* nothing more */ break; } else { printlogf(L, "Error", "Read fail on fsevents"); @@ -150,40 +250,9 @@ fsevents_ready(lua_State *L, struct observance *obs) } { int off = 0; - int32_t atype; - uint32_t aflags; - while (off < len && !hup && !term) { struct kfs_event *event = (struct kfs_event *) &readbuf[off]; - off += sizeof(int32_t) + sizeof(pid_t); - - if (event->type == FSE_EVENTS_DROPPED) { - logstring("Fsevents", "Events dropped!"); - load_runner_func(L, "overflow"); - if (lua_pcall(L, 0, 0, -2)) { - exit(-1); // ERRNO - } - lua_pop(L, 1); - hup = 1; - off += sizeof(u_int16_t); - continue; - } - atype = event->type & FSE_TYPE_MASK; - aflags = FSE_GET_FLAGS(event->type); - - if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) { - printlogf(L, "Fsevents", "got event %s", eventNames[atype]); - if (aflags & FSE_COMBINED_EVENTS) { - logstring("Fsevents", "combined events"); - } - if (aflags & FSE_CONTAINS_DROPPED_EVENTS) { - logstring("Fsevents", "contains dropped events"); - } - } else { - printlogf(L, "Error", "unknown event(%d) in fsevents.", - atype); - exit(-1); // ERRNO - } + off += handle_event(L, event, len); } } } @@ -220,8 +289,6 @@ register_fsevents(lua_State *L) { extern void open_fsevents(lua_State *L) { - return; - int8_t event_list[] = { // action to take for each event FSE_REPORT, /* FSE_CREATE_FILE */ FSE_REPORT, /* FSE_DELETE */ diff --git a/lsyncd.lua b/lsyncd.lua index 2faf5aa..f505d35 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -1871,60 +1871,60 @@ local Inotify = (function() } end)() ------- ----- Interface to OSX /dev/fsevents, watches the whole filesystems ---- ----- All fsevents specific implementation should be enclosed here. ----- ---local Fsevents = (function() --- ----- --- -- A list indexed by sync's containing the root path this --- -- sync is interested in. --- -- --- local syncPaths = {} +-- Interface to OSX /dev/fsevents, watches the whole filesystems -- --- ----- --- -- adds a Sync to receive events --- -- --- -- @param sync Object to receive events --- -- @param dir dir to watch --- -- --- local function addSync(sync, dir) --- if syncRoots[sync] then --- error("duplicate sync in Fanotify.addSync()") --- end --- -- TODO for non subdirs adddir only --- syncRoots[sync] = dir --- end +-- All fsevents specific implementation should be enclosed here. -- --- ----- --- -- Called when any event has occured. --- -- --- -- @param etype "Attrib", "Mofify", "Create", "Delete", "Move") --- -- @param wd watch descriptor (matches lsyncd.inotifyadd()) --- -- @param isdir true if filename is a directory --- -- @param time time of event --- -- @param filename string filename without path --- -- @param filename2 --- -- --- local function event(etype, isdir, time, filename, filename2) --- log("Fsevents", etype, isdir, time, filename, filename2) --- end --- --- ----- --- -- Writes a status report about inotifies to a filedescriptor --- -- --- local function statusReport(f) --- -- TODO --- end --- --- -- public interface --- return { --- addSync = addSync, --- event = event, --- statusReport = statusReport --- } ---end)() +local Fsevents = (function() + ----- + -- A list indexed by sync's containing the root path this + -- sync is interested in. + -- + local syncRoots = {} + + ----- + -- adds a Sync to receive events + -- + -- @param sync Object to receive events + -- @param dir dir to watch + -- + local function addSync(sync, dir) + if syncRoots[sync] then + error("duplicate sync in Fanotify.addSync()") + end + -- TODO for non subdirs adddir only + syncRoots[sync] = dir + end + + ----- + -- Called when any event has occured. + -- + -- @param etype "Attrib", "Mofify", "Create", "Delete", "Move") + -- @param wd watch descriptor (matches lsyncd.inotifyadd()) + -- @param isdir true if filename is a directory + -- @param time time of event + -- @param filename string filename without path + -- @param filename2 + -- + local function event(etype, isdir, time, filename, filename2) + log("Fsevents", etype, isdir, time, filename, filename2) + end + + ----- + -- Writes a status report about inotifies to a filedescriptor + -- + local function statusReport(f) + -- TODO + end + + -- public interface + return { + addSync = addSync, + event = event, + statusReport = statusReport + } +end)() ----- -- Holds information about the event monitor capabilities @@ -2643,7 +2643,7 @@ function runner.initialize() for _, s in Syncs.iwalk() do if s.config.monitor == "inotify" then Inotify.addSync(s, s.source) - elseif s.config.monitor == "fanotify" then + elseif s.config.monitor == "fsevents" then Fsevents.addSync(s, s.source) else error("sync "..s.config.name..