Imported Upstream version 2.5.1
[debian/amanda] / common-src / debug.c
index ced7bc1cd1ee9f720ce43f214a5d8a7fc8c0494f..b958b6325fef1015e2dfa69ab60eccb816780d56 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: debug.c,v 1.17.4.3.4.3.2.9 2003/01/04 17:46:09 martinea Exp $
+ * $Id: debug.c,v 1.40 2006/07/26 11:49:32 martinea Exp $
  *
  * debug log subroutines
  */
 
 #include "amanda.h"
-#include "clock.h"
 #include "util.h"
 #include "arglist.h"
+#include "clock.h"
 
 #ifndef AMANDA_DBGDIR
 #  define AMANDA_DBGDIR                AMANDA_TMPDIR
@@ -47,17 +47,20 @@ int debug = 1;
 
 static int db_fd = 2;                  /* default is stderr */
 static FILE *db_file = NULL;           /* stderr may not be a constant */
-static char *db_filename = NULL;
+static char *db_name  = NULL;          /* filename */
+static char *db_filename = NULL;       /* /path/to/filename */
 
 static pid_t debug_prefix_pid = 0;
+static char *get_debug_name(time_t t, int n);
+static void debug_setup_1(char *config, char *subdir);
+static void debug_setup_2(char *s, int fd, char *notation);
 
 /*
  * Format and write a debug message to the process debug file.
  */
-printf_arglist_function(void debug_printf, char *, format)
+printf_arglist_function(void debug_printf, const char *, format)
 {
     va_list argp;
-    int save_errno;
 
     /*
      * It is common in the code to call dbprintf to write out
@@ -65,19 +68,21 @@ printf_arglist_function(void debug_printf, char *, format)
      * with errno (e.g. printf() or log()), so we make sure errno goes
      * back out with the same value it came in with.
      */
-    save_errno = errno;
+    if (debug != 0) {
+        int save_errno;
 
-    if(db_file == NULL && db_fd == 2) {
-       db_file = stderr;
-    }
-    if(db_file != NULL) {
-       arglist_start(argp, format);
-       vfprintf(db_file, format, argp);
-       fflush(db_file);
-       arglist_end(argp);
+       save_errno = errno;
+       if(db_file == NULL && db_fd == 2) {
+           db_file = stderr;
+       }
+       if(db_file != NULL) {
+           arglist_start(argp, format);
+           vfprintf(db_file, format, argp);
+           fflush(db_file);
+           arglist_end(argp);
+       }
+       errno = save_errno;
     }
-
-    errno = save_errno;
 }
 
 /*
@@ -85,9 +90,9 @@ printf_arglist_function(void debug_printf, char *, format)
  * followed by a timestamp, an optional sequence number, and ".debug".
  */
 static char *
-get_debug_name(t, n)
-    time_t t;
-    int n;
+get_debug_name(
+    time_t     t,
+    int                n)
 {
     char number[NUM_STR_SIZE];
     char *ts;
@@ -100,52 +105,66 @@ get_debug_name(t, n)
     if(n == 0) {
        number[0] = '\0';
     } else {
-       ap_snprintf(number, sizeof(number), "%03d", n - 1);
+       snprintf(number, SIZEOF(number), "%03d", n - 1);
     }
     result = vstralloc(get_pname(), ".", ts, number, ".debug", NULL);
     amfree(ts);
     return result;
 }
 
-void debug_open()
+static char *dbgdir = NULL;
+static time_t curtime;
+
+static void
+debug_setup_1(char *config, char *subdir)
 {
-    time_t curtime;
-    int saved_debug;
-    char *dbgdir = NULL;
+    struct passwd *pwent;
+    char *pname;
+    size_t pname_len;
     char *e = NULL;
     char *s = NULL;
-    char *dbfilename = NULL;
     DIR *d;
     struct dirent *entry;
-    char *pname;
-    size_t pname_len;
     int do_rename;
-    char *test_name = NULL;
+    char *test_name;
     size_t test_name_len;
-    int fd = -1;
-    int i;
     size_t d_name_len;
-    int fd_close[MIN_DB_FD+1];
-    struct passwd *pwent;
     struct stat sbuf;
+    char *dbfilename = NULL;
+    char *sane_config = NULL;
+    int i;
 
-    pname = get_pname();
-    pname_len = strlen(pname);
-
+    memset(&sbuf, 0, SIZEOF(sbuf));
     if(client_uid == (uid_t) -1 && (pwent = getpwnam(CLIENT_LOGIN)) != NULL) {
        client_uid = pwent->pw_uid;
        client_gid = pwent->pw_gid;
        endpwent();
     }
 
+    pname = get_pname();
+    pname_len = strlen(pname);
+
     /*
      * Create the debug directory if it does not yet exist.
      */
-    dbgdir = stralloc2(AMANDA_DBGDIR, "/");
+    amfree(dbgdir);
+    if (config)
+       sane_config = sanitise_filename(config);
+    if (sane_config && subdir)
+       dbgdir = vstralloc(AMANDA_DBGDIR, "/", subdir, "/", sane_config,
+                          "/", NULL);
+    else if (sane_config)
+       dbgdir = vstralloc(AMANDA_DBGDIR, "/", sane_config, "/", NULL);
+    else if (subdir)
+       dbgdir = vstralloc(AMANDA_DBGDIR, "/", subdir, "/", NULL);
+    else
+       dbgdir = stralloc2(AMANDA_DBGDIR, "/");
     if(mkpdir(dbgdir, 02700, client_uid, client_gid) == -1) {
         error("create debug directory \"%s\": %s",
              AMANDA_DBGDIR, strerror(errno));
+        /*NOTREACHED*/
     }
+    amfree(sane_config);
 
     /*
      * Clean out old debug files.  We also rename files with old style
@@ -156,6 +175,7 @@ void debug_open()
     if((d = opendir(AMANDA_DBGDIR)) == NULL) {
         error("open debug directory \"%s\": %s",
              AMANDA_DBGDIR, strerror(errno));
+        /*NOTREACHED*/
     }
     time(&curtime);
     test_name = get_debug_name(curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
@@ -203,6 +223,7 @@ void debug_open()
            }
            if(dbfilename == NULL) {
                error("cannot rename old debug file \"%s\"", entry->d_name);
+               /*NOTREACHED*/
            }
        }
     }
