1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk_internal/log.h" 35 36 #include <stdarg.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <strings.h> 41 #include <syslog.h> 42 #include <ctype.h> 43 #include <errno.h> 44 45 static TAILQ_HEAD(, spdk_trace_flag) g_trace_flags = TAILQ_HEAD_INITIALIZER(g_trace_flags); 46 47 unsigned int spdk_g_notice_stderr_flag = 1; 48 int spdk_g_log_facility = LOG_DAEMON; 49 unsigned int spdk_g_log_priority = LOG_NOTICE; 50 51 SPDK_LOG_REGISTER_TRACE_FLAG("debug", SPDK_TRACE_DEBUG) 52 53 #define MAX_TMPBUF 1024 54 55 struct syslog_code { 56 const char *c_name; 57 int c_val; 58 }; 59 60 static const struct syslog_code facilitynames[] = { 61 { "auth", LOG_AUTH, }, 62 { "authpriv", LOG_AUTHPRIV, }, 63 { "cron", LOG_CRON, }, 64 { "daemon", LOG_DAEMON, }, 65 { "ftp", LOG_FTP, }, 66 { "kern", LOG_KERN, }, 67 { "lpr", LOG_LPR, }, 68 { "mail", LOG_MAIL, }, 69 { "news", LOG_NEWS, }, 70 { "syslog", LOG_SYSLOG, }, 71 { "user", LOG_USER, }, 72 { "uucp", LOG_UUCP, }, 73 { "local0", LOG_LOCAL0, }, 74 { "local1", LOG_LOCAL1, }, 75 { "local2", LOG_LOCAL2, }, 76 { "local3", LOG_LOCAL3, }, 77 { "local4", LOG_LOCAL4, }, 78 { "local5", LOG_LOCAL5, }, 79 { "local6", LOG_LOCAL6, }, 80 { "local7", LOG_LOCAL7, }, 81 #ifdef __FreeBSD__ 82 { "console", LOG_CONSOLE, }, 83 { "ntp", LOG_NTP, }, 84 { "security", LOG_SECURITY, }, 85 #endif 86 { NULL, -1, } 87 }; 88 89 static const struct syslog_code prioritynames[] = { 90 { "alert", LOG_ALERT, }, 91 { "crit", LOG_CRIT, }, 92 { "debug", LOG_DEBUG, }, 93 { "emerg", LOG_EMERG, }, 94 { "err", LOG_ERR, }, 95 { "info", LOG_INFO, }, 96 { "notice", LOG_NOTICE, }, 97 { "warning", LOG_WARNING, }, 98 { NULL, -1, } 99 }; 100 101 int 102 spdk_set_log_facility(const char *facility) 103 { 104 int i; 105 106 for (i = 0; facilitynames[i].c_name != NULL; i++) { 107 if (strcasecmp(facilitynames[i].c_name, facility) == 0) { 108 spdk_g_log_facility = facilitynames[i].c_val; 109 return 0; 110 } 111 } 112 113 spdk_g_log_facility = LOG_DAEMON; 114 return -1; 115 } 116 117 const char * 118 spdk_get_log_facility(void) 119 { 120 const char *def_name = NULL; 121 int i; 122 123 for (i = 0; facilitynames[i].c_name != NULL; i++) { 124 if (facilitynames[i].c_val == spdk_g_log_facility) { 125 return facilitynames[i].c_name; 126 } else if (facilitynames[i].c_val == LOG_DAEMON) { 127 def_name = facilitynames[i].c_name; 128 } 129 } 130 131 return def_name; 132 } 133 134 int 135 spdk_set_log_priority(const char *priority) 136 { 137 int i; 138 139 for (i = 0; prioritynames[i].c_name != NULL; i++) { 140 if (strcasecmp(prioritynames[i].c_name, priority) == 0) { 141 spdk_g_log_priority = prioritynames[i].c_val; 142 return 0; 143 } 144 } 145 146 spdk_g_log_priority = LOG_NOTICE; 147 return -1; 148 } 149 150 void 151 spdk_noticelog(const char *file, const int line, const char *func, 152 const char *format, ...) 153 { 154 char buf[MAX_TMPBUF]; 155 va_list ap; 156 157 va_start(ap, format); 158 vsnprintf(buf, sizeof buf, format, ap); 159 if (file != NULL) { 160 if (func != NULL) { 161 if (spdk_g_notice_stderr_flag) { 162 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 163 } 164 syslog(LOG_NOTICE, "%s:%4d:%s: %s", file, line, func, buf); 165 } else { 166 if (spdk_g_notice_stderr_flag) { 167 fprintf(stderr, "%s:%4d: %s", file, line, buf); 168 } 169 syslog(LOG_NOTICE, "%s:%4d: %s", file, line, buf); 170 } 171 } else { 172 if (spdk_g_notice_stderr_flag) { 173 fprintf(stderr, "%s", buf); 174 } 175 syslog(LOG_NOTICE, "%s", buf); 176 } 177 va_end(ap); 178 } 179 180 void 181 spdk_warnlog(const char *file, const int line, const char *func, 182 const char *format, ...) 183 { 184 char buf[MAX_TMPBUF]; 185 va_list ap; 186 187 va_start(ap, format); 188 vsnprintf(buf, sizeof buf, format, ap); 189 if (file != NULL) { 190 if (func != NULL) { 191 fprintf(stderr, "%s:%4d:%s: %s", file, line, func, buf); 192 syslog(LOG_WARNING, "%s:%4d:%s: %s", 193 file, line, func, buf); 194 } else { 195 fprintf(stderr, "%s:%4d: %s", file, line, buf); 196 syslog(LOG_WARNING, "%s:%4d: %s", file, line, buf); 197 } 198 } else { 199 fprintf(stderr, "%s", buf); 200 syslog(LOG_WARNING, "%s", buf); 201 } 202 203 va_end(ap); 204 } 205 206 void 207 spdk_tracelog(const char *flag, const char *file, const int line, const char *func, 208 const char *format, ...) 209 { 210 char buf[MAX_TMPBUF]; 211 va_list ap; 212 213 va_start(ap, format); 214 vsnprintf(buf, sizeof buf, format, ap); 215 if (func != NULL) { 216 fprintf(stderr, "[%s] %s:%4d:%s: %s", flag, file, line, func, buf); 217 //syslog(LOG_INFO, "[%s] %s:%4d:%s: %s", flag, file, line, func, buf); 218 } else { 219 fprintf(stderr, "[%s] %s:%4d: %s", flag, file, line, buf); 220 //syslog(LOG_INFO, "[%s] %s:%4d: %s", flag, file, line, buf); 221 } 222 va_end(ap); 223 } 224 225 void 226 spdk_errlog(const char *file, const int line, const char *func, 227 const char *format, ...) 228 { 229 char buf[MAX_TMPBUF]; 230 va_list ap; 231 232 va_start(ap, format); 233 vsnprintf(buf, sizeof buf, format, ap); 234 if (func != NULL) { 235 fprintf(stderr, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 236 syslog(LOG_ERR, "%s:%4d:%s: ***ERROR*** %s", file, line, func, buf); 237 } else { 238 fprintf(stderr, "%s:%4d: ***ERROR*** %s", file, line, buf); 239 syslog(LOG_ERR, "%s:%4d: ***ERROR*** %s", file, line, buf); 240 } 241 va_end(ap); 242 } 243 244 static void 245 fdump(FILE *fp, const char *label, const uint8_t *buf, size_t len) 246 { 247 char tmpbuf[MAX_TMPBUF]; 248 char buf16[16 + 1]; 249 size_t total; 250 unsigned int idx; 251 252 fprintf(fp, "%s\n", label); 253 254 memset(buf16, 0, sizeof buf16); 255 total = 0; 256 for (idx = 0; idx < len; idx++) { 257 if (idx != 0 && idx % 16 == 0) { 258 snprintf(tmpbuf + total, sizeof tmpbuf - total, 259 " %s", buf16); 260 fprintf(fp, "%s\n", tmpbuf); 261 total = 0; 262 } 263 if (idx % 16 == 0) { 264 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 265 "%08x ", idx); 266 } 267 if (idx % 8 == 0) { 268 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 269 "%s", " "); 270 } 271 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, 272 "%2.2x ", buf[idx] & 0xff); 273 buf16[idx % 16] = isprint(buf[idx]) ? buf[idx] : '.'; 274 } 275 for (; idx % 16 != 0; idx++) { 276 total += snprintf(tmpbuf + total, sizeof tmpbuf - total, " "); 277 buf16[idx % 16] = ' '; 278 } 279 snprintf(tmpbuf + total, sizeof tmpbuf - total, " %s", buf16); 280 fprintf(fp, "%s\n", tmpbuf); 281 fflush(fp); 282 } 283 284 void 285 spdk_trace_dump(const char *label, const uint8_t *buf, size_t len) 286 { 287 fdump(stderr, label, buf, len); 288 } 289 290 static struct spdk_trace_flag * 291 get_trace_flag(const char *name) 292 { 293 struct spdk_trace_flag *flag; 294 295 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 296 if (strcasecmp(name, flag->name) == 0) { 297 return flag; 298 } 299 } 300 301 return NULL; 302 } 303 304 void 305 spdk_log_register_trace_flag(const char *name, struct spdk_trace_flag *flag) 306 { 307 struct spdk_trace_flag *iter; 308 309 if (name == NULL || flag == NULL) { 310 fprintf(stderr, "missing spdk_trace_flag parameters\n"); 311 abort(); 312 } 313 314 if (get_trace_flag(name)) { 315 fprintf(stderr, "duplicate spdk_trace_flag '%s'\n", name); 316 abort(); 317 } 318 319 TAILQ_FOREACH(iter, &g_trace_flags, tailq) { 320 if (strcasecmp(iter->name, flag->name) > 0) { 321 TAILQ_INSERT_BEFORE(iter, flag, tailq); 322 return; 323 } 324 } 325 326 TAILQ_INSERT_TAIL(&g_trace_flags, flag, tailq); 327 } 328 329 bool 330 spdk_log_get_trace_flag(const char *name) 331 { 332 struct spdk_trace_flag *flag = get_trace_flag(name); 333 334 if (flag && flag->enabled) { 335 return true; 336 } 337 338 return false; 339 } 340 341 static int 342 set_trace_flag(const char *name, bool value) 343 { 344 struct spdk_trace_flag *flag; 345 346 if (strcasecmp(name, "all") == 0) { 347 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 348 flag->enabled = value; 349 } 350 return 0; 351 } 352 353 flag = get_trace_flag(name); 354 if (flag == NULL) { 355 return -1; 356 } 357 358 flag->enabled = value; 359 360 return 0; 361 } 362 363 int 364 spdk_log_set_trace_flag(const char *name) 365 { 366 return set_trace_flag(name, true); 367 } 368 369 int 370 spdk_log_clear_trace_flag(const char *name) 371 { 372 return set_trace_flag(name, false); 373 } 374 375 struct spdk_trace_flag * 376 spdk_log_get_first_trace_flag(void) 377 { 378 return TAILQ_FIRST(&g_trace_flags); 379 } 380 381 struct spdk_trace_flag * 382 spdk_log_get_next_trace_flag(struct spdk_trace_flag *flag) 383 { 384 return TAILQ_NEXT(flag, tailq); 385 } 386 387 void 388 spdk_open_log(void) 389 { 390 if (spdk_g_log_facility != 0) { 391 openlog("spdk", LOG_PID, spdk_g_log_facility); 392 } else { 393 openlog("spdk", LOG_PID, LOG_DAEMON); 394 } 395 } 396 397 void 398 spdk_close_log(void) 399 { 400 closelog(); 401 } 402 403 void 404 spdk_tracelog_usage(FILE *f, const char *trace_arg) 405 { 406 #ifdef DEBUG 407 struct spdk_trace_flag *flag; 408 409 fprintf(f, " %s flag enable trace flag (all", trace_arg); 410 411 TAILQ_FOREACH(flag, &g_trace_flags, tailq) { 412 fprintf(f, ", %s", flag->name); 413 } 414 415 fprintf(f, ")\n"); 416 #else 417 fprintf(f, " %s flag enable trace flag (not supported - must rebuild with CONFIG_DEBUG=y)\n", 418 trace_arg); 419 #endif 420 } 421