]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/log.h
cgroup: check for non-empty conf
[mirror_lxc.git] / src / lxc / log.h
index cfe52c054cd0cc9ddae4a1766f708492c998d3e8..5afe4e0935ef1a4a08e6664cf34842729a54e2a8 100644 (file)
@@ -4,7 +4,7 @@
  * (C) Copyright IBM Corp. 2007, 2008
  *
  * Authors:
- * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * Daniel Lezcano <daniel.lezcano at free.fr>
  * Cedric Le Goater <legoater@free.fr>
  *
  * This library is free software; you can redistribute it and/or
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
-#ifndef _log_h
-#define _log_h
+#ifndef __LXC_LOG_H
+#define __LXC_LOG_H
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <sys/time.h>
 #include <string.h>
+#include <strings.h>
+#include <stdbool.h>
+#include <syslog.h>
+#include <time.h>
+
+#include "conf.h"
 
 #ifndef O_CLOEXEC
 #define O_CLOEXEC 02000000
 #endif
 
 #define LXC_LOG_PREFIX_SIZE    32
-#define LXC_LOG_BUFFER_SIZE    512
-
-/* predefined priorities. */
-enum {
-       LXC_LOG_PRIORITY_TRACE,
-       LXC_LOG_PRIORITY_DEBUG,
-       LXC_LOG_PRIORITY_INFO,
-       LXC_LOG_PRIORITY_NOTICE,
-       LXC_LOG_PRIORITY_WARN,
-       LXC_LOG_PRIORITY_ERROR,
-       LXC_LOG_PRIORITY_CRIT,
-       LXC_LOG_PRIORITY_ALERT,
-       LXC_LOG_PRIORITY_FATAL,
-       LXC_LOG_PRIORITY_NOTSET,
+#define LXC_LOG_BUFFER_SIZE    4096
+
+/* This attribute is required to silence clang warnings */
+#if defined(__GNUC__)
+#define ATTR_UNUSED __attribute__ ((unused))
+#else
+#define ATTR_UNUSED
+#endif
+
+/* predefined lxc log priorities. */
+enum lxc_loglevel {
+       LXC_LOG_LEVEL_TRACE,
+       LXC_LOG_LEVEL_DEBUG,
+       LXC_LOG_LEVEL_INFO,
+       LXC_LOG_LEVEL_NOTICE,
+       LXC_LOG_LEVEL_WARN,
+       LXC_LOG_LEVEL_ERROR,
+       LXC_LOG_LEVEL_CRIT,
+       LXC_LOG_LEVEL_ALERT,
+       LXC_LOG_LEVEL_FATAL,
+       LXC_LOG_LEVEL_NOTSET,
 };
 
 /* location information of the logging event */
 struct lxc_log_locinfo {
-       const char      *file;
-       const char      *func;
-       int             line;
+       const char *file;
+       const char *func;
+       int line;
 };
 
 #define LXC_LOG_LOCINFO_INIT                                           \
@@ -66,99 +80,180 @@ struct lxc_log_locinfo {
 
 /* brief logging event object */
 struct lxc_log_event {
-       const char*             category;
-       int                     priority;
-       struct timeval          timestamp;
-       struct lxc_log_locinfo  *locinfo;
-       const char              *fmt;
-       va_list                 va;
+       const char *category;
+       int priority;
+       struct timespec timestamp;
+       struct lxc_log_locinfo *locinfo;
+       const char *fmt;
+       va_list *vap;
 };
 
 /* log appender object */
 struct lxc_log_appender {
-       const char*     name;
-       int (*append)(const struct lxc_log_appender *,
-                     const struct lxc_log_event *);
+       const char *name;
+       int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
 
        /*
         * appenders can be stacked
         */
-       struct lxc_log_appender *next;
+       struct lxc_log_appender *next;
 };
 
 /* log category object */
 struct lxc_log_category {
-       const char                      *name;
-       int                             priority;
-       struct lxc_log_appender         *appender;
-       const struct lxc_log_category   *parent;
+       const char *name;
+       int priority;
+       struct lxc_log_appender *appender;
+       const struct lxc_log_category *parent;
 };
 
+#ifndef NO_LXC_CONF
+extern int lxc_log_use_global_fd;
+#endif
+
 /*
  * Returns true if the chained priority is equal to or higher than
  * given priority.
  */
-static inline int
-lxc_log_priority_is_enabled(const struct lxc_log_category* category,
-                          int priority)
+static inline int lxc_log_priority_is_enabled(const struct lxc_log_category *category,
+                                             int priority)
 {
-       while (category->priority == LXC_LOG_PRIORITY_NOTSET &&
-              category->parent)
+       while (category->priority == LXC_LOG_LEVEL_NOTSET && category->parent)
                category = category->parent;
 
-       return priority >= category->priority;
+       int cmp_prio = category->priority;
+#ifndef NO_LXC_CONF
+       if (!lxc_log_use_global_fd && current_config &&
+           current_config->loglevel != LXC_LOG_LEVEL_NOTSET)
+               cmp_prio = current_config->loglevel;
+#endif
+
+       return priority >= cmp_prio;
 }
 
 /*
  * converts a priority to a literal string
  */
-static inline const char* lxc_log_priority_to_string(int priority)
+static inline const char *lxc_log_priority_to_string(int priority)
+{
+       switch (priority) {
+       case LXC_LOG_LEVEL_TRACE:
+               return "TRACE";
+       case LXC_LOG_LEVEL_DEBUG:
+               return "DEBUG";
+       case LXC_LOG_LEVEL_INFO:
+               return "INFO";
+       case LXC_LOG_LEVEL_NOTICE:
+               return "NOTICE";
+       case LXC_LOG_LEVEL_WARN:
+               return "WARN";
+       case LXC_LOG_LEVEL_ERROR:
+               return "ERROR";
+       case LXC_LOG_LEVEL_CRIT:
+               return "CRIT";
+       case LXC_LOG_LEVEL_ALERT:
+               return "ALERT";
+       case LXC_LOG_LEVEL_FATAL:
+               return "FATAL";
+       }
+
+       return "NOTSET";
+}
+
+static inline const char *lxc_syslog_priority_to_string(int priority)
 {
        switch (priority) {
-       case LXC_LOG_PRIORITY_TRACE:    return "TRACE";
-       case LXC_LOG_PRIORITY_DEBUG:    return "DEBUG";
-       case LXC_LOG_PRIORITY_INFO:     return "INFO";
-       case LXC_LOG_PRIORITY_NOTICE:   return "NOTICE";
-       case LXC_LOG_PRIORITY_WARN:     return "WARN";
-       case LXC_LOG_PRIORITY_ERROR:    return "ERROR";
-       case LXC_LOG_PRIORITY_CRIT:     return "CRIT";
-       case LXC_LOG_PRIORITY_ALERT:    return "ALERT";
-       case LXC_LOG_PRIORITY_FATAL:    return "FATAL";
-       default:
-               return "NOTSET";
+       case LOG_DAEMON:
+               return "daemon";
+       case LOG_LOCAL0:
+               return "local0";
+       case LOG_LOCAL1:
+               return "local1";
+       case LOG_LOCAL2:
+               return "local2";
+       case LOG_LOCAL3:
+               return "local3";
+       case LOG_LOCAL4:
+               return "local4";
+       case LOG_LOCAL5:
+               return "local5";
+       case LOG_LOCAL6:
+               return "local6";
+       case LOG_LOCAL7:
+               return "local7";
        }
+
+       return "NOTSET";
 }
+
 /*
  * converts a literal priority to an int
  */
-static inline int lxc_log_priority_to_int(const charname)
+static inline int lxc_log_priority_to_int(const char *name)
 {
-       if (!strcasecmp("TRACE",  name)) return LXC_LOG_PRIORITY_TRACE;
-       if (!strcasecmp("DEBUG",  name)) return LXC_LOG_PRIORITY_DEBUG;
-       if (!strcasecmp("INFO",   name)) return LXC_LOG_PRIORITY_INFO;
-       if (!strcasecmp("NOTICE", name)) return LXC_LOG_PRIORITY_NOTICE;
-       if (!strcasecmp("WARN",   name)) return LXC_LOG_PRIORITY_WARN;
-       if (!strcasecmp("ERROR",  name)) return LXC_LOG_PRIORITY_ERROR;
-       if (!strcasecmp("CRIT",   name)) return LXC_LOG_PRIORITY_CRIT;
-       if (!strcasecmp("ALERT",  name)) return LXC_LOG_PRIORITY_ALERT;
-       if (!strcasecmp("FATAL",  name)) return LXC_LOG_PRIORITY_FATAL;
-
-       return LXC_LOG_PRIORITY_NOTSET;
+       if (strcasecmp("TRACE", name) == 0)
+               return LXC_LOG_LEVEL_TRACE;
+       if (strcasecmp("DEBUG", name) == 0)
+               return LXC_LOG_LEVEL_DEBUG;
+       if (strcasecmp("INFO", name) == 0)
+               return LXC_LOG_LEVEL_INFO;
+       if (strcasecmp("NOTICE", name) == 0)
+               return LXC_LOG_LEVEL_NOTICE;
+       if (strcasecmp("WARN", name) == 0)
+               return LXC_LOG_LEVEL_WARN;
+       if (strcasecmp("ERROR", name) == 0)
+               return LXC_LOG_LEVEL_ERROR;
+       if (strcasecmp("CRIT", name) == 0)
+               return LXC_LOG_LEVEL_CRIT;
+       if (strcasecmp("ALERT", name) == 0)
+               return LXC_LOG_LEVEL_ALERT;
+       if (strcasecmp("FATAL", name) == 0)
+               return LXC_LOG_LEVEL_FATAL;
+
+       return LXC_LOG_LEVEL_NOTSET;
 }
 
-static inline void
-__lxc_log_append(const struct lxc_log_appender *appender,
-               const struct lxc_log_event* event)
+static inline int lxc_syslog_priority_to_int(const char *name)
 {
+       if (strcasecmp("daemon", name) == 0)
+               return LOG_DAEMON;
+       if (strcasecmp("local0", name) == 0)
+               return LOG_LOCAL0;
+       if (strcasecmp("local1", name) == 0)
+               return LOG_LOCAL1;
+       if (strcasecmp("local2", name) == 0)
+               return LOG_LOCAL2;
+       if (strcasecmp("local3", name) == 0)
+               return LOG_LOCAL3;
+       if (strcasecmp("local4", name) == 0)
+               return LOG_LOCAL4;
+       if (strcasecmp("local5", name) == 0)
+               return LOG_LOCAL5;
+       if (strcasecmp("local6", name) == 0)
+               return LOG_LOCAL6;
+       if (strcasecmp("local7", name) == 0)
+               return LOG_LOCAL7;
+
+       return -EINVAL;
+}
+
+static inline void __lxc_log_append(const struct lxc_log_appender *appender,
+                                   struct lxc_log_event *event)
+{
+       va_list va;
+       va_list *va_keep = event->vap;
+
        while (appender) {
+               va_copy(va, *va_keep);
+               event->vap = &va;
                appender->append(appender, event);
                appender = appender->next;
+               va_end(va);
        }
 }
 
-static inline void
-__lxc_log(const struct lxc_log_category* category,
-        const struct lxc_log_event* event)
+static inline void __lxc_log(const struct lxc_log_category *category,
+                            struct lxc_log_event *event)
 {
        while (category) {
                __lxc_log_append(category->appender, event);
@@ -167,31 +262,39 @@ __lxc_log(const struct lxc_log_category* category,
 }
 
 /*
- * Helper macro to define log fonctions.
+ * Helper macro to define log functions.
  */
-#define lxc_log_priority_define(acategory, PRIORITY)                   \
-                                                                       \
-static inline void LXC_##PRIORITY(struct lxc_log_locinfo *,            \
-       const char *, ...) __attribute__ ((format (printf, 2, 3)));     \
-                                                                       \
-static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo,     \
-                                 const char* format, ...)              \
-{                                                                      \
-       if (lxc_log_priority_is_enabled(acategory,                      \
-                                       LXC_LOG_PRIORITY_##PRIORITY)) { \
-               struct lxc_log_event evt = {                            \
-                       .category       = (acategory)->name,            \
-                       .priority       = LXC_LOG_PRIORITY_##PRIORITY,  \
-                       .fmt            = format,                       \
-                       .locinfo        = locinfo                       \
-               };                                                      \
-                                                                       \
-               gettimeofday(&evt.timestamp, NULL);                     \
-                                                                       \
-               va_start(evt.va, format);                               \
-               __lxc_log(acategory, &evt);                             \
-               va_end(evt.va);                                         \
-       }                                                               \
+#define lxc_log_priority_define(acategory, LEVEL)                              \
+                                                                               \
+ATTR_UNUSED __attribute__ ((format (printf, 2, 3)))                            \
+static inline void LXC_##LEVEL(struct lxc_log_locinfo *, const char *, ...);   \
+                                                                               \
+ATTR_UNUSED static inline void LXC_##LEVEL(struct lxc_log_locinfo* locinfo,    \
+                                          const char* format, ...)             \
+{                                                                              \
+       if (lxc_log_priority_is_enabled(acategory, LXC_LOG_LEVEL_##LEVEL)) {    \
+               va_list va_ref;                                                 \
+               int saved_errno;                                                \
+               struct lxc_log_event evt = {                                    \
+                       .category       = (acategory)->name,                    \
+                       .priority       = LXC_LOG_LEVEL_##LEVEL,                \
+                       .fmt            = format,                               \
+                       .locinfo        = locinfo                               \
+               };                                                              \
+                                                                               \
+               /* clock_gettime() is explicitly marked as MT-Safe              \
+                * without restrictions. So let's use it for our                \
+                * logging stamps.                                              \
+                */                                                             \
+               saved_errno = errno;                                            \
+               (void)clock_gettime(CLOCK_REALTIME, &evt.timestamp);            \
+                                                                               \
+               va_start(va_ref, format);                                       \
+               evt.vap = &va_ref;                                              \
+               __lxc_log(acategory, &evt);                                     \
+               va_end(va_ref);                                                 \
+               errno = saved_errno;                                            \
+       }                                                                       \
 }
 
 /*
@@ -201,7 +304,7 @@ static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo,  \
        extern struct lxc_log_category lxc_log_category_##parent;       \
        struct lxc_log_category lxc_log_category_##name = {             \
                #name,                                                  \
-               LXC_LOG_PRIORITY_NOTSET,                                \
+               LXC_LOG_LEVEL_NOTSET,                                   \
                NULL,                                                   \
                &lxc_log_category_##parent                              \
        };
@@ -223,10 +326,51 @@ static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo,        \
        (lxc_log_priority_to_string(lxc_log_category_##name.priority))
 
 /*
- * top categories
+ * Helper macro to define errno string.
  */
-extern struct lxc_log_category lxc_log_category_lxc;
+#if HAVE_STRERROR_R
+       #ifndef HAVE_DECL_STRERROR_R
+               #ifdef STRERROR_R_CHAR_P
+                       char *strerror_r(int errnum, char *buf, size_t buflen);
+               #else
+                       int strerror_r(int errnum, char *buf, size_t buflen);
+               #endif
+       #endif
+
+       #ifdef STRERROR_R_CHAR_P
+               #define lxc_log_strerror_r                                               \
+                       char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"};   \
+                       char *ptr = NULL;                                                \
+                       {                                                                \
+                               int __saved_errno = errno;                               \
+                               ptr = strerror_r(errno, errno_buf, sizeof(errno_buf));   \
+                               errno = __saved_errno;                                   \
+                               if (!ptr)                                                \
+                                       ptr = errno_buf;                                 \
+                       }
+       #else
+               #define lxc_log_strerror_r                                               \
+                       char errno_buf[PATH_MAX / 2] = {"Failed to get errno string"};   \
+                       char *ptr = errno_buf;                                           \
+                       {                                                                \
+                               int __saved_errno = errno;                               \
+                               (void)strerror_r(errno, errno_buf, sizeof(errno_buf));   \
+                               errno = __saved_errno;                                   \
+                       }
+       #endif
+#elif ENFORCE_THREAD_SAFETY
+       #error ENFORCE_THREAD_SAFETY was set but cannot be guaranteed
+#else
+       #define lxc_log_strerror_r                                                       \
+               char *ptr = NULL;                                                        \
+               {                                                                        \
+                       ptr = strerror(errno);                                           \
+               }
+#endif
 
+/*
+ * top categories
+ */
 #define TRACE(format, ...) do {                                                \
        struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT;          \
        LXC_TRACE(&locinfo, format, ##__VA_ARGS__);                     \
@@ -272,10 +416,105 @@ extern struct lxc_log_category lxc_log_category_lxc;
        LXC_FATAL(&locinfo, format, ##__VA_ARGS__);                     \
 } while (0)
 
+#if HAVE_M_FORMAT
+#define SYSTRACE(format, ...)                              \
+               TRACE("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSTRACE(format, ...)                              \
+       do {                                               \
+               lxc_log_strerror_r;                        \
+               TRACE("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
 
+#if HAVE_M_FORMAT
+#define SYSDEBUG(format, ...)                              \
+                DEBUG("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSDEBUG(format, ...)                              \
+       do {                                               \
+               lxc_log_strerror_r;                        \
+               DEBUG("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
 
-#define SYSERROR(format, ...) do {                                     \
-       ERROR("%s - " format "\n", strerror(errno), ##__VA_ARGS__);     \
-} while (0)
 
+#if HAVE_M_FORMAT
+#define SYSINFO(format, ...)                              \
+                INFO("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSINFO(format, ...)                              \
+       do {                                              \
+               lxc_log_strerror_r;                       \
+               INFO("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+#if HAVE_M_FORMAT
+#define SYSNOTICE(format, ...)                              \
+               NOTICE("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSNOTICE(format, ...)                              \
+       do {                                                \
+               lxc_log_strerror_r;                         \
+               NOTICE("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+#if HAVE_M_FORMAT
+#define SYSWARN(format, ...)                              \
+               WARN("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSWARN(format, ...)                              \
+       do {                                              \
+               lxc_log_strerror_r;                       \
+               WARN("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+#if HAVE_M_FORMAT
+#define SYSERROR(format, ...)                              \
+               ERROR("%m - " format, ##__VA_ARGS__)
+#else
+#define SYSERROR(format, ...)                              \
+       do {                                               \
+               lxc_log_strerror_r;                        \
+               ERROR("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+#if HAVE_M_FORMAT
+#define CMD_SYSERROR(format, ...)                                    \
+               fprintf(stderr, "%m - " format, ##__VA_ARGS__)
+#else
+#define CMD_SYSERROR(format, ...)                                    \
+       do {                                                         \
+               lxc_log_strerror_r;                                  \
+               fprintf(stderr, "%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+#if HAVE_M_FORMAT
+#define CMD_SYSINFO(format, ...)                            \
+               printf("%m - " format, ##__VA_ARGS__)
+#else
+#define CMD_SYSINFO(format, ...)                            \
+       do {                                                \
+               lxc_log_strerror_r;                         \
+               printf("%s - " format, ptr, ##__VA_ARGS__); \
+       } while (0)
+#endif
+
+extern int lxc_log_fd;
+
+extern int lxc_log_syslog(int facility);
+extern void lxc_log_enable_syslog(void);
+extern int lxc_log_set_level(int *dest, int level);
+extern int lxc_log_get_level(void);
+extern bool lxc_log_has_valid_level(void);
+extern int lxc_log_set_file(int *fd, const char *fname);
+extern const char *lxc_log_get_file(void);
+extern void lxc_log_set_prefix(const char *prefix);
+extern const char *lxc_log_get_prefix(void);
+extern void lxc_log_options_no_override(void);
 #endif