mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-06-02 00:10:49 +00:00
* 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:
parent
9632075d33
commit
ed43c5c68a
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
]]
|
]]
|
||||||
|
|
17
lsyncd.c
17
lsyncd.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
71
lsyncd.lua
71
lsyncd.lua
|
@ -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.
|
||||||
--
|
--
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user