~mir-team/mir/in-process-egl+input-conglomeration

« back to all changes in this revision

Viewing changes to 3rd_party/android-input/android_pristine/system/core/liblog/logprint.c

Merged trunk and fixed issues

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* //device/libs/cutils/logprint.c
2
 
**
3
 
** Copyright 2006, The Android Open Source Project
4
 
**
5
 
** Licensed under the Apache License, Version 2.0 (the "License");
6
 
** you may not use this file except in compliance with the License.
7
 
** You may obtain a copy of the License at
8
 
**
9
 
**     http://www.apache.org/licenses/LICENSE-2.0
10
 
**
11
 
** Unless required by applicable law or agreed to in writing, software
12
 
** distributed under the License is distributed on an "AS IS" BASIS,
13
 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
** See the License for the specific language governing permissions and
15
 
** limitations under the License.
16
 
*/
17
 
 
18
 
#define _GNU_SOURCE /* for asprintf */
19
 
 
20
 
#include <ctype.h>
21
 
#include <stdio.h>
22
 
#include <errno.h>
23
 
#include <stdlib.h>
24
 
#include <stdint.h>
25
 
#include <string.h>
26
 
#include <assert.h>
27
 
#include <arpa/inet.h>
28
 
 
29
 
#include <cutils/logd.h>
30
 
#include <cutils/logprint.h>
31
 
 
32
 
typedef struct FilterInfo_t {
33
 
    char *mTag;
34
 
    android_LogPriority mPri;
35
 
    struct FilterInfo_t *p_next;
36
 
} FilterInfo;
37
 
 
38
 
struct AndroidLogFormat_t {
39
 
    android_LogPriority global_pri;
40
 
    FilterInfo *filters;
41
 
    AndroidLogPrintFormat format;
42
 
};
43
 
 
44
 
static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
45
 
{
46
 
    FilterInfo *p_ret;
47
 
 
48
 
    p_ret = (FilterInfo *)calloc(1, sizeof(FilterInfo));
49
 
    p_ret->mTag = strdup(tag);
50
 
    p_ret->mPri = pri;
51
 
 
52
 
    return p_ret;
53
 
}
54
 
 
55
 
static void filterinfo_free(FilterInfo *p_info)
56
 
{
57
 
    if (p_info == NULL) {
58
 
        return;
59
 
    }
60
 
 
61
 
    free(p_info->mTag);
62
 
    p_info->mTag = NULL;
63
 
}
64
 
 
65
 
/*
66
 
 * Note: also accepts 0-9 priorities
67
 
 * returns ANDROID_LOG_UNKNOWN if the character is unrecognized
68
 
 */
69
 
static android_LogPriority filterCharToPri (char c)
70
 
{
71
 
    android_LogPriority pri;
72
 
 
73
 
    c = tolower(c);
74
 
 
75
 
    if (c >= '0' && c <= '9') {
76
 
        if (c >= ('0'+ANDROID_LOG_SILENT)) {
77
 
            pri = ANDROID_LOG_VERBOSE;
78
 
        } else {
79
 
            pri = (android_LogPriority)(c - '0');
80
 
        }
81
 
    } else if (c == 'v') {
82
 
        pri = ANDROID_LOG_VERBOSE;
83
 
    } else if (c == 'd') {
84
 
        pri = ANDROID_LOG_DEBUG;
85
 
    } else if (c == 'i') {
86
 
        pri = ANDROID_LOG_INFO;
87
 
    } else if (c == 'w') {
88
 
        pri = ANDROID_LOG_WARN;
89
 
    } else if (c == 'e') {
90
 
        pri = ANDROID_LOG_ERROR;
91
 
    } else if (c == 'f') {
92
 
        pri = ANDROID_LOG_FATAL;
93
 
    } else if (c == 's') {
94
 
        pri = ANDROID_LOG_SILENT;
95
 
    } else if (c == '*') {
96
 
        pri = ANDROID_LOG_DEFAULT;
97
 
    } else {
98
 
        pri = ANDROID_LOG_UNKNOWN;
99
 
    }
100
 
 
101
 
    return pri;
102
 
}
103
 
 
104
 
static char filterPriToChar (android_LogPriority pri)
105
 
{
106
 
    switch (pri) {
107
 
        case ANDROID_LOG_VERBOSE:       return 'V';
108
 
        case ANDROID_LOG_DEBUG:         return 'D';
109
 
        case ANDROID_LOG_INFO:          return 'I';
110
 
        case ANDROID_LOG_WARN:          return 'W';
111
 
        case ANDROID_LOG_ERROR:         return 'E';
112
 
        case ANDROID_LOG_FATAL:         return 'F';
113
 
        case ANDROID_LOG_SILENT:        return 'S';
114
 
 
115
 
        case ANDROID_LOG_DEFAULT:
116
 
        case ANDROID_LOG_UNKNOWN:
117
 
        default:                        return '?';
118
 
    }
119
 
}
120
 
 
121
 
