diff --git a/lsyncd-conf.lua b/lsyncd-conf.lua index 0cd3e3e..d6edc7b 100644 --- a/lsyncd-conf.lua +++ b/lsyncd-conf.lua @@ -5,8 +5,8 @@ -- settings = { -- logfile = "/tmp/lsyncd", - nodaemon, - statuspipe = "/tmp/lsyncd.stat", +-- nodaemon, + statusfile = "/tmp/lsyncd.stat", loglevel = DEBUG, } diff --git a/lsyncd.c b/lsyncd.c index 751a053..a21dd60 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -100,7 +101,7 @@ static int inotify_fd; /** * TODO allow configure. */ -static const uint32_t standard_event_mask = +static const uint32_t standard_event_mask = IN_ATTRIB | IN_CLOSE_WRITE | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | IN_MOVED_TO | IN_DONT_FOLLOW | IN_ONLYDIR; @@ -131,11 +132,19 @@ enum loglevel { * configuration parameters */ static struct settings { + /** + * threshold for log messages + */ enum loglevel loglevel; - char * statuspipe; + + /** + * lsyncd will periodically write its status in this + * file if configured so. (for special observing only) + */ + char * statusfile; } settings = { .loglevel = DEBUG, - .statuspipe = NULL, + .statusfile = NULL, }; /** @@ -443,6 +452,7 @@ l_addto_clock(lua_State *L) lua_pushinteger(L, c1 + c2 * clocks_per_sec); return 1; } + /** * Executes a subprocess. Does not wait for it to return. * @@ -468,17 +478,20 @@ l_exec(lua_State *L) pid = fork(); if (pid == 0) { - // TODO - //if (!log->flag_nodaemon && log->logfile) { - // if (!freopen(log->logfile, "a", stdout)) { - // printlogf(log, ERROR, "cannot redirect stdout to [%s].", log->logfile); - // } - // if (!freopen(log->logfile, "a", stderr)) { - // printlogf(log, ERROR, "cannot redirect stderr to [%s].", log->logfile); - // } - //} + /* if lsyncd runs as a daemon and has a logfile it will redirect + stdout/stderr of child processes to the logfile. */ + if (is_daemon && logfile) { + if (!freopen(logfile, "a", stdout)) { + printlogf(L, ERROR, + "cannot redirect stdout to '%s'.", logfile); + } + if (!freopen(logfile, "a", stderr)) { + printlogf(L, ERROR, + "cannot redirect stderr to '%s'.", logfile); + } + } execv(binary, (char **)argv); - // in a sane world execv does not return! + /* in a sane world execv does not return! */ printlogf(L, ERROR, "Failed executing [%s]!", binary); exit(-1); // ERRNO } @@ -511,10 +524,16 @@ l_real_dir(lua_State *L) { /* makes sure its a directory */ struct stat st; - stat(cbuf, &st); + if (stat(cbuf, &st)) { + printlogf(L, ERROR, + "cannot get absolute path of dir '%s': %s", + rdir, strerror(errno)); + return 0; + } if (!S_ISDIR(st.st_mode)) { printlogf(L, ERROR, - "failure in real_dir '%s' is not a directory", rdir); + "cannot get absolute path of dir '%s': is not a directory", + rdir); free(cbuf); return 0; } @@ -617,6 +636,21 @@ l_sub_dirs (lua_State *L) return 1; } +/** + * Writes a string to a file descriptor + * + * @param (Lua Stack) file descriptor + * @param (Lua Stack) string. + */ +int +l_writefd(lua_State *L) +{ + int fd = luaL_checkinteger(L, 1); + const char *s = luaL_checkstring(L, 2); + write(fd, s, strlen(s)); + return 0; +} + /** * Terminates lsyncd daemon. * @@ -740,13 +774,12 @@ static int l_configure(lua_State *L) { const char * command = luaL_checkstring(L, 1); - if (!strcmp(command, "statuspipe")) { - /* configures the status pipe lsyncd will dump - * its status to if opened*/ - if (settings.statuspipe) { - free(settings.statuspipe); + if (!strcmp(command, "statusfile")) { + /* configures the status file lsyncd will dump its status to */ + if (settings.statusfile) { + free(settings.statusfile); } - settings.statuspipe = s_strdup(luaL_checkstring(L, 2)); + settings.statusfile = s_strdup(luaL_checkstring(L, 2)); } else if (!strcmp(command, "loglevel")) { settings.loglevel = luaL_checkinteger(L, 2); } else if (!strcmp(command, "running")) { @@ -773,6 +806,7 @@ static const luaL_reg lsyncdlib[] = { {"exec", l_exec }, {"log", l_log }, {"now", l_now }, + {"writefd", l_writefd }, {"real_dir", l_real_dir }, {"stackdump", l_stackdump }, {"sub_dirs", l_sub_dirs }, @@ -813,8 +847,15 @@ printlogf(lua_State *L, * Lsyncd buffers MOVE_FROM events to check if */ struct inotify_event * move_event_buf = NULL; + +/** + * Memory allocated for move_event_buf + */ size_t move_event_buf_size = 0; -/* true if the buffer is used.*/ + +/** + * true if the buffer is used. + */ bool move_event = false; /** @@ -826,6 +867,7 @@ void handle_event(lua_State *L, struct inotify_event *event) { /* used to execute two events in case of unmatched MOVE_FROM buffer */ struct inotify_event *after_buf = NULL; + logstring(DEBUG, "got an event"); if (reset) { return; @@ -1015,7 +1057,7 @@ masterloop(lua_State *L) handle_event(L, NULL); } - /* collect zombified child processes */ + /* collects zombified child processes */ while(1) { int status; pid_t pid = waitpid(0, &status, WNOHANG); @@ -1028,7 +1070,29 @@ masterloop(lua_State *L) lua_call(L, 2, 0); } - /* let the runner spawn new processes */ + /* writes status of lsyncd in a file */ + /* this is not a real loop, it will only be runned once max. + * this is just using break as comfortable jump down. */ + while (settings.statusfile) { + int fd = open(settings.statusfile, O_WRONLY | O_CREAT | O_TRUNC); + if (fd < 0) { + printlogf(L, ERROR, + "Cannot open statusfile '%s' for writing.", + settings.statusfile); + break; + } + /* calls the lua runner to write the status. */ + lua_getglobal(L, "lsyncd_status_report"); + lua_pushinteger(L, fd); + lua_call(L, 1, 0); + + /* TODO */ + fsync(fd); + close(fd); + break; + } + + /* lets the runner spawn new processes */ lua_getglobal(L, "lsyncd_alarm"); lua_pushinteger(L, times(NULL)); lua_call(L, 1, 0); @@ -1036,7 +1100,7 @@ masterloop(lua_State *L) } /** - * Prints a minimal help if e.g. config_file is missing + * Prints a minimal help if e.g. config_file is missing. */ void minihelp(char *arg0) { @@ -1045,7 +1109,6 @@ void minihelp(char *arg0) fprintf(stderr, " Specify -help for more help.\n"); } - /** * Main */ diff --git a/lsyncd.lua b/lsyncd.lua index ca78354..694fe89 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -188,7 +188,9 @@ end ---- --- Table of all root directories to sync, +-- origins +-- +-- table of all root directories to sync. -- filled during initialization. -- -- [#] { @@ -212,11 +214,19 @@ end -- } -- local origins = new_array() -local proto_origin = {actions=true, source=true, targetident=true, processes=true, delays=true, delaywd=true} -local proto_delay = {atype =true, alarm=true, wd=true, sync=true, filename=true, movepeer=true} +local proto_origin = { + actions=true, source=true, targetident=true, + processes=true, delays=true, delaywd=true + } +local proto_delay = { + atype =true, alarm=true, wd=true, + sync=true, filename=true, movepeer=true + } ----- --- all watches +-- watches +-- +-- contains all inotify watches. -- -- structure: -- [wd] = { @@ -439,6 +449,25 @@ local function invoke_action(delay) end +---- +-- Called from core to get a status report written into a file descriptor +-- +function lsyncd_status_report(fd) + local w = lsyncd.writefd + w(fd, "Lsyncd status report at "..os.date().."\n\n") + w(fd, "Watching "..watches.size.." directories\n") + for i, v in pairs(watches) do + w(fd, " "..i..": ") + if i ~= v.wd then + w(fd, "[Error: wd/v.wd "..i.."~="..v.wd.."]") + end + for _, s in pairs(v.syncs) do + w(fd, "("..s.origin.source.."//"..s.origin.path..")") + end + w(fd, "\n") + end +end + ---- -- Called from core everytime at the latest of an -- expired alarm (or more often) @@ -511,7 +540,7 @@ function lsyncd_initialize(args) terminate(-1); -- ERRNO end end}, - statuspipe = {1, nil}, + statusfile = {1, nil}, } -- check all entries in the settings table