mirror of https://github.com/octoleo/lsyncd.git
log to syslog (or alternatively to file).
This commit is contained in:
parent
f4416eba1f
commit
7fc6677f7e
360
lsyncd.c
360
lsyncd.c
|
@ -31,6 +31,7 @@
|
|||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
#include <assert.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef XML_CONFIG
|
||||
#include <libxml/parser.h>
|
||||
|
@ -39,15 +40,16 @@
|
|||
|
||||
#define INOTIFY_BUF_LEN (512 * (sizeof(struct inotify_event) + 16))
|
||||
|
||||
#define LOG_DEBUG 1
|
||||
#define LOG_NORMAL 2
|
||||
#define LOG_ERROR 3
|
||||
enum log_code {
|
||||
DEBUG = 1,
|
||||
NORMAL = 2,
|
||||
ERROR = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible Exit codes for this application
|
||||
*/
|
||||
enum lsyncd_exit_code
|
||||
{
|
||||
enum lsyncd_exit_code {
|
||||
LSYNCD_SUCCESS = 0,
|
||||
|
||||
/* out-of memory */
|
||||
|
@ -186,7 +188,7 @@ struct inotify_mask_text {
|
|||
/**
|
||||
* Global Option: The loglevel is how eloquent lsyncd will be.
|
||||
*/
|
||||
int loglevel = LOG_NORMAL;
|
||||
int loglevel = NORMAL;
|
||||
|
||||
/**
|
||||
* Global Option: if true no action will actually be called.
|
||||
|
@ -308,16 +310,21 @@ int dir_watch_size = 0;
|
|||
int dir_watch_num = 0;
|
||||
|
||||
/**
|
||||
* lsyncd will log into this file/stream.
|
||||
* If not NULL, this file will be accessed directly to write log messages to.
|
||||
* If NULL, syslog will be used.
|
||||
*
|
||||
* Not as difference that the output of child processes (rsync) will be redirected
|
||||
* to the logfile if specified, if syslogging the child-output will run into /dev/null.
|
||||
*
|
||||
* If flag_nodaemon is present stdout/stderr will be used.
|
||||
*/
|
||||
char * logfile = "/var/log/lsyncd";
|
||||
char * logfile = NULL;
|
||||
|
||||
/**
|
||||
* The inotify instance.
|
||||
*/
|
||||
int inotf;
|
||||
|
||||
|
||||
/**
|
||||
* Array of strings of directory names to include.
|
||||
* This is limited to MAX_EXCLUDES.
|
||||
|
@ -346,58 +353,121 @@ void catch_alarm(int sig)
|
|||
}
|
||||
|
||||
/**
|
||||
* Prints a message to the log stream, preceding a timestamp.
|
||||
* Just like exit, but logs the exit.
|
||||
*
|
||||
* Does not return!
|
||||
*/
|
||||
void terminate(int status)
|
||||
{
|
||||
if (!flag_nodaemon) {
|
||||
if (logfile) {
|
||||
FILE * flog;
|
||||
flog = fopen(logfile, "a");
|
||||
if (flog) {
|
||||
fprintf(flog, "exit!");
|
||||
fclose(flog);
|
||||
}
|
||||
} else {
|
||||
syslog(LOG_ERR, "exit!");
|
||||
}
|
||||
}
|
||||
exit(status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints a message to either the log stream, preceding a timestamp or
|
||||
* forwards a message to syslogd.
|
||||
*
|
||||
* Otherwise it behaves like printf();
|
||||
*
|
||||
* It will also always produce error messages on stderr.
|
||||
* So when startup fails, the message will be logged
|
||||
* _and_ displayed on screen. If lsyncd daemonized already,
|
||||
* stderr will be run into the void of /dev/null.
|
||||
*/
|
||||
void printlogf(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char * ct;
|
||||
time_t mtime;
|
||||
FILE * flog;
|
||||
FILE * flog1 = NULL, * flog2 = NULL;
|
||||
int sysp = 0;
|
||||
|
||||
if (level < loglevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!flag_nodaemon) {
|
||||
flog = fopen(logfile, "a");
|
||||
if (!flag_nodaemon && logfile) {
|
||||
flog1 = fopen(logfile, "a");
|
||||
|
||||
if (flog == NULL) {
|
||||
if (flog1 == NULL) {
|
||||
fprintf(stderr, "cannot open logfile [%s]!\n", logfile);
|
||||
exit(LSYNCD_FILENOTFOUND);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
} else {
|
||||
flog = stdout;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
time(&mtime);
|
||||
ct = ctime(&mtime);
|
||||
ct[strlen(ct) - 1] = 0; // cut trailing \n
|
||||
fprintf(flog, "%s: ", ct);
|
||||
ct[strlen(ct) - 1] = 0; // cut trailing linefeed
|
||||
|
||||
switch (level) {
|
||||
|
||||
case LOG_DEBUG :
|
||||
case DEBUG :
|
||||
sysp = LOG_DEBUG;
|
||||
if (flag_nodaemon) {
|
||||
flog2 = stdout;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG_NORMAL :
|
||||
case NORMAL :
|
||||
sysp = LOG_NOTICE;
|
||||
if (flag_nodaemon) {
|
||||
flog2 = stdout;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOG_ERROR :
|
||||
fprintf(flog, "ERROR: ");
|
||||
case ERROR :
|
||||
sysp = LOG_ERR;
|
||||
// write on stderr even when daemon.
|
||||
flog2 = stderr;
|
||||
break;
|
||||
}
|
||||
|
||||
vfprintf(flog, fmt, ap);
|
||||
// write time on fileoutput
|
||||
if (flog1) {
|
||||
fprintf(flog1, "%s: ", ct);
|
||||
}
|
||||
|
||||
fprintf(flog, "\n");
|
||||
if (level == ERROR) {
|
||||
if (flog1) {
|
||||
fprintf(flog1, "ERROR: ");
|
||||
}
|
||||
if (flog2) {
|
||||
fprintf(flog2, "ERROR: ");
|
||||
}
|
||||
}
|
||||
|
||||
if (flog1) {
|
||||
vfprintf(flog1, fmt, ap);
|
||||
} else {
|
||||
vsyslog(sysp, fmt, ap);
|
||||
}
|
||||
if (flog2) {
|
||||
vfprintf(flog2, fmt, ap);
|
||||
}
|
||||
|
||||
if (flog1) {
|
||||
fprintf(flog1, "\n");
|
||||
}
|
||||
if (flog2) {
|
||||
fprintf(flog2, "\n");
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if (!flag_nodaemon) {
|
||||
fclose(flog);
|
||||
if (flog1) {
|
||||
fclose(flog1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,8 +486,8 @@ void *s_malloc(size_t size)
|
|||
void *r = malloc(size);
|
||||
|
||||
if (r == NULL) {
|
||||
printlogf(LOG_ERROR, "Out of memory!");
|
||||
exit(LSYNCD_OUTOFMEMORY);
|
||||
printlogf(ERROR, "Out of memory!");
|
||||
terminate(LSYNCD_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -431,8 +501,8 @@ void *s_calloc(size_t nmemb, size_t size)
|
|||
void *r = calloc(nmemb, size);
|
||||
|
||||
if (r == NULL) {
|
||||
printlogf(LOG_ERROR, "Out of memory!");
|
||||
exit(LSYNCD_OUTOFMEMORY);
|
||||
printlogf(ERROR, "Out of memory!");
|
||||
terminate(LSYNCD_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -446,8 +516,8 @@ void *s_realloc(void *ptr, size_t size)
|
|||
void *r = realloc(ptr, size);
|
||||
|
||||
if (r == NULL) {
|
||||
printlogf(LOG_ERROR, "Out of memory!");
|
||||
exit(LSYNCD_OUTOFMEMORY);
|
||||
printlogf(ERROR, "Out of memory!");
|
||||
terminate(LSYNCD_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -461,8 +531,8 @@ char *s_strdup(const char* src)
|
|||
char *s = strdup(src);
|
||||
|
||||
if (s == NULL) {
|
||||
printlogf(LOG_ERROR, "Out of memory!");
|
||||
exit(LSYNCD_OUTOFMEMORY);
|
||||
printlogf(ERROR, "Out of memory!");
|
||||
terminate(LSYNCD_OUTOFMEMORY);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
@ -559,7 +629,7 @@ void dir_conf_add_target(struct dir_conf * dir_conf, char *target)
|
|||
bool append_tosync_watch(int watch) {
|
||||
int i;
|
||||
|
||||
printlogf(LOG_DEBUG, "append_tosync_watch(%d)", watch);
|
||||
printlogf(DEBUG, "append_tosync_watch(%d)", watch);
|
||||
// look if its already in the tosync list.
|
||||
for(i = 0; i < tosync_pos; i++) {
|
||||
if (tosync[i] == watch) {
|
||||
|
@ -620,9 +690,9 @@ char *parse_option_text(char *text, bool recursive)
|
|||
break;
|
||||
case 0: // wtf, '%' was at the end of the string!
|
||||
default : // unknown char
|
||||
printlogf(LOG_ERROR,
|
||||
printlogf(ERROR,
|
||||
"don't know how to handle '\%' specifier in \"%s\"!", *text);
|
||||
exit(LSYNCD_BADPARAMETERS);
|
||||
terminate(LSYNCD_BADPARAMETERS);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
|
@ -679,7 +749,7 @@ bool action(struct dir_conf * dir_conf,
|
|||
}
|
||||
if (argc >= MAX_ARGS) {
|
||||
/* check for error condition */
|
||||
printlogf(LOG_ERROR,
|
||||
printlogf(ERROR,
|
||||
"Internal error: too many (>%i) options passed", argc);
|
||||
return false;
|
||||
}
|
||||
|
@ -688,7 +758,7 @@ bool action(struct dir_conf * dir_conf,
|
|||
|
||||
/* debug dump of command-line options */
|
||||
//for (i=0; i<argc; ++i) {
|
||||
// printlogf(LOG_DEBUG, "exec parameter %i:%s", i, argv[i]);
|
||||
// printlogf(DEBUG, "exec parameter %i:%s", i, argv[i]);
|
||||
//}
|
||||
|
||||
if (flag_dryrun) {
|
||||
|
@ -699,18 +769,18 @@ bool action(struct dir_conf * dir_conf,
|
|||
|
||||
if (pid == 0) {
|
||||
char * binary = dir_conf->binary ? dir_conf->binary : default_binary;
|
||||
if (!flag_nodaemon) {
|
||||
if (!flag_nodaemon && logfile) {
|
||||
if (!freopen(logfile, "a", stdout)) {
|
||||
printlogf(LOG_ERROR, "cannot redirect stdout to [%s].", logfile);
|
||||
printlogf(ERROR, "cannot redirect stdout to [%s].", logfile);
|
||||
}
|
||||
if (!freopen(logfile, "a", stderr)) {
|
||||
printlogf(LOG_ERROR, "cannot redirect stderr to [%s].", logfile);
|
||||
printlogf(ERROR, "cannot redirect stderr to [%s].", logfile);
|
||||
}
|
||||
}
|
||||
|
||||
execv(binary, argv); // in a sane world does not return!
|
||||
printlogf(LOG_ERROR, "Failed executing [%s]", binary);
|
||||
exit(LSYNCD_INTERNALFAIL);
|
||||
printlogf(ERROR, "Failed executing [%s]", binary);
|
||||
terminate(LSYNCD_INTERNALFAIL);
|
||||
}
|
||||
|
||||
for (i=0; i<argc; ++i) {
|
||||
|
@ -722,18 +792,18 @@ bool action(struct dir_conf * dir_conf,
|
|||
waitpid(pid, &status, 0);
|
||||
assert(WIFEXITED(status));
|
||||
if (WEXITSTATUS(status)==LSYNCD_INTERNALFAIL){
|
||||
printlogf(LOG_ERROR,
|
||||
printlogf(ERROR,
|
||||
"Fork exit code of %i, execv failure",
|
||||
WEXITSTATUS(status));
|
||||
return false;
|
||||
} else if (WEXITSTATUS(status)) {
|
||||
printlogf(LOG_NORMAL,
|
||||
printlogf(NORMAL,
|
||||
"Forked binary process returned non-zero return code: %i",
|
||||
WEXITSTATUS(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
printlogf(LOG_DEBUG, "Rsync of [%s] -> [%s] finished", src, dest);
|
||||
printlogf(DEBUG, "Rsync of [%s] -> [%s] finished", src, dest);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -761,7 +831,7 @@ int add_watch(char const * pathname,
|
|||
IN_MOVED_TO | IN_DONT_FOLLOW | IN_ONLYDIR);
|
||||
|
||||
if (wd == -1) {
|
||||
printlogf(LOG_ERROR, "Cannot add watch %s (%d:%s)",
|
||||
printlogf(ERROR, "Cannot add watch %s (%d:%s)",
|
||||
pathname, errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
@ -856,17 +926,17 @@ bool buildpath(char *pathname,
|
|||
{
|
||||
int len = builddir(pathname, pathsize, watch, prefix);
|
||||
if (len < 0) {
|
||||
printlogf(LOG_ERROR, "path too long!");
|
||||
printlogf(ERROR, "path too long!");
|
||||
return false;
|
||||
}
|
||||
if (dirname) {
|
||||
if (pathsize < len + strlen(dirname) + 1) {
|
||||
printlogf(LOG_ERROR, "path too long!");
|
||||
printlogf(ERROR, "path too long!");
|
||||
return false;
|
||||
}
|
||||
strcat(pathname, dirname);
|
||||
}
|
||||
printlogf(LOG_DEBUG, " BUILDPATH(%d, %s, %s) -> %s", watch, dirname, prefix, pathname);
|
||||
printlogf(DEBUG, " BUILDPATH(%d, %s, %s) -> %s", watch, dirname, prefix, pathname);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -893,11 +963,11 @@ bool rsync_dir(int watch)
|
|||
status = false;
|
||||
continue;
|
||||
}
|
||||
printlogf(LOG_NORMAL, "rsyncing %s --> %s", pathname, destname);
|
||||
printlogf(NORMAL, "rsyncing %s --> %s", pathname, destname);
|
||||
|
||||
// call rsync to propagate changes in the directory
|
||||
if (!action(dir_watches[watch].dir_conf, pathname, destname, false)) {
|
||||
printlogf(LOG_ERROR, "Rsync from %s to %s failed", pathname, destname);
|
||||
printlogf(ERROR, "Rsync from %s to %s failed", pathname, destname);
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
|
@ -922,7 +992,7 @@ int add_dirwatch(char const * dirname, int parent, struct dir_conf * dir_conf)
|
|||
int dw, i;
|
||||
char pathname[PATH_MAX+1];
|
||||
|
||||
printlogf(LOG_DEBUG, "add_dirwatch(%s, p->dirname:%s, ...)",
|
||||
printlogf(DEBUG, "add_dirwatch(%s, p->dirname:%s, ...)",
|
||||
dirname,
|
||||
parent >= 0 ? dir_watches[parent].dirname : "NULL");
|
||||
|
||||
|
@ -942,14 +1012,14 @@ int add_dirwatch(char const * dirname, int parent, struct dir_conf * dir_conf)
|
|||
}
|
||||
|
||||
if (strlen(pathname) + strlen(dirname) + 2 > sizeof(pathname)) {
|
||||
printlogf(LOG_ERROR, "pathname too long %s//%s", pathname, dirname);
|
||||
printlogf(ERROR, "pathname too long %s//%s", pathname, dirname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d = opendir(pathname);
|
||||
|
||||
if (d == NULL) {
|
||||
printlogf(LOG_ERROR, "cannot open dir %s.", dirname);
|
||||
printlogf(ERROR, "cannot open dir %s.", dirname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -976,7 +1046,7 @@ int add_dirwatch(char const * dirname, int parent, struct dir_conf * dir_conf)
|
|||
}
|
||||
if (isdir && strcmp(de->d_name, "..") && strcmp(de->d_name, ".")) {
|
||||
int ndw = add_dirwatch(de->d_name, dw, dir_conf);
|
||||
printlogf(LOG_NORMAL,
|
||||
printlogf(NORMAL,
|
||||
"found new directory: %s in %s -- added on tosync stack.",
|
||||
de->d_name, dirname);
|
||||
append_tosync_watch(ndw);
|
||||
|
@ -1011,7 +1081,7 @@ bool remove_dirwatch(const char * name, int parent)
|
|||
}
|
||||
|
||||
if (i >= dir_watch_num) {
|
||||
printlogf(LOG_ERROR, "Cannot find entry for %s:/:%s :-(",
|
||||
printlogf(ERROR, "Cannot find entry for %s:/:%s :-(",
|
||||
dir_watches[parent].dirname, name);
|
||||
return false;
|
||||
}
|
||||
|
@ -1064,11 +1134,11 @@ int get_dirwatch_offset(int wd) {
|
|||
*/
|
||||
bool process_tosync_stack()
|
||||
{
|
||||
printlogf(LOG_DEBUG, "Processing through tosync stack.");
|
||||
printlogf(DEBUG, "Processing through tosync stack.");
|
||||
while(tosync_pos > 0) {
|
||||
rsync_dir(tosync[--tosync_pos]);
|
||||
}
|
||||
printlogf(LOG_DEBUG, "being done with tosync stack");
|
||||
printlogf(DEBUG, "being done with tosync stack");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1091,7 +1161,7 @@ bool handle_event(struct inotify_event *event)
|
|||
for (p = mask_texts; p->mask; p++) {
|
||||
if (mask & p->mask) {
|
||||
if (strlen(masktext) + strlen(p->text) + 3 >= sizeof(masktext)) {
|
||||
printlogf(LOG_ERROR, "bufferoverflow in handle_event");
|
||||
printlogf(ERROR, "bufferoverflow in handle_event");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1102,7 +1172,7 @@ bool handle_event(struct inotify_event *event)
|
|||
strcat(masktext, p->text);
|
||||
}
|
||||
}
|
||||
printlogf(LOG_DEBUG, "inotfy event: %s:%s", masktext, event->name);
|
||||
printlogf(DEBUG, "inotfy event: %s:%s", masktext, event->name);
|
||||
|
||||
if (IN_IGNORED & event->mask) {
|
||||
return true;
|
||||
|
@ -1116,7 +1186,7 @@ bool handle_event(struct inotify_event *event)
|
|||
|
||||
watch = get_dirwatch_offset(event->wd);
|
||||
if (watch == -1) {
|
||||
printlogf(LOG_ERROR,
|
||||
printlogf(ERROR,
|
||||
"received an inotify event that doesnt match any watched directory :-(%d,%d)",
|
||||
event->mask, event->wd);
|
||||
return false;
|
||||
|
@ -1133,13 +1203,13 @@ bool handle_event(struct inotify_event *event)
|
|||
if ((IN_CREATE | IN_CLOSE_WRITE | IN_DELETE |
|
||||
IN_MOVED_TO | IN_MOVED_FROM) & event->mask
|
||||
) {
|
||||
printlogf(LOG_NORMAL, "event %s:%s triggered.", masktext, event->name);
|
||||
printlogf(NORMAL, "event %s:%s triggered.", masktext, event->name);
|
||||
rsync_dir(watch); // TODO, worry about errors?
|
||||
if (subwatch >= 0) { // sync through the new created directory as well.
|
||||
rsync_dir(subwatch);
|
||||
}
|
||||
} else {
|
||||
printlogf(LOG_DEBUG, "... ignored this event.");
|
||||
printlogf(DEBUG, "... ignored this event.");
|
||||
}
|
||||
process_tosync_stack();
|
||||
return true;
|
||||
|
@ -1157,12 +1227,12 @@ bool master_loop()
|
|||
len = read (inotf, buf, INOTIFY_BUF_LEN);
|
||||
|
||||
if (len < 0) {
|
||||
printlogf(LOG_ERROR, "failed to read from inotify (%d:%s)", errno, strerror(errno));
|
||||
printlogf(ERROR, "failed to read from inotify (%d:%s)", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
printlogf(LOG_ERROR, "eof?");
|
||||
printlogf(ERROR, "eof?");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1187,8 +1257,8 @@ void check_file_exists(const char* filename)
|
|||
{
|
||||
struct stat st;
|
||||
if (-1==stat(filename, &st)) {
|
||||
printlogf(LOG_ERROR, "File [%s] does not exist\n", filename);
|
||||
exit (LSYNCD_FILENOTFOUND);
|
||||
printlogf(ERROR, "File [%s] does not exist\n", filename);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1201,8 +1271,8 @@ void check_file_exists(const char* filename)
|
|||
void check_absolute_path(const char* filename)
|
||||
{
|
||||
if (filename[0] != '/') {
|
||||
printlogf(LOG_ERROR, "Filename [%s] is not an absolute path\n", filename);
|
||||
exit (LSYNCD_FILENOTFOUND);
|
||||
printlogf(ERROR, "Filename [%s] is not an absolute path\n", filename);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1241,16 +1311,13 @@ void print_help(char *arg0)
|
|||
printf(" --dryrun Do not call any actions, run dry only\n");
|
||||
printf(" --exclude-from FILE Exclude file handled to rsync (DEFAULT: None)\n");
|
||||
printf(" --help Print this help text and exit.\n");
|
||||
printf(" --logfile FILE Put log here (DEFAULT: %s)\n",
|
||||
logfile);
|
||||
printf(" --logfile FILE Put log here (DEFAULT: uses syslog if not specified)\n");
|
||||
printf(" --no-daemon Do not detach, log to stdout/stderr\n");
|
||||
printf(" --pidfile FILE Create a file containing pid of the daemon\n");
|
||||
printf(" --scarce Only log errors\n");
|
||||
printf(" --stubborn Ignore rsync errors on startup.\n");
|
||||
printf(" --version Print version an exit.\n");
|
||||
printf("\n");
|
||||
printf("Take care that lsyncd is allowed to write to the logfile specified.\n");
|
||||
printf("\n");
|
||||
printf("EXCLUDE FILE: \n");
|
||||
printf(" The exclude file may have either filebased general masks like \"*.php\" without directory specifications,\n");
|
||||
printf(" or exclude complete directories like \"Data/\". lsyncd will recognize directory excludes by the trailing '/'\n");
|
||||
|
@ -1293,8 +1360,8 @@ struct call_option * parse_callopts(xmlNodePtr node) {
|
|||
xmlStrcmp(cnode->name, BAD_CAST "source") &&
|
||||
xmlStrcmp(cnode->name, BAD_CAST "destination")
|
||||
) {
|
||||
fprintf(stderr, "error unknown call option type \"%s\"", cnode->name);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error unknown call option type \"%s\"", cnode->name);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
opt_n++;
|
||||
}
|
||||
|
@ -1311,8 +1378,8 @@ struct call_option * parse_callopts(xmlNodePtr node) {
|
|||
if (!xmlStrcmp(cnode->name, BAD_CAST "option")) {
|
||||
xc = xmlGetProp(cnode, BAD_CAST "text");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: text attribute missing from <option/>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: text attribute missing from <option/>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
asw[opt_n].kind = CO_TEXT;
|
||||
asw[opt_n].text = s_strdup((char *) xc);
|
||||
|
@ -1346,47 +1413,47 @@ bool parse_directory(xmlNodePtr node) {
|
|||
if (!xmlStrcmp(dnode->name, BAD_CAST "source")) {
|
||||
xc = xmlGetProp(dnode, BAD_CAST "path");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute path missing from <source>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute path missing from <source>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
if (dc->source) {
|
||||
fprintf(stderr, "error in config file: cannot have more than one source in one <directory>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: cannot have more than one source in one <directory>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
// TODO: use realdir() on xc
|
||||
dc->source = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(dnode->name, BAD_CAST "target")) {
|
||||
xc = xmlGetProp(dnode, BAD_CAST "path");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute path missing from <target>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute path missing from <target>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
dir_conf_add_target(dc, (char *) xc);
|
||||
} else if (!xmlStrcmp(dnode->name, BAD_CAST "binary")) {
|
||||
xc = xmlGetProp(dnode, BAD_CAST "filename");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute filename missing from <binary>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute filename missing from <binary>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
dc->exclude_file = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(dnode->name, BAD_CAST "callopts")) {
|
||||
if (dc->callopts) {
|
||||
fprintf(stderr, "error in config file: there is more than one <callopts> in a <directory>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: there is more than one <callopts> in a <directory>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
dc->callopts = parse_callopts(dnode);
|
||||
} else {
|
||||
fprintf(stderr, "error in config file: unknown node in <directory> \"%s\"\n", dnode->name);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: unknown node in <directory> \"%s\"\n", dnode->name);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
}
|
||||
if (!dc->source) {
|
||||
fprintf(stderr, "error in config file: source missing from <directory>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: source missing from <directory>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
if (dc->targets[0] == NULL) {
|
||||
fprintf(stderr, "error in config file: target missing from <directory>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: target missing from <directory>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1409,29 +1476,29 @@ bool parse_settings(xmlNodePtr node) {
|
|||
} else if (!xmlStrcmp(snode->name, BAD_CAST "exclude-from")) {
|
||||
xc = xmlGetProp(snode, BAD_CAST "filename");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute filename missing from <exclude-from/>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute filename missing from <exclude-from/>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
default_exclude_file = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(snode->name, BAD_CAST "logfile")) {
|
||||
xc = xmlGetProp(snode, BAD_CAST "filename");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute filename missing from <logfile/>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute filename missing from <logfile/>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
logfile = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(snode->name, BAD_CAST "binary")) {
|
||||
xc = xmlGetProp(snode, BAD_CAST "filename");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute filename missing from <binary/>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute filename missing from <binary/>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
default_binary = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(snode->name, BAD_CAST "pidfile")) {
|
||||
xc = xmlGetProp(snode, BAD_CAST "filename");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: attribute filename missing from <pidfile/>\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: attribute filename missing from <pidfile/>\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
pidfile = s_strdup((char *) xc);
|
||||
} else if (!xmlStrcmp(snode->name, BAD_CAST "callopts")) {
|
||||
|
@ -1443,8 +1510,8 @@ bool parse_settings(xmlNodePtr node) {
|
|||
} else if (!xmlStrcmp(snode->name, BAD_CAST "stubborn")) {
|
||||
flag_stubborn = 1;
|
||||
} else {
|
||||
fprintf(stderr, "error unknown node in <settings> \"%s\"", snode->name);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error unknown node in <settings> \"%s\"", snode->name);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -1466,24 +1533,24 @@ bool parse_config(bool fullparse) {
|
|||
|
||||
doc = xmlReadFile(conf_filename, NULL, 0);
|
||||
if (doc == NULL) {
|
||||
fprintf(stderr, "error: could not parse config file \"%s\"\n", conf_filename);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error: could not parse config file \"%s\"\n", conf_filename);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
root_element = xmlDocGetRootElement(doc);
|
||||
|
||||
// check version specifier
|
||||
if (xmlStrcmp(root_element->name, BAD_CAST "lsyncd")) {
|
||||
fprintf(stderr, "error in config file: root node is not \"lsyncd\".\n");
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: root node is not \"lsyncd\".\n");
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
xc = xmlGetProp(root_element, BAD_CAST "version");
|
||||
if (xc == NULL) {
|
||||
fprintf(stderr, "error in config file: version specifier missing in \"%s\",\n", conf_filename);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: version specifier missing in \"%s\",\n", conf_filename);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
if (xmlStrcmp(xc, BAD_CAST "1") && xmlStrcmp(xc, BAD_CAST "1.25")) { //1.25, backward stuff
|
||||
fprintf(stderr, "error in config file: expected a \"1\" versioned file, found \"%s\"\n", xc);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: expected a \"1\" versioned file, found \"%s\"\n", xc);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
|
||||
for (node = root_element->children; node; node = node->next) {
|
||||
|
@ -1497,8 +1564,8 @@ bool parse_config(bool fullparse) {
|
|||
parse_directory(node);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "error in config file: unknown node in <lsyncd> \"%s\"\n", node->name);
|
||||
exit(LSYNCD_BADCONFIGFILE);
|
||||
printlogf(ERROR, "error in config file: unknown node in <lsyncd> \"%s\"\n", node->name);
|
||||
terminate(LSYNCD_BADCONFIGFILE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1513,7 +1580,7 @@ bool parse_config(bool fullparse) {
|
|||
/**
|
||||
* Parses the command line options.
|
||||
*
|
||||
* exits() in some cases of badparameters, or on
|
||||
* terminates in some cases of badparameters, or on
|
||||
* --version or --help
|
||||
*/
|
||||
void parse_options(int argc, char **argv)
|
||||
|
@ -1556,7 +1623,7 @@ void parse_options(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
if (c == '?') {
|
||||
exit(LSYNCD_BADPARAMETERS);
|
||||
terminate(LSYNCD_BADPARAMETERS);
|
||||
}
|
||||
if (c == 0) { // longoption
|
||||
if (!strcmp("conf", long_options[oi].name)) {
|
||||
|
@ -1573,7 +1640,7 @@ void parse_options(int argc, char **argv)
|
|||
if (!strcmp("version", long_options[oi].name)) {
|
||||
// same here
|
||||
printf("Version: %s\n", VERSION);
|
||||
exit(LSYNCD_SUCCESS);
|
||||
terminate(LSYNCD_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1594,7 +1661,7 @@ void parse_options(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (c == '?') {
|
||||
exit(LSYNCD_BADPARAMETERS);
|
||||
terminate(LSYNCD_BADPARAMETERS);
|
||||
}
|
||||
|
||||
if (c == 0) { // longoption
|
||||
|
@ -1620,7 +1687,7 @@ void parse_options(int argc, char **argv)
|
|||
|
||||
if (!strcmp("version", long_options[oi].name)) {
|
||||
printf("Version: %s\n", VERSION);
|
||||
exit(LSYNCD_SUCCESS);
|
||||
terminate(LSYNCD_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1632,27 +1699,27 @@ void parse_options(int argc, char **argv)
|
|||
bool first_target = true;
|
||||
|
||||
if (optind + 2 > argc) {
|
||||
fprintf(stderr, "Error: please specify SOURCE and at least one TARGET (see --help)\n");
|
||||
printlogf(ERROR, "Error: please specify SOURCE and at least one TARGET (see --help)\n");
|
||||
#ifdef XML_CONFIG
|
||||
fprintf(stderr, " or at least one <directory> entry in the conf file.\n");
|
||||
printlogf(ERROR, " or at least one <directory> entry in the conf file.\n");
|
||||
#endif
|
||||
exit(LSYNCD_BADPARAMETERS);
|
||||
terminate(LSYNCD_BADPARAMETERS);
|
||||
}
|
||||
odc = new_dir_conf();
|
||||
/* Resolves relative source path, lsyncd might chdir to / later. */
|
||||
odc->source = realdir(argv[optind]);
|
||||
if (!odc->source) {
|
||||
fprintf(stderr, "Error: Source [%s] not found or not a directory.\n", argv[optind]);
|
||||
exit(LSYNCD_FILENOTFOUND);
|
||||
printlogf(ERROR, "Error: Source [%s] not found or not a directory.\n", argv[optind]);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
for (target = &argv[optind + 1]; *target; target++) {
|
||||
dir_conf_add_target(odc, *target);
|
||||
if (first_target) {
|
||||
printlogf(LOG_NORMAL, "command line options: syncing %s -> %s\n",
|
||||
printlogf(NORMAL, "command line options: syncing %s -> %s\n",
|
||||
odc->source, *target);
|
||||
first_target = false;
|
||||
} else {
|
||||
printlogf(LOG_NORMAL, " and -> %s\n",
|
||||
printlogf(NORMAL, " and -> %s\n",
|
||||
*target);
|
||||
}
|
||||
}
|
||||
|
@ -1678,8 +1745,8 @@ bool parse_exclude_file(char *filename) {
|
|||
|
||||
ef = fopen(filename, "r");
|
||||
if (ef == NULL) {
|
||||
printlogf(LOG_ERROR, "Meh, cannot open exclude file '%s'\n", filename);
|
||||
exit(LSYNCD_FILENOTFOUND);
|
||||
printlogf(ERROR, "Meh, cannot open exclude file '%s'\n", filename);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
|
@ -1688,10 +1755,10 @@ bool parse_exclude_file(char *filename) {
|
|||
fclose(ef);
|
||||
return true;
|
||||
}
|
||||
printlogf(LOG_ERROR, "Reading file '%s' (%d:%s)\n",
|
||||
printlogf(ERROR, "Reading file '%s' (%d:%s)\n",
|
||||
filename, errno, strerror(errno));
|
||||
|
||||
exit(LSYNCD_FILENOTFOUND);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
|
||||
sl = strlen(line);
|
||||
|
@ -1711,10 +1778,10 @@ bool parse_exclude_file(char *filename) {
|
|||
|
||||
if (line[sl - 1] == '/') {
|
||||
if (exclude_dir_n + 1 >= MAX_EXCLUDES) {
|
||||
printlogf(LOG_ERROR,
|
||||
printlogf(ERROR,
|
||||
"Too many directory excludes, can only have %d at the most",
|
||||
MAX_EXCLUDES);
|
||||
exit(LSYNCD_TOOMANYDIRECTORYEXCLUDES);
|
||||
terminate(LSYNCD_TOOMANYDIRECTORYEXCLUDES);
|
||||
}
|
||||
|
||||
line[sl - 1] = 0;
|
||||
|
@ -1725,7 +1792,7 @@ bool parse_exclude_file(char *filename) {
|
|||
continue;
|
||||
}
|
||||
|
||||
printlogf(LOG_NORMAL, "Excluding directories of the name '%s'", line);
|
||||
printlogf(NORMAL, "Excluding directories of the name '%s'", line);
|
||||
|
||||
exclude_dirs[exclude_dir_n] = s_malloc(strlen(line) + 1);
|
||||
strcpy(exclude_dirs[exclude_dir_n], line);
|
||||
|
@ -1742,8 +1809,8 @@ bool parse_exclude_file(char *filename) {
|
|||
void write_pidfile() {
|
||||
FILE* f = fopen(pidfile, "w");
|
||||
if (!f) {
|
||||
printlogf(LOG_ERROR, "Error: cannot write pidfile [%s]\n", pidfile);
|
||||
exit(LSYNCD_FILENOTFOUND);
|
||||
printlogf(ERROR, "Error: cannot write pidfile [%s]\n", pidfile);
|
||||
terminate(LSYNCD_FILENOTFOUND);
|
||||
}
|
||||
|
||||
fprintf(f, "%i\n", getpid());
|
||||
|
@ -1756,6 +1823,7 @@ void write_pidfile() {
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
openlog("lsyncd", LOG_CONS | LOG_PID, LOG_DAEMON);
|
||||
|
||||
parse_options(argc, argv);
|
||||
|
||||
|
@ -1765,7 +1833,7 @@ int main(int argc, char **argv)
|
|||
|
||||
inotf = inotify_init();
|
||||
if (inotf == -1) {
|
||||
printlogf(LOG_ERROR, "Cannot create inotify instance! (%d:%s)",
|
||||
printlogf(ERROR, "Cannot create inotify instance! (%d:%s)",
|
||||
errno, strerror(errno));
|
||||
return LSYNCD_NOINOTIFY;
|
||||
}
|
||||
|
@ -1775,13 +1843,13 @@ int main(int argc, char **argv)
|
|||
// close stdin/stdout/stderr and
|
||||
// chdir to /
|
||||
if (daemon(0, 0)) {
|
||||
printlogf(LOG_ERROR, "Cannot daemonize! (%d:%s)",
|
||||
printlogf(ERROR, "Cannot daemonize! (%d:%s)",
|
||||
errno, strerror(errno));
|
||||
return LSYNCD_INTERNALFAIL;
|
||||
}
|
||||
}
|
||||
|
||||
printlogf(LOG_NORMAL, "Starting up");
|
||||
printlogf(NORMAL, "Starting up");
|
||||
|
||||
if (pidfile) {
|
||||
write_pidfile();
|
||||
|
@ -1795,13 +1863,13 @@ int main(int argc, char **argv)
|
|||
|
||||
// add all watches
|
||||
for (i = 0; i < dir_conf_n; i++) {
|
||||
printlogf(LOG_NORMAL, "watching %s", dir_confs[i].source);
|
||||
printlogf(NORMAL, "watching %s", dir_confs[i].source);
|
||||
add_dirwatch(dir_confs[i].source, -1, &dir_confs[i]);
|
||||
}
|
||||
|
||||
// clears tosync stack again, because the startup
|
||||
// super recursive rsync will handle it eitherway.
|
||||
printlogf(LOG_DEBUG, "dumped tosync stack.");
|
||||
printlogf(DEBUG, "dumped tosync stack.");
|
||||
tosync_pos = 0;
|
||||
|
||||
// startup recursive sync.
|
||||
|
@ -1809,17 +1877,17 @@ int main(int argc, char **argv)
|
|||
char **target;
|
||||
for (target = dir_confs[i].targets; *target; ++target) {
|
||||
if (!action(&dir_confs[i], dir_confs[i].source, *target, true)) {
|
||||
printlogf(LOG_ERROR, "Initial rsync from %s to %s failed%s",
|
||||
printlogf(ERROR, "Initial rsync from %s to %s failed%s",
|
||||
dir_confs[i].source, *target,
|
||||
flag_stubborn ? ", but continuing because being stubborn." : ".");
|
||||
if (!flag_stubborn) {
|
||||
exit(LSYNCD_EXECFAIL);
|
||||
terminate(LSYNCD_EXECFAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printlogf(LOG_NORMAL,
|
||||
printlogf(NORMAL,
|
||||
"--- Entering normal operation with [%d] monitored directories ---",
|
||||
dir_watch_num);
|
||||
|
||||
|
|
Loading…
Reference in New Issue