static android_LogPriority filterPriForTag(
122
 
        AndroidLogFormat *p_format, const char *tag)
123
 
{
124
 
    FilterInfo *p_curFilter;
125
 
 
126
 
    for (p_curFilter = p_format->filters
127
 
            ; p_curFilter != NULL
128
 
            ; p_curFilter = p_curFilter->p_next
129
 
    ) {
130
 
        if (0 == strcmp(tag, p_curFilter->mTag)) {
131
 
            if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) {
132
 
                return p_format->global_pri;
133
 
            } else {
134
 
                return p_curFilter->mPri;
135
 
            }
136
 
        }
137
 
    }
138
 
 
139
 
    return p_format->global_pri;
140
 
}
141
 
 
142
 
/** for debugging */
143
 
static void dumpFilters(AndroidLogFormat *p_format)
144
 
{
145
 
    FilterInfo *p_fi;
146
 
 
147
 
    for (p_fi = p_format->filters ; p_fi != NULL ; p_fi = p_fi->p_next) {
148
 
        char cPri = filterPriToChar(p_fi->mPri);
149
 
        if (p_fi->mPri == ANDROID_LOG_DEFAULT) {
150
 
            cPri = filterPriToChar(p_format->global_pri);
151
 
        }
152
 
        fprintf(stderr,"%s:%c\n", p_fi->mTag, cPri);
153
 
    }
154
 
 
155
 
    fprintf(stderr,"*:%c\n", filterPriToChar(p_format->global_pri));
156
 
 
157
 
}
158
 
 
159
 
/**
160
 
 * returns 1 if this log line should be printed based on its priority
161
 
 * and tag, and 0 if it should not
162
 
 */
163
 
int android_log_shouldPrintLine (
164
 
        AndroidLogFormat *p_format, const char *tag, android_LogPriority pri)
165
 
{
166
 
    return pri >= filterPriForTag(p_format, tag);
167
 
}
168
 
 
169
 
AndroidLogFormat *android_log_format_new()
170
 
{
171
 
    AndroidLogFormat *p_ret;
172
 
 
173
 
    p_ret = calloc(1, sizeof(AndroidLogFormat));
174
 
 
175
 
    p_ret->global_pri = ANDROID_LOG_VERBOSE;
176
 
    p_ret->format = FORMAT_BRIEF;
177
 
 
178
 
    return p_ret;
179
 
}
180
 
 
181
 
void android_log_format_free(AndroidLogFormat *p_format)
182
 
{
183
 
    FilterInfo *p_info, *p_info_old;
184
 
 
185
 
    p_info = p_format->filters;
186
 
 
187
 
    while (p_info != NULL) {
188
 
        p_info_old = p_info;
189
 
        p_info = p_info->p_next;
190
 
 
191
 
        free(p_info_old);
192
 
    }
193
 
 
194
 
    free(p_format);
195
 
}
196
 
 
197
 
 
198
 
 
199
 
void android_log_setPrintFormat(AndroidLogFormat *p_format,
200
 
        AndroidLogPrintFormat format)
201
 
{
202
 
    p_format->format=format;
203
 
}
204
 
 
205
 
/**
206
 
 * Returns FORMAT_OFF on invalid string
207
 
 */
208
 
AndroidLogPrintFormat android_log_formatFromString(const char * formatString)
209
 
{
210
 
    static AndroidLogPrintFormat format;
211
 
 
212
 
    if (strcmp(formatString, "brief") == 0) format = FORMAT_BRIEF;
213
 
    else if (strcmp(formatString, "process") == 0) format = FORMAT_PROCESS;
214
 
    else if (strcmp(formatString, "tag") == 0) format = FORMAT_TAG;
215
 
    else if (strcmp(formatString, "thread") == 0) format = FORMAT_THREAD;
216
 
    else if (strcmp(formatString, "raw") == 0) format = FORMAT_RAW;
217
 
    else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME;
218
 
    else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME;
219
 
    else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG;
220
 
    else format = FORMAT_OFF;
221
 
 
222
 
    return format;
223
 
}
224
 
 
225
 
/**
226
 
 * filterExpression: a single filter expression
227
 
 * eg "AT:d"
228
 
 *
229
 
 * returns 0 on success and -1 on invalid expression
230
 
 *
231
 
 * Assumes single threaded execution
232
 
 */
233
 
 
234
 
int android_log_addFilterRule(AndroidLogFormat *p_format,
235
 
        const char *filterExpression)
236
 