@@ -211,51 +232,204 @@ void debug_open()
     amfree(s);
     amfree(test_name);
     closedir(d);
+}
+
+static void
+debug_setup_2(
+    char *     s,
+    int                fd,
+    char *     notation)
+{
+    int saved_debug;
+    int i, rc;
+    int fd_close[MIN_DB_FD+1];
 
-    /*
-     * Create the new file.
-     */
-    for(i = 0;
-       (dbfilename = get_debug_name(curtime, i)) != NULL
-       && (s = newvstralloc(s, dbgdir, dbfilename, NULL)) != NULL
-       && (fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0600)) < 0;
-       i++, free(dbfilename)) {}
-    if(dbfilename == NULL) {
-       error("cannot create %s debug file", get_pname());
-    }
-    amfree(dbfilename);
     amfree(db_filename);
     db_filename = s;
     s = NULL;
-    (void) chown(db_filename, client_uid, client_gid);
+    if ((rc = chown(db_filename, client_uid, client_gid)) < 0) {
+       dbprintf(("chown(%s, %d, %d) failed. <%s>",
+                 db_filename, client_uid, client_gid, strerror(errno)));
+       (void)rc;
+    }
     amfree(dbgdir);
-
     /*
      * Move the file descriptor up high so it stays out of the way
      * of other processing, e.g. sendbackup.
      */
