d3c13404ddd2e91ddbe2298ca079cb61c057606e
[debian/amanda] / common-src / debug.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author: James da Silva, Systems Design and Analysis Group
24  *                         Computer Science Department
25  *                         University of Maryland at College Park
26  */
27 /*
28  * $Id: debug.c,v 1.40 2006/07/26 11:49:32 martinea Exp $
29  *
30  * Logging support
31  */
32
33 #include "amanda.h"
34 #include "util.h"
35 #include "arglist.h"
36 #include "clock.h"
37 #include "timestamp.h"
38 #include "conffile.h"
39
40 #ifdef HAVE_GLIBC_BACKTRACE
41 #include <execinfo.h>
42 #endif
43
44 /* Minimum file descriptor on which to keep the debug file.  This is intended
45  * to keep the descriptor "out of the way" of other processing.  It's not clear
46  * that this is required any longer, but it doesn't hurt anything.
47  */
48 #define MIN_DB_FD                       10
49
50 /* information on the current debug file */
51 static int db_fd = 2;                   /* file descriptor (default stderr) */
52 static FILE *db_file = NULL;            /* stdio stream */
53 static char *db_name  = NULL;           /* unqualified filename */
54 static char *db_filename = NULL;        /* fully qualified pathname */
55
56 /* directory containing debug file, including trailing slash */
57 static char *dbgdir = NULL;
58
59 /* time debug log was opened (timestamp of the file) */
60 static time_t open_time;
61
62 /* pointer to logfile.c's 'logerror()', if we're linked
63  * with it */
64 static void (*logerror_fn)(char *) = NULL;
65
66 /* storage for global variables */
67 erroutput_type_t erroutput_type = ERR_FROM_CONTEXT;
68 int error_exit_status = 1;
69
70 /* static function prototypes */
71 static char *get_debug_name(time_t t, int n);
72 static void debug_setup_1(char *config, char *subdir);
73 static void debug_setup_2(char *s, int fd, char *annotation);
74 static char *msg_timestamp(void);
75
76 static void debug_logging_handler(const gchar *log_domain,
77         GLogLevelFlags log_level,
78         const gchar *message,
79         gpointer user_data);
80 static void debug_setup_logging(void);
81
82 /*
83  * Generate a debug file name.  The name is based on the program name,
84  * followed by a timestamp, an optional sequence number, and ".debug".
85  *
86  * @param t: timestamp
87  * @param n: sequence number between 1 and 1000; if zero, no sequence number
88  * is included.
89  */
90 static char *
91 get_debug_name(
92     time_t      t,
93     int         n)
94 {
95     char number[NUM_STR_SIZE];
96     char *ts;
97     char *result;
98
99     if(n < 0 || n > 1000) {
100         return NULL;
101     }
102     ts = get_timestamp_from_time(t);
103     if(n == 0) {
104         number[0] = '\0';
105     } else {
106         g_snprintf(number, SIZEOF(number), "%03d", n - 1);
107     }
108     result = vstralloc(get_pname(), ".", ts, number, ".debug", NULL);
109     amfree(ts);
110     return result;
111 }
112
113 /* A GLogFunc to handle g_log calls.  This function assumes that user_data
114  * is either NULL or a pointer to one of the debug_* configuration variables
115  * in conffile.c, indicating whether logging for this log domain is enabled.
116  *
117  * @param log_domain: the log domain, or NULL for general logging
118  * @param log_level: level, fatality, and recursion flags
119  * @param message: the message to log
120  * @param user_pointer: unused
121  */
122 static void
123 debug_logging_handler(const gchar *log_domain G_GNUC_UNUSED,
124             GLogLevelFlags log_level,
125             const gchar *message,
126             gpointer user_data G_GNUC_UNUSED)
127 {
128     char *maxlevel = NULL;
129     pcontext_t context = get_pcontext();
130
131     /* scriptutil context doesn't do any logging except for critical
132      * and error levels */
133     if (context != CONTEXT_SCRIPTUTIL) {
134         /* convert the highest level to a string and dbprintf it */
135         if (log_level & G_LOG_LEVEL_ERROR)
136             maxlevel = _("error (fatal): ");
137         else if (log_level & G_LOG_LEVEL_CRITICAL)
138             maxlevel = _("critical (fatal): ");
139         else if (log_level & G_LOG_LEVEL_WARNING)
140             maxlevel = _("warning: ");
141         else if (log_level & G_LOG_LEVEL_MESSAGE)
142             maxlevel = _("message: ");
143         else if (log_level & G_LOG_LEVEL_INFO)
144             maxlevel = _("info: ");
145         else
146             maxlevel = ""; /* no level displayed for debugging */
147
148         debug_printf("%s%s\n", maxlevel, message);
149     }
150
151     /* error and critical levels have special handling */
152     if (log_level & (G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL)) {
153         erroutput_type_t local_erroutput;
154
155         /* Calculate a local version of erroutput_type, based on the
156          * context if the process has not set erroutput_type explicitly */
157         if (!(erroutput_type & ERR_FROM_CONTEXT)) {
158             local_erroutput = erroutput_type;
159         } else {
160             switch (context) {
161                 case CONTEXT_SCRIPTUTIL:
162                     local_erroutput = ERR_INTERACTIVE;
163                     break;
164
165                 case CONTEXT_DAEMON:
166                     local_erroutput = ERR_INTERACTIVE
167                                     | ERR_AMANDALOG
168                                     | ERR_SYSLOG;
169                     break;
170
171                 case CONTEXT_CMDLINE:
172                 case CONTEXT_DEFAULT:
173                 default:
174                     local_erroutput = ERR_INTERACTIVE;
175                     break;
176             }
177         }
178
179         if (local_erroutput & ERR_AMANDALOG && logerror_fn != NULL)
180             (*logerror_fn)((char *)message); /* discard 'const' */
181
182         if (local_erroutput & ERR_SYSLOG) {
183 #ifdef LOG_AUTH
184             openlog(get_pname(), LOG_PID, LOG_AUTH);
185 #else
186             openlog(get_pname(), LOG_PID, 0);
187 #endif
188             syslog(LOG_NOTICE, "%s", message);
189             closelog();
190         }
191
192         if (local_erroutput & ERR_INTERACTIVE) {
193             g_fprintf(stderr, "%s: %s\n", get_pname(), message);
194             fflush(stderr);
195         }
196
197 #ifdef HAVE_GLIBC_BACKTRACE
198         /* try logging a traceback to the debug log */
199         if (db_fd != -1) {
200             void *stack[32];
201             int naddrs;
202             naddrs = backtrace(stack, sizeof(stack)/sizeof(*stack));
203             backtrace_symbols_fd(stack, naddrs, db_fd);
204         }
205 #endif
206
207         /* we're done */
208         if (log_level & G_LOG_LEVEL_CRITICAL)
209             exit(error_exit_status);
210         else
211             abort();
212         g_assert_not_reached();
213     }
214 }
215
216 /* Install our handler into the glib log handling system.
217  */
218 static void
219 debug_setup_logging(void)
220 {
221     /* g_error and g_critical should be fatal, although the log handler
222      * takes care of this anyway */
223     g_log_set_always_fatal(G_LOG_LEVEL_ERROR |  G_LOG_LEVEL_CRITICAL);
224
225     /* set up handler (g_log_set_default_handler is new in glib-2.6, and
226      * hence not useable here) */
227     g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
228                       debug_logging_handler, NULL);
229 }
230
231 /* Set the global dbgdir according to 'config' and 'subdir', and clean
232  * old debug files out of that directory
233  *
234  * The global open_time is set to the current time, and used to delete
235  * old files.
236  *
237  * @param config: configuration or NULL
238  * @param subdir: subdirectory (server, client, etc.) or NULL
239  */
240 static void
241 debug_setup_1(char *config, char *subdir)
242 {
243     char *pname;
244     size_t pname_len;
245     char *e = NULL;
246     char *s = NULL;
247     DIR *d;
248     struct dirent *entry;
249     int do_rename;
250     char *test_name;
251     size_t test_name_len;
252     size_t d_name_len;
253     struct stat sbuf;
254     char *dbfilename = NULL;
255     char *sane_config = NULL;
256     int i;
257
258     memset(&sbuf, 0, SIZEOF(sbuf));
259
260     pname = get_pname();
261     pname_len = strlen(pname);
262
263     /*
264      * Create the debug directory if it does not yet exist.
265      */
266     amfree(dbgdir);
267     if (config)
268         sane_config = sanitise_filename(config);
269     if (sane_config && subdir)
270         dbgdir = vstralloc(AMANDA_DBGDIR, "/", subdir, "/", sane_config,
271                            "/", NULL);
272     else if (sane_config)
273         dbgdir = vstralloc(AMANDA_DBGDIR, "/", sane_config, "/", NULL);
274     else if (subdir)
275         dbgdir = vstralloc(AMANDA_DBGDIR, "/", subdir, "/", NULL);
276     else
277         dbgdir = stralloc2(AMANDA_DBGDIR, "/");
278     if(mkpdir(dbgdir, 0700, get_client_uid(), get_client_gid()) == -1) {
279         error(_("create debug directory \"%s\": %s"),
280               dbgdir, strerror(errno));
281         /*NOTREACHED*/
282     }
283     amfree(sane_config);
284
285     /*
286      * Clean out old debug files.  We also rename files with old style
287      * names (XXX.debug or XXX.$PID.debug) into the new name format.
288      * We assume no system has 17 digit PID-s :-) and that there will
289      * not be a conflict between an old and new name.
290      */
291     if((d = opendir(dbgdir)) == NULL) {
292         error(_("open debug directory \"%s\": %s"),
293               dbgdir, strerror(errno));
294         /*NOTREACHED*/
295     }
296     time(&open_time);
297     test_name = get_debug_name(open_time - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
298     test_name_len = strlen(test_name);
299     while((entry = readdir(d)) != NULL) {
300         if(is_dot_or_dotdot(entry->d_name)) {
301             continue;
302         }
303         d_name_len = strlen(entry->d_name);
304         if(strncmp(entry->d_name, pname, pname_len) != 0
305            || entry->d_name[pname_len] != '.'
306            || d_name_len < 6
307            || strcmp(entry->d_name + d_name_len - 6, ".debug") != 0) {
308             continue;                           /* not one of our debug files */
309         }
310         e = newvstralloc(e, dbgdir, entry->d_name, NULL);
311         if(d_name_len < test_name_len) {
312             /*
313              * Create a "pretend" name based on the last modification
314              * time.  This name will be used to decide if the real name
315              * should be removed.  If not, it will be used to rename the
316              * real name.
317              */
318             if(stat(e, &sbuf) != 0) {
319                 continue;                       /* ignore errors */
320             }
321             amfree(dbfilename);
322             dbfilename = get_debug_name((time_t)sbuf.st_mtime, 0);
323             do_rename = 1;
324         } else {
325             dbfilename = newstralloc(dbfilename, entry->d_name);
326             do_rename = 0;
327         }
328         if(strcmp(dbfilename, test_name) < 0) {
329             (void) unlink(e);                   /* get rid of old file */
330             continue;
331         }
332         if(do_rename) {
333             i = 0;
334             while(dbfilename != NULL
335                   && (s = newvstralloc(s, dbgdir, dbfilename, NULL)) != NULL
336                   && rename(e, s) != 0 && errno != ENOENT) {
337                 amfree(dbfilename);
338                 dbfilename = get_debug_name((time_t)sbuf.st_mtime, ++i);
339             }
340             if(dbfilename == NULL) {
341                 error(_("cannot rename old debug file \"%s\""), entry->d_name);
342                 /*NOTREACHED*/
343             }
344         }
345     }
346     amfree(dbfilename);
347     amfree(e);
348     amfree(s);
349     amfree(test_name);
350     closedir(d);
351 }
352
353 /* Given an already-opened debug file, set the file's ownership
354  * appropriately, move its file descriptor above MIN_DB_FD, and
355  * add an initial log entry to the file.
356  *
357  * This function records the file's identity in the globals
358  * db_filename, db_fd, and db_file.  It does *not* set db_name.
359  * db_file is not set if fd is -1
360  *
361  * This function uses the global 'open_time', which is set by
362  * debug_setup_1.
363  *
364  * @param s: the filename of the debug file; string should be malloc'd,
365  * and should *not* be freed by the caller.
366  * @param fd: the descriptor connected to the debug file, or -1 if
367  * no decriptor moving should take place.
368  * @param annotation: an extra string to include in the initial
369  * log entry.
370  */
371 static void
372 debug_setup_2(
373     char *      s,
374     int         fd,
375     char *      annotation)
376 {
377     int i;
378     int fd_close[MIN_DB_FD+1];
379
380     amfree(db_filename);
381     db_filename = s;
382     s = NULL;
383
384     /* If we're root, change the ownership of the debug files.  If we're not root,
385      * this would either be redundant or an error. */
386     if (geteuid() == 0) {
387         if (chown(db_filename, get_client_uid(), get_client_gid()) < 0) {
388             dbprintf(_("chown(%s, %d, %d) failed: %s"),
389                      db_filename, (int)get_client_uid(), (int)get_client_gid(), strerror(errno));
390         }
391     }
392     amfree(dbgdir);
393     /*
394      * Move the file descriptor up high so it stays out of the way
395      * of other processing, e.g. sendbackup.
396      */
397     if (fd >= 0) {
398         i = 0;
399         fd_close[i++] = fd;
400         while((db_fd = dup(fd)) < MIN_DB_FD) {
401             fd_close[i++] = db_fd;
402         }
403         while(--i >= 0) {
404             close(fd_close[i]);
405         }
406         db_file = fdopen(db_fd, "a");
407     }
408
409     if (annotation) {
410         /*
411          * Make the first debug log file entry.
412          */
413         debug_printf(_("pid %ld ruid %ld euid %ld version %s: %s at %s"),
414                      (long)getpid(),
415                      (long)getuid(), (long)geteuid(),
416                      VERSION,
417                      annotation,
418                      ctime(&open_time));
419     }
420 }
421
422 /* Get current GMT time and return a message timestamp.
423  * Used for g_printf calls to logs and such.  The return value
424  * is to a static buffer, so it should be used immediately.
425  *
426  * @returns: timestamp
427  */
428 static char *
429 msg_timestamp(void)
430 {
431     static char timestamp[128];
432     struct timeval tv;
433
434     gettimeofday(&tv, NULL);
435     g_snprintf(timestamp, SIZEOF(timestamp), "%lld.%06ld",
436                 (long long)tv.tv_sec, (long)tv.tv_usec);
437
438     return timestamp;
439 }
440
441 /*
442  * ---- public functions
443  */
444
445 void
446 debug_init(void)
447 {
448     debug_setup_logging();
449
450     /* the scriptutil context does not create a debug log, since such
451      * processes are invoked many times.
452      */
453     if (get_pcontext() != CONTEXT_SCRIPTUTIL) {
454         debug_open(get_ptype());
455     }
456 }
457
458 void
459 set_logerror(void (*f)(char *))
460 {
461     logerror_fn = f;
462 }
463
464 void
465 debug_open(char *subdir)
466 {
467     int fd = -1;
468     int i;
469     char *s = NULL;
470     mode_t mask;
471
472     /* set up logging while we're here */
473     debug_setup_logging();
474
475     /* set 'dbgdir' and clean out old debug files */
476     debug_setup_1(NULL, subdir);
477
478     /*
479      * Create the new file with a unique sequence number.
480      */
481     mask = (mode_t)umask((mode_t)0037); /* Allow the group read bit through */
482
483     /* iteratate through sequence numbers until we find one that
484      * is not already in use */
485     for(i = 0; fd < 0; i++) {
486         amfree(db_name);
487         if ((db_name = get_debug_name(open_time, i)) == NULL) {
488             error(_("Cannot create debug file name in %d tries."), i);
489             /*NOTREACHED*/
490         }
491
492         if ((s = newvstralloc(s, dbgdir, db_name, NULL)) == NULL) {
493             error(_("Cannot allocate debug file name memory"));
494             /*NOTREACHED*/
495         }
496
497         if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
498             if (errno != EEXIST) {
499                 error(_("Cannot create debug file \"%s\": %s"),
500                         s, strerror(errno));
501                 /*NOTREACHED*/
502             }
503             amfree(s);
504         }
505     }
506     (void)umask(mask); /* Restore mask */
507
508     /*
509      * Finish setup.
510      *
511      * Note: we release control of the string 's' points to.
512      */
513     debug_setup_2(s, fd, "start");
514 }
515
516 void
517 debug_reopen(
518     char *      dbfilename,
519     char *      annotation)
520 {
521     char *s = NULL;
522     int fd;
523
524     if (dbfilename == NULL) {
525         return;
526     }
527
528     /* set 'dbgdir' and clean out old debug files */
529     debug_setup_1(NULL, NULL);
530
531     /*
532      * Reopen the file.
533      */
534     if (*dbfilename == '/') {
535         s = stralloc(dbfilename);
536     } else {
537         s = newvstralloc(s, dbgdir, dbfilename, NULL);
538     }
539     if ((fd = open(s, O_RDWR|O_APPEND)) < 0) {
540         error(_("cannot reopen debug file %s"), dbfilename);
541         /*NOTREACHED*/
542     }
543
544     /*
545      * Finish setup.
546      *
547      * Note: we release control of the string 's' points to.
548      */
549     debug_setup_2(s, fd, annotation);
550 }
551
552 void
553 debug_rename(
554     char *config,
555     char *subdir)
556 {
557     int fd = -1;
558     int i;
559     char *s = NULL;
560     mode_t mask;
561
562     if (!db_filename)
563         return;
564
565     /* set 'dbgdir' and clean out old debug files */
566     debug_setup_1(config, subdir);
567
568     s = newvstralloc(s, dbgdir, db_name, NULL);
569
570     if (strcmp(db_filename, s) == 0) {
571         amfree(s);
572         return;
573     }
574
575     mask = (mode_t)umask((mode_t)0037);
576
577 #if defined(__CYGWIN__)
578     /*
579      * On cygwin, rename will not overwrite an existing file nor
580      * will it rename a file that is open for writing...
581      *
582      * Rename file directly.  Expect failure if file already exists
583      * or is open by another user.
584      */
585
586     i = 0;
587     while (rename(db_filename, s) < 0) {
588         if (errno != EEXIST) {
589             /*
590              * If the failure was not due to the target file name already
591              * existing then we have bigger issues at hand so we keep 
592              * the existing file.
593              */
594             dbprintf(_("Cannot rename \"%s\" to \"%s\": %s\n"),
595                      db_filename, s, strerror(errno));
596             s = newvstralloc(s, db_filename, NULL);
597             i = -1;
598             break;
599         }
600
601         /*
602          * Files already exists:
603          * Continue searching for a unique file name that will work.
604          */
605         amfree(db_name);
606         if ((db_name = get_debug_name(open_time, i++)) == NULL) {
607             dbprintf(_("Cannot create unique debug file name"));
608             break;
609         }
610         s = newvstralloc(s, dbgdir, db_name, NULL);
611     }
612     if (i >= 0) {
613         /*
614          * We need to close and reopen the original file handle to
615          * release control of the original debug file name.
616          */
617         if ((fd = open(s, O_WRONLY|O_APPEND, 0640)) >= 0) {
618             /*
619              * We can safely close the the original log file
620              * since we now have a new working handle.
621              */
622             db_fd = 2;
623             fclose(db_file);
624             db_file = NULL;
625         }
626     }
627 #else
628     /* check if a file with the same name already exists. */
629     if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
630         for(i = 0; fd < 0; i++) {
631             amfree(db_name);
632             if ((db_name = get_debug_name(open_time, i)) == NULL) {
633                 dbprintf(_("Cannot create debug file"));
634                 break;
635             }
636
637             s = newvstralloc(s, dbgdir, db_name, NULL);
638             if ((fd = open(s, O_WRONLY|O_CREAT|O_EXCL|O_APPEND, 0640)) < 0) {
639                 if (errno != EEXIST) {
640                     dbprintf(_("Cannot create debug file: %s"),
641                               strerror(errno));
642                     break;
643                 }
644             }
645         }
646     }
647
648     if (fd >= 0) {
649         close(fd);
650         if (rename(db_filename, s) == -1) {
651             dbprintf(_("Cannot rename \"%s\" to \"%s\": %s\n"),
652                      db_filename, s, strerror(errno));
653         }
654         fd = -1;
655     }
656 #endif
657
658     (void)umask(mask); /* Restore mask */
659     /*
660      * Finish setup.
661      *
662      * Note: we release control of the string 's' points to.
663      */
664     debug_setup_2(s, fd, "rename");
665 }
666
667 void
668 debug_close(void)
669 {
670     time_t curtime;
671
672     time(&curtime);
673     debug_printf(_("pid %ld finish time %s"), (long)getpid(), ctime(&curtime));
674
675     if(db_file && fclose(db_file) == EOF) {
676         int save_errno = errno;
677
678         db_file = NULL;                         /* prevent recursion */
679         g_fprintf(stderr, _("close debug file: %s"), strerror(save_errno));
680         /*NOTREACHED*/
681     }
682     db_fd = 2;
683     db_file = NULL;
684     amfree(db_filename);
685     amfree(db_name);
686 }
687
688 /*
689  * Format and write a debug message to the process debug file.
690  */
691 printf_arglist_function(void debug_printf, const char *, format)
692 {
693     va_list argp;
694     int save_errno;
695
696     /*
697      * It is common in the code to call dbprintf to write out
698      * syserrno(errno) and then turn around and try to do something else
699      * with errno (e.g. g_printf() or log()), so we make sure errno goes
700      * back out with the same value it came in with.
701      */
702
703     save_errno = errno;
704
705     /* handle the default (stderr) if debug_open hasn't been called yet */
706     if(db_file == NULL && db_fd == 2) {
707         db_file = stderr;
708     }
709     if(db_file != NULL) {
710         char *prefix;
711         char *text;
712
713         if (db_file != stderr)
714             prefix = g_strdup_printf("%s: %s:", msg_timestamp(), get_pname());
715         else 
716             prefix = g_strdup_printf("%s:", get_pname());
717         arglist_start(argp, format);
718         text = g_strdup_vprintf(format, argp);
719         arglist_end(argp);
720         fprintf(db_file, "%s %s", prefix, text);
721         amfree(prefix);
722         amfree(text);
723         fflush(db_file);
724     }
725     errno = save_errno;
726 }
727
728 int
729 debug_fd(void)
730 {
731     return db_fd;
732 }
733
734 FILE *
735 debug_fp(void)
736 {
737     return db_file;
738 }
739
740 char *
741 debug_fn(void)
742 {
743     return db_filename;
744 }
745
746 void
747 debug_dup_stderr_to_debug(void)
748 {
749     if(db_fd != -1 && db_fd != STDERR_FILENO)
750     {
751        if(dup2(db_fd, STDERR_FILENO) != STDERR_FILENO)
752        {
753            error(_("can't redirect stderr to the debug file"));
754            g_assert_not_reached();
755        }
756     }
757 }
758