{
237
 
    size_t i=0;
238
 
    size_t tagNameLength;
239
 
    android_LogPriority pri = ANDROID_LOG_DEFAULT;
240
 
 
241
 
    tagNameLength = strcspn(filterExpression, ":");
242
 
 
243
 
    if (tagNameLength == 0) {
244
 
        goto error;
245
 
    }
246
 
 
247
 
    if(filterExpression[tagNameLength] == ':') {
248
 
        pri = filterCharToPri(filterExpression[tagNameLength+1]);
249
 
 
250
 
        if (pri == ANDROID_LOG_UNKNOWN) {
251
 
            goto error;
252
 
        }
253
 
    }
254
 
 
255
 
    if(0 == strncmp("*", filterExpression, tagNameLength)) {
256
 
        // This filter expression refers to the global filter
257
 
        // The default level for this is DEBUG if the priority
258
 
        // is unspecified
259
 
        if (pri == ANDROID_LOG_DEFAULT) {
260
 
            pri = ANDROID_LOG_DEBUG;
261
 
        }
262
 
 
263
 
        p_format->global_pri = pri;
264
 
    } else {
265
 
        // for filter expressions that don't refer to the global
266
 
        // filter, the default is verbose if the priority is unspecified
267
 
        if (pri == ANDROID_LOG_DEFAULT) {
268
 
            pri = ANDROID_LOG_VERBOSE;
269
 
        }
270
 
 
271
 
        char *tagName;
272
 
 
273
 
// Presently HAVE_STRNDUP is never defined, so the second case is always taken
274
 
// Darwin doesn't have strnup, everything else does
275
 
#ifdef HAVE_STRNDUP
276
 
        tagName = strndup(filterExpression, tagNameLength);
277
 
#else
278
 
        //a few extra bytes copied...
279
 
        tagName = strdup(filterExpression);
280
 
        tagName[tagNameLength] = '\0';
281
 
#endif /*HAVE_STRNDUP*/
282
 
 
283
 
        FilterInfo *p_fi = filterinfo_new(tagName, pri);
284
 
        free(tagName);
285
 
 
286
 
        p_fi->p_next = p_format->filters;
287
 
        p_format->filters = p_fi;
288
 
    }
289
 
 
290
 
    return 0;
291
 
error:
292
 
    return -1;
293
 
}
294
 
 
295
 
 
296
 
/**
297
 
 * filterString: a comma/whitespace-separated set of filter expressions
298
 
 *
299
 
 * eg "AT:d *:i"
300
 
 *
301
 
 * returns 0 on success and -1 on invalid expression
302
 
 *
303
 
 * Assumes single threaded execution
304
 
 *
305
 
 */
306
 
 
307
 
int android_log_addFilterString(AndroidLogFormat *p_format,
308
 
        const char *filterString)
309
 
{
310
 
    char *filterStringCopy = strdup (filterString);
311
 
    char *p_cur = filterStringCopy;
312
 
    char *p_ret;
313
 
    int err;
314
 
 
315
 
    // Yes, I'm using strsep
316
 
    while (NULL != (p_ret = strsep(&p_cur, " \t,"))) {
317
 
        // ignore whitespace-only entries
318
 
        if(p_ret[0] != '\0') {
319
 
            err = android_log_addFilterRule(p_format, p_ret);
320
 
 
321
 
            if (err < 0) {
322
 
                goto error;
323
 
            }
324
 
        }
325
 
    }
326
 
 
327
 
    free (filterStringCopy);
328
 
    return 0;
329
 
error:
330
 
    free (filterStringCopy);
331
 
    return -1;
332
 
}
333
 
 
334
 
static inline char * strip_end(char *str)
335
 
{
336
 
    char *end = str + strlen(str) - 1;
337
 
 
338
 
    while (end >= str && isspace(*end))
339
 
        *end-- = '\0';
340
 
    return str;
341
 
}
342
 
 
343
 
/**
344
 
 * Splits a wire-format buffer into an AndroidLogEntry
345
 
 * entry allocated by caller. Pointers will point directly into buf
346
 
 *
347
 
 * Returns 0 on success and -1 on invalid wire format (entry will be
348
 
 * in unspecified state)
349
 
 */
350
 
int android_log_processLogBuffer(struct logger_entry *buf,
351
 
                                 AndroidLogEntry *entry)
352
 
