diff options
author | Shuai Fan <shuai900217@126.com> | 2013-06-19 11:59:08 +0800 |
---|---|---|
committer | Tanu Kaskinen <tanu.kaskinen@linux.intel.com> | 2013-06-20 16:34:57 +0300 |
commit | b0bf132f8f643dcafda9d52c76543fafaf93f3a0 (patch) | |
tree | 818cf20ba9780cf3da8be7538dbc7906c9e2e044 /src/pulsecore/log.c | |
parent | e05c12f28b4bc8e4d7c5ba47f4bdb51243f9f252 (diff) | |
download | pulseaudio-b0bf132f8f643dcafda9d52c76543fafaf93f3a0.tar.gz |
cli, log: Improve the set-log-target functionality
Add a new log target 'newfile:PATH', and refactoring 'pa_log_target_type'.
Signed-off-by: Shuai Fan <shuai900217@126.com>
Diffstat (limited to 'src/pulsecore/log.c')
-rw-r--r-- | src/pulsecore/log.c | 143 |
1 files changed, 135 insertions, 8 deletions
diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c index 8eaef54e8..1c0209790 100644 --- a/src/pulsecore/log.c +++ b/src/pulsecore/log.c @@ -29,6 +29,7 @@ #include <unistd.h> #include <string.h> #include <errno.h> +#include <fcntl.h> #ifdef HAVE_EXECINFO_H #include <execinfo.h> @@ -47,9 +48,11 @@ #include <pulsecore/macro.h> #include <pulsecore/core-util.h> +#include <pulsecore/core-error.h> #include <pulsecore/once.h> #include <pulsecore/ratelimit.h> #include <pulsecore/thread.h> +#include <pulsecore/i18n.h> #include "log.h" @@ -63,9 +66,11 @@ #define ENV_LOG_BACKTRACE "PULSE_LOG_BACKTRACE" #define ENV_LOG_BACKTRACE_SKIP "PULSE_LOG_BACKTRACE_SKIP" #define ENV_LOG_NO_RATELIMIT "PULSE_LOG_NO_RATE_LIMIT" +#define LOG_MAX_SUFFIX_NUMBER 99 static char *ident = NULL; /* in local charset format */ -static pa_log_target_t target = PA_LOG_STDERR, target_override; +static pa_log_target target = { PA_LOG_STDERR, NULL }; +static pa_log_target_type_t target_override; static pa_bool_t target_override_set = FALSE; static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_LOG_ERROR; static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0; @@ -113,10 +118,65 @@ void pa_log_set_level(pa_log_level_t l) { maximum_level = l; } -void pa_log_set_target(pa_log_target_t t) { - pa_assert(t < PA_LOG_TARGET_MAX); +int pa_log_set_target(pa_log_target *t) { + int fd = -1; + int old_fd; + + pa_assert(t); + + switch (t->type) { + case PA_LOG_STDERR: + case PA_LOG_SYSLOG: + case PA_LOG_NULL: + break; + case PA_LOG_FILE: + if ((fd = pa_open_cloexec(t->file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { + pa_log(_("Failed to open target file '%s'."), t->file); + return -1; + } + break; + case PA_LOG_NEWFILE: { + char *file_path; + char *p; + unsigned version; + + file_path = pa_sprintf_malloc("%s.xx", t->file); + p = file_path + strlen(t->file); + + for (version = 0; version <= LOG_MAX_SUFFIX_NUMBER; version++) { + memset(p, 0, 3); /* Overwrite the ".xx" part in file_path with zero bytes. */ + + if (version > 0) + pa_snprintf(p, 4, ".%u", version); /* Why 4? ".xx" + termitating zero byte. */ - target = t; + if ((fd = pa_open_cloexec(file_path, O_WRONLY | O_TRUNC | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) >= 0) + break; + } + + if (version > LOG_MAX_SUFFIX_NUMBER) { + pa_log(_("Tried to open target file '%s', '%s.1', '%s.2' ... '%s.%d', but all failed."), + file_path, file_path, file_path, file_path, LOG_MAX_SUFFIX_NUMBER); + pa_xfree(file_path); + return -1; + } else + pa_log_debug("Opened target file %s\n", file_path); + + pa_xfree(file_path); + break; + } + } + + target.type = t->type; + pa_xfree(target.file); + target.file = pa_xstrdup(t->file); + + old_fd = log_fd; + log_fd = fd; + + if (old_fd >= 0) + pa_close(old_fd); + + return 0; } void pa_log_set_flags(pa_log_flags_t _flags, pa_log_merge_t merge) { @@ -276,7 +336,7 @@ void pa_log_levelv_meta( char *t, *n; int saved_errno = errno; char *bt = NULL; - pa_log_target_t _target; + pa_log_target_type_t _target; pa_log_level_t _maximum_level; unsigned _show_backtrace; pa_log_flags_t _flags; @@ -290,7 +350,7 @@ void pa_log_levelv_meta( init_defaults(); - _target = target_override_set ? target_override : target; + _target = target_override_set ? target_override : target.type; _maximum_level = PA_MAX(maximum_level, maximum_level_override); _show_backtrace = PA_MAX(show_backtrace, show_backtrace_override); _flags = flags | flags_override; @@ -410,18 +470,20 @@ void pa_log_levelv_meta( } #endif - case PA_LOG_FD: { + case PA_LOG_FILE: + case PA_LOG_NEWFILE: { if (log_fd >= 0) { char metadata[256]; pa_snprintf(metadata, sizeof(metadata), "\n%c %s %s", level_to_char[level], timestamp, location); if ((write(log_fd, metadata, strlen(metadata)) < 0) || (write(log_fd, t, strlen(t)) < 0)) { + pa_log_target new_target = { .type = PA_LOG_STDERR, .file = NULL }; saved_errno = errno; pa_log_set_fd(-1); fprintf(stderr, "%s\n", "Error writing logs to a file descriptor. Redirect log messages to console."); fprintf(stderr, "%s %s\n", metadata, t); - pa_log_set_target(PA_LOG_STDERR); + pa_log_set_target(&new_target); } } @@ -473,3 +535,68 @@ pa_bool_t pa_log_ratelimit(pa_log_level_t level) { return pa_ratelimit_test(&ratelimit, level); } + +pa_log_target *pa_log_target_new(pa_log_target_type_t type, const char *file) { + pa_log_target *t = NULL; + + t = pa_xnew(pa_log_target, 1); + + t->type = type; + t->file = pa_xstrdup(file); + + return t; +} + +void pa_log_target_free(pa_log_target *t) { + pa_assert(t); + + pa_xfree(t->file); + pa_xfree(t); +} + +pa_log_target *pa_log_parse_target(const char *string) { + pa_log_target *t = NULL; + + pa_assert(string); + + if (pa_streq(string, "stderr")) + t = pa_log_target_new(PA_LOG_STDERR, NULL); + else if (pa_streq(string, "syslog")) + t = pa_log_target_new(PA_LOG_SYSLOG, NULL); + else if (pa_streq(string, "null")) + t = pa_log_target_new(PA_LOG_NULL, NULL); + else if (pa_startswith(string, "file:")) + t = pa_log_target_new(PA_LOG_FILE, string + 5); + else if (pa_startswith(string, "newfile:")) + t = pa_log_target_new(PA_LOG_NEWFILE, string + 8); + else + pa_log(_("Invalid log target.")); + + return t; +} + +char *pa_log_target_to_string(const pa_log_target *t) { + char *string = NULL; + + pa_assert(t); + + switch (t->type) { + case PA_LOG_STDERR: + string = pa_xstrdup("stderr"); + break; + case PA_LOG_SYSLOG: + string = pa_xstrdup("syslog"); + break; + case PA_LOG_NULL: + string = pa_xstrdup("null"); + break; + case PA_LOG_FILE: + string = pa_sprintf_malloc("file:%s", t->file); + break; + case PA_LOG_NEWFILE: + string = pa_sprintf_malloc("newfile:%s", t->file); + break; + } + + return string; +} |