* use zero instead of \n delimiter in rsyncd / rsyncssh

* allowed zeros in pipes
* allow overriding delay values
* use a layer ^ in layer 3 scripts to force shell instead of
  direct binary calls
* escape ?*[] for rsync PATTERNS
This commit is contained in:
Axel Kittenberger 2010-11-28 20:16:56 +00:00
parent 9632075d33
commit ed43c5c68a
6 changed files with 91 additions and 49 deletions

View File

@ -1,5 +1,5 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
CFLAGS = -Wall $(LIBLUA_CFLAGS) CFLAGS = -Wall $(LUA_CFLAGS)
bin_PROGRAMS = lsyncd bin_PROGRAMS = lsyncd
lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua
if INOTIFY if INOTIFY
@ -13,7 +13,7 @@ if FSEVENTS
lsyncd_SOURCES += fsevents.c lsyncd_SOURCES += fsevents.c
endif endif
lsyncd_LDADD = $(LIBLUA_LIBS) lsyncd_LDADD = $(LUA_LIBS)
exampledir = $(datarootdir)/doc/@PACKAGE@ exampledir = $(datarootdir)/doc/@PACKAGE@
dist_example_DATA = \ dist_example_DATA = \
examples/lbash.lua \ examples/lbash.lua \

View File

@ -56,13 +56,11 @@ fi
-- all group permissions are set to rw -- all group permissions are set to rw
-- and to executable flag for directories -- and to executable flag for directories
-- --
-- the hash in the first line is important, otherwise due to the starting -- the carret as first char tells Lsycnd to call a shell altough it
-- slash, Lsyncd would think it is a call to the binary /bin/chgrp only -- starts with a slash otherwisw
-- and would optimize the bash away.
-- --
startup = startup =
[[# [[^/bin/chgrp -R ]]..fgroup..[[ ^source || /bin/true &&
/bin/chgrp -R ]]..fgroup..[[ ^source || /bin/true &&
/bin/chmod -R g+rw ^source || /bin/true && /bin/chmod -R g+rw ^source || /bin/true &&
/usr/bin/find ^source -type d | xargs chmod g+x /usr/bin/find ^source -type d | xargs chmod g+x
]] ]]

View File