{
353
 
    entry->tv_sec = buf->sec;
354
 
    entry->tv_nsec = buf->nsec;
355
 
    entry->pid = buf->pid;
356
 
    entry->tid = buf->tid;
357
 
 
358
 
    /*
359
 
     * format: <priority:1><tag:N>\0<message:N>\0
360
 
     *
361
 
     * tag str
362
 
     *   starts at buf->msg+1
363
 
     * msg
364
 
     *   starts at buf->msg+1+len(tag)+1
365
 
     *
366
 
     * The message may have been truncated by the kernel log driver.
367
 
     * When that happens, we must null-terminate the message ourselves.
368
 
     */
369
 
    if (buf->len < 3) {
370
 
        // An well-formed entry must consist of at least a priority
371
 
        // and two null characters
372
 
        fprintf(stderr, "+++ LOG: entry too small\n");
373
 
        return -1;
374
 
    }
375
 
 
376
 
    int msgStart = -1;
377
 
    int msgEnd = -1;
378
 
 
379
 
    int i;
380
 
    for (i = 1; i < buf->len; i++) {
381
 
        if (buf->msg[i] == '\0') {
382
 
            if (msgStart == -1) {
383
 
                msgStart = i + 1;
384
 
            } else {
385
 
                msgEnd = i;
386
 
                break;
387
 
            }
388
 
        }
389
 
    }
390
 
 
391
 
    if (msgStart == -1) {
392
 
        fprintf(stderr, "+++ LOG: malformed log message\n");
393
 
        return -1;
394
 
    }
395
 
    if (msgEnd == -1) {
396
 
        // incoming message not null-terminated; force it
397
 
        msgEnd = buf->len - 1;
398
 
        buf->msg[msgEnd] = '\0';
399
 
    }
400
 
 
401
 
    entry->priority = buf->msg[0];
402
 
    entry->tag = buf->msg + 1;
403
 
    entry->message = buf->msg + msgStart;
404
 
    entry->messageLen = msgEnd - msgStart;
405
 
 
406
 
    return 0;
407
 
}
408
 
 
409
 
/*
410
 
 * Extract a 4-byte value from a byte stream.
411
 
 */
412
 
static inline uint32_t get4LE(const uint8_t* src)
413
 
{
414
 
    return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
415
 
}
416
 
 
417
 
/*
418
 
 * Extract an 8-byte value from a byte stream.
419
 
 */
420
 
static inline uint64_t get8LE(const uint8_t* src)
421
 
{
422
 
    uint32_t low, high;
423
 
 
424
 
    low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
425
 
    high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
426
 
    return ((long long) high << 32) | (long long) low;
427
 
}
428
 
 
429
 
 
430
 
/*
431
 
 * Recursively convert binary log data to printable form.
432
 
 *
433
 
 * This needs to be recursive because you can have lists of lists.
434
 
 *
435
 
 * If we run out of room, we stop processing immediately.  It's important
436
 
 * for us to check for space on every output element to avoid producing
437
 
 * garbled output.
438
 
 *
439
 
 * Returns 0 on success, 1 on buffer full, -1 on failure.
440
 
 */
441
 
static int android_log_printBinaryEvent(const unsigned char** pEventData,
442
 
    size_t* pEventDataLen, char** pOutBuf, size_t* pOutBufLen)
443
 
