This commit is contained in:
Axel Kittenberger 2010-10-28 17:56:33 +00:00
parent 9976269bfb
commit d823e8b580
3 changed files with 125 additions and 33 deletions

View File

@ -5,8 +5,8 @@
--
settings = {
-- logfile = "/tmp/lsyncd",
nodaemon,
statuspipe = "/tmp/lsyncd.stat",
-- nodaemon,
statusfile = "/tmp/lsyncd.stat",
loglevel = DEBUG,
}

115
lsyncd.c
View File

@ -24,6 +24,7 @@
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdbool.h>
@ -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
*/

View File

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