]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/log.c
use a default per-container logfile
[mirror_lxc.git] / src / lxc / log.c
index d2a90de7a6846045cd0564d7a24935031aa94107..ff512e38ba4b95ad830827e783eb29e590dbafb8 100644 (file)
@@ -42,6 +42,8 @@
 int lxc_log_fd = -1;
 static char log_prefix[LXC_LOG_PREFIX_SIZE] = "lxc";
 static int lxc_loglevel_specified = 0;
+// if logfile was specifed on command line, it won't be overridden by lxc.logfile
+static int lxc_log_specified = 0;
 
 lxc_log_define(lxc_log, lxc);
 
@@ -123,6 +125,36 @@ extern void lxc_log_setprefix(const char *prefix)
        log_prefix[sizeof(log_prefix) - 1] = 0;
 }
 
+static int build_dir(const char *name)
+{
+       char *n = strdup(name);  // because we'll be modifying it
+       char *p, *e;
+       int ret;
+
+       if (!n) {
+               ERROR("Out of memory while creating directory '%s'.", name);
+               return -1;
+       }
+
+       e = &n[strlen(n)];
+       for (p = n+1; p < e; p++) {
+               if (*p != '/')
+                       continue;
+               *p = '\0';
+               if (access(n, F_OK)) {
+                       ret = lxc_unpriv(mkdir(n, 0755));
+                       if (ret && errno != -EEXIST) {
+                               SYSERROR("failed to create directory '%s'.", n);
+                               free(n);
+                               return -1;
+                       }
+               }
+               *p = '/';
+       }
+       free(n);
+       return 0;
+}
+
 /*---------------------------------------------------------------------------*/
 static int log_open(const char *name)
 {
@@ -148,11 +180,46 @@ static int log_open(const char *name)
        return newfd;
 }
 
+static char *build_log_path(const char *name)
+{
+       char *p;
+       int len, ret;
+
+       /*
+        * '$logpath' + '/' + '$name' + '.log' + '\0'
+        * or
+        * '$logpath' + '/' + '$name' + '/' + '$name' + '.log' + '\0'
+        * sizeof(LOGPATH) includes its \0
+        */
+       len = sizeof(LOGPATH) + strlen(name) + 6;
+#if USE_CONFIGPATH_LOGS
+       len += strlen(name) + 1;  /* add "/$container_name/" */
+#endif
+       p = malloc(len);
+       if (!p)
+               return p;
+#if USE_CONFIGPATH_LOGS
+       ret = snprintf(p, len, "%s/%s/%s.log", LOGPATH, name, name);
+#else
+       ret = snprintf(p, len, "%s/%s.log", LOGPATH, name);
+#endif
+       if (ret < 0 || ret >= len) {
+               free(p);
+               return NULL;
+       }
+       return p;
+}
+
+int do_lxc_log_set_file(const char *fname, int from_default);
+
 /*---------------------------------------------------------------------------*/
-extern int lxc_log_init(const char *file, const char *priority,
-                       const char *prefix, int quiet)
+extern int lxc_log_init(const char *name, const char *file,
+                       const char *priority, const char *prefix, int quiet)
 {
        int lxc_priority = LXC_LOG_PRIORITY_ERROR;
+       int ret;
+       char *tmpfile = NULL;
+       int want_lxc_log_specified = 0;
 
        if (lxc_log_fd != -1)
                return 0;
@@ -176,10 +243,38 @@ extern int lxc_log_init(const char *file, const char *priority,
        if (prefix)
                lxc_log_setprefix(prefix);
 
-       if (file)
-               return lxc_log_set_file(file);
+       if (file && strcmp(file, "none") == 0) {
+               want_lxc_log_specified = 1;
+               return 0;
+       }
 
-       return 0;
+       if (!file) {
+               tmpfile = build_log_path(name);
+               if (!tmpfile) {
+                       ERROR("could not build log path");
+                       return -1;
+               }
+       } else {
+               want_lxc_log_specified = 1;
+       }
+
+       ret = do_lxc_log_set_file(tmpfile ? tmpfile : file, !want_lxc_log_specified);
+
+       if (want_lxc_log_specified)
+               lxc_log_specified = 1;
+       /*
+        * If !want_lxc_log_specified, that is, if the user did not request
+        * this logpath, then ignore failures and continue logging to console
+        */
+       if (!want_lxc_log_specified && ret != 0) {
+               INFO("Ignoring failure to open default logfile.");
+               ret = 0;
+       }
+
+       if (tmpfile)
+               free(tmpfile);
+
+       return ret;
 }
 
 /*
@@ -200,30 +295,50 @@ extern int lxc_log_set_level(int level)
 }
 
 char *log_fname;  // default to NULL, set in lxc_log_set_file.
-
 /*
- * This is called when we read a lxc.logfile entry in a lxc.conf file.  This
- * happens after processing command line arguments, which override the .conf
- * settings.  So only set the logfile if previously unset.
+ * This can be called:
+ *   1. when a program calls lxc_log_init with no logfile parameter (in which
+ *      case the default is used).  In this case lxc.logfile can override this.
+ *   2. when a program calls lxc_log_init with a logfile parameter.  In this
+ *     case we don't want lxc.logfile to override this.
+ *   3. When a lxc.logfile entry is found in config file.
  */
-extern int lxc_log_set_file(const char *fname)
+int do_lxc_log_set_file(const char *fname, int from_default)
 {
+       if (lxc_log_specified) {
+               INFO("lxc.logfile overriden by command line");
+               return 0;
+       }
        if (lxc_log_fd != -1) {
-               // this should've been caught at config_logfile.
-               ERROR("Race in setting logfile?");
+               // we are overriding the default.
+               close(lxc_log_fd);
+               free(log_fname);
+       }
+
+#if USE_CONFIGPATH_LOGS
+       // we don't build_dir for the default if the default is
+       // i.e. /var/lib/lxc/$container/$container.log
+       if (!from_default)
+#endif
+       if (build_dir(fname)) {
+               ERROR("failed to create dir for log file \"%s\" : %s", fname,
+                     strerror(errno));
                return -1;
        }
 
        lxc_log_fd = log_open(fname);
-       if (lxc_log_fd == -1) {
-               ERROR("failed to open log file %s\n", fname);
+       if (lxc_log_fd == -1)
                return -1;
-       }
 
        log_fname = strdup(fname);
        return 0;
 }
 
+extern int lxc_log_set_file(const char *fname)
+{
+       return do_lxc_log_set_file(fname, 0);
+}
+
 extern int lxc_log_get_level(void)
 {
        if (!lxc_loglevel_specified)