diff --git a/spa/include/spa/utils/string.h b/spa/include/spa/utils/string.h index bab60de2b..35e4ea026 100644 --- a/spa/include/spa/utils/string.h +++ b/spa/include/spa/utils/string.h @@ -380,17 +380,26 @@ SPA_API_STRING void spa_strbuf_init(struct spa_strbuf *buf, char *buffer, size_t buf->buffer[0] = '\0'; } +SPA_PRINTF_FUNC(2, 0) +SPA_API_STRING int spa_strbuf_appendv(struct spa_strbuf *buf, const char *fmt, va_list args) +{ + size_t remain = buf->maxsize - buf->pos; + int written = vsnprintf(&buf->buffer[buf->pos], remain, fmt, args); + if (written > 0) + buf->pos += SPA_MIN(remain, (size_t)written); + return written; +} + SPA_PRINTF_FUNC(2, 3) SPA_API_STRING int spa_strbuf_append(struct spa_strbuf *buf, const char *fmt, ...) { - size_t remain = buf->maxsize - buf->pos; - ssize_t written; va_list args; + int written; + va_start(args, fmt); - written = vsnprintf(&buf->buffer[buf->pos], remain, fmt, args); + written = spa_strbuf_appendv(buf, fmt, args); va_end(args); - if (written > 0) - buf->pos += SPA_MIN(remain, (size_t)written); + return written; } diff --git a/spa/plugins/support/logger.c b/spa/plugins/support/logger.c index 6ea5f31b5..9a20ff241 100644 --- a/spa/plugins/support/logger.c +++ b/spa/plugins/support/logger.c @@ -67,16 +67,10 @@ impl_log_logtv(void *object, const char *fmt, va_list args) { -#define RESERVED_LENGTH 24 - struct impl *impl = object; - char timestamp[18] = {0}; - char topicstr[32] = {0}; - char filename[64] = {0}; - char location[1000 + RESERVED_LENGTH], *p; + char location[1024]; static const char * const levels[] = { "-", "E", "W", "I", "D", "T", "*T*" }; const char *prefix = "", *suffix = ""; - int size, len; bool do_trace; if ((do_trace = (level == SPA_LOG_LEVEL_TRACE && impl->have_source))) @@ -93,8 +87,10 @@ impl_log_logtv(void *object, suffix = SPA_ANSI_RESET; } - p = location; - len = sizeof(location) - RESERVED_LENGTH; + struct spa_strbuf msg; + spa_strbuf_init(&msg, location, sizeof(location)); + + spa_strbuf_append(&msg, "%s[%s]", prefix, levels[level]); if (impl->local_timestamp) { char buf[64]; @@ -104,67 +100,52 @@ impl_log_logtv(void *object, clock_gettime(impl->clock_id, &now); localtime_r(&now.tv_sec, &now_tm); strftime(buf, sizeof(buf), "%H:%M:%S", &now_tm); - spa_scnprintf(timestamp, sizeof(timestamp), "[%s.%06d]", buf, + spa_strbuf_append(&msg, "[%s.%06d]", buf, (int)(now.tv_nsec / SPA_NSEC_PER_USEC)); } else if (impl->timestamp) { struct timespec now; clock_gettime(impl->clock_id, &now); - spa_scnprintf(timestamp, sizeof(timestamp), "[%05jd.%06jd]", + spa_strbuf_append(&msg, "[%05jd.%06jd]", (intmax_t) (now.tv_sec & 0x1FFFFFFF) % 100000, (intmax_t) now.tv_nsec / 1000); } if (topic && topic->topic) - spa_scnprintf(topicstr, sizeof(topicstr), " %-12s | ", topic->topic); + spa_strbuf_append(&msg, " %-12s | ", topic->topic); if (impl->line && line != 0) { const char *s = strrchr(file, '/'); - spa_scnprintf(filename, sizeof(filename), "[%16.16s:%5i %s()]", + spa_strbuf_append(&msg, "[%16.16s:%5i %s()]", s ? s + 1 : file, line, func); } - size = spa_scnprintf(p, len, "%s[%s]%s%s%s ", prefix, levels[level], - timestamp, topicstr, filename); - /* - * it is assumed that at this point `size` <= `len`, - * which is reasonable as long as file names and function names - * don't become very long - */ - size += spa_vscnprintf(p + size, len - size, fmt, args); + spa_strbuf_append(&msg, " "); + spa_strbuf_appendv(&msg, fmt, args); + spa_strbuf_append(&msg, "%s\n", suffix); - /* - * `RESERVED_LENGTH` bytes are reserved for printing the suffix - * (at the moment it's "... (truncated)\x1B[0m\n" at its longest - 21 bytes), - * its length must be less than `RESERVED_LENGTH` (including the null byte), - * otherwise a stack buffer overrun could ensue - */ + if (SPA_UNLIKELY(msg.pos >= msg.maxsize)) { + static const char truncated_text[] = "... (truncated)"; + size_t suffix_length = strlen(suffix) + strlen(truncated_text) + 1 + 1; - /* if the message could not fit entirely... */ - if (size >= len - 1) { - size = len - 1; /* index of the null byte */ - len = sizeof(location); - size += spa_scnprintf(p + size, len - size, "... (truncated)"); + spa_assert(msg.maxsize >= suffix_length); + msg.pos = msg.maxsize - suffix_length; + + spa_strbuf_append(&msg, "%s%s\n", truncated_text, suffix); + spa_assert(msg.pos < msg.maxsize); } - else { - len = sizeof(location); - } - - size += spa_scnprintf(p + size, len - size, "%s\n", suffix); if (SPA_UNLIKELY(do_trace)) { uint32_t index; spa_ringbuffer_get_write_index(&impl->trace_rb, &index); spa_ringbuffer_write_data(&impl->trace_rb, impl->trace_data, TRACE_BUFFER, - index & (TRACE_BUFFER - 1), location, size); - spa_ringbuffer_write_update(&impl->trace_rb, index + size); + index & (TRACE_BUFFER - 1), msg.buffer, msg.pos); + spa_ringbuffer_write_update(&impl->trace_rb, index + msg.pos); if (spa_system_eventfd_write(impl->system, impl->source.fd, 1) < 0) fprintf(impl->file, "error signaling eventfd: %s\n", strerror(errno)); } else - fputs(location, impl->file); - -#undef RESERVED_LENGTH + fputs(msg.buffer, impl->file); } static SPA_PRINTF_FUNC(6,0) void