aboutsummaryrefslogtreecommitdiffstats
path: root/liblog
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
commite54eebbf1a908d65ee8cf80bab62821c05666d70 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /liblog
parenta1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff)
downloadsystem_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz
system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2
system_core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'liblog')
-rw-r--r--liblog/Android.mk72
-rw-r--r--liblog/event_tag_map.c438
-rw-r--r--liblog/fake_log_device.c677
-rw-r--r--liblog/logd_write.c230
-rw-r--r--liblog/logprint.c972
5 files changed, 0 insertions, 2389 deletions
diff --git a/liblog/Android.mk b/liblog/Android.mk
deleted file mode 100644
index 0eec87f0..00000000
--- a/liblog/Android.mk
+++ /dev/null
@@ -1,72 +0,0 @@
-#
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-
-liblog_sources := logd_write.c
-
-# some files must not be compiled when building against Mingw
-# they correspond to features not used by our host development tools
-# which are also hard or even impossible to port to native Win32
-WITH_MINGW :=
-ifeq ($(HOST_OS),windows)
- ifeq ($(strip $(USE_CYGWIN)),)
- WITH_MINGW := true
- endif
-endif
-# USE_MINGW is defined when we build against Mingw on Linux
-ifneq ($(strip $(USE_MINGW)),)
- WITH_MINGW := true
-endif
-
-ifndef WITH_MINGW
- liblog_sources += \
- logprint.c \
- event_tag_map.c
-endif
-
-liblog_host_sources := $(liblog_sources) fake_log_device.c
-
-# Static library for host
-# ========================================================
-LOCAL_MODULE := liblog
-LOCAL_SRC_FILES := $(liblog_host_sources)
-LOCAL_LDLIBS := -lpthread
-LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-ifeq ($(TARGET_SIMULATOR),true)
- # Shared library for simulator
- # ========================================================
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_SRC_FILES := $(liblog_host_sources)
- LOCAL_LDLIBS := -lpthread
- LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1
- include $(BUILD_SHARED_LIBRARY)
-else # !sim
- # Shared and static library for target
- # ========================================================
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_SRC_FILES := $(liblog_sources)
- include $(BUILD_STATIC_LIBRARY)
-
- include $(CLEAR_VARS)
- LOCAL_MODULE := liblog
- LOCAL_WHOLE_STATIC_LIBRARIES := liblog
- include $(BUILD_SHARED_LIBRARY)
-endif # !sim
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
deleted file mode 100644
index e70754e1..00000000
--- a/liblog/event_tag_map.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "cutils/event_tag_map.h"
-#include "cutils/log.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <assert.h>
-
-#define OUT_TAG "EventTagMap"
-
-/*
- * Single entry.
- */
-typedef struct EventTag {
- unsigned int tagIndex;
- const char* tagStr;
-} EventTag;
-
-/*
- * Map.
- */
-struct EventTagMap {
- /* memory-mapped source file; we get strings from here */
- void* mapAddr;
- size_t mapLen;
-
- /* array of event tags, sorted numerically by tag index */
- EventTag* tagArray;
- int numTags;
-};
-
-/* fwd */
-static int processFile(EventTagMap* map);
-static int countMapLines(const EventTagMap* map);
-static int parseMapLines(EventTagMap* map);
-static int scanTagLine(char** pData, EventTag* tag, int lineNum);
-static int sortTags(EventTagMap* map);
-static void dumpTags(const EventTagMap* map);
-
-
-/*
- * Open the map file and allocate a structure to manage it.
- *
- * We create a private mapping because we want to terminate the log tag
- * strings with '\0'.
- */
-EventTagMap* android_openEventTagMap(const char* fileName)
-{
- EventTagMap* newTagMap;
- off_t end;
- int fd = -1;
-
- newTagMap = calloc(1, sizeof(EventTagMap));
- if (newTagMap == NULL)
- return NULL;
-
- fd = open(fileName, O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "%s: unable to open map '%s': %s\n",
- OUT_TAG, fileName, strerror(errno));
- goto fail;
- }
-
- end = lseek(fd, 0L, SEEK_END);
- (void) lseek(fd, 0L, SEEK_SET);
- if (end < 0) {
- fprintf(stderr, "%s: unable to seek map '%s'\n", OUT_TAG, fileName);
- goto fail;
- }
-
- newTagMap->mapAddr = mmap(NULL, end, PROT_READ | PROT_WRITE, MAP_PRIVATE,
- fd, 0);
- if (newTagMap->mapAddr == MAP_FAILED) {
- fprintf(stderr, "%s: mmap(%s) failed: %s\n",
- OUT_TAG, fileName, strerror(errno));
- goto fail;
- }
- newTagMap->mapLen = end;
-
- if (processFile(newTagMap) != 0)
- goto fail;
-
- return newTagMap;
-
-fail:
- android_closeEventTagMap(newTagMap);
- if (fd >= 0)
- close(fd);
- return NULL;
-}
-
-/*
- * Close the map.
- */
-void android_closeEventTagMap(EventTagMap* map)
-{
- if (map == NULL)
- return;
-
- munmap(map->mapAddr, map->mapLen);
- free(map);
-}
-
-/*
- * Look up an entry in the map.
- *
- * The entries are sorted by tag number, so we can do a binary search.
- */
-const char* android_lookupEventTag(const EventTagMap* map, int tag)
-{
- int hi, lo, mid;
-
- lo = 0;
- hi = map->numTags-1;
-
- while (lo <= hi) {
- int cmp;
-
- mid = (lo+hi)/2;
- cmp = map->tagArray[mid].tagIndex - tag;
- if (cmp < 0) {
- /* tag is bigger */
- lo = mid + 1;
- } else if (cmp > 0) {
- /* tag is smaller */
- hi = mid - 1;
- } else {
- /* found */
- return map->tagArray[mid].tagStr;
- }
- }
-
- return NULL;
-}
-
-
-
-/*
- * Determine whether "c" is a whitespace char.
- */
-static inline int isCharWhitespace(char c)
-{
- return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
-}
-
-/*
- * Determine whether "c" is a valid tag char.
- */
-static inline int isCharValidTag(char c)
-{
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- (c == '_'));
-}
-
-/*
- * Determine whether "c" is a valid decimal digit.
- */
-static inline int isCharDigit(char c)
-{
- return (c >= '0' && c <= '9');
-}
-
-
-/*
- * Crunch through the file, parsing the contents and creating a tag index.
- */
-static int processFile(EventTagMap* map)
-{
- EventTag* tagArray = NULL;
-
- /* get a tag count */
- map->numTags = countMapLines(map);
- if (map->numTags < 0)
- return -1;
-
- //printf("+++ found %d tags\n", map->numTags);
-
- /* allocate storage for the tag index array */
- map->tagArray = calloc(1, sizeof(EventTag) * map->numTags);
- if (map->tagArray == NULL)
- return -1;
-
- /* parse the file, null-terminating tag strings */
- if (parseMapLines(map) != 0) {
- fprintf(stderr, "%s: file parse failed\n", OUT_TAG);
- return -1;
- }
-
- /* sort the tags and check for duplicates */
- if (sortTags(map) != 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Run through all lines in the file, determining whether they're blank,
- * comments, or possibly have a tag entry.
- *
- * This is a very "loose" scan. We don't try to detect syntax errors here.
- * The later pass is more careful, but the number of tags found there must
- * match the number of tags found here.
- *
- * Returns the number of potential tag entries found.
- */
-static int countMapLines(const EventTagMap* map)
-{
- int numTags, unknown;
- const char* cp;
- const char* endp;
-
- cp = (const char*) map->mapAddr;
- endp = cp + map->mapLen;
-
- numTags = 0;
- unknown = 1;
- while (cp < endp) {
- if (*cp == '\n') {
- unknown = 1;
- } else if (unknown) {
- if (isCharDigit(*cp)) {
- /* looks like a tag to me */
- numTags++;
- unknown = 0;
- } else if (isCharWhitespace(*cp)) {
- /* might be leading whitespace before tag num, keep going */
- } else {
- /* assume comment; second pass can complain in detail */
- unknown = 0;
- }
- } else {
- /* we've made up our mind; just scan to end of line */
- }
- cp++;
- }
-
- return numTags;
-}
-
-/*
- * Parse the tags out of the file.
- */
-static int parseMapLines(EventTagMap* map)
-{
- int tagNum, lineStart, lineNum;
- char* cp;
- char* endp;
-
- cp = (char*) map->mapAddr;
- endp = cp + map->mapLen;
-
- /* insist on EOL at EOF; simplifies parsing and null-termination */
- if (*(endp-1) != '\n') {
- fprintf(stderr, "%s: map file missing EOL on last line\n", OUT_TAG);
- return -1;
- }
-
- tagNum = 0;
- lineStart = 1;
- lineNum = 1;
- while (cp < endp) {
- //printf("{%02x}", *cp); fflush(stdout);
- if (*cp == '\n') {
- lineStart = 1;
- lineNum++;
- } else if (lineStart) {
- if (*cp == '#') {
- /* comment; just scan to end */
- lineStart = 0;
- } else if (isCharDigit(*cp)) {
- /* looks like a tag; scan it out */
- if (tagNum >= map->numTags) {
- fprintf(stderr,
- "%s: more tags than expected (%d)\n", OUT_TAG, tagNum);
- return -1;
- }
- if (scanTagLine(&cp, &map->tagArray[tagNum], lineNum) != 0)
- return -1;
- tagNum++;
- lineNum++; // we eat the '\n'
- /* leave lineStart==1 */
- } else if (isCharWhitespace(*cp)) {
- /* looks like leading whitespace; keep scanning */
- } else {
- fprintf(stderr,
- "%s: unexpected chars (0x%02x) in tag number on line %d\n",
- OUT_TAG, *cp, lineNum);
- return -1;
- }
- } else {
- /* this is a blank or comment line */
- }
- cp++;
- }
-
- if (tagNum != map->numTags) {
- fprintf(stderr, "%s: parsed %d tags, expected %d\n",
- OUT_TAG, tagNum, map->numTags);
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Scan one tag line.
- *
- * "*pData" should be pointing to the first digit in the tag number. On
- * successful return, it will be pointing to the last character in the
- * tag line (i.e. the character before the start of the next line).
- *
- * Returns 0 on success, nonzero on failure.
- */
-static int scanTagLine(char** pData, EventTag* tag, int lineNum)
-{
- char* cp = *pData;
- char* startp;
- char* endp;
- unsigned long val;
-
- startp = cp;
- while (isCharDigit(*++cp))
- ;
- *cp = '\0';
-
- val = strtoul(startp, &endp, 10);
- assert(endp == cp);
- if (endp != cp)
- fprintf(stderr, "ARRRRGH\n");
-
- tag->tagIndex = val;
-
- while (*++cp != '\n' && isCharWhitespace(*cp))
- ;
-
- if (*cp == '\n') {
- fprintf(stderr,
- "%s: missing tag string on line %d\n", OUT_TAG, lineNum);
- return -1;
- }
-
- tag->tagStr = cp;
-
- while (isCharValidTag(*++cp))
- ;
-
- if (*cp == '\n') {
- /* null terminate and return */
- *cp = '\0';
- } else if (isCharWhitespace(*cp)) {
- /* CRLF or trailin spaces; zap this char, then scan for the '\n' */
- *cp = '\0';
-
- /* just ignore the rest of the line till \n
- TODO: read the tag description that follows the tag name
- */
- while (*++cp != '\n') {
- }
- } else {
- fprintf(stderr,
- "%s: invalid tag chars on line %d\n", OUT_TAG, lineNum);
- return -1;
- }
-
- *pData = cp;
-
- //printf("+++ Line %d: got %d '%s'\n", lineNum, tag->tagIndex, tag->tagStr);
- return 0;
-}
-
-/*
- * Compare two EventTags.
- */
-static int compareEventTags(const void* v1, const void* v2)
-{
- const EventTag* tag1 = (const EventTag*) v1;
- const EventTag* tag2 = (const EventTag*) v2;
-
- return tag1->tagIndex - tag2->tagIndex;
-}
-
-/*
- * Sort the EventTag array so we can do fast lookups by tag index. After
- * the sort we do a quick check for duplicate tag indices.
- *
- * Returns 0 on success.
- */
-static int sortTags(EventTagMap* map)
-{
- int i;
-
- qsort(map->tagArray, map->numTags, sizeof(EventTag), compareEventTags);
-
- for (i = 1; i < map->numTags; i++) {
- if (map->tagArray[i].tagIndex == map->tagArray[i-1].tagIndex) {
- fprintf(stderr, "%s: duplicate tag entries (%d:%s and %d:%s)\n",
- OUT_TAG,
- map->tagArray[i].tagIndex, map->tagArray[i].tagStr,
- map->tagArray[i-1].tagIndex, map->tagArray[i-1].tagStr);
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- * Dump the tag array for debugging.
- */
-static void dumpTags(const EventTagMap* map)
-{
- int i;
-
- for (i = 0; i < map->numTags; i++) {
- const EventTag* tag = &map->tagArray[i];
- printf(" %3d: %6d '%s'\n", i, tag->tagIndex, tag->tagStr);
- }
-}
-
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
deleted file mode 100644
index d9d67b47..00000000
--- a/liblog/fake_log_device.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Intercepts log messages intended for the Android log device.
- * When running in the context of the simulator, the messages are
- * passed on to the underlying (fake) log device. When not in the
- * simulator, messages are printed to stderr.
- */
-#include "cutils/logd.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-
-#define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
-
-#define kTagSetSize 16 /* arbitrary */
-
-#if 0
-#define TRACE(...) printf("fake_log_device: " __VA_ARGS__)
-#else
-#define TRACE(...) ((void)0)
-#endif
-
-/* from the long-dead utils/Log.cpp */
-typedef enum {
- FORMAT_OFF = 0,
- FORMAT_BRIEF,
- FORMAT_PROCESS,
- FORMAT_TAG,
- FORMAT_THREAD,
- FORMAT_RAW,
- FORMAT_TIME,
- FORMAT_THREADTIME,
- FORMAT_LONG
-} LogFormat;
-
-
-/*
- * Log driver state.
- */
-typedef struct LogState {
- /* the fake fd that's seen by the user */
- int fakeFd;
-
- /* a printable name for this fake device */
- char *debugName;
-
- /* nonzero if this is a binary log */
- int isBinary;
-
- /* global minimum priority */
- int globalMinPriority;
-
- /* output format */
- LogFormat outputFormat;
-
- /* tags and priorities */
- struct {
- char tag[kMaxTagLen];
- int minPriority;
- } tagSet[kTagSetSize];
-} LogState;
-
-
-#ifdef HAVE_PTHREADS
-/*
- * Locking. Since we're emulating a device, we need to be prepared
- * to have multiple callers at the same time. This lock is used
- * to both protect the fd list and to prevent LogStates from being
- * freed out from under a user.
- */
-static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
-
-static void lock()
-{
- pthread_mutex_lock(&fakeLogDeviceLock);
-}
-
-static void unlock()
-{
- pthread_mutex_unlock(&fakeLogDeviceLock);
-}
-#else // !HAVE_PTHREADS
-#define lock() ((void)0)
-#define unlock() ((void)0)
-#endif // !HAVE_PTHREADS
-
-
-/*
- * File descriptor management.
- */
-#define FAKE_FD_BASE 10000
-#define MAX_OPEN_LOGS 16
-static LogState *openLogTable[MAX_OPEN_LOGS];
-
-/*
- * Allocate an fd and associate a new LogState with it.
- * The fd is available via the fakeFd field of the return value.
- */
-static LogState *createLogState()
-{
- size_t i;
-
- for (i = 0; i < sizeof(openLogTable); i++) {
- if (openLogTable[i] == NULL) {
- openLogTable[i] = calloc(1, sizeof(LogState));
- openLogTable[i]->fakeFd = FAKE_FD_BASE + i;
- return openLogTable[i];
- }
- }
- return NULL;
-}
-
-/*
- * Translate an fd to a LogState.
- */
-static LogState *fdToLogState(int fd)
-{
- if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) {
- return openLogTable[fd - FAKE_FD_BASE];
- }
- return NULL;
-}
-
-/*
- * Unregister the fake fd and free the memory it pointed to.
- */
-static void deleteFakeFd(int fd)
-{
- LogState *ls;
-
- lock();
-
- ls = fdToLogState(fd);
- if (ls != NULL) {
- openLogTable[fd - FAKE_FD_BASE] = NULL;
- free(ls->debugName);
- free(ls);
- }
-
- unlock();
-}
-
-/*
- * Configure logging based on ANDROID_LOG_TAGS environment variable. We
- * need to parse a string that looks like
- *
- * *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
- *
- * The tag (or '*' for the global level) comes first, followed by a colon
- * and a letter indicating the minimum priority level we're expected to log.
- * This can be used to reveal or conceal logs with specific tags.
- *
- * We also want to check ANDROID_PRINTF_LOG to determine how the output
- * will look.
- */
-static void configureInitialState(const char* pathName, LogState* logState)
-{
- static const int kDevLogLen = sizeof("/dev/log/") - 1;
-
- logState->debugName = strdup(pathName);
-
- /* identify binary logs */
- if (strcmp(pathName + kDevLogLen, "events") == 0) {
- logState->isBinary = 1;
- }
-
- /* global min priority defaults to "info" level */
- logState->globalMinPriority = ANDROID_LOG_INFO;
-
- /*
- * This is based on the the long-dead utils/Log.cpp code.
- */
- const char* tags = getenv("ANDROID_LOG_TAGS");
- TRACE("Found ANDROID_LOG_TAGS='%s'\n", tags);
- if (tags != NULL) {
- int entry = 0;
-
- while (*tags != '\0') {
- char tagName[kMaxTagLen];
- int i, minPrio;
-
- while (isspace(*tags))
- tags++;
-
- i = 0;
- while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&
- i < kMaxTagLen)
- {
- tagName[i++] = *tags++;
- }
- if (i == kMaxTagLen) {
- TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen-1);
- return;
- }
- tagName[i] = '\0';
-
- /* default priority, if there's no ":" part; also zero out '*' */
- minPrio = ANDROID_LOG_VERBOSE;
- if (tagName[0] == '*' && tagName[1] == '\0') {
- minPrio = ANDROID_LOG_DEBUG;
- tagName[0] = '\0';
- }
-
- if (*tags == ':') {
- tags++;
- if (*tags >= '0' && *tags <= '9') {
- if (*tags >= ('0' + ANDROID_LOG_SILENT))
- minPrio = ANDROID_LOG_VERBOSE;
- else
- minPrio = *tags - '\0';
- } else {
- switch (*tags) {
- case 'v': minPrio = ANDROID_LOG_VERBOSE; break;
- case 'd': minPrio = ANDROID_LOG_DEBUG; break;
- case 'i': minPrio = ANDROID_LOG_INFO; break;
- case 'w': minPrio = ANDROID_LOG_WARN; break;
- case 'e': minPrio = ANDROID_LOG_ERROR; break;
- case 'f': minPrio = ANDROID_LOG_FATAL; break;
- case 's': minPrio = ANDROID_LOG_SILENT; break;
- default: minPrio = ANDROID_LOG_DEFAULT; break;
- }
- }
-
- tags++;
- if (*tags != '\0' && !isspace(*tags)) {
- TRACE("ERROR: garbage in tag env; expected whitespace\n");
- TRACE(" env='%s'\n", tags);
- return;
- }
- }
-
- if (tagName[0] == 0) {
- logState->globalMinPriority = minPrio;
- TRACE("+++ global min prio %d\n", logState->globalMinPriority);
- } else {
- logState->tagSet[entry].minPriority = minPrio;
- strcpy(logState->tagSet[entry].tag, tagName);
- TRACE("+++ entry %d: %s:%d\n",
- entry,
- logState->tagSet[entry].tag,
- logState->tagSet[entry].minPriority);
- entry++;
- }
- }
- }
-
-
- /*
- * Taken from the long-dead utils/Log.cpp
- */
- const char* fstr = getenv("ANDROID_PRINTF_LOG");
- LogFormat format;
- if (fstr == NULL) {
- format = FORMAT_BRIEF;
- } else {
- if (strcmp(fstr, "brief") == 0)
- format = FORMAT_BRIEF;
- else if (strcmp(fstr, "process") == 0)
- format = FORMAT_PROCESS;
- else if (strcmp(fstr, "tag") == 0)
- format = FORMAT_PROCESS;
- else if (strcmp(fstr, "thread") == 0)
- format = FORMAT_PROCESS;
- else if (strcmp(fstr, "raw") == 0)
- format = FORMAT_PROCESS;
- else if (strcmp(fstr, "time") == 0)
- format = FORMAT_PROCESS;
- else if (strcmp(fstr, "long") == 0)
- format = FORMAT_PROCESS;
- else
- format = (LogFormat) atoi(fstr); // really?!
- }
-
- logState->outputFormat = format;
-}
-
-/*
- * Return a human-readable string for the priority level. Always returns
- * a valid string.
- */
-static const char* getPriorityString(int priority)
-{
- /* the first character of each string should be unique */
- static const char* priorityStrings[] = {
- "Verbose", "Debug", "Info", "Warn", "Error", "Assert"
- };
- int idx;
-
- idx = (int) priority - (int) ANDROID_LOG_VERBOSE;
- if (idx < 0 ||
- idx >= (int) (sizeof(priorityStrings) / sizeof(priorityStrings[0])))
- return "?unknown?";
- return priorityStrings[idx];
-}
-
-#ifndef HAVE_WRITEV
-/*
- * Some platforms like WIN32 do not have writev().
- * Make up something to replace it.
- */
-static ssize_t fake_writev(int fd, const struct iovec *iov, int iovcnt) {
- int result = 0;
- struct iovec* end = iov + iovcnt;
- for (; iov < end; iov++) {
- int w = write(fd, iov->iov_base, iov->iov_len);
- if (w != iov->iov_len) {
- if (w < 0)
- return w;
- return result + w;
- }
- result += w;
- }
- return result;
-}
-
-#define writev fake_writev
-#endif
-
-
-/*
- * Write a filtered log message to stderr.
- *
- * Log format parsing taken from the long-dead utils/Log.cpp.
- */
-static void showLog(LogState *state,
- int logPrio, const char* tag, const char* msg)
-{
-#if defined(HAVE_LOCALTIME_R)
- struct tm tmBuf;
-#endif
- struct tm* ptm;
- char timeBuf[32];
- char prefixBuf[128], suffixBuf[128];
- char priChar;
- time_t when;
- pid_t pid, tid;
-
- TRACE("LOG %d: %s %s", logPrio, tag, msg);
-
- priChar = getPriorityString(logPrio)[0];
- when = time(NULL);
- pid = tid = getpid(); // find gettid()?
-
- /*
- * Get the current date/time in pretty form
- *
- * It's often useful when examining a log with "less" to jump to
- * a specific point in the file by searching for the date/time stamp.
- * For this reason it's very annoying to have regexp meta characters
- * in the time stamp. Don't use forward slashes, parenthesis,
- * brackets, asterisks, or other special chars here.
- */
-#if defined(HAVE_LOCALTIME_R)
- ptm = localtime_r(&when, &tmBuf);
-#else
- ptm = localtime(&when);
-#endif
- //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
- strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
-
- /*
- * Construct a buffer containing the log header and log message.
- */
- size_t prefixLen, suffixLen;
-
- switch (state->outputFormat) {
- case FORMAT_TAG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s: ", priChar, tag);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_PROCESS:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c(%5d) ", priChar, pid);
- suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
- " (%s)\n", tag);
- break;
- case FORMAT_THREAD:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c(%5d:%p) ", priChar, pid, (void*)tid);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_RAW:
- prefixBuf[0] = 0; prefixLen = 0;
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_TIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%s %-8s\n\t", timeBuf, tag);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_THREADTIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%s %5d %5d %c %-8s \n\t", timeBuf, pid, tid, priChar, tag);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_LONG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "[ %s %5d:%p %c/%-8s ]\n",
- timeBuf, pid, (void*)tid, priChar, tag);
- strcpy(suffixBuf, "\n\n"); suffixLen = 2;
- break;
- default:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s(%5d): ", priChar, tag, pid);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- }
-
- /*
- * Figure out how many lines there will be.
- */
- const char* end = msg + strlen(msg);
- size_t numLines = 0;
- const char* p = msg;
- while (p < end) {
- if (*p++ == '\n') numLines++;
- }
- if (p > msg && *(p-1) != '\n') numLines++;
-
- /*
- * Create an array of iovecs large enough to write all of
- * the lines with a prefix and a suffix.
- */
- const size_t INLINE_VECS = 6;
- struct iovec stackVec[INLINE_VECS];
- struct iovec* vec = stackVec;
-
- numLines *= 3; // 3 iovecs per line.
- if (numLines > INLINE_VECS) {
- vec = (struct iovec*)malloc(sizeof(struct iovec)*numLines);
- if (vec == NULL) {
- msg = "LOG: write failed, no memory";
- numLines = 3;
- }
- }
-
- /*
- * Fill in the iovec pointers.
- */
- p = msg;
- struct iovec* v = vec;
- int totalLen = 0;
- while (p < end) {
- if (prefixLen > 0) {
- v->iov_base = prefixBuf;
- v->iov_len = prefixLen;
- totalLen += prefixLen;
- v++;
- }
- const char* start = p;
- while (p < end && *p != '\n') p++;
- if ((p-start) > 0) {
- v->iov_base = (void*)start;
- v->iov_len = p-start;
- totalLen += p-start;
- v++;
- }
- if (*p == '\n') p++;
- if (suffixLen > 0) {
- v->iov_base = suffixBuf;
- v->iov_len = suffixLen;
- totalLen += suffixLen;
- v++;
- }
- }
-
- /*
- * Write the entire message to the log file with a single writev() call.
- * We need to use this rather than a collection of printf()s on a FILE*
- * because of multi-threading and multi-process issues.
- *
- * If the file was not opened with O_APPEND, this will produce interleaved
- * output when called on the same file from multiple processes.
- *
- * If the file descriptor is actually a network socket, the writev()
- * call may return with a partial write. Putting the writev() call in
- * a loop can result in interleaved data. This can be alleviated
- * somewhat by wrapping the writev call in the Mutex.
- */
-
- for(;;) {
- int cc = writev(fileno(stderr), vec, v-vec);
-
- if (cc == totalLen) break;
-
- if (cc < 0) {
- if(errno == EINTR) continue;
-
- /* can't really log the failure; for now, throw out a stderr */
- fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
- break;
- } else {
- /* shouldn't happen when writing to file or tty */
- fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", cc, totalLen);
- break;
- }
- }
-
- /* if we allocated storage for the iovecs, free it */
- if (vec != stackVec)
- free(vec);
-}
-
-
-/*
- * Receive a log message. We happen to know that "vector" has three parts:
- *
- * priority (1 byte)
- * tag (N bytes -- null-terminated ASCII string)
- * message (N bytes -- null-terminated ASCII string)
- */
-static ssize_t logWritev(int fd, const struct iovec* vector, int count)
-{
- LogState* state;
-
- /* Make sure that no-one frees the LogState while we're using it.
- * Also guarantees that only one thread is in showLog() at a given
- * time (if it matters).
- */
- lock();
-
- state = fdToLogState(fd);
- if (state == NULL) {
- errno = EBADF;
- goto error;
- }
-
- if (state->isBinary) {
- TRACE("%s: ignoring binary log\n", state->debugName);
- goto bail;
- }
-
- if (count != 3) {
- TRACE("%s: writevLog with count=%d not expected\n",
- state->debugName, count);
- goto error;
- }
-
- /* pull out the three fields */
- int logPrio = *(const char*)vector[0].iov_base;
- const char* tag = (const char*) vector[1].iov_base;
- const char* msg = (const char*) vector[2].iov_base;
-
- /* see if this log tag is configured */
- int i;
- int minPrio = state->globalMinPriority;
- for (i = 0; i < kTagSetSize; i++) {
- if (state->tagSet[i].minPriority == ANDROID_LOG_UNKNOWN)
- break; /* reached end of configured values */
-
- if (strcmp(state->tagSet[i].tag, tag) == 0) {
- //TRACE("MATCH tag '%s'\n", tag);
- minPrio = state->tagSet[i].minPriority;
- break;
- }
- }
-
- if (logPrio >= minPrio) {
- showLog(state, logPrio, tag, msg);
- } else {
- //TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg);
- }
-
-bail:
- unlock();
- return vector[0].iov_len + vector[1].iov_len + vector[2].iov_len;
-error:
- unlock();
- return -1;
-}
-
-/*
- * Free up our state and close the fake descriptor.
- */
-static int logClose(int fd)
-{
- deleteFakeFd(fd);
- return 0;
-}
-
-/*
- * Open a log output device and return a fake fd.
- */
-static int logOpen(const char* pathName, int flags)
-{
- LogState *logState;
- int fd = -1;
-
- lock();
-
- logState = createLogState();
- if (logState != NULL) {
- configureInitialState(pathName, logState);
- fd = logState->fakeFd;
- } else {
- errno = ENFILE;
- }
-
- unlock();
-
- return fd;
-}
-
-
-/*
- * Runtime redirection. If this binary is running in the simulator,
- * just pass log messages to the emulated device. If it's running
- * outside of the simulator, write the log messages to stderr.
- */
-
-static int (*redirectOpen)(const char *pathName, int flags) = NULL;
-static int (*redirectClose)(int fd) = NULL;
-static ssize_t (*redirectWritev)(int fd, const struct iovec* vector, int count)
- = NULL;
-
-static void setRedirects()
-{
- const char *ws;
-
- /* Wrapsim sets this environment variable on children that it's
- * created using its LD_PRELOAD wrapper.
- */
- ws = getenv("ANDROID_WRAPSIM");
- if (ws != NULL && strcmp(ws, "1") == 0) {
- /* We're running inside wrapsim, so we can just write to the device. */
- redirectOpen = (int (*)(const char *pathName, int flags))open;
- redirectClose = close;
- redirectWritev = writev;
- } else {
- /* There's no device to delegate to; handle the logging ourselves. */
- redirectOpen = logOpen;
- redirectClose = logClose;
- redirectWritev = logWritev;
- }
-}
-
-int fakeLogOpen(const char *pathName, int flags)
-{
- if (redirectOpen == NULL) {
- setRedirects();
- }
- return redirectOpen(pathName, flags);
-}
-
-int fakeLogClose(int fd)
-{
- /* Assume that open() was called first. */
- return redirectClose(fd);
-}
-
-ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count)
-{
- /* Assume that open() was called first. */
- return redirectWritev(fd, vector, count);
-}
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
deleted file mode 100644
index 80867d1d..00000000
--- a/liblog/logd_write.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <time.h>
-#include <stdio.h>
-#ifdef HAVE_PTHREADS
-#include <pthread.h>
-#endif
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include <cutils/logger.h>
-#include <cutils/logd.h>
-
-#define LOG_BUF_SIZE 1024
-
-#if FAKE_LOG_DEVICE
-// This will be defined when building for the host.
-#define log_open(pathname, flags) fakeLogOpen(pathname, flags)
-#define log_writev(filedes, vector, count) fakeLogWritev(filedes, vector, count)
-#define log_close(filedes) fakeLogClose(filedes)
-#else
-#define log_open(pathname, flags) open(pathname, flags)
-#define log_writev(filedes, vector, count) writev(filedes, vector, count)
-#define log_close(filedes) close(filedes)
-#endif
-
-typedef enum {
- LOG_ID_MAIN = 0,
- LOG_ID_RADIO,
- LOG_ID_EVENTS,
- LOG_ID_MAX
-} log_id_t;
-
-static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
-static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) =
- __write_to_log_init;
-#ifdef HAVE_PTHREADS
-static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1 };
-
-/*
- * This is used by the C++ code to decide if it should write logs through
- * the C code. Basically, if /dev/log/... is available, we're running in
- * the simulator rather than a desktop tool and want to use the device.
- */
-static enum {
- kLogUninitialized, kLogNotAvailable, kLogAvailable
-} g_log_status = kLogUninitialized;
-int __android_log_dev_available(void)
-{
- if (g_log_status == kLogUninitialized) {
- if (access("/dev/"LOGGER_LOG_MAIN, W_OK) == 0)
- g_log_status = kLogAvailable;
- else
- g_log_status = kLogNotAvailable;
- }
-
- return (g_log_status == kLogAvailable);
-}
-
-static int __write_to_log_null(log_id_t log_fd, struct iovec *vec, size_t nr)
-{
- return -1;
-}
-
-static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
-{
- ssize_t ret;
- int log_fd;
-
- if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
- log_fd = log_fds[(int)log_id];
- } else {
- return EBADF;
- }
-
- do {
- ret = log_writev(log_fd, vec, nr);
- } while (ret < 0 && errno == EINTR);
-
- return ret;
-}
-
-static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
-{
-#ifdef HAVE_PTHREADS
- pthread_mutex_lock(&log_init_lock);
-#endif
-
- if (write_to_log == __write_to_log_init) {
- log_fds[LOG_ID_MAIN] = log_open("/dev/"LOGGER_LOG_MAIN, O_WRONLY);
- log_fds[LOG_ID_RADIO] = log_open("/dev/"LOGGER_LOG_RADIO, O_WRONLY);
- log_fds[LOG_ID_EVENTS] = log_open("/dev/"LOGGER_LOG_EVENTS, O_WRONLY);
-
- write_to_log = __write_to_log_kernel;
-
- if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0 ||
- log_fds[LOG_ID_EVENTS] < 0) {
- log_close(log_fds[LOG_ID_MAIN]);
- log_close(log_fds[LOG_ID_RADIO]);
- log_close(log_fds[LOG_ID_EVENTS]);
- log_fds[LOG_ID_MAIN] = -1;
- log_fds[LOG_ID_RADIO] = -1;
- log_fds[LOG_ID_EVENTS] = -1;
- write_to_log = __write_to_log_null;
- }
- }
-
-#ifdef HAVE_PTHREADS
- pthread_mutex_unlock(&log_init_lock);
-#endif
-
- return write_to_log(log_id, vec, nr);
-}
-
-int __android_log_write(int prio, const char *tag, const char *msg)
-{
- struct iovec vec[3];
- log_id_t log_id = LOG_ID_MAIN;
-
- if (!tag)
- tag = "";
-
- /* XXX: This needs to go! */
- if (!strcmp(tag, "HTC_RIL") ||
- !strcmp(tag, "RILJ") ||
- !strcmp(tag, "RILC") ||
- !strcmp(tag, "RILD") ||
- !strcmp(tag, "RIL") ||
- !strcmp(tag, "AT") ||
- !strcmp(tag, "GSM") ||
- !strcmp(tag, "STK"))
- log_id = LOG_ID_RADIO;
-
- vec[0].iov_base = (unsigned char *) &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = (void *) tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = (void *) msg;
- vec[2].iov_len = strlen(msg) + 1;
-
- return write_to_log(log_id, vec, 3);
-}
-
-int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
-{
- char buf[LOG_BUF_SIZE];
-
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
-
- return __android_log_write(prio, tag, buf);
-}
-
-int __android_log_print(int prio, const char *tag, const char *fmt, ...)
-{
- va_list ap;
- char buf[LOG_BUF_SIZE];
-
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
-
- return __android_log_write(prio, tag, buf);
-}
-
-void __android_log_assert(const char *cond, const char *tag,
- const char *fmt, ...)
-{
- va_list ap;
- char buf[LOG_BUF_SIZE];
-
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
- va_end(ap);
-
- __android_log_write(ANDROID_LOG_FATAL, tag, buf);
-
- __builtin_trap(); /* trap so we have a chance to debug the situation */
-}
-
-int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
-{
- struct iovec vec[2];
-
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = (void*)payload;
- vec[1].iov_len = len;
-
- return write_to_log(LOG_ID_EVENTS, vec, 2);
-}
-
-/*
- * Like __android_log_bwrite, but takes the type as well. Doesn't work
- * for the general case where we're generating lists of stuff, but very
- * handy if we just want to dump an integer into the log.
- */
-int __android_log_btwrite(int32_t tag, char type, const void *payload,
- size_t len)
-{
- struct iovec vec[3];
-
- vec[0].iov_base = &tag;
- vec[0].iov_len = sizeof(tag);
- vec[1].iov_base = &type;
- vec[1].iov_len = sizeof(type);
- vec[2].iov_base = (void*)payload;
- vec[2].iov_len = len;
-
- return write_to_log(LOG_ID_EVENTS, vec, 3);
-}
diff --git a/liblog/logprint.c b/liblog/logprint.c
deleted file mode 100644
index 2cf12545..00000000
--- a/liblog/logprint.c
+++ /dev/null
@@ -1,972 +0,0 @@
-/* //device/libs/cutils/logprint.c
-**
-** Copyright 2006, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define _GNU_SOURCE /* for asprintf */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <alloca.h>
-#include <assert.h>
-#include <arpa/inet.h>
-
-#include <cutils/logd.h>
-#include <cutils/logprint.h>
-
-typedef struct FilterInfo_t {
- char *mTag;
- android_LogPriority mPri;
- struct FilterInfo_t *p_next;
-} FilterInfo;
-
-struct AndroidLogFormat_t {
- android_LogPriority global_pri;
- FilterInfo *filters;
- AndroidLogPrintFormat format;
-};
-
-static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
-{
- FilterInfo *p_ret;
-
- p_ret = (FilterInfo *)calloc(1, sizeof(FilterInfo));
- p_ret->mTag = strdup(tag);
- p_ret->mPri = pri;
-
- return p_ret;
-}
-
-static void filterinfo_free(FilterInfo *p_info)
-{
- if (p_info == NULL) {
- return;
- }
-
- free(p_info->mTag);
- p_info->mTag = NULL;
-}
-
-/*
- * Note: also accepts 0-9 priorities
- * returns ANDROID_LOG_UNKNOWN if the character is unrecognized
- */
-static android_LogPriority filterCharToPri (char c)
-{
- android_LogPriority pri;
-
- c = tolower(c);
-
- if (c >= '0' && c <= '9') {
- if (c >= ('0'+ANDROID_LOG_SILENT)) {
- pri = ANDROID_LOG_VERBOSE;
- } else {
- pri = (android_LogPriority)(c - '0');
- }
- } else if (c == 'v') {
- pri = ANDROID_LOG_VERBOSE;
- } else if (c == 'd') {
- pri = ANDROID_LOG_DEBUG;
- } else if (c == 'i') {
- pri = ANDROID_LOG_INFO;
- } else if (c == 'w') {
- pri = ANDROID_LOG_WARN;
- } else if (c == 'e') {
- pri = ANDROID_LOG_ERROR;
- } else if (c == 'f') {
- pri = ANDROID_LOG_FATAL;
- } else if (c == 's') {
- pri = ANDROID_LOG_SILENT;
- } else if (c == '*') {
- pri = ANDROID_LOG_DEFAULT;
- } else {
- pri = ANDROID_LOG_UNKNOWN;
- }
-
- return pri;
-}
-
-static char filterPriToChar (android_LogPriority pri)
-{
- switch (pri) {
- case ANDROID_LOG_VERBOSE: return 'V';
- case ANDROID_LOG_DEBUG: return 'D';
- case ANDROID_LOG_INFO: return 'I';
- case ANDROID_LOG_WARN: return 'W';
- case ANDROID_LOG_ERROR: return 'E';
- case ANDROID_LOG_FATAL: return 'F';
- case ANDROID_LOG_SILENT: return 'S';
-
- case ANDROID_LOG_DEFAULT:
- case ANDROID_LOG_UNKNOWN:
- default: return '?';
- }
-}
-
-static android_LogPriority filterPriForTag(
- AndroidLogFormat *p_format, const char *tag)
-{
- FilterInfo *p_curFilter;
-
- for (p_curFilter = p_format->filters
- ; p_curFilter != NULL
- ; p_curFilter = p_curFilter->p_next
- ) {
- if (0 == strcmp(tag, p_curFilter->mTag)) {
- if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) {
- return p_format->global_pri;
- } else {
- return p_curFilter->mPri;
- }
- }
- }
-
- return p_format->global_pri;
-}
-
-/** for debugging */
-static void dumpFilters(AndroidLogFormat *p_format)
-{
- FilterInfo *p_fi;
-
- for (p_fi = p_format->filters ; p_fi != NULL ; p_fi = p_fi->p_next) {
- char cPri = filterPriToChar(p_fi->mPri);
- if (p_fi->mPri == ANDROID_LOG_DEFAULT) {
- cPri = filterPriToChar(p_format->global_pri);
- }
- fprintf(stderr,"%s:%c\n", p_fi->mTag, cPri);
- }
-
- fprintf(stderr,"*:%c\n", filterPriToChar(p_format->global_pri));
-
-}
-
-/**
- * returns 1 if this log line should be printed based on its priority
- * and tag, and 0 if it should not
- */
-int android_log_shouldPrintLine (
- AndroidLogFormat *p_format, const char *tag, android_LogPriority pri)
-{
- return pri >= filterPriForTag(p_format, tag);
-}
-
-AndroidLogFormat *android_log_format_new()
-{
- AndroidLogFormat *p_ret;
-
- p_ret = calloc(1, sizeof(AndroidLogFormat));
-
- p_ret->global_pri = ANDROID_LOG_VERBOSE;
- p_ret->format = FORMAT_BRIEF;
-
- return p_ret;
-}
-
-void android_log_format_free(AndroidLogFormat *p_format)
-{
- FilterInfo *p_info, *p_info_old;
-
- p_info = p_format->filters;
-
- while (p_info != NULL) {
- p_info_old = p_info;
- p_info = p_info->p_next;
-
- free(p_info_old);
- }
-
- free(p_format);
-}
-
-
-
-void android_log_setPrintFormat(AndroidLogFormat *p_format,
- AndroidLogPrintFormat format)
-{
- p_format->format=format;
-}
-
-/**
- * Returns FORMAT_OFF on invalid string
- */
-AndroidLogPrintFormat android_log_formatFromString(const char * formatString)
-{
- static AndroidLogPrintFormat format;
-
- if (strcmp(formatString, "brief") == 0) format = FORMAT_BRIEF;
- else if (strcmp(formatString, "process") == 0) format = FORMAT_PROCESS;
- else if (strcmp(formatString, "tag") == 0) format = FORMAT_TAG;
- else if (strcmp(formatString, "thread") == 0) format = FORMAT_THREAD;
- else if (strcmp(formatString, "raw") == 0) format = FORMAT_RAW;
- else if (strcmp(formatString, "time") == 0) format = FORMAT_TIME;
- else if (strcmp(formatString, "threadtime") == 0) format = FORMAT_THREADTIME;
- else if (strcmp(formatString, "long") == 0) format = FORMAT_LONG;
- else format = FORMAT_OFF;
-
- return format;
-}
-
-/**
- * filterExpression: a single filter expression
- * eg "AT:d"
- *
- * returns 0 on success and -1 on invalid expression
- *
- * Assumes single threaded execution
- */
-
-int android_log_addFilterRule(AndroidLogFormat *p_format,
- const char *filterExpression)
-{
- size_t i=0;
- size_t tagNameLength;
- android_LogPriority pri = ANDROID_LOG_DEFAULT;
-
- tagNameLength = strcspn(filterExpression, ":");
-
- if (tagNameLength == 0) {
- goto error;
- }
-
- if(filterExpression[tagNameLength] == ':') {
- pri = filterCharToPri(filterExpression[tagNameLength+1]);
-
- if (pri == ANDROID_LOG_UNKNOWN) {
- goto error;
- }
- }
-
- if(0 == strncmp("*", filterExpression, tagNameLength)) {
- // This filter expression refers to the global filter
- // The default level for this is DEBUG if the priority
- // is unspecified
- if (pri == ANDROID_LOG_DEFAULT) {
- pri = ANDROID_LOG_DEBUG;
- }
-
- p_format->global_pri = pri;
- } else {
- // for filter expressions that don't refer to the global
- // filter, the default is verbose if the priority is unspecified
- if (pri == ANDROID_LOG_DEFAULT) {
- pri = ANDROID_LOG_VERBOSE;
- }
-
- char *tagName;
-
-// Presently HAVE_STRNDUP is never defined, so the second case is always taken
-// Darwin doesn't have strnup, everything else does
-#ifdef HAVE_STRNDUP
- tagName = strndup(filterExpression, tagNameLength);
-#else
- //a few extra bytes copied...
- tagName = strdup(filterExpression);
- tagName[tagNameLength] = '\0';
-#endif /*HAVE_STRNDUP*/
-
- FilterInfo *p_fi = filterinfo_new(tagName, pri);
- free(tagName);
-
- p_fi->p_next = p_format->filters;
- p_format->filters = p_fi;
- }
-
- return 0;
-error:
- return -1;
-}
-
-
-/**
- * filterString: a comma/whitespace-separated set of filter expressions
- *
- * eg "AT:d *:i"
- *
- * returns 0 on success and -1 on invalid expression
- *
- * Assumes single threaded execution
- *
- */
-
-int android_log_addFilterString(AndroidLogFormat *p_format,
- const char *filterString)
-{
- char *filterStringCopy = strdup (filterString);
- char *p_cur = filterStringCopy;
- char *p_ret;
- int err;
-
- // Yes, I'm using strsep
- while (NULL != (p_ret = strsep(&p_cur, " \t,"))) {
- // ignore whitespace-only entries
- if(p_ret[0] != '\0') {
- err = android_log_addFilterRule(p_format, p_ret);
-
- if (err < 0) {
- goto error;
- }
- }
- }
-
- free (filterStringCopy);
- return 0;
-error:
- free (filterStringCopy);
- return -1;
-}
-
-static inline char * strip_end(char *str)
-{
- char *end = str + strlen(str) - 1;
-
- while (end >= str && isspace(*end))
- *end-- = '\0';
- return str;
-}
-
-/**
- * Splits a wire-format buffer into an AndroidLogEntry
- * entry allocated by caller. Pointers will point directly into buf
- *
- * Returns 0 on success and -1 on invalid wire format (entry will be
- * in unspecified state)
- */
-int android_log_processLogBuffer(struct logger_entry *buf,
- AndroidLogEntry *entry)
-{
- size_t tag_len;
-
- entry->tv_sec = buf->sec;
- entry->tv_nsec = buf->nsec;
- entry->priority = buf->msg[0];
- entry->pid = buf->pid;
- entry->tid = buf->tid;
- entry->tag = buf->msg + 1;
- tag_len = strlen(entry->tag);
- entry->messageLen = buf->len - tag_len - 3;
- entry->message = entry->tag + tag_len + 1;
-
- return 0;
-}
-
-/*
- * Extract a 4-byte value from a byte stream.
- */
-static inline uint32_t get4LE(const uint8_t* src)
-{
- return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-/*
- * Extract an 8-byte value from a byte stream.
- */
-static inline uint64_t get8LE(const uint8_t* src)
-{
- uint32_t low, high;
-
- low = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
- high = src[4] | (src[5] << 8) | (src[6] << 16) | (src[7] << 24);
- return ((long long) high << 32) | (long long) low;
-}
-
-
-/*
- * Recursively convert binary log data to printable form.
- *
- * This needs to be recursive because you can have lists of lists.
- *
- * If we run out of room, we stop processing immediately. It's important
- * for us to check for space on every output element to avoid producing
- * garbled output.
- *
- * Returns 0 on success, 1 on buffer full, -1 on failure.
- */
-static int android_log_printBinaryEvent(const unsigned char** pEventData,
- size_t* pEventDataLen, char** pOutBuf, size_t* pOutBufLen)
-{
- const unsigned char* eventData = *pEventData;
- size_t eventDataLen = *pEventDataLen;
- char* outBuf = *pOutBuf;
- size_t outBufLen = *pOutBufLen;
- unsigned char type;
- size_t outCount;
- int result = 0;
-
- if (eventDataLen < 1)
- return -1;
- type = *eventData++;
- eventDataLen--;
-
- //fprintf(stderr, "--- type=%d (rem len=%d)\n", type, eventDataLen);
-
- switch (type) {
- case EVENT_TYPE_INT:
- /* 32-bit signed int */
- {
- int ival;
-
- if (eventDataLen < 4)
- return -1;
- ival = get4LE(eventData);
- eventData += 4;
- eventDataLen -= 4;
-
- outCount = snprintf(outBuf, outBufLen, "%d", ival);
- if (outCount < outBufLen) {
- outBuf += outCount;
- outBufLen -= outCount;
- } else {
- /* halt output */
- goto no_room;
- }
- }
- break;
- case EVENT_TYPE_LONG:
- /* 64-bit signed long */
- {
- long long lval;
-
- if (eventDataLen < 8)
- return -1;
- lval = get8LE(eventData);
- eventData += 8;
- eventDataLen -= 8;
-
- outCount = snprintf(outBuf, outBufLen, "%lld", lval);
- if (outCount < outBufLen) {
- outBuf += outCount;
- outBufLen -= outCount;
- } else {
- /* halt output */
- goto no_room;
- }
- }
- break;
- case EVENT_TYPE_STRING:
- /* UTF-8 chars, not NULL-terminated */
- {
- unsigned int strLen;
-
- if (eventDataLen < 4)
- return -1;
- strLen = get4LE(eventData);
- eventData += 4;
- eventDataLen -= 4;
-
- if (eventDataLen < strLen)
- return -1;
-
- if (strLen < outBufLen) {
- memcpy(outBuf, eventData, strLen);
- outBuf += strLen;
- outBufLen -= strLen;
- } else if (outBufLen > 0) {
- /* copy what we can */
- memcpy(outBuf, eventData, outBufLen);
- outBuf += outBufLen;
- outBufLen -= outBufLen;
- goto no_room;
- }
- eventData += strLen;
- eventDataLen -= strLen;
- break;
- }
- case EVENT_TYPE_LIST:
- /* N items, all different types */
- {
- unsigned char count;
- int i;
-
- if (eventDataLen < 1)
- return -1;
-
- count = *eventData++;
- eventDataLen--;
-
- if (outBufLen > 0) {
- *outBuf++ = '[';
- outBufLen--;
- } else {
- goto no_room;
- }
-
- for (i = 0; i < count; i++) {
- result = android_log_printBinaryEvent(&eventData, &eventDataLen,
- &outBuf, &outBufLen);
- if (result != 0)
- goto bail;
-
- if (i < count-1) {
- if (outBufLen > 0) {
- *outBuf++ = ',';
- outBufLen--;
- } else {
- goto no_room;
- }
- }
- }
-
- if (outBufLen > 0) {
- *outBuf++ = ']';
- outBufLen--;
- } else {
- goto no_room;
- }
- }
- break;
- default:
- fprintf(stderr, "Unknown binary event type %d\n", type);
- return -1;
- }
-
-bail:
- *pEventData = eventData;
- *pEventDataLen = eventDataLen;
- *pOutBuf = outBuf;
- *pOutBufLen = outBufLen;
- return result;
-
-no_room:
- result = 1;
- goto bail;
-}
-
-/**
- * Convert a binary log entry to ASCII form.
- *
- * For convenience we mimic the processLogBuffer API. There is no
- * pre-defined output length for the binary data, since we're free to format
- * it however we choose, which means we can't really use a fixed-size buffer
- * here.
- */
-int android_log_processBinaryLogBuffer(struct logger_entry *buf,
- AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
- int messageBufLen)
-{
- size_t inCount;
- unsigned int tagIndex;
- const unsigned char* eventData;
-
- entry->tv_sec = buf->sec;
- entry->tv_nsec = buf->nsec;
- entry->priority = ANDROID_LOG_INFO;
- entry->pid = buf->pid;
- entry->tid = buf->tid;
-
- /*
- * Pull the tag out.
- */
- eventData = (const unsigned char*) buf->msg;
- inCount = buf->len;
- if (inCount < 4)
- return -1;
- tagIndex = get4LE(eventData);
- eventData += 4;
- inCount -= 4;
-
- if (map != NULL) {
- entry->tag = android_lookupEventTag(map, tagIndex);
- } else {
- entry->tag = NULL;
- }
-
- /*
- * If we don't have a map, or didn't find the tag number in the map,
- * stuff a generated tag value into the start of the output buffer and
- * shift the buffer pointers down.
- */
- if (entry->tag == NULL) {
- int tagLen;
-
- tagLen = snprintf(messageBuf, messageBufLen, "[%d]", tagIndex);
- entry->tag = messageBuf;
- messageBuf += tagLen+1;
- messageBufLen -= tagLen+1;
- }
-
- /*
- * Format the event log data into the buffer.
- */
- char* outBuf = messageBuf;
- size_t outRemaining = messageBufLen-1; /* leave one for nul byte */
- int result;
- result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
- &outRemaining);
- if (result < 0) {
- fprintf(stderr, "Binary log entry conversion failed\n");
- return -1;
- } else if (result == 1) {
- if (outBuf > messageBuf) {
- /* leave an indicator */
- *(outBuf-1) = '!';
- } else {
- /* no room to output anything at all */
- *outBuf++ = '!';
- outRemaining--;
- }
- /* pretend we ate all the data */
- inCount = 0;
- }
-
- /* eat the silly terminating '\n' */
- if (inCount == 1 && *eventData == '\n') {
- eventData++;
- inCount--;
- }
-
- if (inCount != 0) {
- fprintf(stderr,
- "Warning: leftover binary log data (%d bytes)\n", inCount);
- }
-
- /*
- * Terminate the buffer. The NUL byte does not count as part of
- * entry->messageLen.
- */
- *outBuf = '\0';
- entry->messageLen = outBuf - messageBuf;
- assert(entry->messageLen == (messageBufLen-1) - outRemaining);
-
- entry->message = messageBuf;
-
- return 0;
-}
-
-/**
- * Formats a log message into a buffer
- *
- * Uses defaultBuffer if it can, otherwise malloc()'s a new buffer
- * If return value != defaultBuffer, caller must call free()
- * Returns NULL on malloc error
- */
-
-char *android_log_formatLogLine (
- AndroidLogFormat *p_format,
- char *defaultBuffer,
- size_t defaultBufferSize,
- const AndroidLogEntry *entry,
- size_t *p_outLength)
-{
-#if defined(HAVE_LOCALTIME_R)
- struct tm tmBuf;
-#endif
- struct tm* ptm;
- char timeBuf[32];
- char headerBuf[128];
- char prefixBuf[128], suffixBuf[128];
- char priChar;
- int prefixSuffixIsHeaderFooter = 0;
- char * ret = NULL;
-
- priChar = filterPriToChar(entry->priority);
-
- /*
- * Get the current date/time in pretty form
- *
- * It's often useful when examining a log with "less" to jump to
- * a specific point in the file by searching for the date/time stamp.
- * For this reason it's very annoying to have regexp meta characters
- * in the time stamp. Don't use forward slashes, parenthesis,
- * brackets, asterisks, or other special chars here.
- */
-#if defined(HAVE_LOCALTIME_R)
- ptm = localtime_r(&(entry->tv_sec), &tmBuf);
-#else
- ptm = localtime(&(entry->tv_sec));
-#endif
- //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
- strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
-
- /*
- * Construct a buffer containing the log header and log message.
- */
- size_t prefixLen, suffixLen;
-
- switch (p_format->format) {
- case FORMAT_TAG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s: ", priChar, entry->tag);
- strcpy(suffixBuf, "\n"); suffixLen = 1;
- break;
- case FORMAT_PROCESS:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c(%5d) ", priChar, entry->pid);
- suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
- " (%s)\n", entry->tag);
- break;
- case FORMAT_THREAD:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c(%5d:%p) ", priChar, entry->pid, (void*)entry->tid);
- strcpy(suffixBuf, "\n");
- suffixLen = 1;
- break;
- case FORMAT_RAW:
- prefixBuf[0] = 0;
- prefixLen = 0;
- strcpy(suffixBuf, "\n");
- suffixLen = 1;
- break;
- case FORMAT_TIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
- priChar, entry->tag, entry->pid);
- strcpy(suffixBuf, "\n");
- suffixLen = 1;
- break;
- case FORMAT_THREADTIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
- (int)entry->pid, (int)entry->tid, priChar, entry->tag);
- strcpy(suffixBuf, "\n");
- suffixLen = 1;
- break;
- case FORMAT_LONG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "[ %s.%03ld %5d:%p %c/%-8s ]\n",
- timeBuf, entry->tv_nsec / 1000000, entry->pid,
- (void*)entry->tid, priChar, entry->tag);
- strcpy(suffixBuf, "\n\n");
- suffixLen = 2;
- prefixSuffixIsHeaderFooter = 1;
- break;
- case FORMAT_BRIEF:
- default:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
- strcpy(suffixBuf, "\n");
- suffixLen = 1;
- break;
- }
-
- /* the following code is tragically unreadable */
-
- size_t numLines;
- size_t i;
- char *p;
- size_t bufferSize;
- const char *pm;
-
- if (prefixSuffixIsHeaderFooter) {
- // we're just wrapping message with a header/footer
- numLines = 1;
- } else {
- pm = entry->message;
- numLines = 0;
-
- // The line-end finding here must match the line-end finding
- // in for ( ... numLines...) loop below
- while (pm < (entry->message + entry->messageLen)) {
- if (*pm++ == '\n') numLines++;
- }
- // plus one line for anything not newline-terminated at the end
- if (pm > entry->message && *(pm-1) != '\n') numLines++;
- }
-
- // this is an upper bound--newlines in message may be counted
- // extraneously
- bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
-
- if (defaultBufferSize >= bufferSize) {
- ret = defaultBuffer;
- } else {
- ret = (char *)malloc(bufferSize);
-
- if (ret == NULL) {
- return ret;
- }
- }
-
- ret[0] = '\0'; /* to start strcat off */
-
- p = ret;
- pm = entry->message;
-
- if (prefixSuffixIsHeaderFooter) {
- strcat(p, prefixBuf);
- p += prefixLen;
- strncat(p, entry->message, entry->messageLen);
- p += entry->messageLen;
- strcat(p, suffixBuf);
- p += suffixLen;
- } else {
- while(pm < (entry->message + entry->messageLen)) {
- const char *lineStart;
- size_t lineLen;
-
- lineStart = pm;
-
- // Find the next end-of-line in message
- while (pm < (entry->message + entry->messageLen)
- && *pm != '\n') pm++;
- lineLen = pm - lineStart;
-
- strcat(p, prefixBuf);
- p += prefixLen;
- strncat(p, lineStart, lineLen);
- p += lineLen;
- strcat(p, suffixBuf);
- p += suffixLen;
-
- if (*pm == '\n') pm++;
- }
- }
-
- if (p_outLength != NULL) {
- *p_outLength = p - ret;
- }
-
- return ret;
-}
-
-/**
- * Either print or do not print log line, based on filter
- *
- * Returns count bytes written
- */
-
-int android_log_filterAndPrintLogLine(
- AndroidLogFormat *p_format,
- int fd,
- const AndroidLogEntry *entry)
-{
- int ret;
- char defaultBuffer[512];
- char *outBuffer = NULL;
- size_t totalLen;
-
- if (0 == android_log_shouldPrintLine(p_format, entry->tag,
- entry->priority)) {
- return 0;
- }
-
- outBuffer = android_log_formatLogLine(p_format, defaultBuffer,
- sizeof(defaultBuffer), entry, &totalLen);
-
- if (!outBuffer)
- return -1;
-
- do {
- ret = write(fd, outBuffer, totalLen);
- } while (ret < 0 && errno == EINTR);
-
- if (ret < 0) {
- fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
- ret = 0;
- goto done;
- }
-
- if (((size_t)ret) < totalLen) {
- fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", ret,
- (int)totalLen);
- goto done;
- }
-
-done:
- if (outBuffer != defaultBuffer) {
- free(outBuffer);
- }
-
- return ret;
-}
-
-
-
-void logprint_run_tests()
-{
-#if 0
-
- fprintf(stderr, "tests disabled\n");
-
-#else
-
- int err;
- const char *tag;
- AndroidLogFormat *p_format;
-
- p_format = android_log_format_new();
-
- fprintf(stderr, "running tests\n");
-
- tag = "random";
-
- android_log_addFilterRule(p_format,"*:i");
-
- assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
- android_log_addFilterRule(p_format, "*");
- assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
- android_log_addFilterRule(p_format, "*:v");
- assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
- android_log_addFilterRule(p_format, "*:i");
- assert (ANDROID_LOG_INFO == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
-
- android_log_addFilterRule(p_format, "random");
- assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
- android_log_addFilterRule(p_format, "random:v");
- assert (ANDROID_LOG_VERBOSE == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
- android_log_addFilterRule(p_format, "random:d");
- assert (ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) > 0);
- android_log_addFilterRule(p_format, "random:w");
- assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
-
- android_log_addFilterRule(p_format, "crap:*");
- assert (ANDROID_LOG_VERBOSE== filterPriForTag(p_format, "crap"));
- assert(android_log_shouldPrintLine(p_format, "crap", ANDROID_LOG_VERBOSE) > 0);
-
- // invalid expression
- err = android_log_addFilterRule(p_format, "random:z");
- assert (err < 0);
- assert (ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
- assert(android_log_shouldPrintLine(p_format, tag, ANDROID_LOG_DEBUG) == 0);
-
- // Issue #550946
- err = android_log_addFilterString(p_format, " ");
- assert(err == 0);
- assert(ANDROID_LOG_WARN == filterPriForTag(p_format, "random"));
-
- // note trailing space
- err = android_log_addFilterString(p_format, "*:s random:d ");
- assert(err == 0);
- assert(ANDROID_LOG_DEBUG == filterPriForTag(p_format, "random"));
-
- err = android_log_addFilterString(p_format, "*:s random:z");
- assert(err < 0);
-
-
-#if 0
- char *ret;
- char defaultBuffer[512];
-
- ret = android_log_formatLogLine(p_format,
- defaultBuffer, sizeof(defaultBuffer), 0, ANDROID_LOG_ERROR, 123,
- 123, 123, "random", "nofile", strlen("Hello"), "Hello", NULL);
-#endif
-
-
- fprintf(stderr, "tests complete\n");
-#endif
-}