diff --git a/Makefile.am b/Makefile.am index 025a6ed..e4762fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,9 +6,9 @@ if INOTIFY lsyncd_SOURCES += inotify.c endif -#if FSEVENTS -#lsyncd_SOURCES += fsevents.c -#endif +if FSEVENTS +lsyncd_SOURCES += fsevents.c +endif lsyncd_LDADD = $(LUA_LIBS) exampledir = $(docdir)/ @@ -29,7 +29,7 @@ TESTS = \ tests/l4rsyncdata.lua dist_man1_MANS = doc/lsyncd.1 -EXTRA_DIST = doc/lsyncd.1.txt doc/lsyncd.1.xml +EXTRA_DIST = doc/lsyncd.1.txt doc/lsyncd.1.xml inotify.c fsevents.c doc/lsyncd.1: doc/lsyncd.1.xml xsltproc -o $@ -nonet /etc/asciidoc/docbook-xsl/manpage.xsl $< @@ -37,6 +37,8 @@ doc/lsyncd.1: doc/lsyncd.1.xml doc/lsyncd.1.xml: doc/lsyncd.1.txt asciidoc -o $@ -b docbook -d manpage $< +CLEANFILES = luac.out luac.c + if RUNNER # installs the runner script runnerdir = $(RUNNER_DIR) diff --git a/configure.ac b/configure.ac index cff2cd8..68fd37d 100644 --- a/configure.ac +++ b/configure.ac @@ -43,28 +43,26 @@ AM_CONDITIONAL([RUNNER], [test x${with_runner} != x]) # --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" +if test "x${without_inotify}" != x; then + echo "compiling with inotify" + AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr") else - echo "compiling with inotify" - AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr") + echo "compiling without inotify" fi AM_CONDITIONAL([INOTIFY], [test x${with_inotify} != xno]) -#### -## --with-fsevents -## disabled per default, experimental, works only with OS X 10.5 -#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]) +### +# --with-fsevents +# disabled per default, experimental, works only with OS X 10.5/10.6 +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") +fi +AM_CONDITIONAL([FSEVENTS], + [test x${with_fsevents} != x -a xno${with_fsevents} != xno]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. diff --git a/fsevents.c b/fsevents.c index bddaf6d..39a6295 100644 --- a/fsevents.c +++ b/fsevents.c @@ -3,6 +3,7 @@ * License: GPLv2 (see COPYING) or any later version * * Authors: Axel Kittenberger + * Damian Steward * * ----------------------------------------------------------------------- * @@ -87,8 +88,7 @@ struct kfs_event { pid_t pid; /* event arguments */ - struct kfs_event_arg args[]; - /* struct kfs_event_arg args[KFS_NUM_ARGS]; */ + struct kfs_event_arg* args[FSE_MAX_ARGS]; }; /** @@ -135,15 +135,17 @@ static size_t const readbuf_size = 131072; static char * readbuf = NULL; /** - * Handles one fsevents event - * @returns the size of the event + * The event buffer */ -static ssize_t +static size_t const eventbuf_size = FSEVENT_BUFSIZ; +static char* eventbuf = NULL; + +/** + * Handles one fsevents event + */ +static void 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); - int32_t atype; const char *path = NULL; const char *trg = NULL; @@ -158,35 +160,32 @@ handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) } lua_pop(L, 1); hup = 1; - len += sizeof(u_int16_t); - return len; + return; } - { - 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 + 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 } + { /* assigns the expected arguments */ - struct kfs_event_arg *arg = event->args; - while (len < mlen) { - int eoff; + int whichArg = 0; + while (whichArg < FSE_MAX_ARGS) { + struct kfs_event_arg * arg = event->args[whichArg++]; if (arg->type == FSE_ARG_DONE) { - len += sizeof(u_int16_t); break; } @@ -225,10 +224,6 @@ handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) } break; } - - eoff = sizeof(arg->type) + sizeof(arg->len) + arg->len; - len += eoff; - arg = (struct kfs_event_arg *) ((char *) arg + eoff); } } @@ -279,7 +274,6 @@ handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) } lua_pop(L, 1); } - return len; } /** @@ -310,8 +304,53 @@ fsevents_ready(lua_State *L, struct observance *obs) { int off = 0; while (off < len && !hup && !term) { - struct kfs_event *event = (struct kfs_event *) &readbuf[off]; - off += handle_event(L, event, len); + /* deals with alignment issues on 64 bit by copying data bit by bit */ + struct kfs_event* event = (struct kfs_event *) eventbuf; + event->type = *(int32_t*)(readbuf+off); + off += sizeof(int32_t); + event->pid = *(pid_t*)(readbuf+off); + off += sizeof(pid_t); + /* arguments */ + int whichArg = 0; + int eventbufOff = sizeof(struct kfs_event); + size_t ptrSize = sizeof(void*); + if ((eventbufOff % ptrSize) != 0) { + eventbufOff += ptrSize-(eventbufOff%ptrSize); + } + while (off < len && whichArg < FSE_MAX_ARGS) { + /* assign argument pointer to eventbuf based on + known current offset into eventbuf */ + uint16_t argLen = 0; + event->args[whichArg] = (struct kfs_event_arg *) (eventbuf + eventbufOff); + /* copy type */ + uint16_t argType = *(uint16_t*)(readbuf + off); + event->args[whichArg]->type = argType; + off += sizeof(uint16_t); + if (argType == FSE_ARG_DONE) { + /* done */ + break; + } else { + /* copy data length */ + argLen = *(uint16_t *)(readbuf + off); + event->args[whichArg]->len = argLen; + off += sizeof(uint16_t); + /* copy data */ + memcpy(&(event->args[whichArg]->data), readbuf + off, argLen); + off += argLen; + } + /* makes sure alignment is correct for 64 bit systems */ + size_t argStructLen = sizeof(uint16_t) + sizeof(uint16_t); + if ((argStructLen % ptrSize) != 0) { + argStructLen += ptrSize-(argStructLen % ptrSize); + } + argStructLen += argLen; + if ((argStructLen % ptrSize) != 0) { + argStructLen += ptrSize-(argStructLen % ptrSize); + } + eventbufOff += argStructLen; + whichArg++; + } + handle_event(L, event, len); } } } @@ -330,6 +369,8 @@ fsevents_tidy(struct observance *obs) close(fsevents_fd); free(readbuf); readbuf = NULL; + free(eventbuf); + eventbuf = NULL; } /** @@ -386,7 +427,7 @@ open_fsevents(lua_State *L) exit(-1); // ERRNO } readbuf = s_malloc(readbuf_size); - + eventbuf = s_malloc(eventbuf_size); /* fd has been cloned, closes access fd */ close(fd); close_exec_fd(fsevents_fd); diff --git a/lsyncd.c b/lsyncd.c index a591eb2..e971a9c 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -2048,7 +2049,6 @@ main1(int argc, char *argv[]) return 0; } - /** * Main */ diff --git a/lsyncd.h b/lsyncd.h index a9ab31c..227e832 100644 --- a/lsyncd.h +++ b/lsyncd.h @@ -13,7 +13,8 @@ /* some older machines need this to see pselect */ #define _BSD_SOURCE 1 -#define _XOPEN_SOURCE 600 +#define _XOPEN_SOURCE 700 +#define _DARWIN_C_SOURCE 1 /* includes needed for headerfile */ #include "config.h" diff --git a/lsyncd.lua b/lsyncd.lua index b1cc586..47f67c1 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -3156,9 +3156,9 @@ local default_rsync = { "Calling rsync with filter-list of new/modified files/dirs\n", filterS) local config = inlet.getConfig() - spawn(elist, "/usr/bin/rsync", + spawn(elist, config.rsyncBinary, "<", filter0, - config.rsyncOps, + config.rsyncOpts, "-r", "--delete", "--force", @@ -3185,20 +3185,20 @@ local default_rsync = { if #excludes == 0 then log("Normal", "recursive startup rsync: ", config.source, " -> ", config.target) - spawn(event, "/usr/bin/rsync", + spawn(event, config.rsyncBinary, "--delete", - config.rsyncOps, "-r", + config.rsyncOpts, "-r", config.source, config.target) else local exS = table.concat(excludes, "\n") log("Normal", "recursive startup rsync: ", config.source, " -> ", config.target," excluding\n", exS) - spawn(event, "/usr/bin/rsync", + spawn(event, config.rsyncBinary, "<", exS, "--exclude-from=-", "--delete", - config.rsyncOps, "-r", + config.rsyncOpts, "-r", config.source, config.target) end @@ -3212,18 +3212,23 @@ local default_rsync = { error("default.rsync needs 'target' configured", 4) end - if config.rsyncOpts then - if config.rsyncOps then + if config.rsyncOps then + if config.rsyncOpts then error("'rsyncOpts' and 'rsyncOps' provided in config, decide for one.") end - config.rsyncOps = config.rsyncOpts + config.rsyncOpts = config.rsyncOps end end, + + ----- + -- The rsync binary called. + -- + rsyncBinary = "/usr/bin/rsync", ----- -- Calls rsync with this default short opts. -- - rsyncOps = "-lts", + rsyncOpts = "-lts", ----- -- exit codes for rsync. @@ -3314,9 +3319,9 @@ local default_rsyncssh = { local zPaths = table.concat(paths, "\000") log("Normal", "Rsyncing list\n", sPaths) spawn( - elist, "/usr/bin/rsync", + elist, rsyncBinary, "<", zPaths, - config.rsyncOps, + config.rsyncOpts, "--from0", "--files-from=-", config.source, @@ -3383,10 +3388,10 @@ local default_rsyncssh = { log("Normal", "recursive startup rsync: ", config.source, " -> ", config.host .. ":" .. config.targetdir) spawn( - event, "/usr/bin/rsync", + event, rsyncBinary, "--delete", "-r", - config.rsyncOps, + config.rsyncOpts, config.source, config.host .. ":" .. config.targetdir ) @@ -3395,12 +3400,12 @@ local default_rsyncssh = { log("Normal", "recursive startup rsync: ", config.source, " -> ", config.host .. ":" .. config.targetdir, " excluding\n") spawn( - event, "/usr/bin/rsync", + event, rsyncBinary, "<", exS, "--exclude-from=-", "--delete", "-r", - config.rsyncOps, + config.rsyncOpts, config.source, config.host .. ":" .. config.targetdir ) @@ -3411,11 +3416,11 @@ local default_rsyncssh = { -- Checks the configuration. -- prepare = function(config) - if config.rsyncOpts then - if config.rsyncOps then + if config.rsyncOps then + if config.rsyncOpts then error("'rsyncOpts' and 'rsyncOps' provided in config, decide for one.") end - config.rsyncOps = config.rsyncOpts + config.rsyncOpts = config.rsyncOps end if not config.host then error("default.rsyncssh needs 'host' configured", 4) @@ -3424,11 +3429,16 @@ local default_rsyncssh = { error("default.rsyncssh needs 'targetdir' configured", 4) end end, + + ----- + -- The rsync binary called. + -- + rsyncBinary = "/usr/bin/rsync", ----- -- Calls rsync with this default short opts. -- - rsyncOps = "-lts", + rsyncOpts = "-lts", ----- -- allow processes @@ -3451,7 +3461,7 @@ local default_rsyncssh = { -- available this is simpler than to build filters for rsync for this. -- Default uses '0' as limiter, you might override this for old systems. -- - xargs = {delimiter = '\000', binary = "xargs", xparams = {"-0", "rm -rf"}} + xargs = {delimiter = '\000', binary = "/usr/bin/xargs", xparams = {"-0", "rm -rf"}} } ----- @@ -3563,10 +3573,15 @@ local default_direct = { -- onMove = true, + ----- + -- The rsync binary called. + -- + rsyncBinary = "/usr/bin/rsync", + ----- -- For startup sync -- - rsyncOps = "-lts", + rsyncOpts = "-lts", ----- -- On many system multiple disk operations just rather slow down