1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "log.h"
26
27 #if defined(CONFIG_OS_WINDOWS)
28 # include <windows.h>
29 # include <time.h>
30 #else
31 # include <unistd.h>
32 # include <sys/time.h>
33 # include <sys/types.h>
34 # include <time.h>
35 #endif
36
37 #include "strings.h"
38 #include "io.h"
39
40 /*
41 **==============================================================================
42 **
43 mike 1.1 ** Local definitions:
44 **
45 **==============================================================================
46 */
47
48 static FILE* _os;
49
50 static const char* _levelStrings[] =
51 {
52 "FATAL",
53 "ERROR",
54 "WARNING",
55 "INFO",
56 "DEBUG",
57 };
58
59 static Log_Level _level = LOG_WARNING;
60 static Log_Level _currentLevel = LOG_WARNING;
61
62 static int _GetCurrentTimeInUsec(MI_Uint64* usec)
63 {
64 mike 1.1 #if defined(CONFIG_OS_WINDOWS)
65 FILETIME ft;
66 ULARGE_INTEGER tmp;
67
68 GetSystemTimeAsFileTime(&ft);
69 tmp.u.LowPart = ft.dwLowDateTime;
70 tmp.u.HighPart = ft.dwHighDateTime;
71 tmp.QuadPart -= 0X19DB1DED53E8000;
72 *usec = tmp.QuadPart / (UINT64)10;
73
74 return 0;
75 #else
76 struct timeval tv;
77 struct timezone tz;
78 memset(&tv, 0, sizeof(tv));
79 memset(&tz, 0, sizeof(tz));
80
81 if (gettimeofday(&tv, &tz) != 0)
82 return -1;
83
84 *usec = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
85 mike 1.1 return 0;
86 #endif
87 }
88
89 #define TIMESTAMP_SIZE 128
90
91 static int _GetTimeStamp(char buf[TIMESTAMP_SIZE])
92 {
93 MI_Uint64 usec;
94
95 if (_GetCurrentTimeInUsec(&usec) != 0)
96 {
97 buf[0] = '\0';
98 return -1;
99 }
100
101 #if defined(CONFIG_OS_WINDOWS)
102 {
103 time_t t = usec / 1000000;
104 struct tm tm;
105 localtime_s(&tm, &t);
106 mike 1.1 sprintf_s(
107 buf,
108 TIMESTAMP_SIZE,
109 "%02u/%02u/%02u %02u:%02u:%02u",
110 tm.tm_year + 1900,
111 tm.tm_mon + 1,
112 tm.tm_mday,
113 tm.tm_hour,
114 tm.tm_min,
115 tm.tm_sec);
116 }
117 #else
118 {
119 time_t t = usec / 1000000;
120 struct tm tm;
121 localtime_r(&t, &tm);
122 sprintf(
123 buf,
124 "%02u/%02u/%02u %02u:%02u:%02u",
125 tm.tm_year + 1900,
126 tm.tm_mon + 1,
127 mike 1.1 tm.tm_mday,
128 tm.tm_hour,
129 tm.tm_min,
130 tm.tm_sec);
131 }
132 #endif
133
134 return 0;
135 }
136
137 #if (MI_CHAR_TYPE == 2)
138 static char* _StrdupWcharToASCII7(const MI_Char* str)
139 {
140 char* p;
141
142 /* Allocate room for string */
143 p = (char*)malloc(Wcslen(str) + 1);
144
145 if (!p)
146 return NULL;
147
148 mike 1.1 /* Copy string while failing on non-ASCII characters */
149 while (*str)
150 {
151 if ((MI_Uint32)*str >= 128)
152 {
153 free(p);
154 return NULL;
155 }
156 *p++ = (char)*str++;
157 }
158
159 return p;
160 }
161 #endif
162
163 static void _PutHeader(
164 FILE* os,
165 const char* file,
166 unsigned int line,
167 Log_Level level)
168 {
169 mike 1.1 char buf[TIMESTAMP_SIZE];
170
171 _GetTimeStamp(buf);
172 fprintf(os, "%s: ", buf);
173 fprintf(os, "%s: ", _levelStrings[(int)level]);
174 fprintf(os, "%s(%u): ", file, line);
175 }
176
177 /*
178 **==============================================================================
179 **
180 ** Public definitions:
181 **
182 **==============================================================================
183 */
184
185 MI_Result Log_Open(
186 const MI_Char* path)
187 {
188 if (!path || _os)
189 return MI_RESULT_FAILED;
190 mike 1.1
191 #if defined(CONFIG_OS_WINDOWS)
192 # if (MI_CHAR_TYPE == 1)
193 {
194 if (fopen_s(&_os, path, "a") != 0)
195 return MI_RESULT_FAILED;
196
197 return MI_RESULT_OK;
198 }
199 # else
200 {
201 if (_wfopen_s(&_os, path, L"a") != 0)
202 return MI_RESULT_FAILED;
203
204 return MI_RESULT_OK;
205 }
206 # endif
207 #else
208 # if (MI_CHAR_TYPE == 1)
209 {
210 _os = fopen(path, "a");
211 mike 1.1 if (!_os)
212 return MI_RESULT_FAILED;
213
214 return MI_RESULT_OK;
215 }
216 # else
217 {
218 char* path7 = _StrdupWcharToASCII7(path);
219
220 if (!path7)
221 return MI_RESULT_FAILED;
222
223 _os = fopen(path7, _os, "a");
224
225 if (!_os)
226 {
227 free(path7);
228 return MI_RESULT_FAILED;
229 }
230
231 free(path7);
232 mike 1.1 return MI_RESULT_OK;
233 }
234 # endif
235 #endif
236 }
237
238 MI_Result Log_OpenFD(
239 int fd)
240 {
241 #if defined(CONFIG_OS_WINDOWS)
242 MI_UNUSED(fd);
243 return MI_RESULT_FAILED;
244 #else
245 if (fd < 0 || _os)
246 return MI_RESULT_FAILED;
247
248 _os = fdopen(fd, "a");
249 if (!_os)
250 return MI_RESULT_FAILED;
251
252 return MI_RESULT_OK;
253 mike 1.1
254 #endif
255 }
256
257 MI_Result Log_OpenStdErr()
258 {
259 _os = stderr;
260 return MI_RESULT_OK;
261 }
262
263 void Log_Close()
264 {
265 if (_os && _os != stderr)
266 {
267 fclose(_os);
268 _os = NULL;
269 }
270 }
271
272 void Log_SetLevel(
273 Log_Level level)
274 mike 1.1 {
275 _level = level;
276 }
277
278 Log_Level Log_GetLevel()
279 {
280 return _level;
281 }
282
283 int Log_SetLevelFromString(const char* level)
284 {
285 size_t i;
286
287 for (i = 0; i < sizeof(_levelStrings) / sizeof(_levelStrings[0]); i++)
288 {
289 char buf[32];
290
291 Snprintf(buf, sizeof(buf), "%u", (int)i);
292
293 if (Strcasecmp(level, _levelStrings[i]) == 0 ||
294 Strcasecmp(level, buf) == 0)
295 mike 1.1 {
296 _level = (Log_Level)i;
297 return 0;
298 }
299 }
300
301 return -1;
302 }
303
304 const char* Log_GetLevelString(Log_Level level)
305 {
306 return _levelStrings[(int)level];
307 }
308
309 int Log_Put(
310 Log_Level level,
311 const char* file,
312 MI_Uint32 line,
313 const MI_Char* format,
314 ...)
315 {
316 mike 1.1 va_list ap;
317 memset(&ap, 0, sizeof(ap));
318
319 if (!_os || level > _level)
320 return 0;
321
322 _PutHeader(_os, file, line, level);
323 va_start(ap, format);
324 #if (MI_CHAR_TYPE == 1)
325 vfprintf(_os, format, ap);
326 #else
327 vfwprintf(_os, format, ap);
328 #endif
329 va_end(ap);
330 fputc('\n', _os);
331
332 return 1;
333 }
334
335 int Log_VPut(
336 Log_Level level,
337 mike 1.1 const char* file,
338 MI_Uint32 line,
339 const MI_Char* format,
340 va_list ap)
341 {
342 if (!_os || level > _level)
343 return 0;
344
345 _PutHeader(_os, file, line, level);
346 #if (MI_CHAR_TYPE == 1)
347 vfprintf(_os, format, ap);
348 #else
349 vfwprintf(_os, format, ap);
350 #endif
351 fputc('\n', _os);
352
353 return 1;
354 }
355
356 int __Log_Put1(
357 Log_Level level,
358 mike 1.1 const char* file,
359 MI_Uint32 line)
360 {
361 if (!_os || level > _level)
362 return 0;
363
364 _currentLevel = level;
365 _PutHeader(_os, file, line, level);
366
367 return 1;
368 }
369
370 void __Log_Put2(
371 const MI_Char* format,
372 ...)
373 {
374 va_list ap;
375 memset(&ap, 0, sizeof(ap));
376
377 if (!_os || _currentLevel > _level)
378 return;
379 mike 1.1
380 va_start(ap, format);
381 #if (MI_CHAR_TYPE == 1)
382 vfprintf(_os, format, ap);
383 #else
384 vfwprintf(_os, format, ap);
385 #endif
386 fputc('\n', _os);
387 fflush(_os);
388 }
389
390 void __Log_Put2_char(
391 const char* format,
392 ...)
393 {
394 va_list ap;
395 memset(&ap, 0, sizeof(ap));
396
397 if (!_os || _currentLevel > _level)
398 return;
399
400 mike 1.1 va_start(ap, format);
401 vfprintf(_os, format, ap);
402 fputc('\n', _os);
403 fflush(_os);
404 }
|