-    i = 0;
-    fd_close[i++] = fd;
-    while((db_fd = dup(fd)) < MIN_DB_FD) {
-       fd_close[i++] = db_fd;
+    if (fd >= 0) {
+       i = 0;
+       fd_close[i++] = fd;
+       while((db_fd = dup(fd)) < MIN_DB_FD) {
+           fd_close[i++] = db_fd;
+       }
+       while(--i >= 0) {
+           close(fd_close[i]);
+       }
+       db_file = fdopen(db_fd, "a");
     }
-    while(--i >= 0) {
-       close(fd_close[i]);
+
+    if (notation) {
+       /*
+        * Make the first debug log file entry.
+        */
+       saved_debug = debug; debug = 1;
+       debug_printf("%s: debug %d pid %ld ruid %ld euid %ld: %s at %s",
+                    get_pname(), saved_debug, (long)getpid(),
+                    (long)getuid(), (long)geteuid(),
+                    notation,
+                    ctime(&curtime));
+       debug = saved_debug;
     }
-    db_file = fdopen(db_fd, "a");
+}
+
+void
+debug_open(char *subdir)
+{
+    int fd = -1;
+    int i;
+    char *s = NULL;
+    mode_t mask;
 
     /*
-     * Make the first debug log file entry.
+     * Do initial setup.
      */
-    saved_debug = debug; debug = 1;
-    debug_printf("%s: debug %d pid %ld ruid %ld euid %ld: start at %s",
-                pname, saved_debug, (long)getpid(),
-                (long)getuid(), (long)geteuid(),
-                ctime(&curtime));
-    debug = saved_debug;
+    debug_setup_1(NULL, subdir);
+
+    /*
+     * Create the new file with a unique sequence number.
+     */
+    mask = (mode_t)umask((mode_t)0037); /* Allow the group read bit through */
+    for(i = 0; fd < 0; i++) {
+       amfree(db_name);
+       if ((db_name = get_debug_name(curtime, i)) == NULL) {
+           error("Cannot create %s debug file", get_pname());
+           /*NOTREACHED*/
+        }
+
+       if ((s = newvstralloc(s, dbgdir, db_name, NULL)) == NULL) {
+           error("Cannot allocate %s debug file name memory", get_pname());
+           /*NOTREACHED*/
+       }
+
+        if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
+            if (errno != EEXIST) {
+                error("Cannot create %s debug file: %s",
+                       get_pname(), strerror(errno));
+                /*NOTREACHED*/
+            }
+            amfree(s);
+        }
+    }
+    (void)umask(mask); /* Restore mask */
+
+    /*
+     * Finish setup.
+     *
+     * Note: we release control of the string 's' points to.
+     */
+    debug_setup_2(s, fd, "start");
+}
+
+void
+debug_reopen(
+    char *     dbfilename,
+    char *     notation)
+{
+    char *s = NULL;
+    int fd;
+
+    if (dbfilename == NULL) {
+       return;
+    }
+
+    /*
+     * Do initial setup.
+     */
+    debug_setup_1(NULL, NULL);
+
+    /*
+     * Reopen the file.
+     */
+    if (*dbfilename == '/') {
+       s = stralloc(dbfilename);
+    } else {
+       s = newvstralloc(s, dbgdir, dbfilename, NULL);
+    }
+    if ((fd = open(s, O_RDWR|O_APPEND)) < 0) {
+       error("cannot reopen %s debug file %s", get_pname(), dbfilename);
+       /*NOTREACHED*/
+    }
+
+    /*
+     * Finish setup.
+     *
+     * Note: we release control of the string 's' points to.
+     */
+    debug_setup_2(s, fd, notation);
+}
+
+void
+debug_rename(
+    char *config,
+    char *subdir)
+{
+    int fd = -1;
+    int i;
+    char *s = NULL;
+    mode_t mask;
+
+    if (!db_filename)
+       return;
+
+    /*
+     * Do initial setup.
+     */
+    debug_setup_1(config, subdir);
+
+    s = newvstralloc(s, dbgdir, db_name, NULL);
+
+    if (strcmp(db_filename, s) == 0) {
+       amfree(s);
+       return;
+    }
+
+    mask = (mode_t)umask((mode_t)0037);
+    /* check if a file with the same name already exist */
+    if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
+       for(i = 0; fd < 0; i++) {
+           amfree(db_name);
+           if ((db_name = get_debug_name(curtime, i)) == NULL) {
+               dbprintf(("Cannot create %s debug file", get_pname()));
+               break;
+           }
+
+           s = newvstralloc(s, dbgdir, db_name, NULL);
+           if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
+               if (errno != EEXIST) {
+                   dbprintf(("Cannot create %s debug file: %s", get_pname(),
+                             strerror(errno)));
+                   break;
+               }
+           }
+       }
+    }
+
+    if (fd >= 0) {
+       rename(db_filename, s);
+    }
+    (void)umask(mask); /* Restore mask */
+    close(fd);
+    /*
+     * Finish setup.
+     *
+     * Note: we release control of the string 's' points to.
+     */
+    debug_setup_2(s, -1, "rename");
 }
 
-void debug_close()
+void
+debug_close(void)
 {
     time_t curtime;
     int save_debug;
@@ -277,24 +451,28 @@ void debug_close()
        int save_errno = errno;
 
        db_file = NULL;                         /* prevent recursion */
-       error("close debug file: %s", strerror(save_errno));
+       fprintf(stderr, "close debug file: %s", strerror(save_errno));
+       /*NOTREACHED*/
     }
     db_fd = -1;
     db_file = NULL;
     amfree(db_filename);
 }
 
-int debug_fd()
+int
+debug_fd(void)
 {
     return db_fd;
 }
 
-FILE *debug_fp()
+FILE *
+debug_fp(void)
 {
     return db_file;
 }
 
-char *debug_fn()
+char *
+debug_fn(void)
 {
     return db_filename;
 }
@@ -306,35 +484,43 @@ char *debug_fn()
  * time indicator.
  */ 
 
-void set_debug_prefix_pid(p)
-    pid_t p;
+void
+set_debug_prefix_pid(
+    pid_t      p)
 {
     debug_prefix_pid = p;
 }
 
-char *debug_prefix(suffix)
-    char *suffix;
+char *
+debug_prefix(
+    char *     suffix)
 {
+    int save_errno;
     static char *s = NULL;
     char debug_pid[NUM_STR_SIZE];
 
+    save_errno = errno;
     s = newvstralloc(s, get_pname(), suffix, NULL);
     if (debug_prefix_pid != (pid_t) 0) {
-       ap_snprintf(debug_pid, sizeof(debug_pid),
-                   "%ld",
-                   (long) debug_prefix_pid);
+       snprintf(debug_pid, SIZEOF(debug_pid),
+                "%ld",
+                (long) debug_prefix_pid);
        s = newvstralloc(s, s, "[", debug_pid, "]", NULL);
     }
+    errno = save_errno;
     return s;
 }
 
-char *debug_prefix_time(suffix)
-    char *suffix;
+char *
+debug_prefix_time(
+    char *     suffix)
 {
+    int save_errno;
     static char *s = NULL;
     char *t1;
     char *t2;
 
+    save_errno = errno;
     if (clock_is_running()) {
        t1 = ": time ";
        t2 = walltime_str(curclock());
@@ -344,6 +530,7 @@ char *debug_prefix_time(suffix)
 
     s = newvstralloc(s, debug_prefix(suffix), t1, t2, NULL);
 
+    errno = save_errno;
     return s;
 }
 #endif