1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2168021c2827312e17a13d77b54f7d030a08b257bMark Salyzyn * Copyright (C) 2008-2014 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Intercepts log messages intended for the Android log device.
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * When running in the context of the simulator, the messages are
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * passed on to the underlying (fake) log device.  When not in the
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * simulator, messages are printed to stderr.
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
256d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn#if !defined(_WIN32)
266d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn#include <pthread.h>
276d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn#endif
28cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <stdint.h>
29cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <stdio.h>
30a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <stdlib.h>
31a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn#include <string.h>
32cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <time.h>
33a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn
346584d0a35ab7722bdc6590525dee29f72f0ec576Mark Salyzyn#include <android/log.h>
35cfd5b080af8de527d768f0ff7902c26af8d49307Mark Salyzyn#include <log/uio.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
376d753faaf8694792433eb78c5c3572efd74a3d54Mark Salyzyn#include "fake_log_device.h"
38facf94c74a2cc44f294c4789d36d5c7281c7bc3fMark Salyzyn#include "log_portability.h"
39a04464adaf5b95ae953f8577632d3cf8aa2c80a3Mark Salyzyn
402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn#define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn#define kTagSetSize 16 /* arbitrary */
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE(...) printf("fake_log_device: " __VA_ARGS__)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE(...) ((void)0)
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* from the long-dead utils/Log.cpp */
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef enum {
522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_OFF = 0,
532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_BRIEF,
542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_PROCESS,
552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_TAG,
562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_THREAD,
572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_RAW,
582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_TIME,
592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_THREADTIME,
602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  FORMAT_LONG
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} LogFormat;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Log driver state.
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct LogState {
672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* the fake fd that's seen by the user */
682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int fakeFd;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* a printable name for this fake device */
712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char debugName[sizeof("/dev/log/security")];
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* nonzero if this is a binary log */
742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int isBinary;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* global minimum priority */
772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int globalMinPriority;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* output format */
802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  LogFormat outputFormat;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* tags and priorities */
832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct {
842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    char tag[kMaxTagLen];
852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    int minPriority;
862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } tagSet[kTagSetSize];
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} LogState;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
894a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#if !defined(_WIN32)
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Locking.  Since we're emulating a device, we need to be prepared
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to have multiple callers at the same time.  This lock is used
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to both protect the fd list and to prevent LogStates from being
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * freed out from under a user.
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void lock() {
992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
1002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * If we trigger a signal handler in the middle of locked activity and the
1012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * signal handler logs a message, we could get into a deadlock state.
1022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
1032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_lock(&fakeLogDeviceLock);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void unlock() {
1072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pthread_mutex_unlock(&fakeLogDeviceLock);
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1092d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
1102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn#else  // !defined(_WIN32)
1112d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
112c2e7d4965f86dbe90cece6d25e91d934a698d195Mark Salyzyn#define lock() ((void)0)
113c2e7d4965f86dbe90cece6d25e91d934a698d195Mark Salyzyn#define unlock() ((void)0)
1142d2e0a5c5eb0b0ea2fe1349da50e22228965faf9Mark Salyzyn
1154a6e5a3b641dd99b658c4c336490371a3a5ae180Yabin Cui#endif  // !defined(_WIN32)
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * File descriptor management.
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define FAKE_FD_BASE 10000
1218edbbe1dc148006e4cd588f42f580bfdaa7ae585Mark Salyzyn#define MAX_OPEN_LOGS 8
1228edbbe1dc148006e4cd588f42f580bfdaa7ae585Mark Salyzynstatic LogState openLogTable[MAX_OPEN_LOGS];
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Allocate an fd and associate a new LogState with it.
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The fd is available via the fakeFd field of the return value.
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic LogState* createLogState() {
1292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t i;
1302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (i = 0; i < (sizeof(openLogTable) / sizeof(openLogTable[0])); i++) {
1322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (openLogTable[i].fakeFd == 0) {
1332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      openLogTable[i].fakeFd = FAKE_FD_BASE + i;
1342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return &openLogTable[i];
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return NULL;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Translate an fd to a LogState.
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic LogState* fdToLogState(int fd) {
1442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) {
1452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return &openLogTable[fd - FAKE_FD_BASE];
1462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return NULL;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unregister the fake fd and free the memory it pointed to.
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void deleteFakeFd(int fd) {
1542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  LogState* ls;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  lock();
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ls = fdToLogState(fd);
1592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (ls != NULL) {
1602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    memset(&openLogTable[fd - FAKE_FD_BASE], 0, sizeof(openLogTable[0]));
1612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unlock();
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Configure logging based on ANDROID_LOG_TAGS environment variable.  We
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * need to parse a string that looks like
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *   *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The tag (or '*' for the global level) comes first, followed by a colon
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * and a letter indicating the minimum priority level we're expected to log.
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This can be used to reveal or conceal logs with specific tags.
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * We also want to check ANDROID_PRINTF_LOG to determine how the output
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * will look.
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void configureInitialState(const char* pathName, LogState* logState) {
1802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const int kDevLogLen = sizeof("/dev/log/") - 1;
1812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  strncpy(logState->debugName, pathName, sizeof(logState->debugName));
1832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  logState->debugName[sizeof(logState->debugName) - 1] = '\0';
1842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* identify binary logs */
1862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (!strcmp(pathName + kDevLogLen, "events") ||
1872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      !strcmp(pathName + kDevLogLen, "security")) {
1882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    logState->isBinary = 1;
1892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
1902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* global min priority defaults to "info" level */
1922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  logState->globalMinPriority = ANDROID_LOG_INFO;
1932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
1942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
1952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * This is based on the the long-dead utils/Log.cpp code.
1962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
1972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* tags = getenv("ANDROID_LOG_TAGS");
1982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  TRACE("Found ANDROID_LOG_TAGS='%s'\n", tags);
1992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (tags != NULL) {
2002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    int entry = 0;
2012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    while (*tags != '\0') {
2032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      char tagName[kMaxTagLen];
2042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      int i, minPrio;
2052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      while (isspace(*tags)) tags++;
2072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      i = 0;
2092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&
2102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn             i < kMaxTagLen) {
2112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tagName[i++] = *tags++;
2122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
2132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (i == kMaxTagLen) {
2142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen - 1);
2152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        return;
2162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
2172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      tagName[i] = '\0';
2182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* default priority, if there's no ":" part; also zero out '*' */
2202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      minPrio = ANDROID_LOG_VERBOSE;
2212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (tagName[0] == '*' && tagName[1] == '\0') {
2222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        minPrio = ANDROID_LOG_DEBUG;
2232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tagName[0] = '\0';
2242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
2252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (*tags == ':') {
2272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tags++;
2282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (*tags >= '0' && *tags <= '9') {
2292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          if (*tags >= ('0' + ANDROID_LOG_SILENT))
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            minPrio = ANDROID_LOG_VERBOSE;
2312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          else
2322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            minPrio = *tags - '\0';
2332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        } else {
2342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          switch (*tags) {
2352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'v':
2362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_VERBOSE;
2372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'd':
2392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_DEBUG;
2402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'i':
2422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_INFO;
2432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'w':
2452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_WARN;
2462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'e':
2482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_ERROR;
2492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 'f':
2512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_FATAL;
2522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            case 's':
2542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_SILENT;
2552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn            default:
2572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              minPrio = ANDROID_LOG_DEFAULT;
2582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              break;
2592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          }
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        tags++;
2632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        if (*tags != '\0' && !isspace(*tags)) {
2642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          TRACE("ERROR: garbage in tag env; expected whitespace\n");
2652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          TRACE("       env='%s'\n", tags);
2662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          return;
2672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        }
2682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
2692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (tagName[0] == 0) {
2712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        logState->globalMinPriority = minPrio;
2722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        TRACE("+++ global min prio %d\n", logState->globalMinPriority);
2732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      } else {
2742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        logState->tagSet[entry].minPriority = minPrio;
2752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        strcpy(logState->tagSet[entry].tag, tagName);
2762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        TRACE("+++ entry %d: %s:%d\n", entry, logState->tagSet[entry].tag,
2772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn              logState->tagSet[entry].minPriority);
2782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn        entry++;
2792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      }
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
2812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
2822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
2832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
2842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Taken from the long-dead utils/Log.cpp
2852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
2862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* fstr = getenv("ANDROID_PRINTF_LOG");
2872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  LogFormat format;
2882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (fstr == NULL) {
2892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    format = FORMAT_BRIEF;
2902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
2912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (strcmp(fstr, "brief") == 0)
2922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_BRIEF;
2932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "process") == 0)
2942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
2952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "tag") == 0)
2962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
2972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "thread") == 0)
2982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
2992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "raw") == 0)
3002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
3012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "time") == 0)
3022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
3032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else if (strcmp(fstr, "long") == 0)
3042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = FORMAT_PROCESS;
3052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    else
3062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      format = (LogFormat)atoi(fstr);  // really?!
3072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  logState->outputFormat = format;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Return a human-readable string for the priority level.  Always returns
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * a valid string.
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
3162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic const char* getPriorityString(int priority) {
3172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* the first character of each string should be unique */
3182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  static const char* priorityStrings[] = { "Verbose", "Debug", "Info",
3192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                           "Warn",    "Error", "Assert" };
3202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int idx;
3212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  idx = (int)priority - (int)ANDROID_LOG_VERBOSE;
3232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (idx < 0 ||
3242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
3252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    return "?unknown?";
3262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return priorityStrings[idx];
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3292a5fecb3cd0b44432836619d77837b1aca299e89Elliott Hughes#if defined(_WIN32)
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
3312a5fecb3cd0b44432836619d77837b1aca299e89Elliott Hughes * WIN32 does not have writev().
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Make up something to replace it.
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
3342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic ssize_t fake_writev(int fd, const struct iovec* iov, int iovcnt) {
3352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ssize_t result = 0;
3362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const struct iovec* end = iov + iovcnt;
3372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (; iov < end; iov++) {
3382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    ssize_t w = write(fd, iov->iov_base, iov->iov_len);
3392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (w != (ssize_t)iov->iov_len) {
3402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (w < 0) return w;
3412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      return result + w;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
3432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    result += w;
3442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
3452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return result;
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define writev fake_writev
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Write a filtered log message to stderr.
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Log format parsing taken from the long-dead utils/Log.cpp.
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
3562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void showLog(LogState* state, int logPrio, const char* tag,
3572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                    const char* msg) {
3588a98535bcb48dfd4bfe3dfddddc82925a2f1502bYabin Cui#if !defined(_WIN32)
3592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct tm tmBuf;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
3612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct tm* ptm;
3622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char timeBuf[32];
3632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char prefixBuf[128], suffixBuf[128];
3642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  char priChar;
3652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  time_t when;
3669dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#if !defined(_WIN32)
3672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pid_t pid, tid;
3689dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#else
3692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  uint32_t pid, tid;
3709dddd137c72a989b414c1bc8e928fb67ee46fac3Dan Willemsen#endif
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  TRACE("LOG %d: %s %s", logPrio, tag, msg);
3732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  priChar = getPriorityString(logPrio)[0];
3752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  when = time(NULL);
3762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  pid = tid = getpid();  // find gettid()?
3772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
3782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn/*
3792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * Get the current date/time in pretty form
3802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn *
3812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * It's often useful when examining a log with "less" to jump to
3822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * a specific point in the file by searching for the date/time stamp.
3832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * For this reason it's very annoying to have regexp meta characters
3842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * in the time stamp.  Don't use forward slashes, parenthesis,
3852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn * brackets, asterisks, or other special chars here.
3862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn */
3878a98535bcb48dfd4bfe3dfddddc82925a2f1502bYabin Cui#if !defined(_WIN32)
3882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ptm = localtime_r(&when, &tmBuf);
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
3902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ptm = localtime(&when);
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
3922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  // strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
3932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
3962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Construct a buffer containing the log header and log message.
3972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
3982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t prefixLen, suffixLen;
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  switch (state->outputFormat) {
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_TAG:
4022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen =
4032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
4042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_PROCESS:
4082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen =
4092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid);
4102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), "  (%s)\n", tag);
4112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_THREAD:
4132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ",
4142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                           priChar, pid, tid);
4152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_RAW:
4192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixBuf[0] = 0;
4202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen = 0;
4212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_TIME:
4252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen =
4262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag);
4272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_THREADTIME:
4312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen =
4322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t",
4332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                   timeBuf, pid, tid, priChar, tag);
4342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case FORMAT_LONG:
4382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen =
4392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn          snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n",
4402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                   timeBuf, pid, tid, priChar, tag);
4412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n\n");
4422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 2;
4432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
4452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
4462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                           "%c/%-8s(%5d): ", priChar, tag, pid);
4472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      strcpy(suffixBuf, "\n");
4482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      suffixLen = 1;
4492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
4502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
4532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Figure out how many lines there will be.
4542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
4552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* end = msg + strlen(msg);
4562ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t numLines = 0;
4572ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* p = msg;
4582ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  while (p < end) {
4592ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (*p++ == '\n') numLines++;
4602ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4612ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (p > msg && *(p - 1) != '\n') {
4622ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    numLines++;
4632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
4662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Create an array of iovecs large enough to write all of
4672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * the lines with a prefix and a suffix.
4682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
4692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const size_t INLINE_VECS = 64;
4702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const size_t MAX_LINES = ((size_t)~0) / (3 * sizeof(struct iovec*));
4712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct iovec stackVec[INLINE_VECS];
4722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct iovec* vec = stackVec;
4732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  size_t numVecs;
4742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (numLines > MAX_LINES) numLines = MAX_LINES;
4762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  numVecs = numLines * 3;  // 3 iovecs per line.
4782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (numVecs > INLINE_VECS) {
4792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    vec = (struct iovec*)malloc(sizeof(struct iovec) * numVecs);
4802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (vec == NULL) {
4812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      msg = "LOG: write failed, no memory";
4822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      numVecs = INLINE_VECS;
4832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      numLines = numVecs / 3;
4842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      vec = stackVec;
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
4862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
4872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
4882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
4892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Fill in the iovec pointers.
4902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
4912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  p = msg;
4922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  struct iovec* v = vec;
4932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int totalLen = 0;
4942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  while (numLines > 0 && p < end) {
4952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (prefixLen > 0) {
4962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_base = prefixBuf;
4972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_len = prefixLen;
4982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      totalLen += prefixLen;
4992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v++;
5008edbbe1dc148006e4cd588f42f580bfdaa7ae585Mark Salyzyn    }
5012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    const char* start = p;
5022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    while (p < end && *p != '\n') {
5032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      p++;
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
5052ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if ((p - start) > 0) {
5062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_base = (void*)start;
5072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_len = p - start;
5082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      totalLen += p - start;
5092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v++;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
5112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (*p == '\n') p++;
5122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (suffixLen > 0) {
5132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_base = suffixBuf;
5142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v->iov_len = suffixLen;
5152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      totalLen += suffixLen;
5162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      v++;
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
5182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    numLines -= 1;
5192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5212ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /*
5222ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Write the entire message to the log file with a single writev() call.
5232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * We need to use this rather than a collection of printf()s on a FILE*
5242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * because of multi-threading and multi-process issues.
5252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *
5262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * If the file was not opened with O_APPEND, this will produce interleaved
5272ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * output when called on the same file from multiple processes.
5282ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   *
5292ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * If the file descriptor is actually a network socket, the writev()
5302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * call may return with a partial write.  Putting the writev() call in
5312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * a loop can result in interleaved data.  This can be alleviated
5322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * somewhat by wrapping the writev call in the Mutex.
5332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
5342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5352ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (;;) {
5362ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    int cc = writev(fileno(stderr), vec, v - vec);
5372ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (cc == totalLen) break;
5392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (cc < 0) {
5412ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      if (errno == EINTR) continue;
5422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5432ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* can't really log the failure; for now, throw out a stderr */
5442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
5452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
5462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    } else {
5472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      /* shouldn't happen when writing to file or tty */
5482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", cc, totalLen);
5492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
5502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    }
5512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5532ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* if we allocated storage for the iovecs, free it */
5542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (vec != stackVec) free(vec);
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Receive a log message.  We happen to know that "vector" has three parts:
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  priority (1 byte)
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  tag (N bytes -- null-terminated ASCII string)
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  message (N bytes -- null-terminated ASCII string)
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
5642ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic ssize_t logWritev(int fd, const struct iovec* vector, int count) {
5652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  LogState* state;
5662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Make sure that no-one frees the LogState while we're using it.
5682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * Also guarantees that only one thread is in showLog() at a given
5692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * time (if it matters).
5702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
5712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  lock();
5722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  state = fdToLogState(fd);
5742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (state == NULL) {
5752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    errno = EBADF;
5762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    goto error;
5772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (state->isBinary) {
5802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    TRACE("%s: ignoring binary log\n", state->debugName);
5812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    goto bail;
5822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (count != 3) {
5852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    TRACE("%s: writevLog with count=%d not expected\n", state->debugName, count);
5862ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    goto error;
5872ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
5882ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* pull out the three fields */
5902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int logPrio = *(const char*)vector[0].iov_base;
5912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* tag = (const char*)vector[1].iov_base;
5922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* msg = (const char*)vector[2].iov_base;
5932ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
5942ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* see if this log tag is configured */
5952ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int i;
5962ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int minPrio = state->globalMinPriority;
5972ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (i = 0; i < kTagSetSize; i++) {
5982ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (state->tagSet[i].minPriority == ANDROID_LOG_UNKNOWN)
5992ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break; /* reached end of configured values */
6002ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6012ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    if (strcmp(state->tagSet[i].tag, tag) == 0) {
6022ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      // TRACE("MATCH tag '%s'\n", tag);
6032ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      minPrio = state->tagSet[i].minPriority;
6042ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn      break;
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
6062ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (logPrio >= minPrio) {
6092ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    showLog(state, logPrio, tag, msg);
6102ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
6112ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    // TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg);
6122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectbail:
6152ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unlock();
6162ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int len = 0;
6172ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  for (i = 0; i < count; ++i) {
6182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    len += vector[i].iov_len;
6192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6202ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return len;
62162d0d2d683f5d19cf9d451548bd03c4b4f53c42eMark Salyzyn
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecterror:
6232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unlock();
6242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return -1;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Free up our state and close the fake descriptor.
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
6302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int logClose(int fd) {
6312ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  deleteFakeFd(fd);
6322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 0;
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Open a log output device and return a fake fd.
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
6382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int logOpen(const char* pathName, int flags __unused) {
6392ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  LogState* logState;
6402ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int fd = -1;
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6422ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  lock();
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6442ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  logState = createLogState();
6452ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (logState != NULL) {
6462ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    configureInitialState(pathName, logState);
6472ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    fd = logState->fakeFd;
6482ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
6492ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    errno = ENFILE;
6502ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6512ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6522ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  unlock();
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6542ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return fd;
6552ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn}
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Runtime redirection.  If this binary is running in the simulator,
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * just pass log messages to the emulated device.  If it's running
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * outside of the simulator, write the log messages to stderr.
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6632ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic int (*redirectOpen)(const char* pathName, int flags) = NULL;
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int (*redirectClose)(int fd) = NULL;
6652ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic ssize_t (*redirectWritev)(int fd, const struct iovec* vector,
6662ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                 int count) = NULL;
6672ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6682ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzynstatic void setRedirects() {
6692ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  const char* ws;
6702ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn
6712ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Wrapsim sets this environment variable on children that it's
6722ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   * created using its LD_PRELOAD wrapper.
6732ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn   */
6742ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  ws = getenv("ANDROID_WRAPSIM");
6752ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (ws != NULL && strcmp(ws, "1") == 0) {
6762ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* We're running inside wrapsim, so we can just write to the device. */
6772ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectOpen = (int (*)(const char* pathName, int flags))open;
6782ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectClose = close;
6792ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectWritev = writev;
6802ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  } else {
6812ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    /* There's no device to delegate to; handle the logging ourselves. */
6822ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectOpen = logOpen;
6832ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectClose = logClose;
6842ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    redirectWritev = logWritev;
6852ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6882ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_HIDDEN int fakeLogOpen(const char* pathName, int flags) {
6892ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  if (redirectOpen == NULL) {
6902ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn    setRedirects();
6912ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  }
6922ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return redirectOpen(pathName, flags);
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
695029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn/*
696029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * The logger API has no means or need to 'stop' or 'close' using the logs,
697029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * and as such, there is no way for that 'stop' or 'close' to translate into
698029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * a close operation to the fake log handler. fakeLogClose is provided for
699029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * completeness only.
700029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn *
701029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * We have no intention of adding a log close operation as it would complicate
702029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * every user of the logging API with no gain since the only valid place to
703029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * call is in the exit handler. Logging can continue in the exit handler to
704029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn * help debug HOST tools ...
705029c7373801b9e1791df334efa36588c216b4ab2Mark Salyzyn */
7062ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_HIDDEN int fakeLogClose(int fd) {
7072ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Assume that open() was called first. */
7082ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return redirectClose(fd);
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
7112ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
7122ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                    int count) {
7132ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  /* Assume that open() was called first. */
7142ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return redirectWritev(fd, vector, count);
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
716956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn
7172ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_HIDDEN ssize_t __send_log_msg(char* buf __unused,
7182ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                     size_t buf_size __unused) {
7192ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return -ENODEV;
720c9e5f3716626fb8fcbde87c2f7324cc9292a0bd5Mark Salyzyn}
721c9e5f3716626fb8fcbde87c2f7324cc9292a0bd5Mark Salyzyn
7226d753faaf8694792433eb78c5c3572efd74a3d54Mark SalyzynLIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
7232ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                const char* tag __unused,
7242ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                int def) {
7252ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int logLevel = def;
7262ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return logLevel >= 0 && prio >= logLevel;
727956870518ee89b5302b8409ac78f287bf091d9edMark Salyzyn}
728807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn
729807e40ecc9786755e2f74a7a6a9b20c812588119Mark SalyzynLIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
7302ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    const char* tag __unused,
731807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn                                                    size_t len __unused,
7322ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn                                                    int def) {
7332ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  int logLevel = def;
7342ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return logLevel >= 0 && prio >= logLevel;
735807e40ecc9786755e2f74a7a6a9b20c812588119Mark Salyzyn}
7369ea359fce0e401cd7a95fe1ac4e1c9926e2a6eb5Mark Salyzyn
7372ed51d708eda64516ec79ac6397f690de38f0075Mark SalyzynLIBLOG_ABI_PRIVATE int __android_log_is_debuggable() {
7382ed51d708eda64516ec79ac6397f690de38f0075Mark Salyzyn  return 1;
7399ea359fce0e401cd7a95fe1ac4e1c9926e2a6eb5Mark Salyzyn}
740