X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=ucw%2Flog-file.c;h=40f1f3964e487e21e7d85834f194d3b3bdd67d39;hb=564be9c0adf9f5796b60f2727cecc9c7274f86ff;hp=fe85a270f94b1624090cda009c2d418b57c0c19b;hpb=622439339747407ea7bb7db1bcba14eab1d32cbd;p=libucw.git diff --git a/ucw/log-file.c b/ucw/log-file.c index fe85a270..40f1f396 100644 --- a/ucw/log-file.c +++ b/ucw/log-file.c @@ -8,30 +8,25 @@ * of the GNU Lesser General Public License. */ -#include "ucw/lib.h" -#include "ucw/log.h" -#include "ucw/lfs.h" -#include "ucw/threads.h" +#include +#include +#include +#include +#include +#include #include #include #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; + uint flags; // FF_xxx + char *orig_name; // Original name with strftime escapes }; #define MAX_EXPAND 64 // Maximum size of expansion of strftime escapes @@ -39,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; @@ -81,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--; @@ -95,73 +88,34 @@ do_log_switch(struct log_stream *ls, struct tm *tm) return switched; } -void -log_file(const char *name) -{ - if (!name) - return; - - // FIXME -} - -int -log_switch(void) -{ -#if 0 // FIXME - time_t tim = time(NULL); - return do_log_switch(localtime(&tim)); -#else - return 0; -#endif -} - -void -log_switch_disable(void) -{ - log_switch_nest++; -} - -void -log_switch_enable(void) -{ - ASSERT(log_switch_nest); - log_switch_nest--; -} - -/* 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, const char *m, uns cat UNUSED) +file_handler(struct log_stream *ls, struct log_msg *m) { - if (ls->udata & FF_FORMAT_NAME) - { - // FIXME: pass the time - time_t now = time(NULL); - struct tm *tm = localtime(&now); - do_log_switch(ls, tm); - } + struct file_stream *fs = (struct file_stream *) ls; + if ((fs->flags & FF_FORMAT_NAME) && m->tm) + do_log_switch(fs, m->tm); - int len = strlen(m); - int r = write(ls->idata, 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, uint 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; @@ -170,37 +124,74 @@ 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, uint 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->flags = FF_CLOSE_FD | flags; + fs->orig_name = xstrdup(path); if (strchr(path, '%')) - ls->udata = FF_FORMAT_NAME; - ls->udata |= FF_CLOSE_FD; + fs->flags |= FF_FORMAT_NAME; ls->msgfmt = LSFMT_DEFAULT; ls->handler = file_handler; ls->close = file_close; time_t now = time(NULL); struct tm *tm = localtime(&now); - do_log_switch(ls, tm); // die()'s on errors + ASSERT(tm); + do_log_switch(fs, tm); // die()'s on errors return ls; } +int +log_switch(void) +{ + time_t now = time(NULL); + struct tm *tm = localtime(&now); + ASSERT(tm); + + int switched = 0; + for (int i=0; i < log_streams_after; i++) + if (log_streams.ptr[i]->handler == file_handler) + switched |= do_log_switch((struct file_stream *) log_streams.ptr[i], tm); + return switched; +} + +void +log_switch_disable(void) +{ + log_switch_nest++; +} + +void +log_switch_enable(void) +{ + ASSERT(log_switch_nest); + log_switch_nest--; +} + +void +log_file(const char *name) +{ + if (!name) + return; + + log_set_default_stream(log_new_file(name, FF_FD2_FOLLOWS)); +} + #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"); + log_file("/proc/self/fd/1"); + // 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; iregnum, argv[i]); + msg(L_INFO, argv[i]); + log_close_all(); return 0; }