diff --git a/Makefile.am b/Makefile.am index f897136..ff552d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ AUTOMAKE_OPTIONS = foreign -CFLAGS = -Wall $(LIBLUA_CFLAGS) +CFLAGS = -Wall $(LUA_CFLAGS) bin_PROGRAMS = lsyncd lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua if INOTIFY @@ -13,7 +13,7 @@ if FSEVENTS lsyncd_SOURCES += fsevents.c endif -lsyncd_LDADD = $(LIBLUA_LIBS) +lsyncd_LDADD = $(LUA_LIBS) exampledir = $(datarootdir)/doc/@PACKAGE@ dist_example_DATA = \ examples/lbash.lua \ diff --git a/examples/lgforce.lua b/examples/lgforce.lua index 5f49673..938e11c 100644 --- a/examples/lgforce.lua +++ b/examples/lgforce.lua @@ -56,13 +56,11 @@ fi -- all group permissions are set to rw -- and to executable flag for directories -- --- the hash in the first line is important, otherwise due to the starting --- slash, Lsyncd would think it is a call to the binary /bin/chgrp only --- and would optimize the bash away. +-- the carret as first char tells Lsycnd to call a shell altough it +-- starts with a slash otherwisw -- startup = -[[# -/bin/chgrp -R ]]..fgroup..[[ ^source || /bin/true && +[[^/bin/chgrp -R ]]..fgroup..[[ ^source || /bin/true && /bin/chmod -R g+rw ^source || /bin/true && /usr/bin/find ^source -type d | xargs chmod g+x ]] diff --git a/lsyncd.c b/lsyncd.c index faf13a9..d0eaaa9 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -642,6 +642,7 @@ l_exec(lua_State *L) /* the pipe to text */ char const *pipe_text = NULL; + size_t pipe_len = 0; /* the arguments */ char const **argv; /* pipe file descriptors */ @@ -663,7 +664,11 @@ l_exec(lua_State *L) if (argc >= 2 && !strcmp(luaL_checkstring(L, 2), "<")) { /* pipes something into stdin */ - pipe_text = luaL_checkstring(L, 3); + if (!lua_isstring(L, 3)) { + logstring("Error", "in spawn(), expected a string after pipe '<'"); + exit(-1); // ERRNO + } + pipe_text = lua_tolstring(L, 3, &pipe_len); /* creates the pipe */ if (pipe(pipefd) == -1) { logstring("Error", "cannot create a pipe!"); @@ -716,17 +721,16 @@ l_exec(lua_State *L) } if (pipe_text) { - int tlen = strlen(pipe_text); int len; /* first closes read-end of pipe, this is for child process only */ close(pipefd[0]); /* start filling the pipe */ - len = write(pipefd[1], pipe_text, tlen); + len = write(pipefd[1], pipe_text, pipe_len); if (len < 0) { logstring("Normal", "immediatly broken pipe."); close(pipefd[0]); } - if (len == tlen) { + if (len == pipe_len) { /* usual and best case, the pipe accepted all input -> close */ close(pipefd[1]); logstring("Exec", "one-sweeped pipe"); @@ -734,8 +738,9 @@ l_exec(lua_State *L) struct pipemsg *pm; logstring("Exec", "adding pipe observance"); pm = s_calloc(1, sizeof(struct pipemsg)); - pm->text = s_strdup(pipe_text); - pm->tlen = tlen; + pm->text = s_calloc(pipe_len + 1, sizeof(char*)); + memcpy(pm->text, pipe_text, pipe_len + 1); + pm->tlen = pipe_len; pm->pos = len; observe_fd(pipefd[1], NULL, pipe_writey, pipe_tidy, pm); } diff --git a/lsyncd.lua b/lsyncd.lua index 8811d21..d3ea0de 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -1373,11 +1373,18 @@ local Syncs = (function() local uconfig = config config = {} inherit(config, uconfig) - - -- at very first let the userscript 'prepare' function + + ----- + -- Lets settings or commandline override delay values. + -- + if settings then + config.delay = settings.delay or config.delay + end + + -- at very first lets the userscript 'prepare' function -- fill out more values. if type(config.prepare) == "function" then - -- give explicitly a writeable copy of config. + -- explicitly gives a writeable copy of config. config.prepare(config) end @@ -1994,8 +2001,12 @@ local functionWriter = (function() str = string.match(str, "^%s*(.-)%s*$") local ft - if string.byte(str, 1, 1) == 47 then - ft = translateBinary(str) + if string.byte(str, 1, 1) == 47 then + -- starts with / + ft = translateBinary(str) + elseif string.byte(str, 1, 1) == 94 then + -- starts with ^ + ft = translateShell(str:sub(2, -1)) else ft = translateShell(str) end @@ -2185,6 +2196,7 @@ USAGE: lsyncd [OPTIONS] -rsyncssh [SOURCE] [HOST] [TARGETDIR] OPTIONS: + -delay SECS Overrides default delay times -help Shows this -log all Logs everything (debug) -log scarce Logs errors only @@ -2232,11 +2244,15 @@ function runner.configure(args, monitors) -- local options = { -- log is handled by core already. + delay = + {1, function(secs) + clSettings.delay = secs + end}, log = {1, nil}, logfile = {1, function(file) - clSettings.logfile=file + clSettings.logfile = file end}, monitor = {-1, function(monitor) @@ -2289,29 +2305,28 @@ function runner.configure(args, monitors) a = a:sub(2) end local o = options[a] - if o then - if o[1] >= 0 and i + o[1] > #args then - log("Error",a," needs ",o[1]," arguments") - os.exit(-1) -- ERRNO - else - o[1] = -o[1] - end - if o[2] then - if o[1] == 0 then - o[2]() - elseif o[1] == 1 then - o[2](args[i + 1]) - elseif o[1] == 2 then - o[2](args[i + 1], args[i + 2]) - elseif o[1] == 3 then - o[2](args[i + 1], args[i + 2], args[i + 3]) - end - end - i = i + o[1] - else + if not o then log("Error","unknown option command line option ", args[i]) os.exit(-1) -- ERRNO end + if o[1] >= 0 and i + o[1] > #args then + log("Error",a," needs ",o[1]," arguments") + os.exit(-1) -- ERRNO + elseif o[1] < 0 then + o[1] = -o[1] + end + if o[2] then + if o[1] == 0 then + o[2]() + elseif o[1] == 1 then + o[2](args[i + 1]) + elseif o[1] == 2 then + o[2](args[i + 1], args[i + 2]) + elseif o[1] == 3 then + o[2](args[i + 1], args[i + 2], args[i + 3]) + end + end + i = i + o[1] end i = i + 1 end @@ -2644,12 +2659,26 @@ local default_rsync = { action = function(inlet) -- gets all events ready for syncing local elist = inlet.getEvents() + + ----- + -- replaces filter rule by literals + -- + local function sub(p) + if not p then + return + end + return p:gsub("%?", "\\?"): + gsub("%*", "\\*"): + gsub("%[", "\\["): + gsub("%]", "\\]") + end + local paths = elist.getPaths( function(etype, path1, path2) if etype == "Delete" and string.byte(path1, -1) == 47 then - return path1 .. "***", path2 + return sub(path1) .. "***", sub(path2) else - return path1, path2 + return sub(path1), sub(path2) end end) -- stores all filters with integer index @@ -2685,21 +2714,22 @@ local default_rsync = { end local filterS = table.concat(filterI, "\n") + local filter0 = table.concat(filterI, "\000") log("Normal", "Calling rsync with filter-list of new/modified files/dirs\n", filterS) local config = inlet.getConfig() spawn(elist, "/usr/bin/rsync", - "<", filterS, + "<", filter0, config.rsyncOps, "-r", "--delete", "--force", + "--from0", "--include-from=-", "--exclude=*", config.source, config.target) - end, ----- @@ -2782,10 +2812,12 @@ local default_rsyncssh = { end local sPaths = table.concat(paths, "\n") + local zPaths = table.concat(paths, "\000") log("Normal", "Deleting list\n", sPaths) spawn(elist, "/usr/bin/ssh", - "<", sPaths, - config.host, "xargs", "rm -rf") + "<", zPaths, + config.host, + "xargs", "-0", "rm -rf") return end @@ -2802,11 +2834,13 @@ local default_rsyncssh = { paths[k] = string.sub(v, 1, -2) end end - local sPaths = table.concat(paths, "\n") -- TODO 0 delimiter + local sPaths = table.concat(paths, "\n") + local zPaths = table.concat(paths, "\000") log("Normal", "Rsyncing list\n", sPaths) spawn(elist, "/usr/bin/rsync", - "<", sPaths, + "<", zPaths, config.rsyncOps, + "--from0", "--files-from=-", config.source, config.host .. ":" .. config.targetdir) @@ -3071,6 +3105,11 @@ default = { statusIntervall = 10, } +----- +-- provides a default empty settings table. +-- +settings = {} + ----- -- Returns the core the runners function interface. -- diff --git a/tests/churn-rsync.lua b/tests/churn-rsync.lua index f8de951..d7a1a1b 100755 --- a/tests/churn-rsync.lua +++ b/tests/churn-rsync.lua @@ -19,7 +19,7 @@ churn(srcdir, 10) local logs = {} --logs = {"-log", "Inotify", "-log", "Exec" } -local pid = spawn("./lsyncd", "-nodaemon", +local pid = spawn("./lsyncd", "-nodaemon", "-delay", "5", "-rsync", srcdir, trgdir, unpack(logs)) cwriteln("waiting for Lsyncd to startup") diff --git a/tests/churn-rsyncssh.lua b/tests/churn-rsyncssh.lua index 166a25c..046ea3f 100755 --- a/tests/churn-rsyncssh.lua +++ b/tests/churn-rsyncssh.lua @@ -21,7 +21,7 @@ local logs = {} --logs = {"-log", "Inotify", "-log", "Exec" } --logs = {"-log", "Delay"} -local pid = spawn("./lsyncd", "-nodaemon", +local pid = spawn("./lsyncd", "-nodaemon", "-delay", "5", "-rsyncssh", srcdir, "localhost", trgdir, unpack(logs))