diff --git a/Makefile.am b/Makefile.am index 3ca3ced..239028f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,11 @@ AUTOMAKE_OPTIONS = foreign CFLAGS = -Wall $(LIBLUA_CFLAGS) bin_PROGRAMS = lsyncd -lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua inotify.c +lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua +if INOTIFY +lsyncd_SOURCES += inotify.c +endif + lsyncd_LDADD = $(LIBLUA_LIBS) exampledir = $(datarootdir)/doc/@PACKAGE@ dist_example_DATA = \ diff --git a/configure.ac b/configure.ac index 92b1c4a..ce219b4 100644 --- a/configure.ac +++ b/configure.ac @@ -1,9 +1,10 @@ # -*- Autoconf -*- +echo XXXXXXXXX # Process this file with autoconf to produce a configure script. #AC_PREREQ(2.60) AC_INIT(lsyncd, 2.0beta3, axkibe@gmail.com) -AC_CONFIG_SRCDIR([lsyncd.c],[lsyncd.lua],[inotify.c]) -AC_CONFIG_HEADER([config.h],[lsyncd.h]) +AC_CONFIG_SRCDIR([lsyncd.c]) +AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) # Checks for programs. AC_PROG_CC @@ -14,14 +15,28 @@ PKG_CHECK_MODULES(LIBLUA, lua5.1) # Checks for header files. AC_CHECK_HEADERS([sys/inotify.h]) +### +# --with-runner option AC_ARG_WITH([runner], [ --with-runner= Specify directory where lsyncds part written in Lua will be placed. - If missing it will be compiled into the binary)]) + If missing it will be compiled into the binary]) if test "x${with_runner}" != x; then -AC_DEFINE_UNQUOTED(LSYNCD_DEFAULT_RUNNER_FILE, "${with_runner}/lsyncd.lua", "descr") -AC_SUBST(RUNNER_DIR, "${with_runner}") + AC_DEFINE_UNQUOTED(LSYNCD_DEFAULT_RUNNER_FILE, "${with_runner}/lsyncd.lua", "descr") + AC_SUBST(RUNNER_DIR, "${with_runner}") fi -AM_CONDITIONAL([RUNNER], [test x${with_runner} != x]) +AM_CONDITIONAL([RUNNER], [test x${with_runner} != x]) + +### +# --without-inotify option +AC_ARG_WITH([inotify], +[ --without-inotify Do not compile 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]) # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. diff --git a/inotify.c b/inotify.c index e5d119b..24b2206 100644 --- a/inotify.c +++ b/inotify.c @@ -71,7 +71,7 @@ static int l_addwatch(lua_State *L) { const char *path = luaL_checkstring(L, 1); - int wd = inotify_add_watch(inotify_fd, path, standard_event_mask); + lua_Integer wd = inotify_add_watch(inotify_fd, path, standard_event_mask); printlogf(L, "Inotify", "addwatch(%s)->%d", path, wd); lua_pushinteger(L, wd); return 1; @@ -86,7 +86,7 @@ l_addwatch(lua_State *L) static int l_rmwatch(lua_State *L) { - int wd = luaL_checkinteger(L, 1); + lua_Integer wd = luaL_checkinteger(L, 1); inotify_rm_watch(inotify_fd, wd); printlogf(L, "Inotify", "rmwatch()<-%d", wd); return 0; @@ -252,13 +252,8 @@ static char * readbuf = NULL; * to the runner. */ static void -inotify_ready(lua_State *L, struct observance *observance) +inotify_ready(lua_State *L, int fd, void *extra) { - if (observance->fd != inotify_fd) { - logstring("Error", - "internal fail, inotify_ready on non-inotify file descriptor."); - exit(-1); // ERRNO - } while(true) { ptrdiff_t len; int err; @@ -312,24 +307,6 @@ inotify_ready(lua_State *L, struct observance *observance) } } -/** - * Called by function pointer when the core doesnt want the - * inotify fd anymore (term, hup or overflow) - */ -static void -inotify_tidy(struct observance *observance) -{ - if (observance->fd != inotify_fd) { - logstring("Error", - "internal fail, inotify_ready on non-inotify file descriptor."); - exit(-1); // ERRNO - } - close(inotify_fd); - inotify_fd = -1; - free(readbuf); - readbuf = NULL; -} - /** * registers inotify functions. */ @@ -361,6 +338,16 @@ open_inotify(lua_State *L) { close_exec_fd(inotify_fd); non_block_fd(inotify_fd); - observe_fd(inotify_fd, inotify_ready, NULL, inotify_tidy, NULL); + observe_fd(inotify_fd, inotify_ready, NULL, NULL); +} + +/** + * closes inotify + */ +extern void +close_inotify() { + close(inotify_fd); + free(readbuf); + readbuf = NULL; } diff --git a/lsyncd.c b/lsyncd.c index 8822bdc..6755704 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -44,6 +44,16 @@ extern char _binary_luac_out_start; extern char _binary_luac_out_end; #endif + +/** + * The default notification system to use. + */ +#ifdef LSYNCD_WITH_INOTIFY +extern char *default_notify = "Inotify"; +#else +# error "need at least one notifcation system. please rerun ./configure" +#endif + /** * configuration parameters */ @@ -158,7 +168,7 @@ add_logcat(const char *name, int priority) return true; } if (!strcmp("scarce", name)) { - settings.log_level = LOG_WARNING; + settings.log_level = LOG_ERR; return true; } @@ -364,29 +374,24 @@ struct pipemsg { * writeable again */ static void -pipe_writey(lua_State *L, struct observance *observance) { - struct pipemsg *pm = (struct pipemsg *) observance->extra; - int len = write(observance->fd, pm->text + pm->pos, pm->tlen - pm->pos); +pipe_writey(lua_State *L, int fd, void *extra) { + struct pipemsg *pm = (struct pipemsg *) extra; + int len = write(fd, pm->text + pm->pos, pm->tlen - pm->pos); + bool do_close = false; pm->pos += len; if (len < 0) { logstring("Normal", "broken pipe."); - nonobserve_fd(observance->fd); + do_close = true; } else if (pm->pos >= pm->tlen) { logstring("Debug", "finished pipe."); - nonobserve_fd(observance->fd); + do_close = true; + } + if (do_close) { + close(fd); + free(pm->text); + free(extra); + unobserve_fd(fd); } -} - -/** - * TODO - */ -static void -pipe_tidy(struct observance *observance) -{ - struct pipemsg *pm = (struct pipemsg *) observance->extra; - close(observance->fd); - free(pm->text); - free(pm); } @@ -696,6 +701,7 @@ l_exec(lua_State *L) len = write(pipefd[1], pipe_text, tlen); if (len < 0) { logstring("Normal", "immediatly broken pipe."); + close(pipefd[0]); } if (len == tlen) { /* usual and best case, the pipe accepted all input -> close */ @@ -703,13 +709,14 @@ l_exec(lua_State *L) logstring("Exec", "one-sweeped pipe"); } else { struct pipemsg *pm; - logstring("Exec", "adding pipe observance"); + logstring("Exec", "adding pipe observer"); pm = s_calloc(1, sizeof(struct pipemsg)); pm->text = s_strdup(pipe_text); pm->tlen = tlen; pm->pos = len; - observe_fd(pipefd[1], NULL, pipe_writey, pipe_tidy, pm); + observe_fd(pipefd[1], NULL, pipe_writey, pm); } + close(pipefd[0]); } free(argv); lua_pushnumber(L, pid); @@ -890,7 +897,6 @@ l_configure(lua_State *L) if (!settings.log_file) { settings.log_syslog = true; } - // XXX logstring("Debug", "daemonizing now."); if (daemon(0, 0)) { logstring("Error", "Failed to daemonize"); @@ -921,6 +927,7 @@ l_configure(lua_State *L) return 0; } + static const luaL_reg lsyncdlib[] = { {"addtoclock", l_addtoclock }, {"clockbefore", l_clockbefore }, @@ -945,13 +952,13 @@ static const luaL_reg lsyncdlib[] = { * Dummy variable whos address is used as the cores index in the lua registry * to the lua runners function table in the lua registry. */ -static int runner = 0; +static int runner; /** * Dummy variable whos address is used as the cores index n the lua registry * to the lua runners error handler. */ -static int callError = 0; +static int callError; /** * Pushes a function from the runner on the stack. @@ -976,12 +983,38 @@ load_runner_func(lua_State *L, } +/** + * An observer to be called when a file descritor becomes + * read-ready or write-ready. + */ +struct observer { + /** + * The file descriptor to observe. + */ + int fd; + + /** + * Function to call when read becomes ready. + */ + void (*ready)(lua_State *L, int fd, void *extra); + + /** + * Function to call when write becomes ready. + */ + void (*writey)(lua_State *L, int fd, void *extra); + + /** + * Extra tokens to pass to the functions- + */ + void *extra; +}; + /** * List of file descriptor watches. */ -static struct observance * observances = NULL; -static int observances_len = 0; -static int observances_size = 0; +static struct observer * observers = NULL; +static int observers_len = 0; +static int observers_size = 0; /** * List of file descriptors to unobserve. @@ -989,14 +1022,14 @@ static int observances_size = 0; * not be altered, thus unobserve stores here the * actions that will be delayed. */ -static int *nonobservances = NULL; -static int nonobservances_len = 0; -static int nonobservances_size = 0; +static int *unobservers = NULL; +static int unobservers_len = 0; +static int unobservers_size = 0; /** - * true while the observances list is being handled. + * true while the observers list is being handled. */ -static bool observance_action = false; +static bool observer_action = false; /** * Core watches a filedescriptor to become ready, @@ -1004,88 +1037,83 @@ static bool observance_action = false; */ extern void observe_fd(int fd, - void (*ready) (lua_State *L, struct observance *observance), - void (*writey)(lua_State *L, struct observance *observance), - void (*tidy) (struct observance *observance), - void *extra) + void (*ready)(lua_State *L, int fd, void *extra), + void (*writey)(lua_State *L, int fd, void *extra), + void *extra) { int pos; - if (observance_action) { + if (observer_action) { // TODO logstring("Error", - "Adding observance in ready/writey handlers not yet supported"); + "Adding observers in ready/writey handlers not yet supported"); exit(-1); // ERRNO } - if (observances_len + 1 > observances_size) { - observances_size = observances_len + 1; - observances = s_realloc(observances, - observances_size * sizeof(struct observance)); + if (observers_len + 1 > observers_size) { + observers_size = observers_len + 1; + observers = s_realloc(observers, + observers_size * sizeof(struct observer)); } - for(pos = 0; pos < observances_len; pos++) { - if (observances[pos].fd <= fd) { + for(pos = 0; pos < observers_len; pos++) { + if (observers[pos].fd <= fd) { break; } } - if (observances[pos].fd == fd) { + if (observers[pos].fd == fd) { logstring("Error", "Observing already an observed file descriptor."); exit(-1); // ERRNO } - memmove(observances + pos + 1, observances + pos, - (observances_len - pos) * (sizeof(struct observance))); + memmove(observers + pos + 1, observers + pos, + (observers_len - pos) * (sizeof(struct observer))); - observances_len++; - observances[pos].fd = fd; - observances[pos].ready = ready; - observances[pos].writey = writey; - observances[pos].tidy = tidy; - observances[pos].extra = extra; + observers_len++; + observers[pos].fd = fd; + observers[pos].ready = ready; + observers[pos].writey = writey; + observers[pos].extra = extra; } /** * Makes core no longer watch fd. */ extern void -nonobserve_fd(int fd) +unobserve_fd(int fd) { int pos; - if (observance_action) { + if (observer_action) { /* this function is called through a ready/writey handler - * while the core works through the observances list, thus + * while the core works through the observer list, thus * it does not alter the list, but stores this actions * on a stack */ - nonobservances_len++; - if (nonobservances_len > nonobservances_size) { - nonobservances_size = nonobservances_len; - nonobservances = s_realloc(nonobservances, - nonobservances_size * sizeof(int)); + unobservers_len++; + if (unobservers_len > unobservers_size) { + unobservers_size = unobservers_len; + unobservers = s_realloc(unobservers, + unobservers_size * sizeof(int)); } - nonobservances[nonobservances_len - 1] = fd; + unobservers[unobservers_len - 1] = fd; return; } /* looks for the fd */ - for(pos = 0; pos < observances_len; pos++) { - if (observances[pos].fd == fd) { + for(pos = 0; pos < observers_len; pos++) { + if (observers[pos].fd == fd) { break; } } - if (pos >= observances_len) { + if (pos >= observers_len) { logstring("Error", - "internal fail, not observed file descriptor in nonobserve_fd()"); + "internal fail, not observer file descriptor in unobserve"); exit(-1); //ERRNO } - if (observances[pos].tidy) { - observances[pos].tidy(observances + pos); - } /* and moves the list down */ - memmove(observances + pos, observances + pos + 1, - (observances_len - pos) * (sizeof(struct observance))); - observances_len--; + memmove(observers + pos, observers + pos + 1, + (observers_len - pos) * (sizeof(struct observer))); + observers_len--; } /** @@ -1146,52 +1174,52 @@ masterloop(lua_State *L) FD_ZERO(&rfds); FD_ZERO(&wfds); - for(pi = 0; pi < observances_len; pi++) { - int fd = observances[pi].fd; - if (observances[pi].ready) { + for(pi = 0; pi < observers_len; pi++) { + int fd = observers[pi].fd; + if (observers[pi].ready) { FD_SET(fd, &rfds); } - if (observances[pi].writey) { + if (observers[pi].writey) { FD_SET(fd, &wfds); } } /* the great select */ pr = pselect( - observances[observances_len - 1].fd + 1, + observers[observers_len - 1].fd + 1, &rfds, &wfds, NULL, have_alarm ? &tv : NULL, &sigset); if (pr >= 0) { - /* walks through the observances calling ready/writey fds */ - observance_action = true; - for(pi = 0; pi < observances_len; pi++) { - struct observance *obs = observances + pi; - int fd = obs->fd; + /* walks through the observers calling ready/writey fds */ + observer_action = true; + for(pi = 0; pi < observers_len; pi++) { + int fd = observers[pi].fd; + void *extra = observers[pi].extra; if (hup || term) { break; } - if (obs->ready && FD_ISSET(fd, &rfds)) { - obs->ready(L, obs); + if (observers[pi].ready && FD_ISSET(fd, &rfds)) { + observers[pi].ready(L, fd, extra); } if (hup || term) { break; } - if (nonobservances_len > 0 && - nonobservances[nonobservances_len - 1] == fd) { - /* ready() nonobserved itself */ + if (unobservers_len > 0 && + unobservers[unobservers_len - 1] == fd) { + /* ready() unobserved itself */ continue; } - if (obs->writey && FD_ISSET(fd, &wfds)) { - obs->writey(L, obs); + if (observers[pi].writey && FD_ISSET(fd, &wfds)) { + observers[pi].writey(L, fd, extra); } } - observance_action = false; + observer_action = false; /* work through delayed unobserve_fd() calls */ - for (pi = 0; pi < nonobservances_len; pi++) { - nonobserve_fd(nonobservances[pi]); + for (pi = 0; pi < unobservers_len; pi++) { + unobserve_fd(unobservers[pi]); } - nonobservances_len = 0; + unobservers_len = 0; } } } @@ -1287,7 +1315,6 @@ main1(int argc, char *argv[]) /* prepares logging early */ int i = 1; add_logcat("Normal", LOG_NOTICE); - add_logcat("Warn", LOG_WARNING); add_logcat("Error", LOG_ERR); while (i < argc) { if (strcmp(argv[i], "-log") && strcmp(argv[i], "--log")) { @@ -1511,19 +1538,6 @@ main1(int argc, char *argv[]) masterloop(L); /* cleanup */ - { - /* close/frees observances */ - int i; - for(i = 0; i < observances_len; i++) { - struct observance *obs = observances + i; - if (obs->tidy) { - obs->tidy(obs); - } - } - observances_len = 0; - nonobservances_len = 0; - observance_action = false; - } { /* frees logging categories */ int ci; @@ -1552,6 +1566,7 @@ main1(int argc, char *argv[]) settings.log_level = 0, settings.nodaemon = false, + close_inotify(); lua_close(L); return 0; } diff --git a/lsyncd.h b/lsyncd.h index 44d7d38..216e501 100644 --- a/lsyncd.h +++ b/lsyncd.h @@ -103,43 +103,23 @@ extern void non_block_fd(int fd); /* Sets the close-on-exit flag for a file descriptor. */ extern void close_exec_fd(int fd); - -/** - * An observance calls functions when a file descritor becomes - * read-ready or write-ready. - */ -struct observance { - /* The file descriptor observed. */ - int fd; - - /* Function to call when read becomes ready. */ - void (*ready)(lua_State *L, struct observance *observance); - - /* Function to call when write becomes ready. */ - void (*writey)(lua_State *L, struct observance *observance); - - /* Function that tidies up, closes fd, frees extra data. etc. */ - void (*tidy)(struct observance *observance); - - /* Extra tokens to pass to the functions */ - void *extra; -}; - /* makes the core to observe a file descriptor */ -extern void -observe_fd(int fd, - void (*ready) (lua_State *L, struct observance *observance), - void (*writey)(lua_State *L, struct observance *observance), - void (*tidy) (struct observance *observance), - void *extra); +extern void observe_fd( + int fd, + void (*ready)(lua_State *L, int fd, void *extra), + void (*writey)(lua_State *L, int fd, void *extra), + void *extra); /* stops the core to observe a file descriptor */ -extern void nonobserve_fd(int fd); +extern void unobserve_fd(int fd); /*----------------------------------------------------------------------------- * inotify */ extern void register_inotify(lua_State *L); extern void open_inotify(lua_State *L); +extern void close_inotify(); + + #endif diff --git a/lsyncd.lua b/lsyncd.lua index 4448a71..85c4c6c 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -1402,8 +1402,11 @@ local Syncs = (function() end -- loads a default value for an option if not existent + if not settings then + settings = {} + end local defaultValues = { - 'action', + 'action', 'collapse', 'collapseTable', 'collect', @@ -1464,7 +1467,7 @@ end -- So lsyncd can work with other notifications mechanisms just -- by changing this. -- -local Inotifies = (function() +local Inotify = (function() ----- -- A list indexed by inotifies watch descriptor yielding the @@ -1514,7 +1517,7 @@ local Inotifies = (function() -- local function addWatch(path, recurse, raiseSync, raiseTime) log("Function", - "Inotifies.addWatch(",path,", ",recurse,", ", + "Inotify.addWatch(",path,", ",recurse,", ", raiseSync,", ",raiseTime,")") -- lets the core registers watch with the kernel @@ -1574,8 +1577,8 @@ local Inotifies = (function() -- local function addSync(sync, root) if syncRoots[sync] then - error("internal fail, duplicate sync in Inotifies()") - end + error("internal fail, duplicate sync in Inotify.addSync()") + end syncRoots[sync] = root addWatch(root, true) end @@ -1957,7 +1960,7 @@ local StatusFile = (function() f:write("\n") end - Inotifies.statusReport(f) + Inotify.statusReport(f) f:close() end @@ -2072,7 +2075,6 @@ USAGE: lsyncd [OPTIONS] -rsyncssh [SOURCE] [HOST] [TARGETDIR] OPTIONS: - -dryrun Subprocesses are not actually invoked. -help Shows this -log all Logs everything (debug) -log scarce Logs errors only @@ -2109,10 +2111,6 @@ function runner.configure(args) -- a list of all valid --options local options = { -- log is handled by core already. - dryrun = - {0, function() - clSettings.dryrun=true - end}, log = {1, nil}, logfile = @@ -2283,7 +2281,7 @@ function runner.initialize() -- runs through the Syncs created by users for _, s in Syncs.iwalk() do - Inotifies.addSync(s, s.source) + Inotify.addSync(s, s.source) if s.config.init then InletControl.setSync(s) s.config.init(Inlet) @@ -2409,42 +2407,13 @@ function spawn(agent, binary, ...) if lsyncdStatus == "fade" then log("Normal", "ignored spawn processs since status fading") end - if not settings.dryrun then - local pid = lsyncd.exec(binary, ...) - if pid and pid > 0 then - local sync = InletControl.getSync() - local delay = InletControl.getDelay(agent) - if delay then - delay.status = "active" - sync.processes[pid] = delay - else - local dlist = InletControl.getDelayList(agent) - if not dlist then - error("spawning with an unknown agent", 2) - end - for k, d in pairs(dlist) do - if type(k) == "number" then - d.status = "active" - end - end - sync.processes[pid] = dlist - end - end - else - local a1, a2 = ... - if a1 ~= "<" then - log("Normal", "would call ", binary, " ", table.concat({...}, " ")) - else - local aa = {...} - table.remove(aa, 1) - table.remove(aa, 1) - log("Normal", "would call ", binary, " ", table.concat(aa, " "), - "\ninput pipe <\n", a2) - end + local pid = lsyncd.exec(binary, ...) + if pid and pid > 0 then local sync = InletControl.getSync() local delay = InletControl.getDelay(agent) if delay then - sync:removeDelay(delay) + delay.status = "active" + sync.processes[pid] = delay else local dlist = InletControl.getDelayList(agent) if not dlist then @@ -2452,9 +2421,10 @@ function spawn(agent, binary, ...) end for k, d in pairs(dlist) do if type(k) == "number" then - sync:removeDelay(d) + d.status = "active" end end + sync.processes[pid] = dlist end end end @@ -2466,6 +2436,7 @@ function spawnShell(agent, command, ...) return spawn(agent, "/bin/sh", "-c", command, "/bin/sh", ...) end + ----- -- Comfort routine also for user. -- Returns true if 'String' starts with 'Start' @@ -2483,27 +2454,6 @@ function string.ends(String,End) end ------- --- Replaces default os.execute with a warning message, --- doing the execute nevertheless, if not in dryrun. --- -local os_execute = os.execute -os.execute = function(...) - log("Warn", "using os.execute makes Lsyncd splutter, use spawn() instead.") - if not settings.dryrun then - os_execute(...) - else - log("Normal", "would os.execute ", table.concat({...}, " ")) - end -end - ------ --- An empty settings table optionally for the config to --- expand instead of replace. --- -settings = {} - - --============================================================================ -- Lsyncd default settings --============================================================================ @@ -2927,11 +2877,6 @@ default = { return rc end, - ----- - -- default Delay - -- - delay = 5, - ----- -- called on (re)initalizing of Lsyncd. --