diff options
author | Mark Salyzyn | 2017-03-09 10:09:43 -0600 |
---|---|---|
committer | Mark Salyzyn | 2017-03-09 11:36:19 -0600 |
commit | 2ed51d708eda64516ec79ac6397f690de38f0075 (patch) | |
tree | 9ea938a4ee0461c443dc99e197827fc36ecd643b /liblog/fake_log_device.c | |
parent | c1b3c8ef2629eac2a73aa4a95bf43a66edf4cd0f (diff) | |
download | platform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.tar.gz platform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.tar.xz platform-system-core-2ed51d708eda64516ec79ac6397f690de38f0075.zip |
liblog: specify clang format
Switch coding style to match
SideEffects: None
Test: compile
Bug: 27405083
Change-Id: Id426d5c5e3b18f2ceec22b31bbc9781aabf6bcca
Diffstat (limited to 'liblog/fake_log_device.c')
-rw-r--r-- | liblog/fake_log_device.c | 1010 |
1 files changed, 500 insertions, 510 deletions
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c index 1d7a157ae..ae7a33412 100644 --- a/liblog/fake_log_device.c +++ b/liblog/fake_log_device.c | |||
@@ -37,9 +37,9 @@ | |||
37 | #include "fake_log_device.h" | 37 | #include "fake_log_device.h" |
38 | #include "log_portability.h" | 38 | #include "log_portability.h" |
39 | 39 | ||
40 | #define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */ | 40 | #define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */ |
41 | 41 | ||
42 | #define kTagSetSize 16 /* arbitrary */ | 42 | #define kTagSetSize 16 /* arbitrary */ |
43 | 43 | ||
44 | #if 0 | 44 | #if 0 |
45 | #define TRACE(...) printf("fake_log_device: " __VA_ARGS__) | 45 | #define TRACE(...) printf("fake_log_device: " __VA_ARGS__) |
@@ -49,45 +49,43 @@ | |||
49 | 49 | ||
50 | /* from the long-dead utils/Log.cpp */ | 50 | /* from the long-dead utils/Log.cpp */ |
51 | typedef enum { | 51 | typedef enum { |
52 | FORMAT_OFF = 0, | 52 | FORMAT_OFF = 0, |
53 | FORMAT_BRIEF, | 53 | FORMAT_BRIEF, |
54 | FORMAT_PROCESS, | 54 | FORMAT_PROCESS, |
55 | FORMAT_TAG, | 55 | FORMAT_TAG, |
56 | FORMAT_THREAD, | 56 | FORMAT_THREAD, |
57 | FORMAT_RAW, | 57 | FORMAT_RAW, |
58 | FORMAT_TIME, | 58 | FORMAT_TIME, |
59 | FORMAT_THREADTIME, | 59 | FORMAT_THREADTIME, |
60 | FORMAT_LONG | 60 | FORMAT_LONG |
61 | } LogFormat; | 61 | } LogFormat; |
62 | 62 | ||
63 | |||
64 | /* | 63 | /* |
65 | * Log driver state. | 64 | * Log driver state. |
66 | */ | 65 | */ |
67 | typedef struct LogState { | 66 | typedef struct LogState { |
68 | /* the fake fd that's seen by the user */ | 67 | /* the fake fd that's seen by the user */ |
69 | int fakeFd; | 68 | int fakeFd; |
70 | 69 | ||
71 | /* a printable name for this fake device */ | 70 | /* a printable name for this fake device */ |
72 | char debugName[sizeof("/dev/log/security")]; | 71 | char debugName[sizeof("/dev/log/security")]; |
73 | 72 | ||
74 | /* nonzero if this is a binary log */ | 73 | /* nonzero if this is a binary log */ |
75 | int isBinary; | 74 | int isBinary; |
76 | 75 | ||
77 | /* global minimum priority */ | 76 | /* global minimum priority */ |
78 | int globalMinPriority; | 77 | int globalMinPriority; |
79 | 78 | ||
80 | /* output format */ | 79 | /* output format */ |
81 | LogFormat outputFormat; | 80 | LogFormat outputFormat; |
82 | 81 | ||
83 | /* tags and priorities */ | 82 | /* tags and priorities */ |
84 | struct { | 83 | struct { |
85 | char tag[kMaxTagLen]; | 84 | char tag[kMaxTagLen]; |
86 | int minPriority; | 85 | int minPriority; |
87 | } tagSet[kTagSetSize]; | 86 | } tagSet[kTagSetSize]; |
88 | } LogState; | 87 | } LogState; |
89 | 88 | ||
90 | |||
91 | #if !defined(_WIN32) | 89 | #if !defined(_WIN32) |
92 | /* | 90 | /* |
93 | * Locking. Since we're emulating a device, we need to be prepared | 91 | * Locking. Since we're emulating a device, we need to be prepared |
@@ -97,28 +95,25 @@ typedef struct LogState { | |||
97 | */ | 95 | */ |
98 | static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER; | 96 | static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER; |
99 | 97 | ||
100 | static void lock() | 98 | static void lock() { |
101 | { | 99 | /* |
102 | /* | 100 | * If we trigger a signal handler in the middle of locked activity and the |
103 | * If we trigger a signal handler in the middle of locked activity and the | 101 | * signal handler logs a message, we could get into a deadlock state. |
104 | * signal handler logs a message, we could get into a deadlock state. | 102 | */ |
105 | */ | 103 | pthread_mutex_lock(&fakeLogDeviceLock); |
106 | pthread_mutex_lock(&fakeLogDeviceLock); | ||
107 | } | 104 | } |
108 | 105 | ||
109 | static void unlock() | 106 | static void unlock() { |
110 | { | 107 | pthread_mutex_unlock(&fakeLogDeviceLock); |
111 | pthread_mutex_unlock(&fakeLogDeviceLock); | ||
112 | } | 108 | } |
113 | 109 | ||
114 | #else // !defined(_WIN32) | 110 | #else // !defined(_WIN32) |
115 | 111 | ||
116 | #define lock() ((void)0) | 112 | #define lock() ((void)0) |
117 | #define unlock() ((void)0) | 113 | #define unlock() ((void)0) |
118 | 114 | ||
119 | #endif // !defined(_WIN32) | 115 | #endif // !defined(_WIN32) |
120 | 116 | ||
121 | |||
122 | /* | 117 | /* |
123 | * File descriptor management. | 118 | * File descriptor management. |
124 | */ | 119 | */ |
@@ -130,45 +125,42 @@ static LogState openLogTable[MAX_OPEN_LOGS]; | |||
130 | * Allocate an fd and associate a new LogState with it. | 125 | * Allocate an fd and associate a new LogState with it. |
131 | * The fd is available via the fakeFd field of the return value. | 126 | * The fd is available via the fakeFd field of the return value. |
132 | */ | 127 | */ |
133 | static LogState *createLogState() | 128 | static LogState* createLogState() { |
134 | { | 129 | size_t i; |
135 | size_t i; | 130 | |
136 | 131 | for (i = 0; i < (sizeof(openLogTable) / sizeof(openLogTable[0])); i++) { | |
137 | for (i = 0; i < (sizeof(openLogTable) / sizeof(openLogTable[0])); i++) { | 132 | if (openLogTable[i].fakeFd == 0) { |
138 | if (openLogTable[i].fakeFd == 0) { | 133 | openLogTable[i].fakeFd = FAKE_FD_BASE + i; |
139 | openLogTable[i].fakeFd = FAKE_FD_BASE + i; | 134 | return &openLogTable[i]; |
140 | return &openLogTable[i]; | ||
141 | } | ||
142 | } | 135 | } |
143 | return NULL; | 136 | } |
137 | return NULL; | ||
144 | } | 138 | } |
145 | 139 | ||
146 | /* | 140 | /* |
147 | * Translate an fd to a LogState. | 141 | * Translate an fd to a LogState. |
148 | */ | 142 | */ |
149 | static LogState *fdToLogState(int fd) | 143 | static LogState* fdToLogState(int fd) { |
150 | { | 144 | if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) { |
151 | if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) { | 145 | return &openLogTable[fd - FAKE_FD_BASE]; |
152 | return &openLogTable[fd - FAKE_FD_BASE]; | 146 | } |
153 | } | 147 | return NULL; |
154 | return NULL; | ||
155 | } | 148 | } |
156 | 149 | ||
157 | /* | 150 | /* |
158 | * Unregister the fake fd and free the memory it pointed to. | 151 | * Unregister the fake fd and free the memory it pointed to. |
159 | */ | 152 | */ |
160 | static void deleteFakeFd(int fd) | 153 | static void deleteFakeFd(int fd) { |
161 | { | 154 | LogState* ls; |
162 | LogState *ls; | ||
163 | 155 | ||
164 | lock(); | 156 | lock(); |
165 | 157 | ||
166 | ls = fdToLogState(fd); | 158 | ls = fdToLogState(fd); |
167 | if (ls != NULL) { | 159 | if (ls != NULL) { |
168 | memset(&openLogTable[fd - FAKE_FD_BASE], 0, sizeof(openLogTable[0])); | 160 | memset(&openLogTable[fd - FAKE_FD_BASE], 0, sizeof(openLogTable[0])); |
169 | } | 161 | } |
170 | 162 | ||
171 | unlock(); | 163 | unlock(); |
172 | } | 164 | } |
173 | 165 | ||
174 | /* | 166 | /* |
@@ -184,145 +176,154 @@ static void deleteFakeFd(int fd) | |||
184 | * We also want to check ANDROID_PRINTF_LOG to determine how the output | 176 | * We also want to check ANDROID_PRINTF_LOG to determine how the output |
185 | * will look. | 177 | * will look. |
186 | */ | 178 | */ |
187 | static void configureInitialState(const char* pathName, LogState* logState) | 179 | static void configureInitialState(const char* pathName, LogState* logState) { |
188 | { | 180 | static const int kDevLogLen = sizeof("/dev/log/") - 1; |
189 | static const int kDevLogLen = sizeof("/dev/log/") - 1; | 181 | |
190 | 182 | strncpy(logState->debugName, pathName, sizeof(logState->debugName)); | |
191 | strncpy(logState->debugName, pathName, sizeof(logState->debugName)); | 183 | logState->debugName[sizeof(logState->debugName) - 1] = '\0'; |
192 | logState->debugName[sizeof(logState->debugName) - 1] = '\0'; | 184 | |
193 | 185 | /* identify binary logs */ | |
194 | /* identify binary logs */ | 186 | if (!strcmp(pathName + kDevLogLen, "events") || |
195 | if (!strcmp(pathName + kDevLogLen, "events") || | 187 | !strcmp(pathName + kDevLogLen, "security")) { |
196 | !strcmp(pathName + kDevLogLen, "security")) { | 188 | logState->isBinary = 1; |
197 | logState->isBinary = 1; | 189 | } |
198 | } | 190 | |
199 | 191 | /* global min priority defaults to "info" level */ | |
200 | /* global min priority defaults to "info" level */ | 192 | logState->globalMinPriority = ANDROID_LOG_INFO; |
201 | logState->globalMinPriority = ANDROID_LOG_INFO; | 193 | |
202 | 194 | /* | |
203 | /* | 195 | * This is based on the the long-dead utils/Log.cpp code. |
204 | * This is based on the the long-dead utils/Log.cpp code. | 196 | */ |
205 | */ | 197 | const char* tags = getenv("ANDROID_LOG_TAGS"); |
206 | const char* tags = getenv("ANDROID_LOG_TAGS"); | 198 | TRACE("Found ANDROID_LOG_TAGS='%s'\n", tags); |
207 | TRACE("Found ANDROID_LOG_TAGS='%s'\n", tags); | 199 | if (tags != NULL) { |
208 | if (tags != NULL) { | 200 | int entry = 0; |
209 | int entry = 0; | 201 | |
210 | 202 | while (*tags != '\0') { | |
211 | while (*tags != '\0') { | 203 | char tagName[kMaxTagLen]; |
212 | char tagName[kMaxTagLen]; | 204 | int i, minPrio; |
213 | int i, minPrio; | 205 | |
214 | 206 | while (isspace(*tags)) tags++; | |
215 | while (isspace(*tags)) | 207 | |
216 | tags++; | 208 | i = 0; |
217 | 209 | while (*tags != '\0' && !isspace(*tags) && *tags != ':' && | |
218 | i = 0; | 210 | i < kMaxTagLen) { |
219 | while (*tags != '\0' && !isspace(*tags) && *tags != ':' && | 211 | tagName[i++] = *tags++; |
220 | i < kMaxTagLen) { | 212 | } |
221 | tagName[i++] = *tags++; | 213 | if (i == kMaxTagLen) { |
222 | } | 214 | TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen - 1); |
223 | if (i == kMaxTagLen) { | 215 | return; |
224 | TRACE("ERROR: env tag too long (%d chars max)\n", kMaxTagLen-1); | 216 | } |
225 | return; | 217 | tagName[i] = '\0'; |
226 | } | 218 | |
227 | tagName[i] = '\0'; | 219 | /* default priority, if there's no ":" part; also zero out '*' */ |
228 | 220 | minPrio = ANDROID_LOG_VERBOSE; | |
229 | /* default priority, if there's no ":" part; also zero out '*' */ | 221 | if (tagName[0] == '*' && tagName[1] == '\0') { |
222 | minPrio = ANDROID_LOG_DEBUG; | ||
223 | tagName[0] = '\0'; | ||
224 | } | ||
225 | |||
226 | if (*tags == ':') { | ||
227 | tags++; | ||
228 | if (*tags >= '0' && *tags <= '9') { | ||
229 | if (*tags >= ('0' + ANDROID_LOG_SILENT)) | ||
230 | minPrio = ANDROID_LOG_VERBOSE; | 230 | minPrio = ANDROID_LOG_VERBOSE; |
231 | if (tagName[0] == '*' && tagName[1] == '\0') { | 231 | else |
232 | minPrio = ANDROID_LOG_DEBUG; | 232 | minPrio = *tags - '\0'; |
233 | tagName[0] = '\0'; | 233 | } else { |
234 | } | 234 | switch (*tags) { |
235 | 235 | case 'v': | |
236 | if (*tags == ':') { | 236 | minPrio = ANDROID_LOG_VERBOSE; |
237 | tags++; | 237 | break; |
238 | if (*tags >= '0' && *tags <= '9') { | 238 | case 'd': |
239 | if (*tags >= ('0' + ANDROID_LOG_SILENT)) | 239 | minPrio = ANDROID_LOG_DEBUG; |
240 | minPrio = ANDROID_LOG_VERBOSE; | 240 | break; |
241 | else | 241 | case 'i': |
242 | minPrio = *tags - '\0'; | 242 | minPrio = ANDROID_LOG_INFO; |
243 | } else { | 243 | break; |
244 | switch (*tags) { | 244 | case 'w': |
245 | case 'v': minPrio = ANDROID_LOG_VERBOSE; break; | 245 | minPrio = ANDROID_LOG_WARN; |
246 | case 'd': minPrio = ANDROID_LOG_DEBUG; break; | 246 | break; |
247 | case 'i': minPrio = ANDROID_LOG_INFO; break; | 247 | case 'e': |
248 | case 'w': minPrio = ANDROID_LOG_WARN; break; | 248 | minPrio = ANDROID_LOG_ERROR; |
249 | case 'e': minPrio = ANDROID_LOG_ERROR; break; | 249 | break; |
250 | case 'f': minPrio = ANDROID_LOG_FATAL; break; | 250 | case 'f': |
251 | case 's': minPrio = ANDROID_LOG_SILENT; break; | 251 | minPrio = ANDROID_LOG_FATAL; |
252 | default: minPrio = ANDROID_LOG_DEFAULT; break; | 252 | break; |
253 | } | 253 | case 's': |
254 | } | 254 | minPrio = ANDROID_LOG_SILENT; |
255 | 255 | break; | |
256 | tags++; | 256 | default: |
257 | if (*tags != '\0' && !isspace(*tags)) { | 257 | minPrio = ANDROID_LOG_DEFAULT; |
258 | TRACE("ERROR: garbage in tag env; expected whitespace\n"); | 258 | break; |
259 | TRACE(" env='%s'\n", tags); | 259 | } |
260 | return; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | if (tagName[0] == 0) { | ||
265 | logState->globalMinPriority = minPrio; | ||
266 | TRACE("+++ global min prio %d\n", logState->globalMinPriority); | ||
267 | } else { | ||
268 | logState->tagSet[entry].minPriority = minPrio; | ||
269 | strcpy(logState->tagSet[entry].tag, tagName); | ||
270 | TRACE("+++ entry %d: %s:%d\n", | ||
271 | entry, | ||
272 | logState->tagSet[entry].tag, | ||
273 | logState->tagSet[entry].minPriority); | ||
274 | entry++; | ||
275 | } | ||
276 | } | 260 | } |
277 | } | ||
278 | |||
279 | 261 | ||
280 | /* | 262 | tags++; |
281 | * Taken from the long-dead utils/Log.cpp | 263 | if (*tags != '\0' && !isspace(*tags)) { |
282 | */ | 264 | TRACE("ERROR: garbage in tag env; expected whitespace\n"); |
283 | const char* fstr = getenv("ANDROID_PRINTF_LOG"); | 265 | TRACE(" env='%s'\n", tags); |
284 | LogFormat format; | 266 | return; |
285 | if (fstr == NULL) { | 267 | } |
286 | format = FORMAT_BRIEF; | 268 | } |
287 | } else { | 269 | |
288 | if (strcmp(fstr, "brief") == 0) | 270 | if (tagName[0] == 0) { |
289 | format = FORMAT_BRIEF; | 271 | logState->globalMinPriority = minPrio; |
290 | else if (strcmp(fstr, "process") == 0) | 272 | TRACE("+++ global min prio %d\n", logState->globalMinPriority); |
291 | format = FORMAT_PROCESS; | 273 | } else { |
292 | else if (strcmp(fstr, "tag") == 0) | 274 | logState->tagSet[entry].minPriority = minPrio; |
293 | format = FORMAT_PROCESS; | 275 | strcpy(logState->tagSet[entry].tag, tagName); |
294 | else if (strcmp(fstr, "thread") == 0) | 276 | TRACE("+++ entry %d: %s:%d\n", entry, logState->tagSet[entry].tag, |
295 | format = FORMAT_PROCESS; | 277 | logState->tagSet[entry].minPriority); |
296 | else if (strcmp(fstr, "raw") == 0) | 278 | entry++; |
297 | format = FORMAT_PROCESS; | 279 | } |
298 | else if (strcmp(fstr, "time") == 0) | ||
299 | format = FORMAT_PROCESS; | ||
300 | else if (strcmp(fstr, "long") == 0) | ||
301 | format = FORMAT_PROCESS; | ||
302 | else | ||
303 | format = (LogFormat) atoi(fstr); // really?! | ||
304 | } | 280 | } |
305 | 281 | } | |
306 | logState->outputFormat = format; | 282 | |
283 | /* | ||
284 | * Taken from the long-dead utils/Log.cpp | ||
285 | */ | ||
286 | const char* fstr = getenv("ANDROID_PRINTF_LOG"); | ||
287 | LogFormat format; | ||
288 | if (fstr == NULL) { | ||
289 | format = FORMAT_BRIEF; | ||
290 | } else { | ||
291 | if (strcmp(fstr, "brief") == 0) | ||
292 | format = FORMAT_BRIEF; | ||
293 | else if (strcmp(fstr, "process") == 0) | ||
294 | format = FORMAT_PROCESS; | ||
295 | else if (strcmp(fstr, "tag") == 0) | ||
296 | format = FORMAT_PROCESS; | ||
297 | else if (strcmp(fstr, "thread") == 0) | ||
298 | format = FORMAT_PROCESS; | ||
299 | else if (strcmp(fstr, "raw") == 0) | ||
300 | format = FORMAT_PROCESS; | ||
301 | else if (strcmp(fstr, "time") == 0) | ||
302 | format = FORMAT_PROCESS; | ||
303 | else if (strcmp(fstr, "long") == 0) | ||
304 | format = FORMAT_PROCESS; | ||
305 | else | ||
306 | format = (LogFormat)atoi(fstr); // really?! | ||
307 | } | ||
308 | |||
309 | logState->outputFormat = format; | ||
307 | } | 310 | } |
308 | 311 | ||
309 | /* | 312 | /* |
310 | * Return a human-readable string for the priority level. Always returns | 313 | * Return a human-readable string for the priority level. Always returns |
311 | * a valid string. | 314 | * a valid string. |
312 | */ | 315 | */ |
313 | static const char* getPriorityString(int priority) | 316 | static const char* getPriorityString(int priority) { |
314 | { | 317 | /* the first character of each string should be unique */ |
315 | /* the first character of each string should be unique */ | 318 | static const char* priorityStrings[] = { "Verbose", "Debug", "Info", |
316 | static const char* priorityStrings[] = { | 319 | "Warn", "Error", "Assert" }; |
317 | "Verbose", "Debug", "Info", "Warn", "Error", "Assert" | 320 | int idx; |
318 | }; | 321 | |
319 | int idx; | 322 | idx = (int)priority - (int)ANDROID_LOG_VERBOSE; |
320 | 323 | if (idx < 0 || | |
321 | idx = (int)priority - (int)ANDROID_LOG_VERBOSE; | 324 | idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0]))) |
322 | if (idx < 0 || | 325 | return "?unknown?"; |
323 | idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0]))) | 326 | return priorityStrings[idx]; |
324 | return "?unknown?"; | ||
325 | return priorityStrings[idx]; | ||
326 | } | 327 | } |
327 | 328 | ||
328 | #if defined(_WIN32) | 329 | #if defined(_WIN32) |
@@ -330,227 +331,229 @@ static const char* getPriorityString(int priority) | |||
330 | * WIN32 does not have writev(). | 331 | * WIN32 does not have writev(). |
331 | * Make up something to replace it. | 332 | * Make up something to replace it. |
332 | */ | 333 | */ |
333 | static ssize_t fake_writev(int fd, const struct iovec *iov, int iovcnt) { | 334 | static ssize_t fake_writev(int fd, const struct iovec* iov, int iovcnt) { |
334 | ssize_t result = 0; | 335 | ssize_t result = 0; |
335 | const struct iovec* end = iov + iovcnt; | 336 | const struct iovec* end = iov + iovcnt; |
336 | for (; iov < end; iov++) { | 337 | for (; iov < end; iov++) { |
337 | ssize_t w = write(fd, iov->iov_base, iov->iov_len); | 338 | ssize_t w = write(fd, iov->iov_base, iov->iov_len); |
338 | if (w != (ssize_t) iov->iov_len) { | 339 | if (w != (ssize_t)iov->iov_len) { |
339 | if (w < 0) | 340 | if (w < 0) return w; |
340 | return w; | 341 | return result + w; |
341 | return result + w; | ||
342 | } | ||
343 | result += w; | ||
344 | } | 342 | } |
345 | return result; | 343 | result += w; |
344 | } | ||
345 | return result; | ||
346 | } | 346 | } |
347 | 347 | ||
348 | #define writev fake_writev | 348 | #define writev fake_writev |
349 | #endif | 349 | #endif |
350 | 350 | ||
351 | |||
352 | /* | 351 | /* |
353 | * Write a filtered log message to stderr. | 352 | * Write a filtered log message to stderr. |
354 | * | 353 | * |
355 | * Log format parsing taken from the long-dead utils/Log.cpp. | 354 | * Log format parsing taken from the long-dead utils/Log.cpp. |
356 | */ | 355 | */ |
357 | static void showLog(LogState *state, | 356 | static void showLog(LogState* state, int logPrio, const char* tag, |
358 | int logPrio, const char* tag, const char* msg) | 357 | const char* msg) { |
359 | { | ||
360 | #if !defined(_WIN32) | 358 | #if !defined(_WIN32) |
361 | struct tm tmBuf; | 359 | struct tm tmBuf; |
362 | #endif | 360 | #endif |
363 | struct tm* ptm; | 361 | struct tm* ptm; |
364 | char timeBuf[32]; | 362 | char timeBuf[32]; |
365 | char prefixBuf[128], suffixBuf[128]; | 363 | char prefixBuf[128], suffixBuf[128]; |
366 | char priChar; | 364 | char priChar; |
367 | time_t when; | 365 | time_t when; |
368 | #if !defined(_WIN32) | 366 | #if !defined(_WIN32) |
369 | pid_t pid, tid; | 367 | pid_t pid, tid; |
370 | #else | 368 | #else |
371 | uint32_t pid, tid; | 369 | uint32_t pid, tid; |
372 | #endif | 370 | #endif |
373 | 371 | ||
374 | TRACE("LOG %d: %s %s", logPrio, tag, msg); | 372 | TRACE("LOG %d: %s %s", logPrio, tag, msg); |
375 | 373 | ||
376 | priChar = getPriorityString(logPrio)[0]; | 374 | priChar = getPriorityString(logPrio)[0]; |
377 | when = time(NULL); | 375 | when = time(NULL); |
378 | pid = tid = getpid(); // find gettid()? | 376 | pid = tid = getpid(); // find gettid()? |
379 | 377 | ||
380 | /* | 378 | /* |
381 | * Get the current date/time in pretty form | 379 | * Get the current date/time in pretty form |
382 | * | 380 | * |
383 | * It's often useful when examining a log with "less" to jump to | 381 | * It's often useful when examining a log with "less" to jump to |
384 | * a specific point in the file by searching for the date/time stamp. | 382 | * a specific point in the file by searching for the date/time stamp. |
385 | * For this reason it's very annoying to have regexp meta characters | 383 | * For this reason it's very annoying to have regexp meta characters |
386 | * in the time stamp. Don't use forward slashes, parenthesis, | 384 | * in the time stamp. Don't use forward slashes, parenthesis, |
387 | * brackets, asterisks, or other special chars here. | 385 | * brackets, asterisks, or other special chars here. |
388 | */ | 386 | */ |
389 | #if !defined(_WIN32) | 387 | #if !defined(_WIN32) |
390 | ptm = localtime_r(&when, &tmBuf); | 388 | ptm = localtime_r(&when, &tmBuf); |
391 | #else | 389 | #else |
392 | ptm = localtime(&when); | 390 | ptm = localtime(&when); |
393 | #endif | 391 | #endif |
394 | //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm); | 392 | // strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm); |
395 | strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); | 393 | strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); |
396 | 394 | ||
397 | /* | 395 | /* |
398 | * Construct a buffer containing the log header and log message. | 396 | * Construct a buffer containing the log header and log message. |
399 | */ | 397 | */ |
400 | size_t prefixLen, suffixLen; | 398 | size_t prefixLen, suffixLen; |
401 | 399 | ||
402 | switch (state->outputFormat) { | 400 | switch (state->outputFormat) { |
403 | case FORMAT_TAG: | 401 | case FORMAT_TAG: |
404 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 402 | prefixLen = |
405 | "%c/%-8s: ", priChar, tag); | 403 | snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag); |
406 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 404 | strcpy(suffixBuf, "\n"); |
407 | break; | 405 | suffixLen = 1; |
406 | break; | ||
408 | case FORMAT_PROCESS: | 407 | case FORMAT_PROCESS: |
409 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 408 | prefixLen = |
410 | "%c(%5d) ", priChar, pid); | 409 | snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid); |
411 | suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), | 410 | suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), " (%s)\n", tag); |
412 | " (%s)\n", tag); | 411 | break; |
413 | break; | ||
414 | case FORMAT_THREAD: | 412 | case FORMAT_THREAD: |
415 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 413 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ", |
416 | "%c(%5d:%5d) ", priChar, pid, tid); | 414 | priChar, pid, tid); |
417 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 415 | strcpy(suffixBuf, "\n"); |
418 | break; | 416 | suffixLen = 1; |
417 | break; | ||
419 | case FORMAT_RAW: | 418 | case FORMAT_RAW: |
420 | prefixBuf[0] = 0; prefixLen = 0; | 419 | prefixBuf[0] = 0; |
421 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 420 | prefixLen = 0; |
422 | break; | 421 | strcpy(suffixBuf, "\n"); |
422 | suffixLen = 1; | ||
423 | break; | ||
423 | case FORMAT_TIME: | 424 | case FORMAT_TIME: |
424 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 425 | prefixLen = |
425 | "%s %-8s\n\t", timeBuf, tag); | 426 | snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag); |
426 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 427 | strcpy(suffixBuf, "\n"); |
427 | break; | 428 | suffixLen = 1; |
429 | break; | ||
428 | case FORMAT_THREADTIME: | 430 | case FORMAT_THREADTIME: |
429 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 431 | prefixLen = |
430 | "%s %5d %5d %c %-8s \n\t", timeBuf, pid, tid, priChar, tag); | 432 | snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t", |
431 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 433 | timeBuf, pid, tid, priChar, tag); |
432 | break; | 434 | strcpy(suffixBuf, "\n"); |
435 | suffixLen = 1; | ||
436 | break; | ||
433 | case FORMAT_LONG: | 437 | case FORMAT_LONG: |
434 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 438 | prefixLen = |
435 | "[ %s %5d:%5d %c/%-8s ]\n", | 439 | snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n", |
436 | timeBuf, pid, tid, priChar, tag); | 440 | timeBuf, pid, tid, priChar, tag); |
437 | strcpy(suffixBuf, "\n\n"); suffixLen = 2; | 441 | strcpy(suffixBuf, "\n\n"); |
438 | break; | 442 | suffixLen = 2; |
443 | break; | ||
439 | default: | 444 | default: |
440 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), | 445 | prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), |
441 | "%c/%-8s(%5d): ", priChar, tag, pid); | 446 | "%c/%-8s(%5d): ", priChar, tag, pid); |
442 | strcpy(suffixBuf, "\n"); suffixLen = 1; | 447 | strcpy(suffixBuf, "\n"); |
443 | break; | 448 | suffixLen = 1; |
444 | } | 449 | break; |
445 | 450 | } | |
446 | /* | 451 | |
447 | * Figure out how many lines there will be. | 452 | /* |
448 | */ | 453 | * Figure out how many lines there will be. |
449 | const char* end = msg + strlen(msg); | 454 | */ |
450 | size_t numLines = 0; | 455 | const char* end = msg + strlen(msg); |
451 | const char* p = msg; | 456 | size_t numLines = 0; |
452 | while (p < end) { | 457 | const char* p = msg; |
453 | if (*p++ == '\n') numLines++; | 458 | while (p < end) { |
459 | if (*p++ == '\n') numLines++; | ||
460 | } | ||
461 | if (p > msg && *(p - 1) != '\n') { | ||
462 | numLines++; | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * Create an array of iovecs large enough to write all of | ||
467 | * the lines with a prefix and a suffix. | ||
468 | */ | ||
469 | const size_t INLINE_VECS = 64; | ||
470 | const size_t MAX_LINES = ((size_t)~0) / (3 * sizeof(struct iovec*)); | ||
471 | struct iovec stackVec[INLINE_VECS]; | ||
472 | struct iovec* vec = stackVec; | ||
473 | size_t numVecs; | ||
474 | |||
475 | if (numLines > MAX_LINES) numLines = MAX_LINES; | ||
476 | |||
477 | numVecs = numLines * 3; // 3 iovecs per line. | ||
478 | if (numVecs > INLINE_VECS) { | ||
479 | vec = (struct iovec*)malloc(sizeof(struct iovec) * numVecs); | ||
480 | if (vec == NULL) { | ||
481 | msg = "LOG: write failed, no memory"; | ||
482 | numVecs = INLINE_VECS; | ||
483 | numLines = numVecs / 3; | ||
484 | vec = stackVec; | ||
454 | } | 485 | } |
455 | if (p > msg && *(p-1) != '\n') { | 486 | } |
456 | numLines++; | 487 | |
488 | /* | ||
489 | * Fill in the iovec pointers. | ||
490 | */ | ||
491 | p = msg; | ||
492 | struct iovec* v = vec; | ||
493 | int totalLen = 0; | ||
494 | while (numLines > 0 && p < end) { | ||
495 | if (prefixLen > 0) { | ||
496 | v->iov_base = prefixBuf; | ||
497 | v->iov_len = prefixLen; | ||
498 | totalLen += prefixLen; | ||
499 | v++; | ||
457 | } | 500 | } |
458 | 501 | const char* start = p; | |
459 | /* | 502 | while (p < end && *p != '\n') { |
460 | * Create an array of iovecs large enough to write all of | 503 | p++; |
461 | * the lines with a prefix and a suffix. | ||
462 | */ | ||
463 | const size_t INLINE_VECS = 64; | ||
464 | const size_t MAX_LINES = ((size_t)~0)/(3*sizeof(struct iovec*)); | ||
465 | struct iovec stackVec[INLINE_VECS]; | ||
466 | struct iovec* vec = stackVec; | ||
467 | size_t numVecs; | ||
468 | |||
469 | if (numLines > MAX_LINES) | ||
470 | numLines = MAX_LINES; | ||
471 | |||
472 | numVecs = numLines * 3; // 3 iovecs per line. | ||
473 | if (numVecs > INLINE_VECS) { | ||
474 | vec = (struct iovec*)malloc(sizeof(struct iovec)*numVecs); | ||
475 | if (vec == NULL) { | ||
476 | msg = "LOG: write failed, no memory"; | ||
477 | numVecs = INLINE_VECS; | ||
478 | numLines = numVecs / 3; | ||
479 | vec = stackVec; | ||
480 | } | ||
481 | } | 504 | } |
482 | 505 | if ((p - start) > 0) { | |
483 | /* | 506 | v->iov_base = (void*)start; |
484 | * Fill in the iovec pointers. | 507 | v->iov_len = p - start; |
485 | */ | 508 | totalLen += p - start; |
486 | p = msg; | 509 | v++; |
487 | struct iovec* v = vec; | ||
488 | int totalLen = 0; | ||
489 | while (numLines > 0 && p < end) { | ||
490 | if (prefixLen > 0) { | ||
491 | v->iov_base = prefixBuf; | ||
492 | v->iov_len = prefixLen; | ||
493 | totalLen += prefixLen; | ||
494 | v++; | ||
495 | } | ||
496 | const char* start = p; | ||
497 | while (p < end && *p != '\n') { | ||
498 | p++; | ||
499 | } | ||
500 | if ((p-start) > 0) { | ||
501 | v->iov_base = (void*)start; | ||
502 | v->iov_len = p-start; | ||
503 | totalLen += p-start; | ||
504 | v++; | ||
505 | } | ||
506 | if (*p == '\n') p++; | ||
507 | if (suffixLen > 0) { | ||
508 | v->iov_base = suffixBuf; | ||
509 | v->iov_len = suffixLen; | ||
510 | totalLen += suffixLen; | ||
511 | v++; | ||
512 | } | ||
513 | numLines -= 1; | ||
514 | } | 510 | } |
515 | 511 | if (*p == '\n') p++; | |
516 | /* | 512 | if (suffixLen > 0) { |
517 | * Write the entire message to the log file with a single writev() call. | 513 | v->iov_base = suffixBuf; |
518 | * We need to use this rather than a collection of printf()s on a FILE* | 514 | v->iov_len = suffixLen; |
519 | * because of multi-threading and multi-process issues. | 515 | totalLen += suffixLen; |
520 | * | 516 | v++; |
521 | * If the file was not opened with O_APPEND, this will produce interleaved | ||
522 | * output when called on the same file from multiple processes. | ||
523 | * | ||
524 | * If the file descriptor is actually a network socket, the writev() | ||
525 | * call may return with a partial write. Putting the writev() call in | ||
526 | * a loop can result in interleaved data. This can be alleviated | ||
527 | * somewhat by wrapping the writev call in the Mutex. | ||
528 | */ | ||
529 | |||
530 | for(;;) { | ||
531 | int cc = writev(fileno(stderr), vec, v-vec); | ||
532 | |||
533 | if (cc == totalLen) break; | ||
534 | |||
535 | if (cc < 0) { | ||
536 | if(errno == EINTR) continue; | ||
537 | |||
538 | /* can't really log the failure; for now, throw out a stderr */ | ||
539 | fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno); | ||
540 | break; | ||
541 | } else { | ||
542 | /* shouldn't happen when writing to file or tty */ | ||
543 | fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", cc, totalLen); | ||
544 | break; | ||
545 | } | ||
546 | } | 517 | } |
518 | numLines -= 1; | ||
519 | } | ||
520 | |||
521 | /* | ||
522 | * Write the entire message to the log file with a single writev() call. | ||
523 | * We need to use this rather than a collection of printf()s on a FILE* | ||
524 | * because of multi-threading and multi-process issues. | ||
525 | * | ||
526 | * If the file was not opened with O_APPEND, this will produce interleaved | ||
527 | * output when called on the same file from multiple processes. | ||
528 | * | ||
529 | * If the file descriptor is actually a network socket, the writev() | ||
530 | * call may return with a partial write. Putting the writev() call in | ||
531 | * a loop can result in interleaved data. This can be alleviated | ||
532 | * somewhat by wrapping the writev call in the Mutex. | ||
533 | */ | ||
534 | |||
535 | for (;;) { | ||
536 | int cc = writev(fileno(stderr), vec, v - vec); | ||
537 | |||
538 | if (cc == totalLen) break; | ||
539 | |||
540 | if (cc < 0) { | ||
541 | if (errno == EINTR) continue; | ||
542 | |||
543 | /* can't really log the failure; for now, throw out a stderr */ | ||
544 | fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno); | ||
545 | break; | ||
546 | } else { | ||
547 | /* shouldn't happen when writing to file or tty */ | ||
548 | fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", cc, totalLen); | ||
549 | break; | ||
550 | } | ||
551 | } | ||
547 | 552 | ||
548 | /* if we allocated storage for the iovecs, free it */ | 553 | /* if we allocated storage for the iovecs, free it */ |
549 | if (vec != stackVec) | 554 | if (vec != stackVec) free(vec); |
550 | free(vec); | ||
551 | } | 555 | } |
552 | 556 | ||
553 | |||
554 | /* | 557 | /* |
555 | * Receive a log message. We happen to know that "vector" has three parts: | 558 | * Receive a log message. We happen to know that "vector" has three parts: |
556 | * | 559 | * |
@@ -558,103 +561,98 @@ static void showLog(LogState *state, | |||
558 | * tag (N bytes -- null-terminated ASCII string) | 561 | * tag (N bytes -- null-terminated ASCII string) |
559 | * message (N bytes -- null-terminated ASCII string) | 562 | * message (N bytes -- null-terminated ASCII string) |
560 | */ | 563 | */ |
561 | static ssize_t logWritev(int fd, const struct iovec* vector, int count) | 564 | static ssize_t logWritev(int fd, const struct iovec* vector, int count) { |
562 | { | 565 | LogState* state; |
563 | LogState* state; | 566 | |
564 | 567 | /* Make sure that no-one frees the LogState while we're using it. | |
565 | /* Make sure that no-one frees the LogState while we're using it. | 568 | * Also guarantees that only one thread is in showLog() at a given |
566 | * Also guarantees that only one thread is in showLog() at a given | 569 | * time (if it matters). |
567 | * time (if it matters). | 570 | */ |
568 | */ | 571 | lock(); |
569 | lock(); | 572 | |
570 | 573 | state = fdToLogState(fd); | |
571 | state = fdToLogState(fd); | 574 | if (state == NULL) { |
572 | if (state == NULL) { | 575 | errno = EBADF; |
573 | errno = EBADF; | 576 | goto error; |
574 | goto error; | 577 | } |
578 | |||
579 | if (state->isBinary) { | ||
580 | TRACE("%s: ignoring binary log\n", state->debugName); | ||
581 | goto bail; | ||
582 | } | ||
583 | |||
584 | if (count != 3) { | ||
585 | TRACE("%s: writevLog with count=%d not expected\n", state->debugName, count); | ||
586 | goto error; | ||
587 | } | ||
588 | |||
589 | /* pull out the three fields */ | ||
590 | int logPrio = *(const char*)vector[0].iov_base; | ||
591 | const char* tag = (const char*)vector[1].iov_base; | ||
592 | const char* msg = (const char*)vector[2].iov_base; | ||
593 | |||
594 | /* see if this log tag is configured */ | ||
595 | int i; | ||
596 | int minPrio = state->globalMinPriority; | ||
597 | for (i = 0; i < kTagSetSize; i++) { | ||
598 | if (state->tagSet[i].minPriority == ANDROID_LOG_UNKNOWN) | ||
599 | break; /* reached end of configured values */ | ||
600 | |||
601 | if (strcmp(state->tagSet[i].tag, tag) == 0) { | ||
602 | // TRACE("MATCH tag '%s'\n", tag); | ||
603 | minPrio = state->tagSet[i].minPriority; | ||
604 | break; | ||
575 | } | 605 | } |
606 | } | ||
576 | 607 | ||
577 | if (state->isBinary) { | 608 | if (logPrio >= minPrio) { |
578 | TRACE("%s: ignoring binary log\n", state->debugName); | 609 | showLog(state, logPrio, tag, msg); |
579 | goto bail; | 610 | } else { |
580 | } | 611 | // TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg); |
581 | 612 | } | |
582 | if (count != 3) { | ||
583 | TRACE("%s: writevLog with count=%d not expected\n", | ||
584 | state->debugName, count); | ||
585 | goto error; | ||
586 | } | ||
587 | |||
588 | /* pull out the three fields */ | ||
589 | int logPrio = *(const char*)vector[0].iov_base; | ||
590 | const char* tag = (const char*) vector[1].iov_base; | ||
591 | const char* msg = (const char*) vector[2].iov_base; | ||
592 | |||
593 | /* see if this log tag is configured */ | ||
594 | int i; | ||
595 | int minPrio = state->globalMinPriority; | ||
596 | for (i = 0; i < kTagSetSize; i++) { | ||
597 | if (state->tagSet[i].minPriority == ANDROID_LOG_UNKNOWN) | ||
598 | break; /* reached end of configured values */ | ||
599 | |||
600 | if (strcmp(state->tagSet[i].tag, tag) == 0) { | ||
601 | //TRACE("MATCH tag '%s'\n", tag); | ||
602 | minPrio = state->tagSet[i].minPriority; | ||
603 | break; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | if (logPrio >= minPrio) { | ||
608 | showLog(state, logPrio, tag, msg); | ||
609 | } else { | ||
610 | //TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg); | ||
611 | } | ||
612 | 613 | ||
613 | bail: | 614 | bail: |
614 | unlock(); | 615 | unlock(); |
615 | int len = 0; | 616 | int len = 0; |
616 | for (i = 0; i < count; ++i) { | 617 | for (i = 0; i < count; ++i) { |
617 | len += vector[i].iov_len; | 618 | len += vector[i].iov_len; |
618 | } | 619 | } |
619 | return len; | 620 | return len; |
620 | 621 | ||
621 | error: | 622 | error: |
622 | unlock(); | 623 | unlock(); |
623 | return -1; | 624 | return -1; |
624 | } | 625 | } |
625 | 626 | ||
626 | /* | 627 | /* |
627 | * Free up our state and close the fake descriptor. | 628 | * Free up our state and close the fake descriptor. |
628 | */ | 629 | */ |
629 | static int logClose(int fd) | 630 | static int logClose(int fd) { |
630 | { | 631 | deleteFakeFd(fd); |
631 | deleteFakeFd(fd); | 632 | return 0; |
632 | return 0; | ||
633 | } | 633 | } |
634 | 634 | ||
635 | /* | 635 | /* |
636 | * Open a log output device and return a fake fd. | 636 | * Open a log output device and return a fake fd. |
637 | */ | 637 | */ |
638 | static int logOpen(const char* pathName, int flags __unused) | 638 | static int logOpen(const char* pathName, int flags __unused) { |
639 | { | 639 | LogState* logState; |
640 | LogState *logState; | 640 | int fd = -1; |
641 | int fd = -1; | ||
642 | |||
643 | lock(); | ||
644 | |||
645 | logState = createLogState(); | ||
646 | if (logState != NULL) { | ||
647 | configureInitialState(pathName, logState); | ||
648 | fd = logState->fakeFd; | ||
649 | } else { | ||
650 | errno = ENFILE; | ||
651 | } | ||
652 | 641 | ||
653 | unlock(); | 642 | lock(); |
654 | 643 | ||
655 | return fd; | 644 | logState = createLogState(); |
656 | } | 645 | if (logState != NULL) { |
646 | configureInitialState(pathName, logState); | ||
647 | fd = logState->fakeFd; | ||
648 | } else { | ||
649 | errno = ENFILE; | ||
650 | } | ||
651 | |||
652 | unlock(); | ||
657 | 653 | ||
654 | return fd; | ||
655 | } | ||
658 | 656 | ||
659 | /* | 657 | /* |
660 | * Runtime redirection. If this binary is running in the simulator, | 658 | * Runtime redirection. If this binary is running in the simulator, |
@@ -662,38 +660,36 @@ static int logOpen(const char* pathName, int flags __unused) | |||
662 | * outside of the simulator, write the log messages to stderr. | 660 | * outside of the simulator, write the log messages to stderr. |
663 | */ | 661 | */ |
664 | 662 | ||
665 | static int (*redirectOpen)(const char *pathName, int flags) = NULL; | 663 | static int (*redirectOpen)(const char* pathName, int flags) = NULL; |
666 | static int (*redirectClose)(int fd) = NULL; | 664 | static int (*redirectClose)(int fd) = NULL; |
667 | static ssize_t (*redirectWritev)(int fd, const struct iovec* vector, int count) | 665 | static ssize_t (*redirectWritev)(int fd, const struct iovec* vector, |
668 | = NULL; | 666 | int count) = NULL; |
669 | 667 | ||
670 | static void setRedirects() | 668 | static void setRedirects() { |
671 | { | 669 | const char* ws; |
672 | const char *ws; | 670 | |
673 | 671 | /* Wrapsim sets this environment variable on children that it's | |
674 | /* Wrapsim sets this environment variable on children that it's | 672 | * created using its LD_PRELOAD wrapper. |
675 | * created using its LD_PRELOAD wrapper. | 673 | */ |
676 | */ | 674 | ws = getenv("ANDROID_WRAPSIM"); |
677 | ws = getenv("ANDROID_WRAPSIM"); | 675 | if (ws != NULL && strcmp(ws, "1") == 0) { |
678 | if (ws != NULL && strcmp(ws, "1") == 0) { | 676 | /* We're running inside wrapsim, so we can just write to the device. */ |
679 | /* We're running inside wrapsim, so we can just write to the device. */ | 677 | redirectOpen = (int (*)(const char* pathName, int flags))open; |
680 | redirectOpen = (int (*)(const char *pathName, int flags))open; | 678 | redirectClose = close; |
681 | redirectClose = close; | 679 | redirectWritev = writev; |
682 | redirectWritev = writev; | 680 | } else { |
683 | } else { | 681 | /* There's no device to delegate to; handle the logging ourselves. */ |
684 | /* There's no device to delegate to; handle the logging ourselves. */ | 682 | redirectOpen = logOpen; |
685 | redirectOpen = logOpen; | 683 | redirectClose = logClose; |
686 | redirectClose = logClose; | 684 | redirectWritev = logWritev; |
687 | redirectWritev = logWritev; | 685 | } |
688 | } | ||
689 | } | 686 | } |
690 | 687 | ||
691 | LIBLOG_HIDDEN int fakeLogOpen(const char *pathName, int flags) | 688 | LIBLOG_HIDDEN int fakeLogOpen(const char* pathName, int flags) { |
692 | { | 689 | if (redirectOpen == NULL) { |
693 | if (redirectOpen == NULL) { | 690 | setRedirects(); |
694 | setRedirects(); | 691 | } |
695 | } | 692 | return redirectOpen(pathName, flags); |
696 | return redirectOpen(pathName, flags); | ||
697 | } | 693 | } |
698 | 694 | ||
699 | /* | 695 | /* |
@@ -707,43 +703,37 @@ LIBLOG_HIDDEN int fakeLogOpen(const char *pathName, int flags) | |||
707 | * call is in the exit handler. Logging can continue in the exit handler to | 703 | * call is in the exit handler. Logging can continue in the exit handler to |
708 | * help debug HOST tools ... | 704 | * help debug HOST tools ... |
709 | */ | 705 | */ |
710 | LIBLOG_HIDDEN int fakeLogClose(int fd) | 706 | LIBLOG_HIDDEN int fakeLogClose(int fd) { |
711 | { | 707 | /* Assume that open() was called first. */ |
712 | /* Assume that open() was called first. */ | 708 | return redirectClose(fd); |
713 | return redirectClose(fd); | ||
714 | } | 709 | } |
715 | 710 | ||
716 | LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, | 711 | LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector, |
717 | const struct iovec* vector, int count) | 712 | int count) { |
718 | { | 713 | /* Assume that open() was called first. */ |
719 | /* Assume that open() was called first. */ | 714 | return redirectWritev(fd, vector, count); |
720 | return redirectWritev(fd, vector, count); | ||
721 | } | 715 | } |
722 | 716 | ||
723 | LIBLOG_HIDDEN ssize_t __send_log_msg(char *buf __unused, | 717 | LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf __unused, |
724 | size_t buf_size __unused) | 718 | size_t buf_size __unused) { |
725 | { | 719 | return -ENODEV; |
726 | return -ENODEV; | ||
727 | } | 720 | } |
728 | 721 | ||
729 | LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, | 722 | LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, |
730 | const char *tag __unused, | 723 | const char* tag __unused, |
731 | int def) | 724 | int def) { |
732 | { | 725 | int logLevel = def; |
733 | int logLevel = def; | 726 | return logLevel >= 0 && prio >= logLevel; |
734 | return logLevel >= 0 && prio >= logLevel; | ||
735 | } | 727 | } |
736 | 728 | ||
737 | LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, | 729 | LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, |
738 | const char *tag __unused, | 730 | const char* tag __unused, |
739 | size_t len __unused, | 731 | size_t len __unused, |
740 | int def) | 732 | int def) { |
741 | { | 733 | int logLevel = def; |
742 | int logLevel = def; | 734 | return logLevel >= 0 && prio >= logLevel; |
743 | return logLevel >= 0 && prio >= logLevel; | ||
744 | } | 735 | } |
745 | 736 | ||
746 | LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() | 737 | LIBLOG_ABI_PRIVATE int __android_log_is_debuggable() { |
747 | { | 738 | return 1; |
748 | return 1; | ||
749 | } | 739 | } |