{
444
 
    const unsigned char* eventData = *pEventData;
445
 
    size_t eventDataLen = *pEventDataLen;
446
 
    char* outBuf = *pOutBuf;
447
 
    size_t outBufLen = *pOutBufLen;
448
 
    unsigned char type;
449
 
    size_t outCount;
450
 
    int result = 0;
451
 
 
452
 
    if (eventDataLen < 1)
453
 
        return -1;
454
 
    type = *eventData++;
455
 
    eventDataLen--;
456
 
 
457
 
    //fprintf(stderr, "--- type=%d (rem len=%d)\n", type, eventDataLen);
458
 
 
459
 
    switch (type) {
460
 
    case EVENT_TYPE_INT:
461
 
        /* 32-bit signed int */
462
 
        {
463
 
            int ival;
464
 
 
465
 
            if (eventDataLen < 4)
466
 
                return -1;
467
 
            ival = get4LE(eventData);
468
 
            eventData += 4;
469
 
            eventDataLen -= 4;
470
 
 
471
 
            outCount = snprintf(outBuf, outBufLen, "%d", ival);
472
 
            if (outCount < outBufLen) {
473
 
                outBuf += outCount;
474
 
                outBufLen -= outCount;
475
 
            } else {
476
 
                /* halt output */
477
 
                goto no_room;
478
 
            }
479
 
        }
480
 
        break;
481
 
    case EVENT_TYPE_LONG:
482
 
        /* 64-bit signed long */
483
 
        {
484
 
            long long lval;
485
 
 
486
 
            if (eventDataLen < 8)
487
 
                return -1;
488
 
            lval = get8LE(eventData);
489
 
            eventData += 8;
490
 
            eventDataLen -= 8;
491
 
 
492
 
            outCount = snprintf(outBuf, outBufLen, "%lld", lval);
493
 
            if (outCount < outBufLen) {
494
 
                outBuf += outCount;
495
 
                outBufLen -= outCount;
496
 
            } else {
497
 
                /* halt output */
498
 
                goto no_room;
499
 
            }
500
 
        }
501
 
        break;
502
 
    case EVENT_TYPE_STRING:
503
 
        /* UTF-8 chars, not NULL-terminated */
504
 
        {
505
 
            unsigned int strLen;
506
 
 
507
 
            if (eventDataLen < 4)
508
 
                return -1;
509
 
            strLen = get4LE(eventData);
510
 
            eventData += 4;
511
 
            eventDataLen -= 4;
512
 
 
513
 
            if (eventDataLen < strLen)
514
 
                return -1;
515
 
 
516
 
            if (strLen < outBufLen) {
517
 
                memcpy(outBuf, eventData, strLen);
518
 
                outBuf += strLen;
519
 
                outBufLen -= strLen;
520
 
            } else if (outBufLen > 0) {
521
 
                /* copy what we can */
522
 
                memcpy(outBuf, eventData, outBufLen);
523
 
                outBuf += outBufLen;
524
 
                outBufLen -= outBufLen;
525
 
                goto no_room;
526
 
            }
527
 
            eventData += strLen;
528
 
            eventDataLen -= strLen;
529
 
            break;
530
 
        }
531
 
    case EVENT_TYPE_LIST:
532
 
        /* N items, all different types */
533
 
        {
534
 
            unsigned char count;
535
 
            int i;
536
 
 
537
 
            if (eventDataLen < 1)
538
 
                return -1;
539
 
 
540
 
            count = *eventData++;
541
 
            eventDataLen--;
542
 
 
543
 
            if (outBufLen > 0) {
544
 
                *outBuf++ = '[';
545
 
                outBufLen--;
546
 
            } else {
547
 
                goto no_room;
548
 
            }
549
 
 
550
 
            for (i = 0; i < count; i++) {
551
 
                result = android_log_printBinaryEvent(&eventData, &eventDataLen,
552
 
                        &outBuf, &outBufLen);
553
 
                if (result != 0)
554
 
                    goto bail;
555
 
 
556
 
                if (i < count-1) {
557
 
                    if (outBufLen > 0) {
558
 
                        *outBuf++ = ',';
559
 
                        outBufLen--;
560
 
                    } else {
561
 
                        goto no_room;
562
 
                    }
563
 
                }
564
 
            }
565
 
 
566
 
            if (outBufLen > 0) {
567
 
                *outBuf++ = ']';
568
 
                outBufLen--;
569
 
            } else {
570
 
                goto no_room;
571
 
            }
572
 
        }
573
 
        break;
574
 
    default:
575
 
        fprintf(stderr, "Unknown binary event type %d\n", type);
576
 
        return -1;
577
 
    }
578
 
 
579
 
bail:
580
 
    *pEventData = eventData;
581
 
    *pEventDataLen = eventDataLen;
582
 
    *pOutBuf = outBuf;
583
 
    *pOutBufLen = outBufLen;
584
 
    return result;
585
 
 
586
 
no_room:
587
 
    result = 1;
588
 
    goto bail;
589
 
}
590
 
 
591
 
/**
592
 
 * Convert a binary log entry to ASCII form.
593
 
 *
594
 
 * For convenience we mimic the processLogBuffer API.  There is no
595
 
 * pre-defined output length for the binary data, since we're free to format
596
 
 * it however we choose, which means we can't really use a fixed-size buffer
597
 
 * here.
598
 
 */
599
 
int android_log_processBinaryLogBuffer(struct logger_entry *buf,
600
 
    AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
601
 
    int messageBufLen)
602
 
{
603
 
    size_t inCount;
604
 
    unsigned int tagIndex;
605
 
    const unsigned char* eventData;
606
 
 
607
 
    entry->tv_sec = buf->sec;
608
 
    entry->tv_nsec = buf->nsec;
609
 
    entry->priority = ANDROID_LOG_INFO;
610
 
    entry->pid = buf->pid;
611
 
    entry->tid = buf->tid;
612
 
 
613
 
    /*
614
 
     * Pull the tag out.
615
 
     */
616
 
    eventData = (const unsigned char*) buf->msg;
617
 
    inCount = buf->len;
618
 
    if (inCount < 4)
619
 
        return -1;
620
 
    tagIndex = get4LE(eventData);
621
 
    eventData += 4;
622
 
    inCount -= 4;
623
 
 
624
 
    if (map != NULL) {
625
 
        entry->tag = android_lookupEventTag(map, tagIndex);
626
 
    } else {
627
 
        entry->tag = NULL;
628
 
    }
629
 
 
630
 
    /*
631
 
     * If we don't have a map, or didn't find the tag number in the map,
632
 
     * stuff a generated tag value into the start of the output buffer and
633
 
     * shift the buffer pointers down.
634
 
     */
635
 
    if (entry->tag == NULL) {
636
 
        int tagLen;
637
 
 
638
 
        tagLen = snprintf(messageBuf, messageBufLen, "[%d]", tagIndex);
639
 
        entry->tag = messageBuf;
640
 
        messageBuf += tagLen+1;
641
 
        messageBufLen -= tagLen+1;
642
 
    }
643
 
 
644
 
    /*
645
 
     * Format the event log data into the buffer.
646
 
     */
647
 
    char* outBuf = messageBuf;
648
 
    size_t outRemaining = messageBufLen-1;      /* leave one for nul byte */
649
 
    int result;
650
 
    result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
651
 
                &outRemaining);
