1*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
2*758e9fbaSOystein Eftevaag #include <config.h>
3*758e9fbaSOystein Eftevaag #endif
4*758e9fbaSOystein Eftevaag
5*758e9fbaSOystein Eftevaag #include <string.h>
6*758e9fbaSOystein Eftevaag #include <stdio.h>
7*758e9fbaSOystein Eftevaag #include <stdarg.h>
8*758e9fbaSOystein Eftevaag #include <stdlib.h>
9*758e9fbaSOystein Eftevaag #include <ctype.h>
10*758e9fbaSOystein Eftevaag
11*758e9fbaSOystein Eftevaag #define LOGMODULE log
12*758e9fbaSOystein Eftevaag #include "log.h"
13*758e9fbaSOystein Eftevaag
14*758e9fbaSOystein Eftevaag #include <android-base/logging.h>
15*758e9fbaSOystein Eftevaag
16*758e9fbaSOystein Eftevaag #if !defined(_MSC_VER) || defined(__INTEL_COMPILER)
17*758e9fbaSOystein Eftevaag #define likely(x) __builtin_expect(!!(x), 1)
18*758e9fbaSOystein Eftevaag #define unlikely(x) __builtin_expect(!!(x), 0)
19*758e9fbaSOystein Eftevaag #else
20*758e9fbaSOystein Eftevaag /* Microsoft Visual Studio gives internal error C1001 with _builtin_expect */
21*758e9fbaSOystein Eftevaag #define likely(x) (x)
22*758e9fbaSOystein Eftevaag #define unlikely(x) (x)
23*758e9fbaSOystein Eftevaag #endif
24*758e9fbaSOystein Eftevaag
25*758e9fbaSOystein Eftevaag extern "C" {
26*758e9fbaSOystein Eftevaag
27*758e9fbaSOystein Eftevaag /**
28*758e9fbaSOystein Eftevaag * Compares two strings byte by byte and ignores the
29*758e9fbaSOystein Eftevaag * character's case. Stops at the n-th byte of both
30*758e9fbaSOystein Eftevaag * strings.
31*758e9fbaSOystein Eftevaag *
32*758e9fbaSOystein Eftevaag * This is basically a replacement of the POSIX-function
33*758e9fbaSOystein Eftevaag * _strncasecmp_. Since tpm2-tss is supposed to be compatible
34*758e9fbaSOystein Eftevaag * with ISO C99 and not with POSIX, _strncasecmp_ had to be
35*758e9fbaSOystein Eftevaag * replaced. This function creates lowercase representations
36*758e9fbaSOystein Eftevaag * of the strings and compares them bytewise.
37*758e9fbaSOystein Eftevaag *
38*758e9fbaSOystein Eftevaag * @param string1 The first of the two strings to compare
39*758e9fbaSOystein Eftevaag * @param string2 The second of the two strings to compare
40*758e9fbaSOystein Eftevaag * @param n The maximum number of bytes to compare
41*758e9fbaSOystein Eftevaag * @return 0 if both strings are equal (case insensitive),
42*758e9fbaSOystein Eftevaag * an integer greater than zero if string1 is greater than
43*758e9fbaSOystein Eftevaag * string 2 and an integer smaller than zero if string1 is
44*758e9fbaSOystein Eftevaag * smaller than string2
45*758e9fbaSOystein Eftevaag *
46*758e9fbaSOystein Eftevaag */
47*758e9fbaSOystein Eftevaag static int
case_insensitive_strncmp(const char * string1,const char * string2,size_t n)48*758e9fbaSOystein Eftevaag case_insensitive_strncmp(const char *string1,
49*758e9fbaSOystein Eftevaag const char *string2,
50*758e9fbaSOystein Eftevaag size_t n)
51*758e9fbaSOystein Eftevaag {
52*758e9fbaSOystein Eftevaag if ((string1 == NULL) && (string2 == NULL)) {
53*758e9fbaSOystein Eftevaag return 0;
54*758e9fbaSOystein Eftevaag }
55*758e9fbaSOystein Eftevaag if ((string1 == NULL) && (string2 != NULL)) {
56*758e9fbaSOystein Eftevaag return -1;
57*758e9fbaSOystein Eftevaag }
58*758e9fbaSOystein Eftevaag if ((string1 != NULL) && (string2 == NULL)) {
59*758e9fbaSOystein Eftevaag return 1;
60*758e9fbaSOystein Eftevaag }
61*758e9fbaSOystein Eftevaag if (n == 0) { // Zero bytes are always equal
62*758e9fbaSOystein Eftevaag return 0;
63*758e9fbaSOystein Eftevaag }
64*758e9fbaSOystein Eftevaag if (string1 == string2) { // return equal if they point to same location
65*758e9fbaSOystein Eftevaag return 0;
66*758e9fbaSOystein Eftevaag }
67*758e9fbaSOystein Eftevaag
68*758e9fbaSOystein Eftevaag int result;
69*758e9fbaSOystein Eftevaag do {
70*758e9fbaSOystein Eftevaag result = tolower((unsigned char) *string1) - tolower((unsigned char) *string2);
71*758e9fbaSOystein Eftevaag if (result != 0) {
72*758e9fbaSOystein Eftevaag break;
73*758e9fbaSOystein Eftevaag }
74*758e9fbaSOystein Eftevaag } while (*string1++ != '\0' && *string2++ != '\0' && --n );
75*758e9fbaSOystein Eftevaag return result;
76*758e9fbaSOystein Eftevaag }
77*758e9fbaSOystein Eftevaag
78*758e9fbaSOystein Eftevaag static log_level
79*758e9fbaSOystein Eftevaag getLogLevel(const char *module, log_level logdefault);
80*758e9fbaSOystein Eftevaag
81*758e9fbaSOystein Eftevaag void
doLogBlob(log_level loglevel,const char * module,log_level logdefault,log_level * status,const char * file,const char * func,int line,const uint8_t * blob,size_t size,const char * fmt,...)82*758e9fbaSOystein Eftevaag doLogBlob(log_level loglevel, const char *module, log_level logdefault,
83*758e9fbaSOystein Eftevaag log_level *status,
84*758e9fbaSOystein Eftevaag const char *file, const char *func, int line,
85*758e9fbaSOystein Eftevaag const uint8_t *blob, size_t size, const char *fmt, ...)
86*758e9fbaSOystein Eftevaag {
87*758e9fbaSOystein Eftevaag if (unlikely(*status == LOGLEVEL_UNDEFINED))
88*758e9fbaSOystein Eftevaag *status = getLogLevel(module, logdefault);
89*758e9fbaSOystein Eftevaag if (loglevel > *status)
90*758e9fbaSOystein Eftevaag return;
91*758e9fbaSOystein Eftevaag
92*758e9fbaSOystein Eftevaag va_list vaargs;
93*758e9fbaSOystein Eftevaag va_start(vaargs, fmt);
94*758e9fbaSOystein Eftevaag /* TODO: Unfortunately, vsnprintf(NULL, 0, ...) do not behave the same as
95*758e9fbaSOystein Eftevaag snprintf(NULL, 0, ...). Until there is an alternative, messages on
96*758e9fbaSOystein Eftevaag logblob are restricted to 255 characters
97*758e9fbaSOystein Eftevaag int msg_len = vsnprintf(NULL, 0, fmt, vaargs); */
98*758e9fbaSOystein Eftevaag int msg_len = 255;
99*758e9fbaSOystein Eftevaag char msg[msg_len+1];
100*758e9fbaSOystein Eftevaag vsnprintf(msg, sizeof(msg), fmt, vaargs);
101*758e9fbaSOystein Eftevaag va_end(vaargs);
102*758e9fbaSOystein Eftevaag
103*758e9fbaSOystein Eftevaag doLog(loglevel, module, logdefault, status, file, func, line,
104*758e9fbaSOystein Eftevaag "%s (size=%zi):", msg, size);
105*758e9fbaSOystein Eftevaag
106*758e9fbaSOystein Eftevaag unsigned int i, y, x, off, off2;
107*758e9fbaSOystein Eftevaag unsigned int width = 16;
108*758e9fbaSOystein Eftevaag #define LINE_LEN 64
109*758e9fbaSOystein Eftevaag char buffer[LINE_LEN];
110*758e9fbaSOystein Eftevaag
111*758e9fbaSOystein Eftevaag for (i = 1, off = 0, off2 = 0; i <= size; i++) {
112*758e9fbaSOystein Eftevaag if (i == 1) {
113*758e9fbaSOystein Eftevaag sprintf(&buffer[off], "%04x: ", i - 1);
114*758e9fbaSOystein Eftevaag off += 6;
115*758e9fbaSOystein Eftevaag }
116*758e9fbaSOystein Eftevaag
117*758e9fbaSOystein Eftevaag /* data output */
118*758e9fbaSOystein Eftevaag sprintf(&buffer[off], "%02x", blob[i-1]);
119*758e9fbaSOystein Eftevaag off += 2;
120*758e9fbaSOystein Eftevaag
121*758e9fbaSOystein Eftevaag /* ASCII output */
122*758e9fbaSOystein Eftevaag if ((i % width == 0 && i > 1) || i == size) {
123*758e9fbaSOystein Eftevaag sprintf(&buffer[off], " ");
124*758e9fbaSOystein Eftevaag off += 2;
125*758e9fbaSOystein Eftevaag /* Align to the right */
126*758e9fbaSOystein Eftevaag for (x = off; x < width * 2 + 8; x++) {
127*758e9fbaSOystein Eftevaag sprintf(&buffer[off], " ");
128*758e9fbaSOystein Eftevaag off++;
129*758e9fbaSOystein Eftevaag }
130*758e9fbaSOystein Eftevaag
131*758e9fbaSOystein Eftevaag /* Account for a line that is not 'full' */
132*758e9fbaSOystein Eftevaag unsigned int less = width - (i % width);
133*758e9fbaSOystein Eftevaag if (less == width)
134*758e9fbaSOystein Eftevaag less = 0;
135*758e9fbaSOystein Eftevaag
136*758e9fbaSOystein Eftevaag for (y = 0; y < width - less; y++) {
137*758e9fbaSOystein Eftevaag if (isgraph(blob[off2 + y])) {
138*758e9fbaSOystein Eftevaag sprintf(&buffer[y + off], "%c", blob[off2 + y]);
139*758e9fbaSOystein Eftevaag } else {
140*758e9fbaSOystein Eftevaag sprintf(&buffer[y + off], "%c", '.');
141*758e9fbaSOystein Eftevaag }
142*758e9fbaSOystein Eftevaag }
143*758e9fbaSOystein Eftevaag /* print the line and restart */
144*758e9fbaSOystein Eftevaag fprintf (stderr, "%s\n", buffer);
145*758e9fbaSOystein Eftevaag off2 = i;
146*758e9fbaSOystein Eftevaag off = 0;
147*758e9fbaSOystein Eftevaag memset(buffer, '\0', LINE_LEN);
148*758e9fbaSOystein Eftevaag sprintf(&buffer[off], "%04x: ", i);
149*758e9fbaSOystein Eftevaag off += 6;
150*758e9fbaSOystein Eftevaag }
151*758e9fbaSOystein Eftevaag }
152*758e9fbaSOystein Eftevaag }
153*758e9fbaSOystein Eftevaag
154*758e9fbaSOystein Eftevaag void
doLog(log_level loglevel,const char * module,log_level logdefault,log_level * status,const char * file,const char * func,int line,const char * msg,...)155*758e9fbaSOystein Eftevaag doLog(log_level loglevel, const char *module, log_level logdefault,
156*758e9fbaSOystein Eftevaag log_level *status,
157*758e9fbaSOystein Eftevaag const char *file, const char *func, int line,
158*758e9fbaSOystein Eftevaag const char *msg, ...)
159*758e9fbaSOystein Eftevaag {
160*758e9fbaSOystein Eftevaag if (unlikely(*status == LOGLEVEL_UNDEFINED))
161*758e9fbaSOystein Eftevaag *status = getLogLevel(module, logdefault);
162*758e9fbaSOystein Eftevaag
163*758e9fbaSOystein Eftevaag if (loglevel > *status)
164*758e9fbaSOystein Eftevaag return;
165*758e9fbaSOystein Eftevaag
166*758e9fbaSOystein Eftevaag int size = snprintf(NULL, 0, "%s:%s:%s:%d:%s() %s ",
167*758e9fbaSOystein Eftevaag log_strings[loglevel], module, file, line, func, msg);
168*758e9fbaSOystein Eftevaag char fmt[size+1];
169*758e9fbaSOystein Eftevaag snprintf(fmt, sizeof(fmt), "%s:%s:%s:%d:%s() %s ",
170*758e9fbaSOystein Eftevaag log_strings[loglevel], module, file, line, func, msg);
171*758e9fbaSOystein Eftevaag
172*758e9fbaSOystein Eftevaag va_list vaargs;
173*758e9fbaSOystein Eftevaag va_start(vaargs, msg);
174*758e9fbaSOystein Eftevaag int complete_size = vsnprintf(NULL, 0, fmt, vaargs);
175*758e9fbaSOystein Eftevaag va_end(vaargs);
176*758e9fbaSOystein Eftevaag
177*758e9fbaSOystein Eftevaag va_start(vaargs, msg);
178*758e9fbaSOystein Eftevaag char complete[complete_size+1];
179*758e9fbaSOystein Eftevaag vsnprintf(complete, sizeof(complete), fmt, vaargs);
180*758e9fbaSOystein Eftevaag va_end(vaargs);
181*758e9fbaSOystein Eftevaag
182*758e9fbaSOystein Eftevaag fprintf(stderr, "%s\n", complete);
183*758e9fbaSOystein Eftevaag
184*758e9fbaSOystein Eftevaag switch (loglevel) {
185*758e9fbaSOystein Eftevaag case LOGLEVEL_NONE:
186*758e9fbaSOystein Eftevaag LOG(ERROR) << complete;
187*758e9fbaSOystein Eftevaag break;
188*758e9fbaSOystein Eftevaag case LOGLEVEL_ERROR:
189*758e9fbaSOystein Eftevaag LOG(ERROR) << complete;
190*758e9fbaSOystein Eftevaag break;
191*758e9fbaSOystein Eftevaag case LOGLEVEL_WARNING:
192*758e9fbaSOystein Eftevaag LOG(WARNING) << complete;
193*758e9fbaSOystein Eftevaag break;
194*758e9fbaSOystein Eftevaag case LOGLEVEL_INFO:
195*758e9fbaSOystein Eftevaag LOG(INFO) << complete;
196*758e9fbaSOystein Eftevaag break;
197*758e9fbaSOystein Eftevaag case LOGLEVEL_DEBUG:
198*758e9fbaSOystein Eftevaag LOG(DEBUG) << complete;
199*758e9fbaSOystein Eftevaag break;
200*758e9fbaSOystein Eftevaag case LOGLEVEL_TRACE:
201*758e9fbaSOystein Eftevaag LOG(VERBOSE) << complete;
202*758e9fbaSOystein Eftevaag break;
203*758e9fbaSOystein Eftevaag case LOGLEVEL_UNDEFINED:
204*758e9fbaSOystein Eftevaag default:
205*758e9fbaSOystein Eftevaag LOG(WARNING) << complete;
206*758e9fbaSOystein Eftevaag break;
207*758e9fbaSOystein Eftevaag }
208*758e9fbaSOystein Eftevaag }
209*758e9fbaSOystein Eftevaag
210*758e9fbaSOystein Eftevaag static log_level
log_stringlevel(const char * n)211*758e9fbaSOystein Eftevaag log_stringlevel(const char *n)
212*758e9fbaSOystein Eftevaag {
213*758e9fbaSOystein Eftevaag log_level i;
214*758e9fbaSOystein Eftevaag for(i = (log_level) 0; i < sizeof(log_strings)/sizeof(log_strings[0]); i = (log_level) ((int) i + 1)) {
215*758e9fbaSOystein Eftevaag if (case_insensitive_strncmp(log_strings[i], n, strlen(log_strings[i])) == 0) {
216*758e9fbaSOystein Eftevaag return i;
217*758e9fbaSOystein Eftevaag }
218*758e9fbaSOystein Eftevaag }
219*758e9fbaSOystein Eftevaag return LOGLEVEL_UNDEFINED;
220*758e9fbaSOystein Eftevaag }
221*758e9fbaSOystein Eftevaag
222*758e9fbaSOystein Eftevaag static log_level
getLogLevel(const char * module,log_level logdefault)223*758e9fbaSOystein Eftevaag getLogLevel(const char *module, log_level logdefault)
224*758e9fbaSOystein Eftevaag {
225*758e9fbaSOystein Eftevaag log_level loglevel = logdefault;
226*758e9fbaSOystein Eftevaag char *envlevel = getenv("TSS2_LOG");
227*758e9fbaSOystein Eftevaag char *i = envlevel;
228*758e9fbaSOystein Eftevaag if (envlevel == NULL)
229*758e9fbaSOystein Eftevaag return loglevel;
230*758e9fbaSOystein Eftevaag while ((i = strchr(i, '+')) != NULL) {
231*758e9fbaSOystein Eftevaag if ((envlevel <= i - strlen("all") &&
232*758e9fbaSOystein Eftevaag case_insensitive_strncmp(i - 3, "all", 3) == 0) ||
233*758e9fbaSOystein Eftevaag (envlevel <= i - strlen(module) &&
234*758e9fbaSOystein Eftevaag case_insensitive_strncmp(i - strlen(module), module, strlen(module)) == 0)) {
235*758e9fbaSOystein Eftevaag log_level tmp = log_stringlevel(i+1);
236*758e9fbaSOystein Eftevaag if (tmp != LOGLEVEL_UNDEFINED)
237*758e9fbaSOystein Eftevaag loglevel = tmp;
238*758e9fbaSOystein Eftevaag }
239*758e9fbaSOystein Eftevaag i = i + 1;
240*758e9fbaSOystein Eftevaag }
241*758e9fbaSOystein Eftevaag return loglevel;
242*758e9fbaSOystein Eftevaag }
243*758e9fbaSOystein Eftevaag
244*758e9fbaSOystein Eftevaag } // extern "C"
245