[go: nahoru, domu]

blob: 8ab9405d202610a08f462a0f68184a6685e3be31 [file] [log] [blame]
Alon Bar-Lev38fcb662019-05-31 18:55:38 +03001#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
Andreas Fuchsbc490762018-01-03 14:36:38 +01005#include <string.h>
6#include <stdio.h>
7#include <stdarg.h>
8#include <stdlib.h>
Lukas Jäger35fc4272018-08-28 13:53:03 +02009#include <ctype.h>
Philip Tricca391e8892017-02-08 13:15:27 -080010
Andreas Fuchsbc490762018-01-03 14:36:38 +010011#define LOGMODULE log
Philip Triccaa7c51ce2018-03-10 18:28:25 -080012#include "log.h"
Andreas Fuchsbc490762018-01-03 14:36:38 +010013
A. Cody Schuffelen13652172020-03-16 19:32:45 -070014#include <android-base/logging.h>
15
dantpm293b4fa2018-04-11 10:31:46 -070016#if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
Andreas Fuchsbc490762018-01-03 14:36:38 +010017#define likely(x) __builtin_expect(!!(x), 1)
18#define unlikely(x) __builtin_expect(!!(x), 0)
dantpm293b4fa2018-04-11 10:31:46 -070019#else
20/* Microsoft Visual Studio gives internal error C1001 with _builtin_expect */
21#define likely(x) (x)
22#define unlikely(x) (x)
23#endif
Andreas Fuchsbc490762018-01-03 14:36:38 +010024
A. Cody Schuffelen13652172020-03-16 19:32:45 -070025extern "C" {
26
Lukas Jäger35fc4272018-08-28 13:53:03 +020027/**
28 * Compares two strings byte by byte and ignores the
29 * character's case. Stops at the n-th byte of both
30 * strings.
Tadeusz Strukca2fa212018-09-13 12:37:02 -070031 *
Lukas Jäger35fc4272018-08-28 13:53:03 +020032 * This is basically a replacement of the POSIX-function
33 * _strncasecmp_. Since tpm2-tss is supposed to be compatible
34 * with ISO C99 and not with POSIX, _strncasecmp_ had to be
35 * replaced. This function creates lowercase representations
Peter Hueweb0986cb2019-02-19 22:26:57 +010036 * of the strings and compares them bytewise.
Lukas Jäger35fc4272018-08-28 13:53:03 +020037 *
38 * @param string1 The first of the two strings to compare
39 * @param string2 The second of the two strings to compare
40 * @param n The maximum number of bytes to compare
41 * @return 0 if both strings are equal (case insensitive),
42 * an integer greater than zero if string1 is greater than
43 * string 2 and an integer smaller than zero if string1 is
44 * smaller than string2
45 *
46 */
Tadeusz Strukca2fa212018-09-13 12:37:02 -070047static int
48case_insensitive_strncmp(const char *string1,
49 const char *string2,
Lukas Jäger35fc4272018-08-28 13:53:03 +020050 size_t n)
51{
52 if ((string1 == NULL) && (string2 == NULL)) {
53 return 0;
54 }
55 if ((string1 == NULL) && (string2 != NULL)) {
56 return -1;
57 }
58 if ((string1 != NULL) && (string2 == NULL)) {
59 return 1;
60 }
Peter Hueweb0986cb2019-02-19 22:26:57 +010061 if (n == 0) { // Zero bytes are always equal
62 return 0;
63 }
64 if (string1 == string2) { // return equal if they point to same location
65 return 0;
66 }
Lukas Jäger35fc4272018-08-28 13:53:03 +020067
Peter Hueweb0986cb2019-02-19 22:26:57 +010068 int result;
69 do {
70 result = tolower((unsigned char) *string1) - tolower((unsigned char) *string2);
71 if (result != 0) {
72 break;
73 }
74 } while (*string1++ != '\0' && *string2++ != '\0' && --n );
75 return result;
Lukas Jäger35fc4272018-08-28 13:53:03 +020076}
77
Peter Huewe04fcab52019-04-16 15:12:45 +020078static log_level
Andreas Fuchsbc490762018-01-03 14:36:38 +010079getLogLevel(const char *module, log_level logdefault);
80
81void
82doLogBlob(log_level loglevel, const char *module, log_level logdefault,
83 log_level *status,
84 const char *file, const char *func, int line,
85 const uint8_t *blob, size_t size, const char *fmt, ...)
Philip Tricca391e8892017-02-08 13:15:27 -080086{
Andreas Fuchsbc490762018-01-03 14:36:38 +010087 if (unlikely(*status == LOGLEVEL_UNDEFINED))
88 *status = getLogLevel(module, logdefault);
Andreas Fuchsbc490762018-01-03 14:36:38 +010089 if (loglevel > *status)
90 return;
91
Andreas Fuchsbc490762018-01-03 14:36:38 +010092 va_list vaargs;
93 va_start(vaargs, fmt);
94 /* TODO: Unfortunately, vsnprintf(NULL, 0, ...) do not behave the same as
95 snprintf(NULL, 0, ...). Until there is an alternative, messages on
96 logblob are restricted to 255 characters
97 int msg_len = vsnprintf(NULL, 0, fmt, vaargs); */
98 int msg_len = 255;
99 char msg[msg_len+1];
100 vsnprintf(msg, sizeof(msg), fmt, vaargs);
101 va_end(vaargs);
102
103 doLog(loglevel, module, logdefault, status, file, func, line,
Tadeusz Strukccc62f32020-02-28 14:24:25 -0800104 "%s (size=%zi):", msg, size);
105
106 unsigned int i, y, x, off, off2;
107 unsigned int width = 16;
108#define LINE_LEN 64
109 char buffer[LINE_LEN];
110
111 for (i = 1, off = 0, off2 = 0; i <= size; i++) {
112 if (i == 1) {
113 sprintf(&buffer[off], "%04x: ", i - 1);
114 off += 6;
115 }
116
117 /* data output */
118 sprintf(&buffer[off], "%02x", blob[i-1]);
119 off += 2;
120
121 /* ASCII output */
122 if ((i % width == 0 && i > 1) || i == size) {
123 sprintf(&buffer[off], " ");
124 off += 2;
125 /* Align to the right */
126 for (x = off; x < width * 2 + 8; x++) {
127 sprintf(&buffer[off], " ");
128 off++;
129 }
130
131 /* Account for a line that is not 'full' */
132 unsigned int less = width - (i % width);
133 if (less == width)
134 less = 0;
135
136 for (y = 0; y < width - less; y++) {
137 if (isgraph(blob[off2 + y])) {
138 sprintf(&buffer[y + off], "%c", blob[off2 + y]);
139 } else {
140 sprintf(&buffer[y + off], "%c", '.');
141 }
142 }
143 /* print the line and restart */
144 fprintf (stderr, "%s\n", buffer);
145 off2 = i;
146 off = 0;
147 memset(buffer, '\0', LINE_LEN);
148 sprintf(&buffer[off], "%04x: ", i);
149 off += 6;
150 }
151 }
Andreas Fuchsbc490762018-01-03 14:36:38 +0100152}
153
154void
155doLog(log_level loglevel, const char *module, log_level logdefault,
156 log_level *status,
157 const char *file, const char *func, int line,
158 const char *msg, ...)
159{
160 if (unlikely(*status == LOGLEVEL_UNDEFINED))
161 *status = getLogLevel(module, logdefault);
162
163 if (loglevel > *status)
164 return;
165
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700166 int size = snprintf(NULL, 0, "%s:%s:%s:%d:%s() %s ",
Andreas Fuchsbc490762018-01-03 14:36:38 +0100167 log_strings[loglevel], module, file, line, func, msg);
168 char fmt[size+1];
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700169 snprintf(fmt, sizeof(fmt), "%s:%s:%s:%d:%s() %s ",
Andreas Fuchsbc490762018-01-03 14:36:38 +0100170 log_strings[loglevel], module, file, line, func, msg);
171
172 va_list vaargs;
173 va_start(vaargs, msg);
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700174 int complete_size = vsnprintf(NULL, 0, fmt, vaargs);
Andreas Fuchsbc490762018-01-03 14:36:38 +0100175 va_end(vaargs);
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700176
177 va_start(vaargs, msg);
178 char complete[complete_size+1];
179 vsnprintf(complete, sizeof(complete), fmt, vaargs);
180 va_end(vaargs);
181
182 fprintf(stderr, "%s\n", complete);
183
184 switch (loglevel) {
185 case LOGLEVEL_NONE:
186 LOG(ERROR) << complete;
187 break;
188 case LOGLEVEL_ERROR:
189 LOG(ERROR) << complete;
190 break;
191 case LOGLEVEL_WARNING:
192 LOG(WARNING) << complete;
193 break;
194 case LOGLEVEL_INFO:
195 LOG(INFO) << complete;
196 break;
197 case LOGLEVEL_DEBUG:
198 LOG(DEBUG) << complete;
199 break;
200 case LOGLEVEL_TRACE:
201 LOG(VERBOSE) << complete;
202 break;
203 case LOGLEVEL_UNDEFINED:
204 default:
205 LOG(WARNING) << complete;
206 break;
207 }
Andreas Fuchsbc490762018-01-03 14:36:38 +0100208}
209
Peter Huewe04fcab52019-04-16 15:12:45 +0200210static log_level
Andreas Fuchsbc490762018-01-03 14:36:38 +0100211log_stringlevel(const char *n)
212{
Fabrice Fontaine9de349b2019-12-14 18:42:26 +0100213 log_level i;
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700214 for(i = (log_level) 0; i < sizeof(log_strings)/sizeof(log_strings[0]); i = (log_level) ((int) i + 1)) {
Lukas Jäger35fc4272018-08-28 13:53:03 +0200215 if (case_insensitive_strncmp(log_strings[i], n, strlen(log_strings[i])) == 0) {
Andreas Fuchsbc490762018-01-03 14:36:38 +0100216 return i;
Philip Tricca391e8892017-02-08 13:15:27 -0800217 }
218 }
Andreas Fuchsbc490762018-01-03 14:36:38 +0100219 return LOGLEVEL_UNDEFINED;
Philip Tricca391e8892017-02-08 13:15:27 -0800220}
Andreas Fuchsbc490762018-01-03 14:36:38 +0100221
Peter Huewe04fcab52019-04-16 15:12:45 +0200222static log_level
Andreas Fuchsbc490762018-01-03 14:36:38 +0100223getLogLevel(const char *module, log_level logdefault)
224{
225 log_level loglevel = logdefault;
226 char *envlevel = getenv("TSS2_LOG");
227 char *i = envlevel;
228 if (envlevel == NULL)
229 return loglevel;
Philip Tricca59814552018-01-20 21:22:02 -0800230 while ((i = strchr(i, '+')) != NULL) {
Tadeusz Strukca2fa212018-09-13 12:37:02 -0700231 if ((envlevel <= i - strlen("all") &&
232 case_insensitive_strncmp(i - 3, "all", 3) == 0) ||
Andreas Fuchsbc490762018-01-03 14:36:38 +0100233 (envlevel <= i - strlen(module) &&
Lukas Jäger35fc4272018-08-28 13:53:03 +0200234 case_insensitive_strncmp(i - strlen(module), module, strlen(module)) == 0)) {
Andreas Fuchsbc490762018-01-03 14:36:38 +0100235 log_level tmp = log_stringlevel(i+1);
236 if (tmp != LOGLEVEL_UNDEFINED)
237 loglevel = tmp;
238 }
239 i = i + 1;
240 }
241 return loglevel;
242}
A. Cody Schuffelen13652172020-03-16 19:32:45 -0700243
244} // extern "C"