652
 
    if (result < 0) {
653
 
        fprintf(stderr, "Binary log entry conversion failed\n");
654
 
        return -1;
655
 
    } else if (result == 1) {
656
 
        if (outBuf > messageBuf) {
657
 
            /* leave an indicator */
658
 
            *(outBuf-1) = '!';
659
 
        } else {
660
 
            /* no room to output anything at all */
661
 
            *outBuf++ = '!';
662
 
            outRemaining--;
663
 
        }
664
 
        /* pretend we ate all the data */
665
 
        inCount = 0;
666
 
    }
667
 
 
668
 
    /* eat the silly terminating '\n' */
669
 
    if (inCount == 1 && *eventData == '\n') {
670
 
        eventData++;
671
 
        inCount--;
672
 
    }
673
 
 
674
 
    if (inCount != 0) {
675
 
        fprintf(stderr,
676
 
            "Warning: leftover binary log data (%zu bytes)\n", inCount);
677
 
    }
678
 
 
679
 
    /*
680
 
     * Terminate the buffer.  The NUL byte does not count as part of
681
 
     * entry->messageLen.
682
 
     */
683
 
    *outBuf = '\0';
684
 
    entry->messageLen = outBuf - messageBuf;
685
 
    assert(entry->messageLen == (messageBufLen-1) - outRemaining);
686
 
 
687
 
    entry->message = messageBuf;
688
 
 
689
 
    return 0;
690
 
}
691
 
 
692
 
/**
693
 
 * Formats a log message into a buffer
694
 
 *
695
 
 * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
696
 
 * If return value != defaultBuffer, caller must call free()
697
 
 * Returns NULL on malloc error
698
 
 */
699
 
 
700
 
char *android_log_formatLogLine (
701
 
    AndroidLogFormat *p_format,
702
 
    char *defaultBuffer,
703
 
    size_t defaultBufferSize,
704
 
    const AndroidLogEntry *entry,
705
 
    size_t *p_outLength)
706
 
{
707
 
#if defined(HAVE_LOCALTIME_R)
708
 
    struct tm tmBuf;
709
 
#endif
710
 
    struct tm* ptm;
711
 
    char timeBuf[32];
712
 
    char headerBuf[128];
713
 
    char prefixBuf[128], suffixBuf[128];
714
 
    char priChar;
715
 
    int prefixSuffixIsHeaderFooter = 0;
716
 
    char * ret = NULL;
717
 
 
718
 
    priChar = filterPriToChar(entry->priority);
719
 
 
720
 
    /*
721
 
     * Get the current date/time in pretty form
722
 
     *
723
 
     * It's often useful when examining a log with "less" to jump to
724
 
     * a specific point in the file by searching for the date/time stamp.
725
 
     * For this reason it's very annoying to have regexp meta characters
726
 
     * in the time stamp.  Don't use forward slashes, parenthesis,
727
 
     * brackets, asterisks, or other special chars here.
728
 
     */
729
 
#if defined(HAVE_LOCALTIME_R)
730
 
    ptm = localtime_r(&(entry->tv_sec), &tmBuf);
731
 
#else
732
 
    ptm = localtime(&(entry->tv_sec));
733
 
#endif
734
 
    //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
735
 
    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
736
 
 
737
 
    /*
738
 
     * Construct a buffer containing the log header and log message.
739
 
     */
740
 
    size_t prefixLen, suffixLen;
741
 
 
742
 
    switch (p_format->format) {
743
 
        case FORMAT_TAG:
744
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
745
 
                "%c/%-8s: ", priChar, entry->tag);
746
 
            strcpy(suffixBuf, "\n"); suffixLen = 1;
747
 
            break;
748
 
        case FORMAT_PROCESS:
749
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
750
 
                "%c(%5d) ", priChar, entry->pid);
751
 
            suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
752
 
                "  (%s)\n", entry->tag);
