When configuring logging settings, keep more information about the
output destination. Add accessors to retrieve the filter and output
settings in the original string form; this to be used to set up
environment for a child process that also logs. Open output files
O_APPEND so child can also write -- was there a reason to truncate
them?
Note this patch changes the API for virLogDefineOutput(), which is
part of the internal libvirt API, but is currently only used within
logging.c.
---
src/libvirt_private.syms | 2 +
src/util/logging.c | 109 +++++++++++++++++++++++++++++++++++++++++++---
src/util/logging.h | 14 +++++-
3 files changed, 116 insertions(+), 9 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fb9b9ae..732fd08 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -253,6 +253,8 @@ virRegisterSecretDriver;
virLogMessage;
virLogGetNbFilters;
virLogGetNbOutputs;
+virLogGetFilters;
+virLogGetOutputs;
virLogGetDefaultPriority;
virLogSetDefaultPriority;
virLogSetFromEnv;
diff --git a/src/util/logging.c b/src/util/logging.c
index 07c2b0e..f3ad0dd 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -37,6 +37,7 @@
#include "logging.h"
#include "memory.h"
#include "util.h"
+#include "buf.h"
#include "threads.h"
/*
@@ -109,6 +110,8 @@ struct _virLogOutput {
virLogOutputFunc f;
virLogCloseFunc c;
int priority;
+ virLogDestination dest;
+ const char *name;
};
typedef struct _virLogOutput virLogOutput;
typedef virLogOutput *virLogOutputPtr;
@@ -138,6 +141,17 @@ static void virLogUnlock(void)
virMutexUnlock(&virLogMutex);
}
+static const char *virLogOutputString(virLogDestination ldest) {
+ switch (ldest) {
+ case VIR_LOG_TO_STDERR:
+ return("stderr");
+ case VIR_LOG_TO_SYSLOG:
+ return("syslog");
+ case VIR_LOG_TO_FILE:
+ return("file");
+ }
+ return("unknown");
+}
static const char *virLogPriorityString(virLogPriority lvl) {
switch (lvl) {
@@ -428,6 +442,7 @@ static int virLogResetOutputs(void) {
for (i = 0;i < virLogNbOutputs;i++) {
if (virLogOutputs[i].c != NULL)
virLogOutputs[i].c(virLogOutputs[i].data);
+ VIR_FREE(virLogOutputs[i].name);
}
VIR_FREE(virLogOutputs);
i = virLogNbOutputs;
@@ -438,9 +453,11 @@ static int virLogResetOutputs(void) {
/**
* virLogDefineOutput:
* @f: the function to call to output a message
- * @f: the function to call to close the output (or NULL)
+ * @c: the function to call to close the output (or NULL)
* @data: extra data passed as first arg to the function
* @priority: minimal priority for this filter, use 0 for none
+ * @dest: where to send output of this priority
+ * @name: optional name data associated with an output
* @flags: extra flag, currently unused
*
* Defines an output function for log messages. Each message once
@@ -449,12 +466,22 @@ static int virLogResetOutputs(void) {
* Returns -1 in case of failure or the output number if successful
*/
int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void *data,
- int priority, int flags ATTRIBUTE_UNUSED) {
+ int priority, int dest, const char *name,
+ int flags ATTRIBUTE_UNUSED) {
int ret = -1;
+ char *ndup = NULL;
if (f == NULL)
return(-1);
+ if (dest == VIR_LOG_TO_SYSLOG || dest == VIR_LOG_TO_FILE) {
+ if (name == NULL)
+ return(-1);
+ ndup = strdup(name);
+ if (ndup == NULL)
+ return(-1);
+ }
+
virLogLock();
if (VIR_REALLOC_N(virLogOutputs, virLogNbOutputs + 1)) {
goto cleanup;
@@ -464,6 +491,8 @@ int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void
*data,
virLogOutputs[ret].c = c;
virLogOutputs[ret].data = data;
virLogOutputs[ret].priority = priority;
+ virLogOutputs[ret].dest = dest;
+ virLogOutputs[ret].name = ndup;
cleanup:
virLogUnlock();
return(ret);
@@ -577,7 +606,8 @@ static void virLogCloseFd(void *data) {
}
static int virLogAddOutputToStderr(int priority) {
- if (virLogDefineOutput(virLogOutputToFd, NULL, (void *)2L, priority, 0) < 0)
+ if (virLogDefineOutput(virLogOutputToFd, NULL, (void *)2L, priority,
+ VIR_LOG_TO_STDERR, NULL, 0) < 0)
return(-1);
return(0);
}
@@ -585,11 +615,11 @@ static int virLogAddOutputToStderr(int priority) {
static int virLogAddOutputToFile(int priority, const char *file) {
int fd;
- fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
+ fd = open(file, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd < 0)
return(-1);
if (virLogDefineOutput(virLogOutputToFd, virLogCloseFd, (void *)(long)fd,
- priority, 0) < 0) {
+ priority, VIR_LOG_TO_FILE, file, 0) < 0) {
close(fd);
return(-1);
}
@@ -643,7 +673,7 @@ static int virLogAddOutputToSyslog(int priority, const char *ident) {
openlog(current_ident, 0, 0);
if (virLogDefineOutput(virLogOutputToSyslog, virLogCloseSyslog, NULL,
- priority, 0) < 0) {
+ priority, VIR_LOG_TO_SYSLOG, ident, 0) < 0) {
closelog();
VIR_FREE(current_ident);
return(-1);
@@ -682,6 +712,7 @@ static int virLogAddOutputToSyslog(int priority, const char *ident) {
int virLogParseOutputs(const char *outputs) {
const char *cur = outputs, *str;
char *name;
+ char *abspath;
int prio;
int ret = -1;
int count = 0;
@@ -732,9 +763,14 @@ int virLogParseOutputs(const char *outputs) {
name = strndup(str, cur - str);
if (name == NULL)
goto cleanup;
- if (virLogAddOutputToFile(prio, name) == 0)
+ if (virFileAbsPath(name, &abspath) < 0) {
+ VIR_FREE(name);
+ return -1; /* skip warning here because setting was fine */
+ }
+ if (virLogAddOutputToFile(prio, abspath) == 0)
count++;
VIR_FREE(name);
+ VIR_FREE(abspath);
} else {
goto cleanup;
}
@@ -813,6 +849,65 @@ int virLogGetDefaultPriority(void) {
}
/**
+ * virLogGetFilters:
+ *
+ * Returns a buffer listing the current filters, in the format originally
+ * specified in the config file or environment.
+ */
+int virLogGetFilters(virBufferPtr filterBuf) {
+
+ int i;
+
+ virLogLock();
+ for (i = 0; i < virLogNbFilters; i++) {
+ virBufferVSprintf(filterBuf, "%d:%s ", virLogFilters[i].priority,
+ virLogFilters[i].match);
+ }
+ virLogUnlock();
+
+ if (virBufferError(filterBuf))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * virLogGetOutputs:
+ *
+ * Returns a buffer listing the current outputs, in the format originally
+ * specified in the config file or environment.
+ */
+int virLogGetOutputs(virBufferPtr outputBuf) {
+ int i;
+
+ virLogLock();
+ for (i = 0; i < virLogNbOutputs; i++) {
+ int dest = virLogOutputs[i].dest;
+ if (i)
+ virBufferVSprintf(outputBuf, " ");
+ switch (dest) {
+ case VIR_LOG_TO_SYSLOG:
+ case VIR_LOG_TO_FILE:
+ virBufferVSprintf(outputBuf, "%d:%s:%s",
+ virLogOutputs[i].priority,
+ virLogOutputString(dest),
+ virLogOutputs[i].name);
+ break;
+ default:
+ virBufferVSprintf(outputBuf, "%d:%s",
+ virLogOutputs[i].priority,
+ virLogOutputString(dest));
+ }
+ }
+ virLogUnlock();
+
+ if (virBufferError(outputBuf))
+ return -1;
+
+ return 0;
+}
+
+/**
* virLogGetNbFilters:
*
* Returns the current number of defined log filters.
diff --git a/src/util/logging.h b/src/util/logging.h
index 8b2b84c..bbc41ad 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -23,6 +23,7 @@
#define __VIRTLOG_H_
#include "internal.h"
+#include "buf.h"
/*
* If configured with --enable-debug=yes then library calls
@@ -79,6 +80,12 @@ typedef enum {
#define VIR_LOG_DEFAULT VIR_LOG_WARN
+typedef enum {
+ VIR_LOG_TO_STDERR = 1,
+ VIR_LOG_TO_SYSLOG,
+ VIR_LOG_TO_FILE,
+} virLogDestination;
+
/**
* virLogOutputFunc:
* @category: the category for the message
@@ -107,12 +114,15 @@ typedef void (*virLogCloseFunc) (void *data);
extern int virLogGetNbFilters(void);
extern int virLogGetNbOutputs(void);
+extern int virLogGetFilters(virBufferPtr);
+extern int virLogGetOutputs(virBufferPtr);
extern int virLogGetDefaultPriority(void);
extern int virLogSetDefaultPriority(int priority);
extern void virLogSetFromEnv(void);
extern int virLogDefineFilter(const char *match, int priority, int flags);
-extern int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c,
- void *data, int priority, int flags);
+extern int virLogDefineOutput(virLogOutputFunc f, virLogCloseFunc c, void *data,
+ int priority, int dest, const char *name,
+ int flags);
/*
* Internal logging API