/* * Copyright (C) 2021 SUSE LLC * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * This file implements basic logging functionality. */ #include #include #include #include #include #include #include #include #include #define LOG_FUNCNAME 1 #include "private.h" #include "log.h" #include "cleanup.h" #ifndef LOG_CLOCK #define LOG_CLOCK CLOCK_MONOTONIC #endif void __attribute__((format(printf, 4, 5))) __nvme_msg(nvme_root_t r, int lvl, const char *func, const char *format, ...) { FILE *fp = r ? r->fp : stderr; va_list ap; char pidbuf[16]; char timebuf[32]; static const char *const formats[] = { "%s%s%s", "%s%s%s: ", "%s<%s>%s ", "%s<%s> %s: ", "[%s] %s%s ", "[%s]%s %s: ", "[%s] <%s>%s ", "[%s] <%s> %s: ", }; char *header __cleanup__(cleanup_charp) = NULL; char *message __cleanup__(cleanup_charp) = NULL; int idx = 0; if (r && lvl > r->log_level) return; if (r && r->log_timestamp) { struct timespec now; clock_gettime(LOG_CLOCK, &now); snprintf(timebuf, sizeof(timebuf), "%6ld.%06ld", (long)now.tv_sec, now.tv_nsec / 1000); idx |= 1 << 2; } else *timebuf = '\0'; if (r && r->log_pid) { snprintf(pidbuf, sizeof(pidbuf), "%ld", (long)getpid()); idx |= 1 << 1; } else *pidbuf = '\0'; if (func) idx |= 1 << 0; if (asprintf(&header, formats[idx], timebuf, pidbuf, func ? func : "") == -1) header = NULL; va_start(ap, format); if (vasprintf(&message, format, ap) == -1) message = NULL; va_end(ap); fprintf(fp, "%s%s", header ? header : "", message ? message : ""); } void nvme_init_logging(nvme_root_t r, int lvl, bool log_pid, bool log_tstamp) { r->log_level = lvl; r->log_pid = log_pid; r->log_timestamp = log_tstamp; }