[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-user: [PATCH] Write logs to $HOME/.gEDA/logs/.



Here is a suggested patch. Portability is still dubious, but I've done
my best to make sure that we create new logfiles in a secure manner.

The format of the log filenames is intended so as to make it easy for a
user to find the most recent log file when troubleshooting.

I'd appreciate comments as to whether this will work (or even compile)
on Windows!

                           Peter

-- 
Peter Brett

Electronic Systems Engineer
Integral Informatics Ltd

From cabf7399d5f7d24559f8c36571e8bdf65fc673fa Mon Sep 17 00:00:00 2001
From: Peter TB Brett <peter@xxxxxxxxxxxxx>
Date: Fri, 16 Jan 2009 22:20:29 +0000
Subject: [PATCH] Write logs to $HOME/.gEDA/logs/.

Rewrite s_log_init() to put log files in a centralised location. A
user application (e.g. gnetlist) provides a prefix, and log file is
opened at:

   $HOME/.gEDA/logs/<prefix>-<YYYYmmdd>-<serial>.log

The serial is found by the following procedure:

1. Read through the directory to find the highest existing <serial>.

2. Starting with that number, repeatedly attempt to open()
   incrementing files with O_CREAT|O_EXCL flags to guarantee that a
   new file is created.

3. If after LOG_OPEN_ATTEMPTS = 5 attempts a unique filename hasn't
   been found, fail.
---
 gattrib/src/gattrib.c     |    6 +--
 gnetlist/src/gnetlist.c   |    4 +-
 gschem/src/gschem.c       |    5 +--
 gsymcheck/src/gsymcheck.c |    4 +-
 libgeda/src/s_log.c       |  103 +++++++++++++++++++++++++++++++++++++++-----
 utils/gschlas/gschlas.c   |    4 +-
 6 files changed, 96 insertions(+), 30 deletions(-)

diff --git a/gattrib/src/gattrib.c b/gattrib/src/gattrib.c
index e5f6818..778d0db 100644
--- a/gattrib/src/gattrib.c
+++ b/gattrib/src/gattrib.c
@@ -142,11 +142,7 @@ void gattrib_main(void *closure, int argc, char *argv[])
   
   /* ----------  create log file right away ---------- */
   /* ----------  even if logging is enabled ---------- */
-  cwd = g_get_current_dir();
-  logfile = g_build_filename (cwd, "gattrib.log", NULL);
-  s_log_init (logfile);
-  g_free (logfile);
-  g_free (cwd);
+  s_log_init ("gattrib");
 
   s_log_message
     ("gEDA/gattrib version %s%s.%s\n", PREPEND_VERSION_STRING, 
diff --git a/gnetlist/src/gnetlist.c b/gnetlist/src/gnetlist.c
index 1f73dbb..ee7b8d4 100644
--- a/gnetlist/src/gnetlist.c
+++ b/gnetlist/src/gnetlist.c
@@ -143,9 +143,7 @@ void main_prog(void *closure, int argc, char *argv[])
 
     /* create log file right away */
     /* even if logging is enabled */
-    logfile = g_build_filename (cwd, "gnetlist.log", NULL);
-    s_log_init (logfile);
-    g_free (logfile);
+    s_log_init ("gnetlist");
 
     s_log_message("gEDA/gnetlist version %s%s.%s\n", PREPEND_VERSION_STRING,
                   DOTTED_VERSION, DATE_VERSION);
diff --git a/gschem/src/gschem.c b/gschem/src/gschem.c
index 1c3122a..af4511e 100644
--- a/gschem/src/gschem.c
+++ b/gschem/src/gschem.c
@@ -178,11 +178,8 @@ void main_prog(void *closure, int argc, char *argv[])
   load_newer_backup_func = x_fileselect_load_backup;
   select_func = o_select_object;
 
-  /*! \todo Probably the file name shuold be defined elsewhere */
   /* create log file right away even if logging is enabled */
-  filename = g_build_filename (cwd, "gschem.log", NULL);
-  s_log_init (filename);
-  g_free (filename);
+  s_log_init ("gschem");
 
   s_log_message(
                 _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
diff --git a/gsymcheck/src/gsymcheck.c b/gsymcheck/src/gsymcheck.c
index 04b1ae3..21f1c3a 100644
--- a/gsymcheck/src/gsymcheck.c
+++ b/gsymcheck/src/gsymcheck.c
@@ -63,10 +63,8 @@ main_prog(void *closure, int argc, char *argv[])
 
   /* create log file right away */
   /* even if logging is enabled */
-  logfile = g_build_filename (cwd, "gsymcheck.log", NULL);
   x_log_update_func = s_log_update;
-  s_log_init (logfile);
-  g_free (logfile);
+  s_log_init ("gsymcheck");
 
   logging_dest=STDOUT_TTY;
   if (!quiet_mode)
diff --git a/libgeda/src/s_log.c b/libgeda/src/s_log.c
index fcc087c..8d1ea52 100644
--- a/libgeda/src/s_log.c
+++ b/libgeda/src/s_log.c
@@ -42,6 +42,8 @@
 
 #include "libgeda_priv.h"
 
+#include <time.h>
+
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
 #endif
@@ -57,6 +59,8 @@ int do_logging = TRUE;
 #define PRINT_LOG_LEVELS (CATCH_LOG_LEVELS ^ \
                           (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE))
 
+#define LOG_OPEN_ATTEMPTS 5
+
 static void s_log_handler (const gchar *log_domain,
                            GLogLevelFlags log_level,
                            const gchar *message,
@@ -73,27 +77,102 @@ static guint log_handler_id;
  *
  *  \param [in] filename  Character string with file name to log to.
  */
-void s_log_init (const gchar *filename)
+void s_log_init (const gchar *prefix)
 {
+  /* FIXME we assume that the prefix is in the filesystem encoding. */
+
+  gchar *full_prefix = NULL;
+  size_t full_prefix_len = 0;
+  time_t nowt;
+  struct tm *nowtm;
+  gchar *dir_path = NULL;
+  gchar *filename = NULL;
+  int s, i;
+  int last_exist_logn = 0;
+  GDir *logdir = NULL;
+
+  if (logfile_fd != -1) {
+    g_critical ("s_log_init: Log already initialised.\n");
+    return;
+  }
   if (do_logging == FALSE) {
-    logfile_fd = -1;
     return;
   }
 
-  /* create log file */
-  logfile_fd = open (filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
-  if (logfile_fd == -1) {
-    fprintf(stderr, "Could not open log file: %s\n", filename);
-    fprintf(stderr, "Errno was: %d\n", errno);
+  time (&nowt);
+  nowtm = gmtime (&nowt);
+
+  /* create "real" prefix -- this has the form "<prefix>-<date>-" */
+  full_prefix = g_strdup_printf ("%s-%04i%02i%02i-", prefix,
+                                 nowtm->tm_year + 1900, nowtm->tm_mon + 1,
+                                 nowtm->tm_mday);
+  full_prefix_len = strlen (full_prefix);
+
+  /* Find/create the directory where we're going to put the logs.
+   * FIXME should this be configured somehow?
+   *
+   * Then run through it finding the "biggest" existing filename with
+   * a matching prefix & date. */
+  dir_path = g_build_filename (g_getenv ("HOME"),
+                               ".gEDA", "logs", NULL);
+  /* Try to create the directory. */
+  s = g_mkdir_with_parents (dir_path, 0777/*octal*/);
+  if (s != 0) {
+    /* FIXME should we report this somehow? */
+    fprintf (stderr, "Could not create log directory %s: %s\n",
+             dir_path, strerror (errno));
+    g_free (dir_path);
+    g_free (full_prefix);
     return;
   }
 
-  /* install the log handler */
-  log_handler_id = g_log_set_handler (NULL,
-                                      CATCH_LOG_LEVELS,
-                                      s_log_handler,
-                                      NULL);
+  logdir = g_dir_open (dir_path, 0, NULL);
+  while (TRUE) {
+    const gchar *file = g_dir_read_name (logdir);
+    int n;
+    if (file == NULL) break;
+    if (strncmp (full_prefix, file, full_prefix_len)) continue;
+
+    s = sscanf (file + full_prefix_len, "%i", &n);
+    if (s != 1) continue;
+
+    if (n > last_exist_logn) last_exist_logn = n;
+  }
+
+  /* Now try and create a new file. When we fail, increment the number. */
+  i = 0;
+  while (logfile_fd == -1 && (LOG_OPEN_ATTEMPTS > i++)) {
+    filename = g_strdup_printf ("%s%s%s%i.log", dir_path,
+                                G_DIR_SEPARATOR_S, full_prefix,
+                                ++last_exist_logn);
+    printf ("%s\n", filename);
+    logfile_fd = open (filename, O_RDWR|O_CREAT|O_EXCL, 0600);
+
+    if (logfile_fd == -1 && (errno != EEXIST)) break;
+  }
+
+  if (logfile_fd != -1) {
+
+    /* install the log handler */
+    log_handler_id = g_log_set_handler (NULL,
+                                        CATCH_LOG_LEVELS,
+                                        s_log_handler,
+                                        NULL);
+
+  } else {
+    /* FIXME convert dir_path to UTF-8 */
+    if (errno == EEXIST) {
+      fprintf (stderr, "Could not create unique log filename in %s\n",
+               dir_path);
+    } else {
+      fprintf (stderr, "Could not create log file in %s: %s\n",
+               dir_path, strerror (errno));
+    }
+  }
 
+  g_free (filename);
+  g_free (dir_path);
+  g_free (full_prefix);
 }
 
 /*! \brief Terminates the logging of messages.
diff --git a/utils/gschlas/gschlas.c b/utils/gschlas/gschlas.c
index a30de63..c98c0aa 100644
--- a/utils/gschlas/gschlas.c
+++ b/utils/gschlas/gschlas.c
@@ -68,9 +68,7 @@ main_prog(void *closure, int argc, char *argv[])
 
   /* create log file right away */
   /* even if logging is enabled */
-  logfile = g_build_filename (cwd, "gschlas.log", NULL);
-  s_log_init (logfile);
-  g_free (logfile);
+  s_log_init ("gschlas");
 	
   logging_dest=STDOUT_TTY;
   if (!quiet_mode)
-- 
1.6.0.6


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user