@ -642,6 +642,7 @@ l_exec(lua_State *L)
/* the pipe to text */ /* the pipe to text */
char const *pipe_text = NULL; char const *pipe_text = NULL;
size_t pipe_len = 0;
/* the arguments */ /* the arguments */
char const **argv; char const **argv;
/* pipe file descriptors */ /* pipe file descriptors */
@ -663,7 +664,11 @@ l_exec(lua_State *L)
if (argc >= 2 && !strcmp(luaL_checkstring(L, 2), "<")) { if (argc >= 2 && !strcmp(luaL_checkstring(L, 2), "<")) {
/* pipes something into stdin */ /* 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 */ /* creates the pipe */
if (pipe(pipefd) == -1) { if (pipe(pipefd) == -1) {
logstring("Error", "cannot create a pipe!"); logstring("Error", "cannot create a pipe!");
@ -716,17 +721,16 @@ l_exec(lua_State *L)
} }
if (pipe_text) { if (pipe_text) {
int tlen = strlen(pipe_text);
int len; int len;
/* first closes read-end of pipe, this is for child process only */ /* first closes read-end of pipe, this is for child process only */
close(pipefd[0]); close(pipefd[0]);
/* start filling the pipe */ /* start filling the pipe */
len = write(pipefd[1], pipe_text, tlen); len = write(pipefd[1], pipe_text, pipe_len);
if (len < 0) { if (len < 0) {
logstring("Normal", "immediatly broken pipe."); logstring("Normal", "immediatly broken pipe.");
close(pipefd[0]); close(pipefd[0]);
} }
if (len == tlen) { if (len == pipe_len) {
/* usual and best case, the pipe accepted all input -> close */ /* usual and best case, the pipe accepted all input -> close */
close(pipefd[1]); close(pipefd[1]);
logstring("Exec", "one-sweeped pipe"); logstring("Exec", "one-sweeped pipe");
@ -734,8 +738,9 @@ l_exec(lua_State *L)
struct pipemsg *pm; struct pipemsg *pm;
logstring("Exec", "adding pipe observance"); logstring("Exec", "adding pipe observance");
pm = s_calloc(1, sizeof(struct pipemsg)); pm = s_calloc(1, sizeof(struct pipemsg));
pm->text = s_strdup(pipe_text); pm->text = s_calloc(pipe_len + 1, sizeof(char*));
pm->tlen = tlen; memcpy(pm->text, pipe_text, pipe_len + 1);
pm->tlen = pipe_len;
pm->pos = len; pm->pos = len;
observe_fd(pipefd[1], NULL, pipe_writey, pipe_tidy, pm); observe_fd(pipefd[1], NULL, pipe_writey, pipe_tidy, pm);
} }

View File

@ -1374,10 +1374,17 @@ local Syncs = (function()
config = {} config = {}
inherit(config, uconfig) 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. -- fill out more values.
if type(config.prepare) == "function" then if type(config.prepare) == "function" then
-- give explicitly a writeable copy of config. -- explicitly gives a writeable copy of config.
config.prepare(config) config.prepare(config)
end end
@ -1995,7 +2002,11 @@ local functionWriter = (function()
local ft local ft
if string.byte(str, 1, 1) == 47 then if string.byte(str, 1, 1) == 47 then
-- starts with /
ft = translateBinary(str) ft = translateBinary(str)
elseif string.byte(str, 1, 1) == 94 then
-- starts with ^
ft = translateShell(str:sub(2, -1))
else else
ft = translateShell(str) ft = translateShell(str)
end end
@ -2185,6 +2196,7 @@ USAGE:
lsyncd [OPTIONS] -rsyncssh [SOURCE] [HOST] [TARGETDIR] lsyncd [OPTIONS] -rsyncssh [SOURCE] [HOST] [TARGETDIR]
OPTIONS: OPTIONS:
-delay SECS Overrides default delay times
-help Shows this -help Shows this
-log all Logs everything (debug) -log all Logs everything (debug)
-log scarce Logs errors only -log scarce Logs errors only
@ -2232,6 +2244,10 @@ function runner.configure(args, monitors)
-- --
local options = { local options = {
-- log is handled by core already. -- log is handled by core already.
delay =
{1, function(secs)
clSettings.delay = secs
end},
log = log =
{1, nil}, {1, nil},
logfile = logfile =
@ -2289,11 +2305,14 @@ function runner.configure(args, monitors)
a = a:sub(2) a = a:sub(2)
end end
local o = options[a] local o = options[a]
if o then 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 if o[1] >= 0 and i + o[1] > #args then
log("Error",a," needs ",o[1]," arguments") log("Error",a," needs ",o[1]," arguments")
os.exit(-1) -- ERRNO os.exit(-1) -- ERRNO
else elseif o[1] < 0 then
o[1] = -o[1] o[1] = -o[1]
end end
if o[2] then if o[2] then
@ -2308,10 +2327,6 @@ function runner.configure(args, monitors)
end end
end end
i = i + o[1] i = i + o[1]
else
log("Error","unknown option command line option ", args[i])
os.exit(-1) -- ERRNO
end
end end
i = i + 1 i = i + 1
end end
@ -2644,12 +2659,26 @@ local default_rsync = {
action = function(inlet) action = function(inlet)
-- gets all events ready for syncing -- gets all events ready for syncing
local elist = inlet.getEvents() 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( local paths = elist.getPaths(
function(etype, path1, path2) function(etype, path1, path2)
if etype == "Delete" and string.byte(path1, -1) == 47 then if etype == "Delete" and string.byte(path1, -1) == 47 then
return path1 .. "***", path2 return sub(path1) .. "***", sub(path2)
else else
return path1, path2 return sub(path1), sub(path2)
end end
end) end)
-- stores all filters with integer index -- stores all filters with integer index
@ -2685,21 +2714,22 @@ local default_rsync = {
end end
local filterS = table.concat(filterI, "\n") local filterS = table.concat(filterI, "\n")
local filter0 = table.concat(filterI, "\000")
log("Normal", log("Normal",
"Calling rsync with filter-list of new/modified files/dirs\n", "Calling rsync with filter-list of new/modified files/dirs\n",
filterS) filterS)
local config = inlet.getConfig() local config = inlet.getConfig()
spawn(elist, "/usr/bin/rsync", spawn(elist, "/usr/bin/rsync",
"<", filterS, "<", filter0,
config.rsyncOps, config.rsyncOps,
"-r", "-r",
"--delete", "--delete",
"--force", "--force",
"--from0",
"--include-from=-", "--include-from=-",
"--exclude=*", "--exclude=*",
config.source, config.source,
config.target) config.target)
end, end,
----- -----
@ -2782,10 +2812,12 @@ local default_rsyncssh = {
end end
local sPaths = table.concat(paths, "\n") local sPaths = table.concat(paths, "\n")
local zPaths = table.concat(paths, "\000")
log("Normal", "Deleting list\n", sPaths) log("Normal", "Deleting list\n", sPaths)
spawn(elist, "/usr/bin/ssh", spawn(elist, "/usr/bin/ssh",
"<", sPaths, "<", zPaths,
config.host, "xargs", "rm -rf") config.host,
"xargs", "-0", "rm -rf")
return return
end end
@ -2802,11 +2834,13 @@ local default_rsyncssh = {
paths[k] = string.sub(v, 1, -2) paths[k] = string.sub(v, 1, -2)
end end
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) log("Normal", "Rsyncing list\n", sPaths)
spawn(elist, "/usr/bin/rsync", spawn(elist, "/usr/bin/rsync",
"<", sPaths, "<", zPaths,
config.rsyncOps, config.rsyncOps,
"--from0",
"--files-from=-", "--files-from=-",
config.source, config.source,
config.host .. ":" .. config.targetdir) config.host .. ":" .. config.targetdir)
@ -3071,6 +3105,11 @@ default = {
statusIntervall = 10, statusIntervall = 10,
} }
-----
-- provides a default empty settings table.
--
settings = {}
----- -----
-- Returns the core the runners function interface. -- Returns the core the runners function interface.
-- --

View File

@ -19,7 +19,7 @@ churn(srcdir, 10)
local logs = {} local logs = {}
--logs = {"-log", "Inotify", "-log", "Exec" } --logs = {"-log", "Inotify", "-log", "Exec" }
local pid = spawn("./lsyncd", "-nodaemon", local pid = spawn("./lsyncd", "-nodaemon", "-delay", "5",
"-rsync", srcdir, trgdir, unpack(logs)) "-rsync", srcdir, trgdir, unpack(logs))
cwriteln("waiting for Lsyncd to startup") cwriteln("waiting for Lsyncd to startup")

View File

@ -21,7 +21,7 @@ local logs = {}
--logs = {"-log", "Inotify", "-log", "Exec" } --logs = {"-log", "Inotify", "-log", "Exec" }
--logs = {"-log", "Delay"} --logs = {"-log", "Delay"}
local pid = spawn("./lsyncd", "-nodaemon", local pid = spawn("./lsyncd", "-nodaemon", "-delay", "5",
"-rsyncssh", srcdir, "localhost", trgdir, "-rsyncssh", srcdir, "localhost", trgdir,
unpack(logs)) unpack(logs))