753
 
            break;
754
 
        case FORMAT_THREAD:
755
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
756
 
                "%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
757
 
            strcpy(suffixBuf, "\n");
758
 
            suffixLen = 1;
759
 
            break;
760
 
        case FORMAT_RAW:
761
 
            prefixBuf[0] = 0;
762
 
            prefixLen = 0;
763
 
            strcpy(suffixBuf, "\n");
764
 
            suffixLen = 1;
765
 
            break;
766
 
        case FORMAT_TIME:
767
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
768
 
                "%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
769
 
                priChar, entry->tag, entry->pid);
770
 
            strcpy(suffixBuf, "\n");
771
 
            suffixLen = 1;
772
 
            break;
773
 
        case FORMAT_THREADTIME:
774
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
775
 
                "%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
776
 
                entry->pid, entry->tid, priChar, entry->tag);
777
 
            strcpy(suffixBuf, "\n");
778
 
            suffixLen = 1;
779
 
            break;
780
 
        case FORMAT_LONG:
781
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
782
 
                "[ %s.%03ld %5d:%5d %c/%-8s ]\n",
783
 
                timeBuf, entry->tv_nsec / 1000000, entry->pid,
784
 
                entry->tid, priChar, entry->tag);
785
 
            strcpy(suffixBuf, "\n\n");
786
 
            suffixLen = 2;
787
 
            prefixSuffixIsHeaderFooter = 1;
788
 
            break;
789
 
        case FORMAT_BRIEF:
790
 
        default:
791
 
            prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
792
 
                "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
793
 
            strcpy(suffixBuf, "\n");
794
 
            suffixLen = 1;
795
 
            break;
796
 
    }
797
 
    /* snprintf has a weird return value.   It returns what would have been
798
 
     * written given a large enough buffer.  In the case that the prefix is
799
 
     * longer then our buffer(128), it messes up the calculations below
800
 
     * possibly causing heap corruption.  To avoid this we double check and
801
 
     * set the length at the maximum (size minus null byte)
802
 
     */
803
 
    if(prefixLen >= sizeof(prefixBuf))
804
 
        prefixLen = sizeof(prefixBuf) - 1;
805
 
    if(suffixLen >= sizeof(suffixBuf))
806
 
        suffixLen = sizeof(suffixBuf) - 1;
807
 
 
808
 
    /* the following code is tragically unreadable */
809
 
 
810
 
    size_t numLines;
811
 
    size_t i;
812
 
    char *p;
813
 
    size_t bufferSize;
814
 
    const char *pm;
815
 
 
816
 
    if (prefixSuffixIsHeaderFooter) {
817
 
        // we're just wrapping message with a header/footer
818
 
        numLines = 1;
819
 
    } else {
820
 
        pm = entry->message;
821
 
        numLines = 0;
822
 
 
823
 
        // The line-end finding here must match the line-end finding
824
 
        // in for ( ... numLines...) loop below
825
 
        while (pm < (entry->message + entry->messageLen)) {
826
 
            if (*pm++ == '\n') numLines++;
827
 
        }
828
 
        // plus one line for anything not newline-terminated at the end
829
 
        if (pm > entry->message && *(pm-1) != '\n') numLines++;
830
 
    }
831
 
 
832
 
    // this is an upper bound--newlines in message may be counted
833
 
    // extraneously
834
 
    bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
835
 
 
836
 
    if (defaultBufferSize >= bufferSize) {
837
 
        ret = defaultBuffer;
838
 
    } else {
839
 
        ret = (char *)malloc(bufferSize);
840
 
 
841
 
        if (ret == NULL) {
842
 
            return ret;
843
 
        }
844
 
    }
845
 
 
846
 
    ret[0] = '\0';       /* to start strcat off */
847
 
 
848
 
    p = ret;
849
 
    pm = entry->message;
850
 
 
851
 
    if (prefixSuffixIsHeaderFooter) {
852
 
        strcat(p, prefixBuf);
853
 
        p += prefixLen;
854
 
        strncat(p, entry->message, entry->messageLen);
855
 
        p += entry->messageLen;
856
 
        strcat(p, suffixBuf);
857
 
        p += suffixLen;
858
 
    } else {
859
 
        while(pm < (entry->message + entry->messageLen)) {
860
 
            const char *lineStart;
861
 
            size_t lineLen;
862
 
            lineStart = pm;
863
 
 
864
 
            // Find the next end-of-line in message
865
 
            while (pm < (entry->message + entry->messageLen)
866
 
                    && *pm != '\n') pm++;
867
 
            lineLen = pm - lineStart;
868
 
 
869
 
            strcat(p, prefixBuf);
870
 
            p += prefixLen;
871
 
            strncat(p, lineStart, lineLen);
872
 
            p += lineLen;
873
 
            strcat(p, suffixBuf);
874
 
            p += suffixLen;
875
 
 
876
 
            if (*pm == '\n') pm++;
877
 
        }
878
 
    }
