Files
s390-tools/pvattest/src/log.c
Marc Hartmayer bec9d1dfcd pvattest: pvattest_hexdump: add beautify parameter
Add `beautify` parameter to `pvattest_hexdump`. If the parameter is set
to true, a offset and whitespaces will be added for better readability.

With beautify set to FALSE:

14141414141414141414141414141414

With beautify set to TRUE:

0x0000  1414 1414 1414 1414 1414 1414 1414 1414

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-08-04 13:10:00 +02:00

204 lines
4.9 KiB
C

/*
* Functions used for logging.
*
* Copyright IBM Corp. 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
/* Must be included before any other header */
#include "config.h"
#include <stdio.h>
#include <stdarg.h>
#include "types.h"
#include "common.h"
#include "log.h"
void pvattest_log_increase_log_lvl(int *log_lvl)
{
if (*log_lvl >= PVATTEST_LOG_LVL_MAX)
return;
*log_lvl = *log_lvl << 1;
}
void pvattest_log_error(const char *format, ...)
{
va_list argp;
va_start(argp, format);
g_logv(NULL, PVATTEST_LOG_LVL_ERROR, format, argp);
va_end(argp);
}
void pvattest_log_warning(const char *format, ...)
{
va_list argp;
va_start(argp, format);
g_logv(NULL, PVATTEST_LOG_LVL_WARNING, format, argp);
va_end(argp);
}
void pvattest_log_info(const char *format, ...)
{
va_list argp;
va_start(argp, format);
g_logv(NULL, PVATTEST_LOG_LVL_INFO, format, argp);
va_end(argp);
}
void pvattest_log_debug(const char *format, ...)
{
va_list argp;
va_start(argp, format);
g_logv(NULL, PVATTEST_LOG_LVL_DEBUG, format, argp);
va_end(argp);
}
static void _log_print(FILE *stream, const char *prefix, const char *message, const char *postfix)
{
g_autofree char *prefix_empty = NULL, *new_msg = NULL;
size_t prefix_len = strlen(prefix);
char **message_v;
if (!prefix || prefix_len == 0) {
printf("%s%s", message, postfix);
return;
}
message_v = g_strsplit(message, "\n", 0);
prefix_empty = g_malloc0(prefix_len + 2);
snprintf(prefix_empty, prefix_len + 2, "\n%*c\b", (int)prefix_len, ' ');
new_msg = g_strjoinv(prefix_empty, message_v);
fprintf(stream, "%s%s%s", prefix, new_msg, postfix);
g_strfreev(message_v);
}
static void _log_logger(GLogLevelFlags level, const char *message, int log_level,
gboolean use_prefix, const char *postfix)
{
const char *prefix = "";
/* filter out messages depending on debugging level */
if ((level & PVATTEST_LOG_LVL_DEBUG) && log_level < PVATTEST_LOG_LVL_DEBUG)
return;
if ((level & PVATTEST_LOG_LVL_INFO) && log_level < PVATTEST_LOG_LVL_INFO)
return;
if (use_prefix && level & (G_LOG_LEVEL_WARNING | PVATTEST_LOG_LVL_WARNING))
prefix = _("WARNING: ");
if (use_prefix && level & (G_LOG_LEVEL_ERROR | PVATTEST_LOG_LVL_ERROR))
prefix = _("ERROR: ");
if (use_prefix && level & (G_LOG_LEVEL_DEBUG | PVATTEST_LOG_LVL_DEBUG))
prefix = _("DEBUG: ");
if (level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR | PVATTEST_LOG_LVL_WARNING |
PVATTEST_LOG_LVL_ERROR))
_log_print(stderr, prefix, message, postfix);
else
_log_print(stdout, prefix, message, postfix);
}
/**
* prefixes type. and adds a "\n" ad the end.
*/
void pvattest_log_default_logger(const char *log_domain G_GNUC_UNUSED, GLogLevelFlags level,
const char *message, void *user_data)
{
int log_level = *(int *)user_data;
_log_logger(level, message, log_level, TRUE, "\n");
}
/*
* writes message as it is if log level is high enough.
*/
void pvattest_log_plain_logger(const char *log_domain G_GNUC_UNUSED, GLogLevelFlags level,
const char *message, void *user_data)
{
int log_level = *(int *)user_data;
_log_logger(level, message, log_level, FALSE, "");
}
void pvattest_log_bytes(const void *data, size_t size, size_t width, const char *prefix,
gboolean beautify, GLogLevelFlags log_lvl)
{
const uint8_t *data_b = data;
pv_wrapped_g_assert(data);
if (beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%s0x0000 ", prefix);
else
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%s", prefix);
for (size_t i = 0; i < size; i++) {
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%02x", data_b[i]);
if (i % 2 == 1 && beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, " ");
if (i == size - 1)
break;
if (i % width == width - 1) {
if (beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n%s0x%04lx ", prefix,
i + 1);
else
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n%s", prefix);
}
}
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n");
}
void pvattest_hexdump(FILE *stream, GBytes *bytes, const size_t width, const char *prefix,
const gboolean beautify)
{
const uint8_t *data;
size_t size;
pv_wrapped_g_assert(bytes);
pv_wrapped_g_assert(stream);
data = g_bytes_get_data(bytes, &size);
pv_wrapped_g_assert(data);
if (beautify)
fprintf(stream, "%s0x0000 ", prefix);
else
fprintf(stream, "%s", prefix);
for (size_t i = 0; i < size; i++) {
fprintf(stream, "%02x", data[i]);
if (i % 2 == 1 && beautify)
fprintf(stream, " ");
if (i == size - 1)
break;
if (width == 0)
continue;
if (i % width == width - 1) {
if (beautify)
fprintf(stream, "\n%s0x%04lx ", prefix, i + 1);
else
fprintf(stream, "\n%s", prefix);
}
}
}
void pvattest_log_GError(const char *info, GError *error)
{
pv_wrapped_g_assert(info);
if (!error)
return;
pvattest_log_error("%s:\n%s", info, error->message);
}