* 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
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 \

View File

@ -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
]]

View File

@ -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);
}

View File

@ -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.
--

View File

@ -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")

View File

@ -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))