879
 
 
880
 
    if (p_outLength != NULL) {
881
 
        *p_outLength = p - ret;
882
 
    }
883
 
 
884
 
    return ret;
885
 
}
886
 
 
887
 
/**
888
 
 * Either print or do not print log line, based on filter
889
 
 *
890
 
 * Returns count bytes written
891
 
 */
892
 
 
893
 
int android_log_printLogLine(
894
 
    AndroidLogFormat *p_format,
895
 
    int fd,
896
 
    const AndroidLogEntry *entry)
897
 
{
898
 
    int ret;
899
 
    char defaultBuffer[512];
900
 
    char *outBuffer = NULL;
901
 
    size_t totalLen;
902
 
 
903
 
    outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
904
 
            sizeof(defaultBuffer), entry, &totalLen);
905
 
 
906
 
    if (!outBuffer)
907
 
        return -1;
908
 
 
909
 
    do {
910
 
        ret = write(fd, outBuffer, totalLen);
911
 
    } while (ret < 0 && errno == EINTR);
912
 
 
913
 
    if (ret < 0) {
914
 
        fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
915
 
        ret = 0;
916
 
        goto done;
917
 
    }
918
 
 
919
 
    if (((size_t)ret) < totalLen) {
920
 
        fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", ret,
921
 
                (int)totalLen);
922
 
        goto done;
923
 
    }
924
 
 
925
 
done:
926
 
    if (outBuffer != defaultBuffer) {
927
 
        free(outBuffer);
928
 
    }
929
 
 
930
 
    return ret;
931
 
}
932
 
 
933
 
 
934
 
 
935
 
void logprint_run_tests()
936
 
{
937
 
#if 0
938
 
 
939
 
    fprintf(stderr, "tests disabled\n");
940
 
 
941
 
#else
942
 
 
943
 
    int err;
944
 
    const char *tag;
945
 
    AndroidLogFormat *p_format;
946
 
 
947
 
    p_format = android_log_format_new();
948
 
 
949
 
    fprintf(stderr, "running tests\n");
950
 
 
951
 
    tag = "random";
952
 
 
953
 
    android_log_addFilterRule(p_format,"*:i");
954
 
 
955
 
    assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
956
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
957
 
    android_log_addFilterRule(p_format, "*");
958
 
    assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
959
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
960
 
    android_log_addFilterRule(p_format, "*:v");
961
 
    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
962
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
963
 
    android_log_addFilterRule(p_format, "*:i");
964
 
    assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
965
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
966
 
 
967
 
    android_log_addFilterRule(p_format, "random");
968
 
    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
969
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
970
 
    android_log_addFilterRule(p_format, "random:v");
971
 
    assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
972
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
973
 
    android_log_addFilterRule(p_format, "random:d");
974
 
    assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
975
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
976
 
    android_log_addFilterRule(p_format, "random:w");
977
 
    assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
978
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
979
 
 
980
 
    android_log_addFilterRule(p_format, "crap:*");
981
 
    assert (ANDROID_LOG_VERBOSE== filterPriForTag(p_format, "crap"));
982
 
    assert(android_log_shouldPrintLine(p_format, "crap", ANDROID_LOG_VERBOSE) > 0);
983
 
 
984
 
    // invalid expression
985
 
    err = android_log_addFilterRule(p_format, "random:z");
986
 
    assert (err < 0);
987
 
    assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
988
 
    assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
989
 
 
990
 
    // Issue #550946
991
 
    err = android_log_addFilterString(p_format, " ");
992
 
    assert(err == 0);
993
 
    assert(ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
994
 
 
995
 
    // note trailing space
996
 
    err = android_log_addFilterString(p_format, "*:s random:d ");
997
 
    assert(err == 0);
998
 
    assert(ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
999
 
 
1000
 
    err = android_log_addFilterString(p_format, "*:s random:z");
1001
 
    assert(err < 0);
1002
 
 
1003
 
 
1004
 
#if 0
1005
 
    char *ret;
1006
 
    char defaultBuffer[512];
1007
 
 
1008
 
    ret = android_log_formatLogLine(p_format,
1009
 
        defaultBuffer, sizeof(defaultBuffer), 0, ANDROID_LOG_ERROR, 123,
1010
 
        123, 123, "random", "nofile", strlen("Hello"), "Hello", NULL);
1011
 
#endif
1012
 
 
1013
 
 
1014
 
    fprintf(stderr, "tests complete\n");
1015
 
#endif
1016
 
}