X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Flog-file.c;h=efa0665f99bde467954390a085f267b6687e502c;hb=0f73a9b90ec53017512c34f7dab56be3a50d87b1;hp=65418a29d16d39de40a7d679a891dde3af50f8b3;hpb=7f9189a660abf6dd3a45afdfdd86cf95249fdfcc;p=libucw.git diff --git a/ucw/log-file.c b/ucw/log-file.c index 65418a29..efa0665f 100644 --- a/ucw/log-file.c +++ b/ucw/log-file.c @@ -10,6 +10,7 @@ #include "ucw/lib.h" #include "ucw/log.h" +#include "ucw/log-internal.h" #include "ucw/lfs.h" #include "ucw/threads.h" #include "ucw/simple-lists.h" @@ -19,20 +20,13 @@ #include #include #include +#include -/* - * Use of the private fields of struct log_stream: - * - * idata file descriptor - * udata various flags (FF_xxx) - * pdata original name with strftime escapes - * name current name of the log file - * (a dynamically allocated buffer) - */ - -enum log_file_flag { - FF_FORMAT_NAME = 1, // Name contains strftime escapes - FF_CLOSE_FD = 2, // Close the fd with the stream +struct file_stream { + struct log_stream ls; // ls.name is the current name of the log file + int fd; + uns flags; // FF_xxx + char *orig_name; // Original name with strftime escapes }; #define MAX_EXPAND 64 // Maximum size of expansion of strftime escapes @@ -40,41 +34,39 @@ enum log_file_flag { static int log_switch_nest; static void -do_log_reopen(struct log_stream *ls, const char *name) +do_log_reopen(struct file_stream *fs, const char *name) { int fd = ucw_open(name, O_WRONLY | O_CREAT | O_APPEND, 0666); if (fd < 0) die("Unable to open log file %s: %m", name); - if (ls->idata < 0) - ls->idata = fd; - else + if (fs->fd >= 0) + close(fs->fd); + fs->fd = fd; + if (fs->flags & FF_FD2_FOLLOWS) + dup2(fd, 2); + if (fs->ls.name) { - dup2(fd, ls->idata); - close(fd); + xfree(fs->ls.name); + fs->ls.name = NULL; // We have to keep the stream consistent -- die() below can invoke logging } - if (ls->name) - { - xfree(ls->name); - ls->name = NULL; // We have to keep this consistent, die() below can invoke logging - } - ls->name = xstrdup(name); + fs->ls.name = xstrdup(name); } static int -do_log_switch(struct log_stream *ls, struct tm *tm) +do_log_switch(struct file_stream *fs, struct tm *tm) { - if (!(ls->udata & FF_FORMAT_NAME)) + if (!(fs->flags & FF_FORMAT_NAME)) { - if (ls->idata >= 0) + if (fs->fd >= 0) return 1; else { - do_log_reopen(ls, ls->pdata); + do_log_reopen(fs, fs->orig_name); return 1; } } - int buflen = strlen(ls->pdata) + MAX_EXPAND; + int buflen = strlen(fs->orig_name) + MAX_EXPAND; char name[buflen]; int switched = 0; @@ -82,12 +74,12 @@ do_log_switch(struct log_stream *ls, struct tm *tm) if (!log_switch_nest) // Avoid infinite loops if we die when switching logs { log_switch_nest++; - int l = strftime(name, buflen, ls->pdata, tm); + int l = strftime(name, buflen, fs->orig_name, tm); if (l < 0 || l >= buflen) die("Error formatting log file name: %m"); - if (!ls->name || strcmp(name, ls->name)) + if (!fs->ls.name || strcmp(name, fs->ls.name)) { - do_log_reopen(ls, name); + do_log_reopen(fs, name); switched = 1; } log_switch_nest--; @@ -96,55 +88,34 @@ do_log_switch(struct log_stream *ls, struct tm *tm) return switched; } -/* Emulate the old single-file interface: close the existing log file and open a new one. */ -void -log_file(const char *name) -{ - if (!name) - return; - - struct log_stream *ls = log_new_file(name); - struct log_stream *def = log_stream_by_flags(0); - simp_node *s; - while (s = clist_head(&def->substreams)) - { - struct log_stream *old = s->p; - log_rm_substream(def, old); - if (old != (struct log_stream *) &log_stream_default) - log_close_stream(old); - } - dup2(ls->idata, 2); // Let fd2 be an alias for the log file - log_add_substream(def, ls); -} - -/* destructor for standard files */ static void file_close(struct log_stream *ls) { - if ((ls->udata & FF_CLOSE_FD) && ls->idata >= 0) - close(ls->idata); - xfree(ls->name); + struct file_stream *fs = (struct file_stream *) ls; + if ((fs->flags & FF_CLOSE_FD) && fs->fd >= 0) + close(fs->fd); + xfree(fs->ls.name); + xfree(fs->orig_name); } -/* handler for standard files */ static int file_handler(struct log_stream *ls, struct log_msg *m) { - if ((ls->udata & FF_FORMAT_NAME) && m->tm) - do_log_switch(ls, m->tm); + struct file_stream *fs = (struct file_stream *) ls; + if ((fs->flags & FF_FORMAT_NAME) && m->tm) + do_log_switch(fs, m->tm); - int r = write(ls->idata, m->m, m->m_len); - /* FIXME: check for errors here? */ - return 0; + int r = write(fs->fd, m->m, m->m_len); + return ((r < 0) ? errno : 0); } -/* assign log to a file descriptor */ -/* initialize with the default formatting, does NOT close the descriptor */ struct log_stream * -log_new_fd(int fd) +log_new_fd(int fd, uns flags) { - struct log_stream *ls = log_new_stream(); - ls->idata = fd; + struct log_stream *ls = log_new_stream(sizeof(struct file_stream)); + struct file_stream *fs = (struct file_stream *) ls; + fs->fd = fd; + fs->flags = flags; ls->msgfmt = LSFMT_DEFAULT; ls->handler = file_handler; ls->close = file_close; @@ -153,17 +124,16 @@ log_new_fd(int fd) return ls; } -/* open() a file (append mode) */ -/* initialize with the default formatting */ struct log_stream * -log_new_file(const char *path) +log_new_file(const char *path, uns flags) { - struct log_stream *ls = log_new_stream(); - ls->idata = -1; - ls->pdata = (void *) path; + struct log_stream *ls = log_new_stream(sizeof(struct file_stream)); + struct file_stream *fs = (struct file_stream *) ls; + fs->fd = -1; + fs->orig_name = xstrdup(path); if (strchr(path, '%')) - ls->udata = FF_FORMAT_NAME; - ls->udata |= FF_CLOSE_FD; + fs->flags = FF_FORMAT_NAME; + fs->flags |= FF_CLOSE_FD | flags; ls->msgfmt = LSFMT_DEFAULT; ls->handler = file_handler; ls->close = file_close; @@ -171,7 +141,7 @@ log_new_file(const char *path) time_t now = time(NULL); struct tm *tm = localtime(&now); ASSERT(tm); - do_log_switch(ls, tm); // die()'s on errors + do_log_switch(fs, tm); // die()'s on errors return ls; } @@ -185,7 +155,7 @@ log_switch(void) int switched = 0; for (int i=0; i < log_streams_after; i++) if (log_streams.ptr[i]->handler == file_handler) - switched |= do_log_switch(log_streams.ptr[i], tm); + switched |= do_log_switch((struct file_stream *) log_streams.ptr[i], tm); return switched; } @@ -202,16 +172,30 @@ log_switch_enable(void) log_switch_nest--; } +void +log_file(const char *name) +{ + if (!name) + return; + + struct log_stream *ls = log_new_file(name, FF_FD2_FOLLOWS); + struct log_stream *def = log_stream_by_flags(0); + log_rm_substream(def, NULL); + log_add_substream(def, ls); + log_close_stream(ls); +} + #ifdef TEST int main(int argc, char **argv) { log_init(argv[0]); log_file("/proc/self/fd/1"); - // struct log_stream *ls = log_new_fd(1); - // struct log_stream *ls = log_new_file("/tmp/quork-%Y%m%d-%H%M%S"); + // struct log_stream *ls = log_new_fd(1, 0); + // struct log_stream *ls = log_new_file("/tmp/quork-%Y%m%d-%H%M%S", 0); for (int i=1; i