diff --git a/configure.ac b/configure.ac index 31ba6b0..43717ae 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. #AC_PREREQ(2.60) -AC_INIT(lsyncd, 2.0, axkibe@gmail.com) +AC_INIT(lsyncd, 2.0b1, axkibe@gmail.com) AC_CONFIG_SRCDIR([lsyncd.c]) AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE(lsyncd, main) diff --git a/lsyncd-conf.lua b/lsyncd-conf.lua index ca279f0..3443c8e 100644 --- a/lsyncd-conf.lua +++ b/lsyncd-conf.lua @@ -1,4 +1,5 @@ settings = { + logfile = "/tmp/lsyncd", nodaemon, } diff --git a/lsyncd.c b/lsyncd.c index abe3d78..1ddeb63 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -26,6 +26,11 @@ #include #include +/** + * The Lua part of lsyncd. + */ +#define LSYNCD_RUNNER_FILE "lsyncd.lua" + /** * The inotify file descriptor. */ @@ -39,6 +44,13 @@ const uint32_t standard_event_mask = IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | IN_MOVED_TO | IN_DONT_FOLLOW | IN_ONLYDIR; +/** + * Configuration settings relevant for core. + */ +struct settings { + char * logfile; +}; +struct settings settings = {0,}; /** * Set to TERM or HUP in signal handler, when lsyncd should end or reset ASAP. @@ -74,6 +86,22 @@ s_malloc(size_t size) return r; } +/** + * "secured" strdup. + */ +char * +s_strdup(const char *src) +{ + char *s = strdup(src); + if (s == NULL) { + printf("Out of memory!\n"); + exit(-1); // ERRNO + } + return s; +} + + + /***************************************************************************** * Library calls for lsyncd.lua * @@ -250,7 +278,7 @@ l_sub_dirs (lua_State *L) isdir = S_ISDIR(st.st_mode); free(subdir); } else { - /* we can trust readdir */ + /* readdir can trusted */ isdir = de->d_type == DT_DIR; } if (!isdir || !strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { @@ -281,10 +309,6 @@ l_terminate(lua_State *L) return 0; } -/***************************************************************************** - * Lsyncd Core - ****************************************************************************/ - static const luaL_reg lsyncdlib[] = { {"add_watch", l_add_watch}, {"exec", l_exec}, @@ -295,6 +319,44 @@ static const luaL_reg lsyncdlib[] = { {NULL, NULL} }; + +/***************************************************************************** + * Lsyncd Core + ****************************************************************************/ + +/** + * Transfers the core relevant settings from lua's global "settings" into core. + * This saves time in normal operation instead of bothering lua all the time. + */ +void +get_settings(lua_State *L) +{ + /* frees old settings */ + if (settings.logfile) { + free(settings.logfile); + settings.logfile = NULL; + } + + /* gets settings table */ + lua_getglobal(L, "settings"); + if (!lua_istable(L, -1)) { + /* user has not specified any settings */ + return; + } + + /* logfile */ + lua_pushstring(L, "logfile"); + lua_gettable(L, -2); + if (settings.logfile) { + free(settings.logfile); + settings.logfile = NULL; + } + if (lua_isstring(L, -1)) { + settings.logfile = s_strdup(luaL_checkstring(L, -1)); + } + lua_pop(L, 1); +} + /** * Waits after startup for all children. * @@ -377,11 +439,9 @@ wait_startup(lua_State *L) } } } - free(pids); } - /** * Main */ @@ -398,20 +458,37 @@ main(int argc, char *argv[]) lua_setglobal(L, "lysncd"); if (luaL_loadfile(L, "lsyncd.lua")) { - printf("error loading lsyncd.lua: %s\n", lua_tostring(L, -1)); + printf("error loading '%s': %s\n", + LSYNCD_RUNNER_FILE, lua_tostring(L, -1)); return -1; // ERRNO } if (lua_pcall(L, 0, LUA_MULTRET, 0)) { - printf("error running lsyncd.lua: %s\n", lua_tostring(L, -1)); + printf("error preparing '%s': %s\n", + LSYNCD_RUNNER_FILE, lua_tostring(L, -1)); return -1; // ERRNO } - + + { + /* checks version match between runner/core */ + const char *lversion; + lua_getglobal(L, "lsyncd_version"); + lversion = luaL_checkstring(L, -1); + lua_pop(L, 1); + if (strcmp(lversion, PACKAGE_VERSION)) { + printf("Version mismatch '%s' is '%s', but core is '%s'\n", + LSYNCD_RUNNER_FILE, + lversion, + PACKAGE_VERSION); + return -1; // ERRNO + } + } + if (luaL_loadfile(L, "lsyncd-conf.lua")) { - printf("error loading lsyncd-conf.lua: %s\n", lua_tostring(L, -1)); + printf("error load lsyncd-conf.lua: %s\n", lua_tostring(L, -1)); return -1; // ERRNO } if (lua_pcall(L, 0, LUA_MULTRET, 0)) { - printf("error running lsyncd-conf.lua: %s\n", lua_tostring(L, -1)); + printf("error prep lsyncd-conf.lua: %s\n", lua_tostring(L, -1)); return -1; // ERRNO } @@ -426,13 +503,21 @@ main(int argc, char *argv[]) /* lua code will set configuration and add watches */ lua_getglobal(L, "lsyncd_initialize"); lua_call(L, 0, 0); + + /* load core settings into core */ + get_settings(L); /* startup */ /* lua code will perform startup calls like recursive rsync */ lua_getglobal(L, "startup"); lua_call(L, 0, 1); + /* wait for children spawned at startup */ wait_startup(L); + /* enter normal operation */ + lua_getglobal(L, "normalop"); + lua_call(L, 0, 1); + /* cleanup */ close(inotify_fd); lua_close(L); diff --git a/lsyncd.lua b/lsyncd.lua index c2c7eb9..30cd2ef 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -2,17 +2,21 @@ -- lsyncd runner implemented in LUA ------------------------------------------------------------------------------ +---- +-- Core will exit if version ids mismatch. +lsyncd_version = "2.0b1" + ---- -- Table of all directories to watch. -local origins = {} +origins = {} ---- -- all targets -local targets = {} +targets = {} ----- -- all watches -local watches = {} +watches = {} ---- -- Adds watches for a directory including all subdirectories. @@ -21,7 +25,6 @@ local watches = {} -- @param target -- local function attend_dir(origin, path, target) - print("attending dir", origin, "+", path, "->", target.path); -- actual dir = origin + path local op = origin .. path -- register watch and receive watch descriptor @@ -54,10 +57,8 @@ end -- Called from core on init or restart after user configuration. -- function lsyncd_initialize() - print("--- INIT ---") local i, o for i, o in ipairs(origins) do - print("Handling ", o.source, "->" , o.targetpath) -- resolves source to be an absolute path local src = lsyncd.real_dir(o.source) if src == nil then @@ -100,12 +101,11 @@ end -- "startup". (and yet may still call default startup) -- function default_startup() - print("--- STARTUP ---") + print("--- startup ---") local pids = { } for i, o in ipairs(origins) do - print("/usr/bin/rsync", "-ltrs", o.source, o.targetpath) + print("initialize recursive rsync: " .. o.source .. " -> " .. o.targetpath) pid = lsyncd.exec("/usr/bin/rsync", "-ltrs", o.source, o.targetpath) - print("started ", pid) table.insert(pids, pid) end return pids @@ -123,7 +123,6 @@ startup = default_startup -- finished/ok. -- function default_startup_returned(pid, exitcode) - print("startup_returned ", pid, exitcode); if exitcode ~= 0 then print("Startup process", pid, " failed") lsyncd.terminate(-1) -- ERRNO @@ -132,3 +131,16 @@ function default_startup_returned(pid, exitcode) end startup_returned = default_startup_returned +----- +-- Called by core after startup phase when finished waiting for +-- children spawned at startup. +-- +function default_normalop() + print("--- Entering normal operation with " .. #watches .. " monitored directories ---") +end +normalop = default_normalop + +---- +-- other functions the user might want to use +exec = lsyncd.exec +