LCOV - code coverage report
Current view: top level - lib/util - debug.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 412 653 63.1 %
Date: 2024-02-14 10:14:15 Functions: 40 64 62.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Elrond               2002
       6             :    Copyright (C) Simo Sorce           2002
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "replace.h"
      23             : #include <talloc.h>
      24             : #include "system/filesys.h"
      25             : #include "system/syslog.h"
      26             : #include "system/locale.h"
      27             : #include "system/network.h"
      28             : #include "system/time.h"
      29             : #include "time_basic.h"
      30             : #include "close_low_fd.h"
      31             : #include "memory.h"
      32             : #include "util_strlist.h" /* LIST_SEP */
      33             : #include "blocking.h"
      34             : #include "debug.h"
      35             : #include <assert.h>
      36             : 
      37             : /* define what facility to use for syslog */
      38             : #ifndef SYSLOG_FACILITY
      39             : #define SYSLOG_FACILITY LOG_DAEMON
      40             : #endif
      41             : 
      42             : /* -------------------------------------------------------------------------- **
      43             :  * Defines...
      44             :  */
      45             : 
      46             : /*
      47             :  * format_bufr[FORMAT_BUFR_SIZE - 1] should always be reserved
      48             :  * for a terminating null byte.
      49             :  */
      50             : #define FORMAT_BUFR_SIZE 4096
      51             : 
      52             : /* -------------------------------------------------------------------------- **
      53             :  * This module implements Samba's debugging utility.
      54             :  *
      55             :  * The syntax of a debugging log file is represented as:
      56             :  *
      57             :  *  <debugfile> :== { <debugmsg> }
      58             :  *
      59             :  *  <debugmsg>  :== <debughdr> '\n' <debugtext>
      60             :  *
      61             :  *  <debughdr>  :== '[' TIME ',' LEVEL ']' [ [FILENAME ':'] [FUNCTION '()'] ]
      62             :  *
      63             :  *  <debugtext> :== { <debugline> }
      64             :  *
      65             :  *  <debugline> :== TEXT '\n'
      66             :  *
      67             :  * TEXT     is a string of characters excluding the newline character.
      68             :  * LEVEL    is the DEBUG level of the message (an integer in the range 0..10).
      69             :  * TIME     is a timestamp.
      70             :  * FILENAME is the name of the file from which the debug message was generated.
      71             :  * FUNCTION is the function from which the debug message was generated.
      72             :  *
      73             :  * Basically, what that all means is:
      74             :  *
      75             :  * - A debugging log file is made up of debug messages.
      76             :  *
      77             :  * - Each debug message is made up of a header and text.  The header is
      78             :  *   separated from the text by a newline.
      79             :  *
      80             :  * - The header begins with the timestamp and debug level of the message
      81             :  *   enclosed in brackets.  The filename and function from which the
      82             :  *   message was generated may follow.  The filename is terminated by a
      83             :  *   colon, and the function name is terminated by parenthesis.
      84             :  *
      85             :  * - The message text is made up of zero or more lines, each terminated by
      86             :  *   a newline.
      87             :  */
      88             : 
      89             : /* state variables for the debug system */
      90             : static struct {
      91             :         bool initialized;
      92             :         enum debug_logtype logtype; /* The type of logging we are doing: eg stdout, file, stderr */
      93             :         char prog_name[255];
      94             :         char hostname[HOST_NAME_MAX+1];
      95             :         bool reopening_logs;
      96             :         bool schedule_reopen_logs;
      97             : 
      98             :         struct debug_settings settings;
      99             :         debug_callback_fn callback;
     100             :         void *callback_private;
     101             :         char header_str[300];
     102             :         char header_str_no_nl[300];
     103             :         size_t hs_len;
     104             :         char msg_no_nl[FORMAT_BUFR_SIZE];
     105             : } state = {
     106             :         .settings = {
     107             :                 .timestamp_logs = true
     108             :         },
     109             : };
     110             : 
     111             : struct debug_class {
     112             :         /*
     113             :          * The debug loglevel of the class.
     114             :          */
     115             :         int loglevel;
     116             : 
     117             :         /*
     118             :          * An optional class specific logfile, may be NULL in which case the
     119             :          * "global" logfile is used and fd is -1.
     120             :          */
     121             :         char *logfile;
     122             :         int fd;
     123             :         /* inode number of the logfile to detect logfile rotation */
     124             :         ino_t ino;
     125             : };
     126             : 
     127             : /*
     128             :  * default_classname_table[] is read in from debug-classname-table.c
     129             :  * so that test_logging.c can use it too.
     130             :  */
     131             : #include "lib/util/debug-classes/debug-classname-table.c"
     132             : 
     133             : /*
     134             :  * This is to allow reading of dbgc_config before the debug
     135             :  * system has been initialized.
     136             :  */
     137             : static struct debug_class debug_class_list_initial[ARRAY_SIZE(default_classname_table)] = {
     138             :         [DBGC_ALL] = { .fd = 2 },
     139             : };
     140             : 
     141             : static size_t debug_num_classes = 0;
     142             : static struct debug_class *dbgc_config = debug_class_list_initial;
     143             : 
     144             : static int current_msg_level = 0;
     145             : static int current_msg_class = 0;
     146             : 
     147             : /*
     148             :  * DBG_DEV(): when and how to user it.
     149             :  *
     150             :  * As a developer, you sometimes want verbose logging between point A and
     151             :  * point B, where the relationship between these points is not easily defined
     152             :  * in terms of the call stack.
     153             :  *
     154             :  * For example, you might be interested in what is going on in functions in
     155             :  * lib/util/util_str.c in an ldap worker process after a particular query. If
     156             :  * you use gdb, something will time out and you won't get the full
     157             :  * conversation. If you add fprintf() or DBG_ERR()s to util_str.c, you'll get
     158             :  * a massive flood, and there's a chance one will accidentally slip into a
     159             :  * release and the whole world will flood. DBG_DEV is a solution.
     160             :  *
     161             :  * On start-up, DBG_DEV() is switched OFF. Nothing is printed.
     162             :  *
     163             :  * 1. Add `DBG_DEV("formatted msg %d, etc\n", i);` where needed.
     164             :  *
     165             :  * 2. At each point you want to start debugging, add `debug_developer_enable()`.
     166             :  *
     167             :  * 3. At each point you want debugging to stop, add `debug_developer_disable()`.
     168             :  *
     169             :  * In DEVELOPER builds, the message will be printed at level 0, as with
     170             :  * DBG_ERR(). In production builds, the macro resolves to nothing.
     171             :  *
     172             :  * The messages are printed with a "<function_name>:DEV:<pid>:" prefix.
     173             :  */
     174             : 
     175             : static bool debug_developer_is_enabled = false;
     176             : 
     177           0 : bool debug_developer_enabled(void)
     178             : {
     179           0 :         return debug_developer_is_enabled;
     180             : }
     181             : 
     182             : /*
     183             :  * debug_developer_disable() will turn DBG_DEV() on in the current
     184             :  * process and children.
     185             :  */
     186           0 : void debug_developer_enable(void)
     187             : {
     188           0 :         debug_developer_is_enabled = true;
     189           0 : }
     190             : 
     191             : /*
     192             :  * debug_developer_disable() will make DBG_DEV() do nothing in the current
     193             :  * process (and children).
     194             :  */
     195           0 : void debug_developer_disable(void)
     196             : {
     197           0 :         debug_developer_is_enabled = false;
     198           0 : }
     199             : 
     200             : /*
     201             :  * Within debug.c, DBG_DEV() always writes to stderr, because some functions
     202             :  * here will attempt infinite recursion with normal DEBUG macros.
     203             :  */
     204             : #ifdef DEVELOPER
     205             : #undef DBG_DEV
     206             : #define DBG_DEV(fmt, ...)                                               \
     207             :         (void)((debug_developer_enabled())                              \
     208             :                && (fprintf(stderr, "%s:DEV:%d: " fmt "%s",          \
     209             :                            __func__, getpid(), ##__VA_ARGS__, "")) )
     210             : #endif
     211             : 
     212             : 
     213             : #if defined(WITH_SYSLOG) || defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
     214           0 : static int debug_level_to_priority(int level)
     215             : {
     216             :         /*
     217             :          * map debug levels to syslog() priorities
     218             :          */
     219             :         static const int priority_map[] = {
     220             :                 LOG_ERR,     /* 0 */
     221             :                 LOG_WARNING, /* 1 */
     222             :                 LOG_NOTICE,  /* 2 */
     223             :                 LOG_NOTICE,  /* 3 */
     224             :                 LOG_NOTICE,  /* 4 */
     225             :                 LOG_NOTICE,  /* 5 */
     226             :                 LOG_INFO,    /* 6 */
     227             :                 LOG_INFO,    /* 7 */
     228             :                 LOG_INFO,    /* 8 */
     229             :                 LOG_INFO,    /* 9 */
     230             :         };
     231             :         int priority;
     232             : 
     233           0 :         if (level < 0 || (size_t)level >= ARRAY_SIZE(priority_map))
     234           0 :                 priority = LOG_DEBUG;
     235             :         else
     236           0 :                 priority = priority_map[level];
     237             : 
     238           0 :         return priority;
     239             : }
     240             : #endif
     241             : 
     242             : /* -------------------------------------------------------------------------- **
     243             :  * Produce a version of the given buffer without any trailing newlines.
     244             :  */
     245             : #if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD) || \
     246             :         defined(HAVE_LTTNG_TRACEF) || defined(HAVE_GPFS)
     247           0 : static void copy_no_nl(char *out,
     248             :                        size_t out_size,
     249             :                        const char *in,
     250             :                        size_t in_len)
     251             : {
     252             :         size_t len;
     253             :         /*
     254             :          * Some backends already add an extra newline, so also provide
     255             :          * a buffer without the newline character.
     256             :          */
     257           0 :         len = MIN(in_len, out_size - 1);
     258           0 :         if ((len > 0) && (in[len - 1] == '\n')) {
     259           0 :                 len--;
     260             :         }
     261             : 
     262           0 :         memcpy(out, in, len);
     263           0 :         out[len] = '\0';
     264           0 : }
     265             : 
     266           0 : static void ensure_copy_no_nl(char *out,
     267             :                               size_t out_size,
     268             :                               const char *in,
     269             :                               size_t in_len)
     270             : {
     271             :         /*
     272             :          * Assume out is a static buffer that is reused as a cache.
     273             :          * If it isn't empty then this has already been done with the
     274             :          * same input.
     275             :          */
     276           0 :         if (out[0] != '\0') {
     277           0 :                 return;
     278             :         }
     279             : 
     280           0 :         copy_no_nl(out, out_size, in, in_len);
     281             : }
     282             : #endif
     283             : 
     284             : /* -------------------------------------------------------------------------- **
     285             :  * Debug backends. When logging to DEBUG_FILE, send the log entries to
     286             :  * all active backends.
     287             :  */
     288             : 
     289         696 : static void debug_file_log(int msg_level, const char *msg, size_t msg_len)
     290             : {
     291         696 :         struct iovec iov[] = {
     292             :                 {
     293             :                         .iov_base = discard_const(state.header_str),
     294         696 :                         .iov_len = state.hs_len,
     295             :                 },
     296             :                 {
     297             :                         .iov_base = discard_const(msg),
     298             :                         .iov_len = msg_len,
     299             :                 },
     300             :         };
     301             :         ssize_t ret;
     302             :         int fd;
     303             : 
     304         696 :         check_log_size();
     305             : 
     306         696 :         if (dbgc_config[current_msg_class].fd != -1) {
     307         678 :                 fd = dbgc_config[current_msg_class].fd;
     308             :         } else {
     309          18 :                 fd = dbgc_config[DBGC_ALL].fd;
     310             :         }
     311             : 
     312             :         do {
     313         696 :                 ret = writev(fd, iov, ARRAY_SIZE(iov));
     314         696 :         } while (ret == -1 && errno == EINTR);
     315         696 : }
     316             : 
     317             : #ifdef WITH_SYSLOG
     318       45898 : static void debug_syslog_reload(bool enabled, bool previously_enabled,
     319             :                                 const char *prog_name, char *option)
     320             : {
     321       45898 :         if (enabled && !previously_enabled) {
     322        7006 :                 const char *ident = NULL;
     323        7006 :                 if ((prog_name != NULL) && (prog_name[0] != '\0')) {
     324        2641 :                         ident = prog_name;
     325             :                 }
     326             : #ifdef LOG_DAEMON
     327        7006 :                 openlog(ident, LOG_PID, SYSLOG_FACILITY);
     328             : #else
     329             :                 /* for old systems that have no facility codes. */
     330             :                 openlog(ident, LOG_PID);
     331             : #endif
     332        7006 :                 return;
     333             :         }
     334             : 
     335       38892 :         if (!enabled && previously_enabled) {
     336           0 :                 closelog();
     337             :         }
     338             : }
     339             : 
     340           0 : static void debug_syslog_log(int msg_level, const char *msg, size_t msg_len)
     341             : {
     342             :         int priority;
     343             : 
     344           0 :         priority = debug_level_to_priority(msg_level);
     345             : 
     346             :         /*
     347             :          * Specify the facility to interoperate with other syslog
     348             :          * callers (vfs_full_audit for example).
     349             :          */
     350           0 :         priority |= SYSLOG_FACILITY;
     351             : 
     352           0 :         if (state.hs_len > 0) {
     353           0 :                 syslog(priority, "%s", state.header_str);
     354             :         }
     355           0 :         syslog(priority, "%s", msg);
     356           0 : }
     357             : #endif /* WITH_SYSLOG */
     358             : 
     359             : #if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
     360             : #include <systemd/sd-journal.h>
     361           0 : static void debug_systemd_log(int msg_level, const char *msg, size_t msg_len)
     362             : {
     363           0 :         if (state.hs_len > 0) {
     364           0 :                 ensure_copy_no_nl(state.header_str_no_nl,
     365             :                                   sizeof(state.header_str_no_nl),
     366             :                                   state.header_str,
     367             :                                   state.hs_len);
     368           0 :                 sd_journal_send("MESSAGE=%s",
     369             :                                 state.header_str_no_nl,
     370             :                                 "PRIORITY=%d",
     371             :                                 debug_level_to_priority(msg_level),
     372             :                                 "LEVEL=%d",
     373             :                                 msg_level,
     374             :                                 NULL);
     375             :         }
     376           0 :         ensure_copy_no_nl(state.msg_no_nl,
     377             :                           sizeof(state.msg_no_nl),
     378             :                           msg, msg_len);
     379           0 :         sd_journal_send("MESSAGE=%s", state.msg_no_nl,
     380             :                         "PRIORITY=%d", debug_level_to_priority(msg_level),
     381             :                         "LEVEL=%d", msg_level,
     382             :                         NULL);
     383           0 : }
     384             : #endif
     385             : 
     386             : #ifdef HAVE_LTTNG_TRACEF
     387             : #include <lttng/tracef.h>
     388             : static void debug_lttng_log(int msg_level, const char *msg, size_t msg_len)
     389             : {
     390             :         if (state.hs_len > 0) {
     391             :                 ensure_copy_no_nl(state.header_str_no_nl,
     392             :                                   sizeof(state.header_str_no_nl),
     393             :                                   state.header_str,
     394             :                                   state.hs_len);
     395             :                 tracef(state.header_str_no_nl);
     396             :         }
     397             :         ensure_copy_no_nl(state.msg_no_nl,
     398             :                           sizeof(state.msg_no_nl),
     399             :                           msg, msg_len);
     400             :         tracef(state.msg_no_nl);
     401             : }
     402             : #endif /* WITH_LTTNG_TRACEF */
     403             : 
     404             : #ifdef HAVE_GPFS
     405             : #include "gpfswrap.h"
     406       45898 : static void debug_gpfs_reload(bool enabled, bool previously_enabled,
     407             :                               const char *prog_name, char *option)
     408             : {
     409       45898 :         gpfswrap_init();
     410             : 
     411       45898 :         if (enabled && !previously_enabled) {
     412           0 :                 gpfswrap_init_trace();
     413           0 :                 return;
     414             :         }
     415             : 
     416       45898 :         if (!enabled && previously_enabled) {
     417           0 :                 gpfswrap_fini_trace();
     418           0 :                 return;
     419             :         }
     420             : 
     421       45898 :         if (enabled) {
     422             :                 /*
     423             :                  * Trigger GPFS library to adjust state if necessary.
     424             :                  */
     425           0 :                 gpfswrap_query_trace();
     426             :         }
     427             : }
     428             : 
     429           0 : static void debug_gpfs_log(int msg_level, const char *msg, size_t msg_len)
     430             : {
     431           0 :         if (state.hs_len > 0) {
     432           0 :                 ensure_copy_no_nl(state.header_str_no_nl,
     433             :                                   sizeof(state.header_str_no_nl),
     434             :                                   state.header_str,
     435             :                                   state.hs_len);
     436           0 :                 gpfswrap_add_trace(msg_level, state.header_str_no_nl);
     437             :         }
     438           0 :         ensure_copy_no_nl(state.msg_no_nl,
     439             :                           sizeof(state.msg_no_nl),
     440             :                           msg, msg_len);
     441           0 :         gpfswrap_add_trace(msg_level, state.msg_no_nl);
     442           0 : }
     443             : #endif /* HAVE_GPFS */
     444             : 
     445             : #define DEBUG_RINGBUF_SIZE (1024 * 1024)
     446             : #define DEBUG_RINGBUF_SIZE_OPT "size="
     447             : 
     448             : static char *debug_ringbuf;
     449             : static size_t debug_ringbuf_size;
     450             : static size_t debug_ringbuf_ofs;
     451             : 
     452             : /* We ensure in debug_ringbuf_log() that this is always \0 terminated */
     453           0 : char *debug_get_ringbuf(void)
     454             : {
     455           0 :         return debug_ringbuf;
     456             : }
     457             : 
     458             : /* Return the size of the ringbuf (including a \0 terminator) */
     459           0 : size_t debug_get_ringbuf_size(void)
     460             : {
     461           0 :         return debug_ringbuf_size;
     462             : }
     463             : 
     464       45898 : static void debug_ringbuf_reload(bool enabled, bool previously_enabled,
     465             :                                  const char *prog_name, char *option)
     466             : {
     467             :         bool cmp;
     468       45898 :         size_t optlen = strlen(DEBUG_RINGBUF_SIZE_OPT);
     469             : 
     470       45898 :         debug_ringbuf_size = DEBUG_RINGBUF_SIZE;
     471       45898 :         debug_ringbuf_ofs = 0;
     472             : 
     473       45898 :         SAFE_FREE(debug_ringbuf);
     474             : 
     475       45898 :         if (!enabled) {
     476       45898 :                 return;
     477             :         }
     478             : 
     479           0 :         if (option != NULL) {
     480           0 :                 cmp = strncmp(option, DEBUG_RINGBUF_SIZE_OPT, optlen);
     481           0 :                 if (cmp == 0) {
     482           0 :                         debug_ringbuf_size = (size_t)strtoull(
     483           0 :                                 option + optlen, NULL, 10);
     484             :                 }
     485             :         }
     486             : 
     487           0 :         debug_ringbuf = calloc(debug_ringbuf_size, sizeof(char));
     488           0 :         if (debug_ringbuf == NULL) {
     489           0 :                 return;
     490             :         }
     491             : }
     492             : 
     493           0 : static void _debug_ringbuf_log(int msg_level, const char *msg, size_t msg_len)
     494             : {
     495             :         size_t allowed_size;
     496             : 
     497           0 :         if (debug_ringbuf == NULL) {
     498           0 :                 return;
     499             :         }
     500             : 
     501             :         /* Ensure the buffer is always \0 terminated */
     502           0 :         allowed_size = debug_ringbuf_size - 1;
     503             : 
     504           0 :         if (msg_len > allowed_size) {
     505           0 :                 return;
     506             :         }
     507             : 
     508           0 :         if ((debug_ringbuf_ofs + msg_len) < debug_ringbuf_ofs) {
     509           0 :                 return;
     510             :         }
     511             : 
     512           0 :         if ((debug_ringbuf_ofs + msg_len) > allowed_size) {
     513           0 :                 debug_ringbuf_ofs = 0;
     514             :         }
     515             : 
     516           0 :         memcpy(debug_ringbuf + debug_ringbuf_ofs, msg, msg_len);
     517           0 :         debug_ringbuf_ofs += msg_len;
     518             : }
     519             : 
     520           0 : static void debug_ringbuf_log(int msg_level, const char *msg, size_t msg_len)
     521             : {
     522           0 :         if (state.hs_len > 0) {
     523           0 :                 _debug_ringbuf_log(msg_level, state.header_str, state.hs_len);
     524             :         }
     525           0 :         _debug_ringbuf_log(msg_level, msg, msg_len);
     526           0 : }
     527             : 
     528             : static struct debug_backend {
     529             :         const char *name;
     530             :         int log_level;
     531             :         int new_log_level;
     532             :         void (*reload)(bool enabled, bool prev_enabled,
     533             :                        const char *prog_name, char *option);
     534             :         void (*log)(int msg_level,
     535             :                     const char *msg,
     536             :                     size_t len);
     537             :         char *option;
     538             : } debug_backends[] = {
     539             :         {
     540             :                 .name = "file",
     541             :                 .log = debug_file_log,
     542             :         },
     543             : #ifdef WITH_SYSLOG
     544             :         {
     545             :                 .name = "syslog",
     546             :                 .reload = debug_syslog_reload,
     547             :                 .log = debug_syslog_log,
     548             :         },
     549             : #endif
     550             : 
     551             : #if defined(HAVE_LIBSYSTEMD_JOURNAL) || defined(HAVE_LIBSYSTEMD)
     552             :         {
     553             :                 .name = "systemd",
     554             :                 .log = debug_systemd_log,
     555             :         },
     556             : #endif
     557             : 
     558             : #ifdef HAVE_LTTNG_TRACEF
     559             :         {
     560             :                 .name = "lttng",
     561             :                 .log = debug_lttng_log,
     562             :         },
     563             : #endif
     564             : 
     565             : #ifdef HAVE_GPFS
     566             :         {
     567             :                 .name = "gpfs",
     568             :                 .reload = debug_gpfs_reload,
     569             :                 .log = debug_gpfs_log,
     570             :         },
     571             : #endif
     572             :         {
     573             :                 .name = "ringbuf",
     574             :                 .log = debug_ringbuf_log,
     575             :                 .reload = debug_ringbuf_reload,
     576             :         },
     577             : };
     578             : 
     579      111779 : static struct debug_backend *debug_find_backend(const char *name)
     580             : {
     581             :         unsigned i;
     582             : 
     583      139314 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
     584      139312 :                 if (strcmp(name, debug_backends[i].name) == 0) {
     585      111777 :                         return &debug_backends[i];
     586             :                 }
     587             :         }
     588             : 
     589           2 :         return NULL;
     590             : }
     591             : 
     592             : /*
     593             :  * parse "backend[:option][@loglevel]
     594             :  */
     595       73421 : static void debug_backend_parse_token(char *tok)
     596             : {
     597             :         char *backend_name_option, *backend_name,*backend_level, *saveptr;
     598             :         char *backend_option;
     599             :         struct debug_backend *b;
     600             : 
     601             :         /*
     602             :          * First parse into backend[:option] and loglevel
     603             :          */
     604       73421 :         backend_name_option = strtok_r(tok, "@\0", &saveptr);
     605       73421 :         if (backend_name_option == NULL) {
     606           2 :                 return;
     607             :         }
     608             : 
     609       73421 :         backend_level = strtok_r(NULL, "\0", &saveptr);
     610             : 
     611             :         /*
     612             :          * Now parse backend[:option]
     613             :          */
     614       73421 :         backend_name = strtok_r(backend_name_option, ":\0", &saveptr);
     615       73421 :         if (backend_name == NULL) {
     616           0 :                 return;
     617             :         }
     618             : 
     619       73421 :         backend_option = strtok_r(NULL, "\0", &saveptr);
     620             : 
     621             :         /*
     622             :          * Find and update backend
     623             :          */
     624       73421 :         b = debug_find_backend(backend_name);
     625       73421 :         if (b == NULL) {
     626           2 :                 return;
     627             :         }
     628             : 
     629       73419 :         if (backend_level == NULL) {
     630       18371 :                 b->new_log_level = MAX_DEBUG_LEVEL;
     631             :         } else {
     632       55048 :                 b->new_log_level = atoi(backend_level);
     633             :         }
     634             : 
     635       73419 :         if (backend_option != NULL) {
     636           0 :                 b->option = strdup(backend_option);
     637           0 :                 if (b->option == NULL) {
     638           0 :                         return;
     639             :                 }
     640             :         }
     641             : }
     642             : 
     643             : /*
     644             :  * parse "backend1[:option1][@loglevel1] backend2[option2][@loglevel2] ... "
     645             :  * and enable/disable backends accordingly
     646             :  */
     647       45898 : static void debug_set_backends(const char *param)
     648       45898 : {
     649       45898 :         size_t str_len = strlen(param);
     650       45898 :         char str[str_len+1];
     651             :         char *tok, *saveptr;
     652             :         unsigned i;
     653             : 
     654             :         /*
     655             :          * initialize new_log_level to detect backends that have been
     656             :          * disabled
     657             :          */
     658      275388 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
     659      229490 :                 SAFE_FREE(debug_backends[i].option);
     660      229490 :                 debug_backends[i].new_log_level = -1;
     661             :         }
     662             : 
     663       45898 :         memcpy(str, param, str_len + 1);
     664             : 
     665       45898 :         tok = strtok_r(str, LIST_SEP, &saveptr);
     666       45898 :         if (tok == NULL) {
     667           0 :                 return;
     668             :         }
     669             : 
     670      119319 :         while (tok != NULL) {
     671       73421 :                 debug_backend_parse_token(tok);
     672       73421 :                 tok = strtok_r(NULL, LIST_SEP, &saveptr);
     673             :         }
     674             : 
     675             :         /*
     676             :          * Let backends react to config changes
     677             :          */
     678      275388 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
     679      229490 :                 struct debug_backend *b = &debug_backends[i];
     680             : 
     681      229490 :                 if (b->reload) {
     682      137694 :                         bool enabled = b->new_log_level > -1;
     683      137694 :                         bool previously_enabled = b->log_level > -1;
     684             : 
     685      137694 :                         b->reload(enabled, previously_enabled, state.prog_name,
     686             :                                   b->option);
     687             :                 }
     688      229490 :                 b->log_level = b->new_log_level;
     689             :         }
     690             : }
     691             : 
     692         696 : static void debug_backends_log(const char *msg, size_t msg_len, int msg_level)
     693             : {
     694             :         size_t i;
     695             : 
     696             :         /*
     697             :          * Some backends already add an extra newline, so initialize a
     698             :          * buffer without the newline character.  It will be filled by
     699             :          * the first backend that needs it.
     700             :          */
     701         696 :         state.msg_no_nl[0] = '\0';
     702             : 
     703        4176 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
     704        3480 :                 if (msg_level <= debug_backends[i].log_level) {
     705         696 :                         debug_backends[i].log(msg_level, msg, msg_len);
     706             :                 }
     707             :         }
     708             : 
     709             :         /* Only log the header once */
     710         696 :         state.hs_len = 0;
     711         696 : }
     712             : 
     713   450805873 : int debuglevel_get_class(size_t idx)
     714             : {
     715   450805873 :         return dbgc_config[idx].loglevel;
     716             : }
     717             : 
     718        2001 : void debuglevel_set_class(size_t idx, int level)
     719             : {
     720        2001 :         dbgc_config[idx].loglevel = level;
     721        2001 : }
     722             : 
     723             : 
     724             : /* -------------------------------------------------------------------------- **
     725             :  * Internal variables.
     726             :  *
     727             :  *  debug_count     - Number of debug messages that have been output.
     728             :  *                    Used to check log size.
     729             :  *
     730             :  *  current_msg_level    - Internal copy of the message debug level.  Written by
     731             :  *                    dbghdr() and read by Debug1().
     732             :  *
     733             :  *  format_bufr     - Used to format debug messages.  The dbgtext() function
     734             :  *                    prints debug messages to a string, and then passes the
     735             :  *                    string to format_debug_text(), which uses format_bufr
     736             :  *                    to build the formatted output.
     737             :  *
     738             :  *  format_pos      - Marks the first free byte of the format_bufr.
     739             :  *
     740             :  *
     741             :  *  log_overflow    - When this variable is true, never attempt to check the
     742             :  *                    size of the log. This is a hack, so that we can write
     743             :  *                    a message using DEBUG, from open_logs() when we
     744             :  *                    are unable to open a new log file for some reason.
     745             :  */
     746             : 
     747             : static int     debug_count    = 0;
     748             : static char format_bufr[FORMAT_BUFR_SIZE];
     749             : static size_t     format_pos     = 0;
     750             : static bool    log_overflow   = false;
     751             : 
     752             : /*
     753             :  * Define all the debug class selection names here. Names *MUST NOT* contain
     754             :  * white space. There must be one name for each DBGC_<class name>, and they
     755             :  * must be in the table in the order of DBGC_<class name>..
     756             :  */
     757             : 
     758             : static char **classname_table = NULL;
     759             : 
     760             : 
     761             : /* -------------------------------------------------------------------------- **
     762             :  * Functions...
     763             :  */
     764             : 
     765             : static void debug_init(void);
     766             : 
     767             : /***************************************************************************
     768             :  Free memory pointed to by global pointers.
     769             : ****************************************************************************/
     770             : 
     771         227 : void gfree_debugsyms(void)
     772             : {
     773             :         unsigned i;
     774             : 
     775         227 :         TALLOC_FREE(classname_table);
     776             : 
     777         227 :         if ( dbgc_config != debug_class_list_initial ) {
     778         227 :                 TALLOC_FREE( dbgc_config );
     779         227 :                 dbgc_config = discard_const_p(struct debug_class,
     780             :                                                    debug_class_list_initial);
     781             :         }
     782             : 
     783         227 :         debug_num_classes = 0;
     784             : 
     785         227 :         state.initialized = false;
     786             : 
     787        1362 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
     788        1135 :                 SAFE_FREE(debug_backends[i].option);
     789             :         }
     790         227 : }
     791             : 
     792             : /****************************************************************************
     793             : utility lists registered debug class names's
     794             : ****************************************************************************/
     795             : 
     796           0 : char *debug_list_class_names_and_levels(void)
     797             : {
     798           0 :         char *buf = talloc_strdup(NULL, "");
     799             :         size_t i;
     800             :         /* prepare strings */
     801           0 :         for (i = 0; i < debug_num_classes; i++) {
     802           0 :                 talloc_asprintf_addbuf(&buf,
     803             :                                        "%s:%d%s",
     804           0 :                                        classname_table[i],
     805           0 :                                        dbgc_config[i].loglevel,
     806           0 :                                        i == (debug_num_classes - 1) ? "\n" : " ");
     807             :         }
     808           0 :         return buf;
     809             : }
     810             : 
     811             : /****************************************************************************
     812             :  Utility to translate names to debug class index's (internal version).
     813             : ****************************************************************************/
     814             : 
     815      532212 : static int debug_lookup_classname_int(const char* classname)
     816             : {
     817             :         size_t i;
     818             : 
     819      532212 :         if (classname == NULL) {
     820           0 :                 return -1;
     821             :         }
     822             : 
     823    10502188 :         for (i=0; i < debug_num_classes; i++) {
     824     9969976 :                 char *entry = classname_table[i];
     825     9969976 :                 if (entry != NULL && strcmp(classname, entry)==0) {
     826           0 :                         return i;
     827             :                 }
     828             :         }
     829      532212 :         return -1;
     830             : }
     831             : 
     832             : /****************************************************************************
     833             :  Add a new debug class to the system.
     834             : ****************************************************************************/
     835             : 
     836      532212 : int debug_add_class(const char *classname)
     837             : {
     838             :         int ndx;
     839      532212 :         struct debug_class *new_class_list = NULL;
     840             :         char **new_name_list;
     841             :         int default_level;
     842             : 
     843      532212 :         if (classname == NULL) {
     844           0 :                 return -1;
     845             :         }
     846             : 
     847             :         /* check the init has yet been called */
     848      532212 :         debug_init();
     849             : 
     850      532212 :         ndx = debug_lookup_classname_int(classname);
     851      532212 :         if (ndx >= 0) {
     852           0 :                 return ndx;
     853             :         }
     854      532212 :         ndx = debug_num_classes;
     855             : 
     856      532212 :         if (dbgc_config == debug_class_list_initial) {
     857             :                 /* Initial loading... */
     858       13842 :                 new_class_list = NULL;
     859             :         } else {
     860      518370 :                 new_class_list = dbgc_config;
     861             :         }
     862             : 
     863      532212 :         default_level = dbgc_config[DBGC_ALL].loglevel;
     864             : 
     865      532212 :         new_class_list = talloc_realloc(NULL,
     866             :                                         new_class_list,
     867             :                                         struct debug_class,
     868             :                                         ndx + 1);
     869      532212 :         if (new_class_list == NULL) {
     870           0 :                 return -1;
     871             :         }
     872             : 
     873      532212 :         dbgc_config = new_class_list;
     874             : 
     875      532212 :         dbgc_config[ndx] = (struct debug_class) {
     876             :                 .loglevel = default_level,
     877             :                 .fd = -1,
     878             :         };
     879             : 
     880      532212 :         new_name_list = talloc_realloc(NULL, classname_table, char *, ndx + 1);
     881      532212 :         if (new_name_list == NULL) {
     882           0 :                 return -1;
     883             :         }
     884      532212 :         classname_table = new_name_list;
     885             : 
     886      532212 :         classname_table[ndx] = talloc_strdup(classname_table, classname);
     887      532212 :         if (classname_table[ndx] == NULL) {
     888           0 :                 return -1;
     889             :         }
     890             : 
     891      532212 :         debug_num_classes = ndx + 1;
     892             : 
     893      532212 :         return ndx;
     894             : }
     895             : 
     896             : /****************************************************************************
     897             :  Utility to translate names to debug class index's (public version).
     898             : ****************************************************************************/
     899             : 
     900           0 : static int debug_lookup_classname(const char *classname)
     901             : {
     902             :         int ndx;
     903             : 
     904           0 :         if (classname == NULL || !*classname)
     905           0 :                 return -1;
     906             : 
     907           0 :         ndx = debug_lookup_classname_int(classname);
     908             : 
     909           0 :         if (ndx != -1)
     910           0 :                 return ndx;
     911             : 
     912           0 :         DBG_WARNING("Unknown classname[%s] -> adding it...\n", classname);
     913           0 :         return debug_add_class(classname);
     914             : }
     915             : 
     916             : /****************************************************************************
     917             :  Dump the current registered debug levels.
     918             : ****************************************************************************/
     919             : 
     920       65122 : static void debug_dump_status(int level)
     921             : {
     922             :         size_t q;
     923             : 
     924       65122 :         DEBUG(level, ("INFO: Current debug levels:\n"));
     925     2540175 :         for (q = 0; q < debug_num_classes; q++) {
     926     2475053 :                 const char *classname = classname_table[q];
     927     2475053 :                 DEBUGADD(level, ("  %s: %d\n",
     928             :                                  classname,
     929             :                                  dbgc_config[q].loglevel));
     930             :         }
     931       65122 : }
     932             : 
     933           0 : static bool debug_parse_param(char *param)
     934             : {
     935             :         char *class_name;
     936           0 :         char *class_file = NULL;
     937             :         char *class_level;
     938           0 :         char *saveptr = NULL;
     939             :         int ndx;
     940             : 
     941           0 :         class_name = strtok_r(param, ":", &saveptr);
     942           0 :         if (class_name == NULL) {
     943           0 :                 return false;
     944             :         }
     945             : 
     946           0 :         class_level = strtok_r(NULL, "@\0", &saveptr);
     947           0 :         if (class_level == NULL) {
     948           0 :                 return false;
     949             :         }
     950             : 
     951           0 :         class_file = strtok_r(NULL, "\0", &saveptr);
     952             : 
     953           0 :         ndx = debug_lookup_classname(class_name);
     954           0 :         if (ndx == -1) {
     955           0 :                 return false;
     956             :         }
     957             : 
     958           0 :         dbgc_config[ndx].loglevel = atoi(class_level);
     959             : 
     960           0 :         if (class_file == NULL) {
     961           0 :                 return true;
     962             :         }
     963             : 
     964           0 :         TALLOC_FREE(dbgc_config[ndx].logfile);
     965             : 
     966           0 :         dbgc_config[ndx].logfile = talloc_strdup(NULL, class_file);
     967           0 :         if (dbgc_config[ndx].logfile == NULL) {
     968           0 :                 return false;
     969             :         }
     970           0 :         return true;
     971             : }
     972             : 
     973             : /****************************************************************************
     974             :  Parse the debug levels from smb.conf. Example debug level string:
     975             :   3 tdb:5 printdrivers:7
     976             :  Note: the 1st param has no "name:" preceding it.
     977             : ****************************************************************************/
     978             : 
     979       65122 : bool debug_parse_levels(const char *params_str)
     980       65122 : {
     981       65122 :         size_t str_len = strlen(params_str);
     982       65122 :         char str[str_len+1];
     983             :         char *tok, *saveptr;
     984             :         size_t i;
     985             : 
     986             :         /* Just in case */
     987       65122 :         debug_init();
     988             : 
     989       65122 :         memcpy(str, params_str, str_len+1);
     990             : 
     991       65122 :         tok = strtok_r(str, LIST_SEP, &saveptr);
     992       65122 :         if (tok == NULL) {
     993           0 :                 return true;
     994             :         }
     995             : 
     996             :         /* Allow DBGC_ALL to be specified w/o requiring its class name e.g."10"
     997             :          * v.s. "all:10", this is the traditional way to set DEBUGLEVEL
     998             :          */
     999       65122 :         if (isdigit(tok[0])) {
    1000       65122 :                 dbgc_config[DBGC_ALL].loglevel = atoi(tok);
    1001       65122 :                 tok = strtok_r(NULL, LIST_SEP, &saveptr);
    1002             :         } else {
    1003           0 :                 dbgc_config[DBGC_ALL].loglevel = 0;
    1004             :         }
    1005             : 
    1006             :         /* Array is debug_num_classes long */
    1007     2475053 :         for (i = DBGC_ALL+1; i < debug_num_classes; i++) {
    1008     2409931 :                 dbgc_config[i].loglevel = dbgc_config[DBGC_ALL].loglevel;
    1009     2409931 :                 TALLOC_FREE(dbgc_config[i].logfile);
    1010             :         }
    1011             : 
    1012       65122 :         while (tok != NULL) {
    1013             :                 bool ok;
    1014             : 
    1015           0 :                 ok = debug_parse_param(tok);
    1016           0 :                 if (!ok) {
    1017           0 :                         DEBUG(0,("debug_parse_params: unrecognized debug "
    1018             :                                  "class name or format [%s]\n", tok));
    1019           0 :                         return false;
    1020             :                 }
    1021             : 
    1022           0 :                 tok = strtok_r(NULL, LIST_SEP, &saveptr);
    1023             :         }
    1024             : 
    1025       65122 :         debug_dump_status(5);
    1026             : 
    1027       65122 :         return true;
    1028             : }
    1029             : 
    1030             : /* setup for logging of talloc warnings */
    1031           0 : static void talloc_log_fn(const char *msg)
    1032             : {
    1033           0 :         DEBUG(0,("%s", msg));
    1034           0 : }
    1035             : 
    1036       21477 : void debug_setup_talloc_log(void)
    1037             : {
    1038       21477 :         talloc_set_log_fn(talloc_log_fn);
    1039       21477 : }
    1040             : 
    1041             : 
    1042             : /****************************************************************************
    1043             : Init debugging (one time stuff)
    1044             : ****************************************************************************/
    1045             : 
    1046      803679 : static void debug_init(void)
    1047             : {
    1048             :         size_t i;
    1049             : 
    1050      803679 :         if (state.initialized)
    1051      789837 :                 return;
    1052             : 
    1053       13842 :         state.initialized = true;
    1054             : 
    1055       13842 :         debug_setup_talloc_log();
    1056             : 
    1057      539838 :         for (i = 0; i < ARRAY_SIZE(default_classname_table); i++) {
    1058      525996 :                 debug_add_class(default_classname_table[i]);
    1059             :         }
    1060       13842 :         dbgc_config[DBGC_ALL].fd = 2;
    1061             : 
    1062       83052 :         for (i = 0; i < ARRAY_SIZE(debug_backends); i++) {
    1063       69210 :                 debug_backends[i].log_level = -1;
    1064       69210 :                 debug_backends[i].new_log_level = -1;
    1065             :         }
    1066             : }
    1067             : 
    1068       45898 : void debug_set_settings(struct debug_settings *settings,
    1069             :                         const char *logging_param,
    1070             :                         int syslog_level, bool syslog_only)
    1071             : {
    1072             :         char fake_param[256];
    1073       45898 :         size_t len = 0;
    1074             : 
    1075             :         /*
    1076             :          * This forces in some smb.conf derived values into the debug
    1077             :          * system. There are no pointers in this structure, so we can
    1078             :          * just structure-assign it in
    1079             :          */
    1080       45898 :         state.settings = *settings;
    1081             : 
    1082             :         /*
    1083             :          * If 'logging' is not set, create backend settings from
    1084             :          * deprecated 'syslog' and 'syslog only' parameters
    1085             :          */
    1086       45898 :         if (logging_param != NULL) {
    1087       45898 :                 len = strlen(logging_param);
    1088             :         }
    1089       45898 :         if (len == 0) {
    1090       27525 :                 if (syslog_only) {
    1091           2 :                         snprintf(fake_param, sizeof(fake_param),
    1092             :                                  "syslog@%d", syslog_level - 1);
    1093             :                 } else {
    1094       27523 :                         snprintf(fake_param, sizeof(fake_param),
    1095             :                                  "syslog@%d file@%d", syslog_level -1,
    1096             :                                  MAX_DEBUG_LEVEL);
    1097             :                 }
    1098             : 
    1099       27525 :                 logging_param = fake_param;
    1100             :         }
    1101             : 
    1102       45898 :         debug_set_backends(logging_param);
    1103       45898 : }
    1104             : 
    1105           0 : static void ensure_hostname(void)
    1106             : {
    1107             :         int ret;
    1108             : 
    1109           0 :         if (state.hostname[0] != '\0') {
    1110           0 :                 return;
    1111             :         }
    1112             : 
    1113           0 :         ret = gethostname(state.hostname, sizeof(state.hostname));
    1114           0 :         if (ret != 0) {
    1115           0 :                 strlcpy(state.hostname, "unknown", sizeof(state.hostname));
    1116           0 :                 return;
    1117             :         }
    1118             : 
    1119             :         /*
    1120             :          * Ensure NUL termination, since POSIX isn't clear about that.
    1121             :          *
    1122             :          * Don't worry about truncating at the first '.' or similar,
    1123             :          * since this is usually not fully qualified.  Trying to
    1124             :          * truncate opens up the multibyte character gates of hell.
    1125             :          */
    1126           0 :         state.hostname[sizeof(state.hostname) - 1] = '\0';
    1127             : }
    1128             : 
    1129           0 : void debug_set_hostname(const char *name)
    1130             : {
    1131           0 :         strlcpy(state.hostname, name, sizeof(state.hostname));
    1132           0 : }
    1133             : 
    1134             : /**
    1135             :  * Ensure debug logs are initialised.
    1136             :  *
    1137             :  * setup_logging() is called to direct logging to the correct outputs, whether
    1138             :  * those be stderr, stdout, files, or syslog, and set the program name used in
    1139             :  * the logs. It can be called multiple times.
    1140             :  *
    1141             :  * There is an order of precedence to the log type. Once set to DEBUG_FILE, it
    1142             :  * cannot be reset DEFAULT_DEBUG_STDERR, but can be set to DEBUG_STDERR, after
    1143             :  * which DEBUG_FILE is unavailable). This makes it possible to override for
    1144             :  * debug to stderr on the command line, as the smb.conf cannot reset it back
    1145             :  * to file-based logging. See enum debug_logtype.
    1146             :  *
    1147             :  * @param prog_name the program name. Directory path component will be
    1148             :  *                  ignored.
    1149             :  *
    1150             :  * @param new_logtype the requested destination for the debug log,
    1151             :  *                    as an enum debug_logtype.
    1152             :  */
    1153        9338 : void setup_logging(const char *prog_name, enum debug_logtype new_logtype)
    1154             : {
    1155        9338 :         debug_init();
    1156        9338 :         if (state.logtype < new_logtype) {
    1157         834 :                 state.logtype = new_logtype;
    1158             :         }
    1159        9338 :         if (prog_name) {
    1160        9338 :                 const char *p = strrchr(prog_name, '/');
    1161             : 
    1162        9338 :                 if (p) {
    1163         282 :                         prog_name = p + 1;
    1164             :                 }
    1165             : 
    1166        9338 :                 strlcpy(state.prog_name, prog_name, sizeof(state.prog_name));
    1167             :         }
    1168        9338 :         reopen_logs_internal();
    1169        9338 : }
    1170             : 
    1171             : /***************************************************************************
    1172             :  Set the logfile name.
    1173             : **************************************************************************/
    1174             : 
    1175       58208 : void debug_set_logfile(const char *name)
    1176             : {
    1177       58208 :         if (name == NULL || *name == 0) {
    1178             :                 /* this copes with calls when smb.conf is not loaded yet */
    1179           0 :                 return;
    1180             :         }
    1181       58208 :         TALLOC_FREE(dbgc_config[DBGC_ALL].logfile);
    1182       58208 :         dbgc_config[DBGC_ALL].logfile = talloc_strdup(NULL, name);
    1183             : 
    1184       58208 :         reopen_logs_internal();
    1185             : }
    1186             : 
    1187     1502049 : static void debug_close_fd(int fd)
    1188             : {
    1189     1502049 :         if (fd > 2) {
    1190       37932 :                 close(fd);
    1191             :         }
    1192     1502049 : }
    1193             : 
    1194         164 : enum debug_logtype debug_get_log_type(void)
    1195             : {
    1196         164 :         return state.logtype;
    1197             : }
    1198             : 
    1199           0 : bool debug_get_output_is_stderr(void)
    1200             : {
    1201           0 :         return (state.logtype == DEBUG_DEFAULT_STDERR) || (state.logtype == DEBUG_STDERR);
    1202             : }
    1203             : 
    1204          95 : bool debug_get_output_is_stdout(void)
    1205             : {
    1206          95 :         return (state.logtype == DEBUG_DEFAULT_STDOUT) || (state.logtype == DEBUG_STDOUT);
    1207             : }
    1208             : 
    1209          43 : void debug_set_callback(void *private_ptr, debug_callback_fn fn)
    1210             : {
    1211          43 :         debug_init();
    1212          43 :         if (fn) {
    1213          28 :                 state.logtype = DEBUG_CALLBACK;
    1214          28 :                 state.callback_private = private_ptr;
    1215          28 :                 state.callback = fn;
    1216             :         } else {
    1217          15 :                 state.logtype = DEBUG_DEFAULT_STDERR;
    1218          15 :                 state.callback_private = NULL;
    1219          15 :                 state.callback = NULL;
    1220             :         }
    1221          43 : }
    1222             : 
    1223          63 : static void debug_callback_log(const char *msg, size_t msg_len, int msg_level)
    1224          63 : {
    1225          63 :         char msg_copy[msg_len];
    1226             : 
    1227          63 :         if ((msg_len > 0) && (msg[msg_len-1] == '\n')) {
    1228          63 :                 memcpy(msg_copy, msg, msg_len-1);
    1229          63 :                 msg_copy[msg_len-1] = '\0';
    1230          63 :                 msg = msg_copy;
    1231             :         }
    1232             : 
    1233          63 :         state.callback(state.callback_private, msg_level, msg);
    1234          63 : }
    1235             : 
    1236             : /**************************************************************************
    1237             :  reopen the log files
    1238             :  note that we now do this unconditionally
    1239             :  We attempt to open the new debug fp before closing the old. This means
    1240             :  if we run out of fd's we just keep using the old fd rather than aborting.
    1241             :  Fix from dgibson@linuxcare.com.
    1242             : **************************************************************************/
    1243             : 
    1244     1446636 : static bool reopen_one_log(struct debug_class *config)
    1245             : {
    1246     1446636 :         int old_fd = config->fd;
    1247     1446636 :         const char *logfile = config->logfile;
    1248             :         struct stat st;
    1249             :         int new_fd;
    1250             :         int ret;
    1251             : 
    1252     1446636 :         if (logfile == NULL) {
    1253     1408278 :                 debug_close_fd(old_fd);
    1254     1408278 :                 config->fd = -1;
    1255     1408278 :                 return true;
    1256             :         }
    1257             : 
    1258       38358 :         new_fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0644);
    1259       38358 :         if (new_fd == -1) {
    1260         300 :                 log_overflow = true;
    1261         300 :                 DBG_ERR("Unable to open new log file '%s': %s\n",
    1262             :                         logfile, strerror(errno));
    1263         300 :                 log_overflow = false;
    1264         300 :                 return false;
    1265             :         }
    1266             : 
    1267       38058 :         debug_close_fd(old_fd);
    1268       38058 :         smb_set_close_on_exec(new_fd);
    1269       38058 :         config->fd = new_fd;
    1270             : 
    1271       38058 :         ret = fstat(new_fd, &st);
    1272       38058 :         if (ret != 0) {
    1273           0 :                 log_overflow = true;
    1274           0 :                 DBG_ERR("Unable to fstat() new log file '%s': %s\n",
    1275             :                         logfile, strerror(errno));
    1276           0 :                 log_overflow = false;
    1277           0 :                 return false;
    1278             :         }
    1279             : 
    1280       38058 :         config->ino = st.st_ino;
    1281       38058 :         return true;
    1282             : }
    1283             : 
    1284             : /**
    1285             :   reopen the log file (usually called because the log file name might have changed)
    1286             : */
    1287       94084 : bool reopen_logs_internal(void)
    1288             : {
    1289       94084 :         struct debug_backend *b = NULL;
    1290             :         mode_t oldumask;
    1291             :         size_t i;
    1292             :         bool ok;
    1293             : 
    1294       94084 :         if (state.reopening_logs) {
    1295           0 :                 return true;
    1296             :         }
    1297             : 
    1298             :         /* Now clear the SIGHUP induced flag */
    1299       94084 :         state.schedule_reopen_logs = false;
    1300             : 
    1301       94084 :         switch (state.logtype) {
    1302          13 :         case DEBUG_CALLBACK:
    1303          13 :                 return true;
    1304       15726 :         case DEBUG_STDOUT:
    1305             :         case DEBUG_DEFAULT_STDOUT:
    1306       15726 :                 debug_close_fd(dbgc_config[DBGC_ALL].fd);
    1307       15726 :                 dbgc_config[DBGC_ALL].fd = 1;
    1308       15726 :                 return true;
    1309             : 
    1310       39987 :         case DEBUG_DEFAULT_STDERR:
    1311             :         case DEBUG_STDERR:
    1312       39987 :                 debug_close_fd(dbgc_config[DBGC_ALL].fd);
    1313       39987 :                 dbgc_config[DBGC_ALL].fd = 2;
    1314       39987 :                 return true;
    1315             : 
    1316       38358 :         case DEBUG_FILE:
    1317       38358 :                 b = debug_find_backend("file");
    1318       38358 :                 assert(b != NULL);
    1319             : 
    1320       38358 :                 b->log_level = MAX_DEBUG_LEVEL;
    1321       38358 :                 break;
    1322             :         }
    1323             : 
    1324       38358 :         oldumask = umask( 022 );
    1325             : 
    1326       38358 :         for (i = DBGC_ALL; i < debug_num_classes; i++) {
    1327       38358 :                 if (dbgc_config[i].logfile != NULL) {
    1328       38358 :                         break;
    1329             :                 }
    1330             :         }
    1331       38358 :         if (i == debug_num_classes) {
    1332           0 :                 return false;
    1333             :         }
    1334             : 
    1335       38358 :         state.reopening_logs = true;
    1336             : 
    1337     1484694 :         for (i = DBGC_ALL; i < debug_num_classes; i++) {
    1338     1446636 :                 ok = reopen_one_log(&dbgc_config[i]);
    1339     1446636 :                 if (!ok) {
    1340         300 :                         break;
    1341             :                 }
    1342             :         }
    1343             : 
    1344             :         /* Fix from klausr@ITAP.Physik.Uni-Stuttgart.De
    1345             :          * to fix problem where smbd's that generate less
    1346             :          * than 100 messages keep growing the log.
    1347             :          */
    1348       38358 :         force_check_log_size();
    1349       38358 :         (void)umask(oldumask);
    1350             : 
    1351             :         /*
    1352             :          * If log file was opened or created successfully, take over stderr to
    1353             :          * catch output into logs.
    1354             :          */
    1355       38358 :         if (!state.settings.debug_no_stderr_redirect &&
    1356       38358 :             dbgc_config[DBGC_ALL].fd > 0) {
    1357       38358 :                 if (dup2(dbgc_config[DBGC_ALL].fd, 2) == -1) {
    1358             :                         /* Close stderr too, if dup2 can't point it -
    1359             :                            at the logfile.  There really isn't much
    1360             :                            that can be done on such a fundamental
    1361             :                            failure... */
    1362           0 :                         close_low_fd(2);
    1363             :                 }
    1364             :         }
    1365             : 
    1366       38358 :         state.reopening_logs = false;
    1367             : 
    1368       38358 :         return ok;
    1369             : }
    1370             : 
    1371             : /**************************************************************************
    1372             :  Force a check of the log size.
    1373             :  ***************************************************************************/
    1374             : 
    1375     9538890 : void force_check_log_size( void )
    1376             : {
    1377     9538890 :         debug_count = 100;
    1378     9538890 : }
    1379             : 
    1380           0 : _PUBLIC_ void debug_schedule_reopen_logs(void)
    1381             : {
    1382           0 :         state.schedule_reopen_logs = true;
    1383           0 : }
    1384             : 
    1385             : 
    1386             : /***************************************************************************
    1387             :  Check to see if there is any need to check if the logfile has grown too big.
    1388             : **************************************************************************/
    1389             : 
    1390     9486924 : bool need_to_check_log_size(void)
    1391             : {
    1392             :         int maxlog;
    1393             :         size_t i;
    1394             : 
    1395     9486924 :         if (debug_count < 100) {
    1396        1550 :                 return false;
    1397             :         }
    1398             : 
    1399     9485374 :         maxlog = state.settings.max_log_size * 1024;
    1400     9485374 :         if (maxlog <= 0) {
    1401         192 :                 debug_count = 0;
    1402         192 :                 return false;
    1403             :         }
    1404             : 
    1405     9485182 :         if (dbgc_config[DBGC_ALL].fd > 2) {
    1406        1056 :                 return true;
    1407             :         }
    1408             : 
    1409   360396788 :         for (i = DBGC_ALL + 1; i < debug_num_classes; i++) {
    1410   350912662 :                 if (dbgc_config[i].fd != -1) {
    1411           0 :                         return true;
    1412             :                 }
    1413             :         }
    1414             : 
    1415     9484126 :         debug_count = 0;
    1416     9484126 :         return false;
    1417             : }
    1418             : 
    1419             : /**************************************************************************
    1420             :  Check to see if the log has grown to be too big.
    1421             :  **************************************************************************/
    1422             : 
    1423         702 : static void do_one_check_log_size(off_t maxlog, struct debug_class *config)
    1424         702 : {
    1425         702 :         char name[strlen(config->logfile) + 5];
    1426             :         struct stat st;
    1427             :         int ret;
    1428         702 :         bool reopen = false;
    1429             :         bool ok;
    1430             : 
    1431         702 :         if (maxlog == 0) {
    1432         702 :                 return;
    1433             :         }
    1434             : 
    1435         702 :         ret = stat(config->logfile, &st);
    1436         702 :         if (ret != 0) {
    1437           0 :                 return;
    1438             :         }
    1439         702 :         if (st.st_size >= maxlog ) {
    1440           0 :                 reopen = true;
    1441             :         }
    1442             : 
    1443         702 :         if (st.st_ino != config->ino) {
    1444           0 :                 reopen = true;
    1445             :         }
    1446             : 
    1447         702 :         if (!reopen) {
    1448         702 :                 return;
    1449             :         }
    1450             : 
    1451             :         /* reopen_logs_internal() modifies *_fd */
    1452           0 :         (void)reopen_logs_internal();
    1453             : 
    1454           0 :         if (config->fd <= 2) {
    1455           0 :                 return;
    1456             :         }
    1457           0 :         ret = fstat(config->fd, &st);
    1458           0 :         if (ret != 0) {
    1459           0 :                 config->ino = (ino_t)0;
    1460           0 :                 return;
    1461             :         }
    1462             : 
    1463           0 :         config->ino = st.st_ino;
    1464             : 
    1465           0 :         if (st.st_size < maxlog) {
    1466           0 :                 return;
    1467             :         }
    1468             : 
    1469           0 :         snprintf(name, sizeof(name), "%s.old", config->logfile);
    1470             : 
    1471           0 :         (void)rename(config->logfile, name);
    1472             : 
    1473           0 :         ok = reopen_logs_internal();
    1474           0 :         if (ok) {
    1475           0 :                 return;
    1476             :         }
    1477             :         /* We failed to reopen a log - continue using the old name. */
    1478           0 :         (void)rename(name, config->logfile);
    1479             : }
    1480             : 
    1481         702 : static void do_check_log_size(off_t maxlog)
    1482             : {
    1483             :         size_t i;
    1484             : 
    1485       28071 :         for (i = DBGC_ALL; i < debug_num_classes; i++) {
    1486       27369 :                 if (dbgc_config[i].fd == -1) {
    1487       26667 :                         continue;
    1488             :                 }
    1489         702 :                 if (dbgc_config[i].logfile == NULL) {
    1490           0 :                         continue;
    1491             :                 }
    1492         702 :                 do_one_check_log_size(maxlog, &dbgc_config[i]);
    1493             :         }
    1494         702 : }
    1495             : 
    1496        1389 : void check_log_size( void )
    1497             : {
    1498             :         off_t maxlog;
    1499             : 
    1500        1389 :         if (geteuid() != 0) {
    1501             :                 /*
    1502             :                  * We need to be root to change the log file (tests use a fake
    1503             :                  * geteuid() from third_party/uid_wrapper). Otherwise we skip
    1504             :                  * this and let the main smbd loop or some other process do
    1505             :                  * the work.
    1506             :                  */
    1507          14 :                 return;
    1508             :         }
    1509             : 
    1510        1375 :         if(log_overflow || (!state.schedule_reopen_logs && !need_to_check_log_size())) {
    1511         673 :                 return;
    1512             :         }
    1513             : 
    1514         702 :         maxlog = state.settings.max_log_size * 1024;
    1515             : 
    1516         702 :         if (state.schedule_reopen_logs) {
    1517           0 :                 (void)reopen_logs_internal();
    1518             :         }
    1519             : 
    1520         702 :         do_check_log_size(maxlog);
    1521             : 
    1522             :         /*
    1523             :          * Here's where we need to panic if dbgc_config[DBGC_ALL].fd == 0 or -1
    1524             :          * (invalid values)
    1525             :          */
    1526             : 
    1527         702 :         if (dbgc_config[DBGC_ALL].fd <= 0) {
    1528             :                 /* This code should only be reached in very strange
    1529             :                  * circumstances. If we merely fail to open the new log we
    1530             :                  * should stick with the old one. ergo this should only be
    1531             :                  * reached when opening the logs for the first time: at
    1532             :                  * startup or when the log level is increased from zero.
    1533             :                  * -dwg 6 June 2000
    1534             :                  */
    1535           0 :                 int fd = open( "/dev/console", O_WRONLY, 0);
    1536           0 :                 if (fd != -1) {
    1537           0 :                         smb_set_close_on_exec(fd);
    1538           0 :                         dbgc_config[DBGC_ALL].fd = fd;
    1539           0 :                         DBG_ERR("check_log_size: open of debug file %s failed "
    1540             :                                 "- using console.\n",
    1541             :                                 dbgc_config[DBGC_ALL].logfile);
    1542             :                 } else {
    1543             :                         /*
    1544             :                          * We cannot continue without a debug file handle.
    1545             :                          */
    1546           0 :                         abort();
    1547             :                 }
    1548             :         }
    1549         702 :         debug_count = 0;
    1550             : }
    1551             : 
    1552             : /*************************************************************************
    1553             :  Write an debug message on the debugfile.
    1554             :  This is called by format_debug_text().
    1555             : ************************************************************************/
    1556             : 
    1557       35804 : static void Debug1(const char *msg, size_t msg_len)
    1558             : {
    1559       35804 :         int old_errno = errno;
    1560             : 
    1561       35804 :         debug_count++;
    1562             : 
    1563       35804 :         switch(state.logtype) {
    1564          63 :         case DEBUG_CALLBACK:
    1565          63 :                 debug_callback_log(msg, msg_len, current_msg_level);
    1566          63 :                 break;
    1567       35045 :         case DEBUG_STDOUT:
    1568             :         case DEBUG_STDERR:
    1569             :         case DEBUG_DEFAULT_STDOUT:
    1570             :         case DEBUG_DEFAULT_STDERR:
    1571       35045 :                 if (dbgc_config[DBGC_ALL].fd > 0) {
    1572             :                         ssize_t ret;
    1573             :                         do {
    1574       35045 :                                 ret = write(dbgc_config[DBGC_ALL].fd,
    1575             :                                             msg,
    1576             :                                             msg_len);
    1577       35045 :                         } while (ret == -1 && errno == EINTR);
    1578             :                 }
    1579       35045 :                 break;
    1580         696 :         case DEBUG_FILE:
    1581         696 :                 debug_backends_log(msg, msg_len, current_msg_level);
    1582         696 :                 break;
    1583             :         };
    1584             : 
    1585       35804 :         errno = old_errno;
    1586       35804 : }
    1587             : 
    1588             : /**************************************************************************
    1589             :  Print the buffer content via Debug1(), then reset the buffer.
    1590             :  Input:  none
    1591             :  Output: none
    1592             : ****************************************************************************/
    1593             : 
    1594       35769 : static void bufr_print( void )
    1595             : {
    1596       35769 :         format_bufr[format_pos] = '\0';
    1597       35769 :         (void)Debug1(format_bufr, format_pos);
    1598       35769 :         format_pos = 0;
    1599       35769 : }
    1600             : 
    1601             : /***************************************************************************
    1602             :  Format the debug message text.
    1603             : 
    1604             :  Input:  msg - Text to be added to the "current" debug message text.
    1605             : 
    1606             :  Output: none.
    1607             : 
    1608             :  Notes:  The purpose of this is two-fold.  First, each call to syslog()
    1609             :          (used by Debug1(), see above) generates a new line of syslog
    1610             :          output.  This is fixed by storing the partial lines until the
    1611             :          newline character is encountered.  Second, printing the debug
    1612             :          message lines when a newline is encountered allows us to add
    1613             :          spaces, thus indenting the body of the message and making it
    1614             :          more readable.
    1615             : **************************************************************************/
    1616             : 
    1617      196964 : static void format_debug_text( const char *msg )
    1618             : {
    1619             :         size_t i;
    1620      196964 :         bool timestamp = (state.logtype == DEBUG_FILE && (state.settings.timestamp_logs));
    1621             : 
    1622      196964 :         debug_init();
    1623             : 
    1624     2937280 :         for( i = 0; msg[i]; i++ ) {
    1625             :                 /* Indent two spaces at each new line. */
    1626     2740316 :                 if(timestamp && 0 == format_pos) {
    1627         696 :                         format_bufr[0] = format_bufr[1] = ' ';
    1628         696 :                         format_pos = 2;
    1629             :                 }
    1630             : 
    1631             :                 /* If there's room, copy the character to the format buffer. */
    1632     2740316 :                 if (format_pos < FORMAT_BUFR_SIZE - 1)
    1633     2740316 :                         format_bufr[format_pos++] = msg[i];
    1634             : 
    1635             :                 /* If a newline is encountered, print & restart. */
    1636     2740316 :                 if( '\n' == msg[i] )
    1637       35734 :                         bufr_print();
    1638             : 
    1639             :                 /* If the buffer is full dump it out, reset it, and put out a line
    1640             :                  * continuation indicator.
    1641             :                  */
    1642     2740316 :                 if (format_pos >= FORMAT_BUFR_SIZE - 1) {
    1643          35 :                         const char cont[] = " +>\n";
    1644          35 :                         bufr_print();
    1645          35 :                         (void)Debug1(cont , sizeof(cont) - 1);
    1646             :                 }
    1647             :         }
    1648             : 
    1649             :         /* Just to be safe... */
    1650      196964 :         format_bufr[format_pos] = '\0';
    1651      196964 : }
    1652             : 
    1653             : /***************************************************************************
    1654             :  Flush debug output, including the format buffer content.
    1655             : 
    1656             :  Input:  none
    1657             :  Output: none
    1658             : ***************************************************************************/
    1659             : 
    1660           0 : void dbgflush( void )
    1661             : {
    1662           0 :         bufr_print();
    1663           0 : }
    1664             : 
    1665      197905 : bool dbgsetclass(int level, int cls)
    1666             : {
    1667             :         /* Set current_msg_level. */
    1668      197905 :         current_msg_level = level;
    1669             : 
    1670             :         /* Set current message class */
    1671      197905 :         current_msg_class = cls;
    1672             : 
    1673      197905 :         return true;
    1674             : }
    1675             : 
    1676             : /***************************************************************************
    1677             :  Put a Debug Header into header_str.
    1678             : 
    1679             :  Input:  level    - Debug level of the message (not the system-wide debug
    1680             :                     level. )
    1681             :          cls      - Debuglevel class of the calling module.
    1682             :          location - Pointer to a string containing the name of the file
    1683             :                     from which this function was called, or an empty string
    1684             :                     if the __FILE__ macro is not implemented.
    1685             :          func     - Pointer to a string containing the name of the function
    1686             :                     from which this function was called, or an empty string
    1687             :                     if the __FUNCTION__ macro is not implemented.
    1688             : 
    1689             :  Output: Always true.  This makes it easy to fudge a call to dbghdr()
    1690             :          in a macro, since the function can be called as part of a test.
    1691             :          Eg: ( (level <= DEBUGLEVEL) && (dbghdr(level,"",line)) )
    1692             : 
    1693             :  Notes:  This function takes care of setting current_msg_level.
    1694             : 
    1695             : ****************************************************************************/
    1696             : 
    1697       20648 : bool dbghdrclass(int level, int cls, const char *location, const char *func)
    1698             : {
    1699             :         /* Ensure we don't lose any real errno value. */
    1700       20648 :         int old_errno = errno;
    1701       20648 :         bool verbose = false;
    1702             :         struct timeval tv;
    1703             :         struct timeval_buf tvbuf;
    1704             : 
    1705             :         /*
    1706             :          * This might be overkill, but if another early return is
    1707             :          * added later then initialising these avoids potential
    1708             :          * problems
    1709             :          */
    1710       20648 :         state.hs_len = 0;
    1711       20648 :         state.header_str[0] = '\0';
    1712             : 
    1713       20648 :         if( format_pos ) {
    1714             :                 /* This is a fudge.  If there is stuff sitting in the format_bufr, then
    1715             :                  * the *right* thing to do is to call
    1716             :                  *   format_debug_text( "\n" );
    1717             :                  * to write the remainder, and then proceed with the new header.
    1718             :                  * Unfortunately, there are several places in the code at which
    1719             :                  * the DEBUG() macro is used to build partial lines.  That in mind,
    1720             :                  * we'll work under the assumption that an incomplete line indicates
    1721             :                  * that a new header is *not* desired.
    1722             :                  */
    1723         121 :                 return( true );
    1724             :         }
    1725             : 
    1726       20527 :         dbgsetclass(level, cls);
    1727             : 
    1728             :         /* Don't print a header if we're logging to stdout. */
    1729       20527 :         if ( state.logtype != DEBUG_FILE ) {
    1730       19958 :                 return( true );
    1731             :         }
    1732             : 
    1733             :         /* Print the header if timestamps are turned on.  If parameters are
    1734             :          * not yet loaded, then default to timestamps on.
    1735             :          */
    1736         569 :         if (!(state.settings.timestamp_logs ||
    1737           0 :               state.settings.debug_prefix_timestamp ||
    1738           0 :               state.settings.debug_syslog_format)) {
    1739           0 :                 return true;
    1740             :         }
    1741             : 
    1742         569 :         GetTimeOfDay(&tv);
    1743             : 
    1744         569 :         if (state.settings.debug_syslog_format) {
    1745           0 :                 if (state.settings.debug_hires_timestamp) {
    1746           0 :                         timeval_str_buf(&tv, true, true, &tvbuf);
    1747             :                 } else {
    1748             :                         time_t t;
    1749             :                         struct tm *tm;
    1750             : 
    1751           0 :                         t = (time_t)tv.tv_sec;
    1752           0 :                         tm = localtime(&t);
    1753           0 :                         if (tm != NULL) {
    1754             :                                 size_t len;
    1755           0 :                                 len = strftime(tvbuf.buf,
    1756             :                                                sizeof(tvbuf.buf),
    1757             :                                                "%b %e %T",
    1758             :                                                tm);
    1759           0 :                                 if (len == 0) {
    1760             :                                         /* Trigger default time format below */
    1761           0 :                                         tm = NULL;
    1762             :                                 }
    1763             :                         }
    1764           0 :                         if (tm == NULL) {
    1765           0 :                                 snprintf(tvbuf.buf,
    1766             :                                          sizeof(tvbuf.buf),
    1767             :                                          "%ld seconds since the Epoch", (long)t);
    1768             :                         }
    1769             :                 }
    1770             : 
    1771           0 :                 ensure_hostname();
    1772           0 :                 state.hs_len = snprintf(state.header_str,
    1773             :                                         sizeof(state.header_str),
    1774             :                                         "%s %.*s %s[%u]: ",
    1775             :                                         tvbuf.buf,
    1776             :                                         (int)(sizeof(state.hostname) - 1),
    1777             :                                         state.hostname,
    1778             :                                         state.prog_name,
    1779           0 :                                         (unsigned int) getpid());
    1780             : 
    1781           0 :                 goto full;
    1782             :         }
    1783             : 
    1784         569 :         timeval_str_buf(&tv, false, state.settings.debug_hires_timestamp,
    1785             :                         &tvbuf);
    1786             : 
    1787         569 :         state.hs_len = snprintf(state.header_str,
    1788             :                                 sizeof(state.header_str),
    1789             :                                 "[%s, %2d",
    1790             :                                 tvbuf.buf,
    1791             :                                 level);
    1792         569 :         if (state.hs_len >= sizeof(state.header_str) - 1) {
    1793           0 :                 goto full;
    1794             :         }
    1795             : 
    1796         569 :         if (unlikely(dbgc_config[cls].loglevel >= 10)) {
    1797           0 :                 verbose = true;
    1798             :         }
    1799             : 
    1800         569 :         if (verbose || state.settings.debug_pid) {
    1801          13 :                 state.hs_len += snprintf(state.header_str + state.hs_len,
    1802          13 :                                          sizeof(state.header_str) - state.hs_len,
    1803             :                                          ", pid=%u",
    1804          13 :                                          (unsigned int)getpid());
    1805          13 :                 if (state.hs_len >= sizeof(state.header_str) - 1) {
    1806           0 :                         goto full;
    1807             :                 }
    1808             :         }
    1809             : 
    1810         569 :         if (verbose || state.settings.debug_uid) {
    1811           0 :                 state.hs_len += snprintf(state.header_str + state.hs_len,
    1812           0 :                                          sizeof(state.header_str) - state.hs_len,
    1813             :                                          ", effective(%u, %u), real(%u, %u)",
    1814           0 :                                          (unsigned int)geteuid(),
    1815           0 :                                          (unsigned int)getegid(),
    1816           0 :                                          (unsigned int)getuid(),
    1817           0 :                                          (unsigned int)getgid());
    1818           0 :                 if (state.hs_len >= sizeof(state.header_str) - 1) {
    1819           0 :                         goto full;
    1820             :                 }
    1821             :         }
    1822             : 
    1823         569 :         if ((verbose || state.settings.debug_class)
    1824           0 :             && (cls != DBGC_ALL)) {
    1825           0 :                 state.hs_len += snprintf(state.header_str + state.hs_len,
    1826           0 :                                          sizeof(state.header_str) - state.hs_len,
    1827             :                                          ", class=%s",
    1828           0 :                                          classname_table[cls]);
    1829           0 :                 if (state.hs_len >= sizeof(state.header_str) - 1) {
    1830           0 :                         goto full;
    1831             :                 }
    1832             :         }
    1833             : 
    1834         569 :         if (debug_traceid_get() != 0) {
    1835           0 :                 state.hs_len += snprintf(state.header_str + state.hs_len,
    1836           0 :                                          sizeof(state.header_str) - state.hs_len,
    1837             :                                          ", traceid=%" PRIu64,
    1838             :                                          debug_traceid_get());
    1839           0 :                 if (state.hs_len >= sizeof(state.header_str) - 1) {
    1840           0 :                         goto full;
    1841             :                 }
    1842             :         }
    1843             : 
    1844         569 :         state.header_str[state.hs_len] = ']';
    1845         569 :         state.hs_len++;
    1846         569 :         if (state.hs_len < sizeof(state.header_str) - 1) {
    1847         569 :                 state.header_str[state.hs_len] = ' ';
    1848         569 :                 state.hs_len++;
    1849             :         }
    1850         569 :         state.header_str[state.hs_len] = '\0';
    1851             : 
    1852         569 :         if (!state.settings.debug_prefix_timestamp) {
    1853         569 :                 state.hs_len += snprintf(state.header_str + state.hs_len,
    1854         569 :                                          sizeof(state.header_str) - state.hs_len,
    1855             :                                          "%s(%s)\n",
    1856             :                                          location,
    1857             :                                          func);
    1858         569 :                 if (state.hs_len >= sizeof(state.header_str)) {
    1859           0 :                         goto full;
    1860             :                 }
    1861             :         }
    1862             : 
    1863         569 : full:
    1864             :         /*
    1865             :          * Above code never overflows state.header_str and always
    1866             :          * NUL-terminates correctly.  However, state.hs_len can point
    1867             :          * past the end of the buffer to indicate that truncation
    1868             :          * occurred, so fix it if necessary, since state.hs_len is
    1869             :          * expected to be used after return.
    1870             :          */
    1871         569 :         if (state.hs_len >= sizeof(state.header_str)) {
    1872           0 :                 state.hs_len = sizeof(state.header_str) - 1;
    1873             :         }
    1874             : 
    1875         569 :         state.header_str_no_nl[0] = '\0';
    1876             : 
    1877         569 :         errno = old_errno;
    1878         569 :         return( true );
    1879             : }
    1880             : 
    1881             : /***************************************************************************
    1882             :  Add text to the body of the "current" debug message via the format buffer.
    1883             : 
    1884             :   Input:  format_str  - Format string, as used in printf(), et. al.
    1885             :           ...         - Variable argument list.
    1886             : 
    1887             :   ..or..  va_alist    - Old style variable parameter list starting point.
    1888             : 
    1889             :   Output: Always true.  See dbghdr() for more info, though this is not
    1890             :           likely to be used in the same way.
    1891             : 
    1892             : ***************************************************************************/
    1893             : 
    1894             : static inline bool __dbgtext_va(const char *format_str, va_list ap) PRINTF_ATTRIBUTE(1,0);
    1895      196964 : static inline bool __dbgtext_va(const char *format_str, va_list ap)
    1896             : {
    1897      196964 :         char *msgbuf = NULL;
    1898      196964 :         bool ret = true;
    1899             :         int res;
    1900             : 
    1901      196964 :         res = vasprintf(&msgbuf, format_str, ap);
    1902      196964 :         if (res != -1) {
    1903      196964 :                 format_debug_text(msgbuf);
    1904             :         } else {
    1905           0 :                 ret = false;
    1906             :         }
    1907      196964 :         SAFE_FREE(msgbuf);
    1908      196964 :         return ret;
    1909             : }
    1910             : 
    1911           0 : bool dbgtext_va(const char *format_str, va_list ap)
    1912             : {
    1913           0 :         return __dbgtext_va(format_str, ap);
    1914             : }
    1915             : 
    1916      196964 : bool dbgtext(const char *format_str, ... )
    1917             : {
    1918             :         va_list ap;
    1919             :         bool ret;
    1920             : 
    1921      196964 :         va_start(ap, format_str);
    1922      196964 :         ret = __dbgtext_va(format_str, ap);
    1923      196964 :         va_end(ap);
    1924             : 
    1925      196964 :         return ret;
    1926             : }
    1927             : 
    1928             : static uint64_t debug_traceid = 0;
    1929             : 
    1930           0 : uint64_t debug_traceid_set(uint64_t id)
    1931             : {
    1932           0 :     uint64_t old_id = debug_traceid;
    1933           0 :     debug_traceid = id;
    1934           0 :     return old_id;
    1935             : }
    1936             : 
    1937       79634 : uint64_t debug_traceid_get(void)
    1938             : {
    1939       79634 :     return debug_traceid;
    1940             : }

Generated by: LCOV version 1.14