blob: 2a971016479146cb35896341a6b2c64413b06680 [file] [log] [blame]
Mark Salyzyn018a96d2016-03-01 13:45:42 -08001/*
2 * Copyright (C) 2007-2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <stdatomic.h>
19#include <stdlib.h>
20#include <string.h>
21#include <sys/time.h>
22
23#ifdef __BIONIC__
24#include <android/set_abort_message.h>
25#endif
26
27#include <log/event_tag_map.h>
Mark Salyzyn850d06e2015-02-04 12:39:57 -080028#include <log/log_frontend.h>
Mark Salyzyn018a96d2016-03-01 13:45:42 -080029#include <private/android_filesystem_config.h>
30#include <private/android_logger.h>
31
Mark Salyzyn71002882016-03-08 16:18:26 -080032#include "config_read.h" /* __android_log_config_read_close() definition */
Mark Salyzyn018a96d2016-03-01 13:45:42 -080033#include "config_write.h"
34#include "log_portability.h"
35#include "logger.h"
36
37#define LOG_BUF_SIZE 1024
38
39static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
40static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
41
42/*
43 * This is used by the C++ code to decide if it should write logs through
44 * the C code. Basically, if /dev/socket/logd is available, we're running in
45 * the simulator rather than a desktop tool and want to use the device.
46 */
47static enum {
48 kLogUninitialized, kLogNotAvailable, kLogAvailable
49} g_log_status = kLogUninitialized;
50
Mark Salyzync33103c2016-03-28 16:20:29 -070051static int check_log_uid_permissions()
52{
Dan Willemsen0910d2d2016-11-29 13:39:55 -080053#if defined(__ANDROID__)
Mark Salyzync33103c2016-03-28 16:20:29 -070054 uid_t uid = __android_log_uid();
55
56 /* Matches clientHasLogCredentials() in logd */
57 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
58 uid = geteuid();
59 if ((uid != AID_SYSTEM) && (uid != AID_ROOT) && (uid != AID_LOG)) {
60 gid_t gid = getgid();
61 if ((gid != AID_SYSTEM) &&
62 (gid != AID_ROOT) &&
63 (gid != AID_LOG)) {
64 gid = getegid();
65 if ((gid != AID_SYSTEM) &&
66 (gid != AID_ROOT) &&
67 (gid != AID_LOG)) {
68 int num_groups;
69 gid_t *groups;
70
71 num_groups = getgroups(0, NULL);
72 if (num_groups <= 0) {
73 return -EPERM;
74 }
75 groups = calloc(num_groups, sizeof(gid_t));
76 if (!groups) {
77 return -ENOMEM;
78 }
79 num_groups = getgroups(num_groups, groups);
80 while (num_groups > 0) {
81 if (groups[num_groups - 1] == AID_LOG) {
82 break;
83 }
84 --num_groups;
85 }
86 free(groups);
87 if (num_groups <= 0) {
88 return -EPERM;
89 }
90 }
91 }
92 }
93 }
94#endif
95 return 0;
96}
97
98static void __android_log_cache_available(
99 struct android_log_transport_write *node)
100{
101 size_t i;
102
103 if (node->logMask) {
104 return;
105 }
106
107 for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
108 if (node->write &&
109 (i != LOG_ID_KERNEL) &&
110 ((i != LOG_ID_SECURITY) ||
111 (check_log_uid_permissions() == 0)) &&
112 (!node->available || ((*node->available)(i) >= 0))) {
113 node->logMask |= 1 << i;
114 }
115 }
116}
117
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800118LIBLOG_ABI_PUBLIC int __android_log_dev_available()
119{
120 struct android_log_transport_write *node;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800121
122 if (list_empty(&__android_log_transport_write)) {
123 return kLogUninitialized;
124 }
Mark Salyzync33103c2016-03-28 16:20:29 -0700125
126 write_transport_for_each(node, &__android_log_transport_write) {
127 __android_log_cache_available(node);
128 if (node->logMask) {
129 return kLogAvailable;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800130 }
131 }
132 return kLogNotAvailable;
133}
Mark Salyzynba1a7982016-09-13 07:28:21 -0700134
Dan Willemsen0910d2d2016-11-29 13:39:55 -0800135#if defined(__ANDROID__)
Mark Salyzynba1a7982016-09-13 07:28:21 -0700136static atomic_uintptr_t tagMap;
137#endif
138
Mark Salyzyndf7a4c62016-08-23 10:23:36 -0700139/*
140 * Release any logger resources. A new log write will immediately re-acquire.
141 */
142LIBLOG_ABI_PUBLIC void __android_log_close()
143{
144 struct android_log_transport_write *transport;
Dan Willemsen0910d2d2016-11-29 13:39:55 -0800145#if defined(__ANDROID__)
Mark Salyzynba1a7982016-09-13 07:28:21 -0700146 EventTagMap *m;
147#endif
Mark Salyzyndf7a4c62016-08-23 10:23:36 -0700148
149 __android_log_lock();
150
151 write_to_log = __write_to_log_init;
152
153 /*
154 * Threads that are actively writing at this point are not held back
155 * by a lock and are at risk of dropping the messages with a return code
156 * -EBADF. Prefer to return error code than add the overhead of a lock to
157 * each log writing call to guarantee delivery. In addition, anyone
158 * calling this is doing so to release the logging resources and shut down,
159 * for them to do so with outstanding log requests in other threads is a
160 * disengenuous use of this function.
161 */
162
163 write_transport_for_each(transport, &__android_log_persist_write) {
164 if (transport->close) {
165 (*transport->close)();
166 }
167 }
168
169 write_transport_for_each(transport, &__android_log_transport_write) {
170 if (transport->close) {
171 (*transport->close)();
172 }
173 }
174
Mark Salyzyn71002882016-03-08 16:18:26 -0800175 __android_log_config_write_close();
176
Dan Willemsen0910d2d2016-11-29 13:39:55 -0800177#if defined(__ANDROID__)
Mark Salyzynba1a7982016-09-13 07:28:21 -0700178 /*
179 * Additional risk here somewhat mitigated by immediately unlock flushing
180 * the processor cache. The multi-threaded race that we choose to accept,
181 * to minimize locking, is an atomic_load in a writer picking up a value
182 * just prior to entering this routine. There will be an use after free.
183 *
184 * Again, anyone calling this is doing so to release the logging resources
185 * is most probably going to quiesce then shut down; or to restart after
186 * a fork so the risk should be non-existent. For this reason we
187 * choose a mitigation stance for efficiency instead of incuring the cost
188 * of a lock for every log write.
189 */
190 m = (EventTagMap *)atomic_exchange(&tagMap, (uintptr_t)0);
191#endif
192
Mark Salyzyndf7a4c62016-08-23 10:23:36 -0700193 __android_log_unlock();
Mark Salyzynba1a7982016-09-13 07:28:21 -0700194
Dan Willemsen0910d2d2016-11-29 13:39:55 -0800195#if defined(__ANDROID__)
Mark Salyzyn53e9fc72016-11-09 10:14:35 -0800196 if (m != (EventTagMap *)(uintptr_t)-1LL) android_closeEventTagMap(m);
Mark Salyzynba1a7982016-09-13 07:28:21 -0700197#endif
198
Mark Salyzyndf7a4c62016-08-23 10:23:36 -0700199}
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800200
201/* log_init_lock assumed */
202static int __write_to_log_initialize()
203{
204 struct android_log_transport_write *transport;
205 struct listnode *n;
206 int i = 0, ret = 0;
207
208 __android_log_config_write();
209 write_transport_for_each_safe(transport, n, &__android_log_transport_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700210 __android_log_cache_available(transport);
211 if (!transport->logMask) {
212 list_remove(&transport->node);
213 continue;
214 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800215 if (!transport->open || ((*transport->open)() < 0)) {
216 if (transport->close) {
217 (*transport->close)();
218 }
219 list_remove(&transport->node);
220 continue;
221 }
222 ++ret;
223 }
224 write_transport_for_each_safe(transport, n, &__android_log_persist_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700225 __android_log_cache_available(transport);
226 if (!transport->logMask) {
227 list_remove(&transport->node);
228 continue;
229 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800230 if (!transport->open || ((*transport->open)() < 0)) {
231 if (transport->close) {
232 (*transport->close)();
233 }
234 list_remove(&transport->node);
235 continue;
236 }
237 ++i;
238 }
239 if (!ret && !i) {
240 return -ENODEV;
241 }
242
243 return ret;
244}
245
246/*
247 * Extract a 4-byte value from a byte stream. le32toh open coded
248 */
249static inline uint32_t get4LE(const uint8_t* src)
250{
251 return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
252}
253
254static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
255{
256 struct android_log_transport_write *node;
257 int ret;
258 struct timespec ts;
259 size_t len, i;
260
261 for (len = i = 0; i < nr; ++i) {
262 len += vec[i].iov_len;
263 }
264 if (!len) {
265 return -EINVAL;
266 }
267
Dan Willemsen0910d2d2016-11-29 13:39:55 -0800268#if defined(__ANDROID__)
Mark Salyzyn142b43d2016-12-28 10:30:57 -0800269 clock_gettime(android_log_clockid(), &ts);
270
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800271 if (log_id == LOG_ID_SECURITY) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800272 if (vec[0].iov_len < 4) {
273 return -EINVAL;
274 }
275
Mark Salyzync33103c2016-03-28 16:20:29 -0700276 ret = check_log_uid_permissions();
277 if (ret < 0) {
278 return ret;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800279 }
280 if (!__android_log_security()) {
281 /* If only we could reset downstream logd counter */
282 return -EPERM;
283 }
284 } else if (log_id == LOG_ID_EVENTS) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800285 const char *tag;
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700286 size_t len;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800287 EventTagMap *m, *f;
288
289 if (vec[0].iov_len < 4) {
290 return -EINVAL;
291 }
292
293 tag = NULL;
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700294 len = 0;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800295 f = NULL;
Mark Salyzynba1a7982016-09-13 07:28:21 -0700296 m = (EventTagMap *)atomic_load(&tagMap);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800297
298 if (!m) {
299 ret = __android_log_trylock();
Mark Salyzynba1a7982016-09-13 07:28:21 -0700300 m = (EventTagMap *)atomic_load(&tagMap); /* trylock flush cache */
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800301 if (!m) {
Mark Salyzyn1179eb82016-11-11 09:48:56 -0800302 m = android_openEventTagMap(NULL);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800303 if (ret) { /* trylock failed, use local copy, mark for close */
304 f = m;
305 } else {
306 if (!m) { /* One chance to open map file */
307 m = (EventTagMap *)(uintptr_t)-1LL;
308 }
Mark Salyzynba1a7982016-09-13 07:28:21 -0700309 atomic_store(&tagMap, (uintptr_t)m);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800310 }
311 }
312 if (!ret) { /* trylock succeeded, unlock */
313 __android_log_unlock();
314 }
315 }
316 if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) {
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700317 tag = android_lookupEventTag_len(m, &len, get4LE(vec[0].iov_base));
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800318 }
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700319 ret = __android_log_is_loggable_len(ANDROID_LOG_INFO,
320 tag, len,
321 ANDROID_LOG_VERBOSE);
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800322 if (f) { /* local copy marked for close */
323 android_closeEventTagMap(f);
324 }
325 if (!ret) {
326 return -EPERM;
327 }
328 } else {
329 /* Validate the incoming tag, tag content can not split across iovec */
330 char prio = ANDROID_LOG_VERBOSE;
331 const char *tag = vec[0].iov_base;
332 size_t len = vec[0].iov_len;
333 if (!tag) {
334 len = 0;
335 }
336 if (len > 0) {
337 prio = *tag;
338 if (len > 1) {
339 --len;
340 ++tag;
341 } else {
342 len = vec[1].iov_len;
343 tag = ((const char *)vec[1].iov_base);
344 if (!tag) {
345 len = 0;
346 }
347 }
348 }
349 /* tag must be nul terminated */
Ting-Yuan Huang6efb8772017-02-07 16:40:35 -0800350 if (tag && strnlen(tag, len) >= len) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800351 tag = NULL;
352 }
353
Mark Salyzyn807e40e2016-09-22 09:56:51 -0700354 if (!__android_log_is_loggable_len(prio,
355 tag, len - 1,
356 ANDROID_LOG_VERBOSE)) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800357 return -EPERM;
358 }
359 }
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800360#else
361 /* simulate clock_gettime(CLOCK_REALTIME, &ts); */
362 {
363 struct timeval tv;
364 gettimeofday(&tv, NULL);
365 ts.tv_sec = tv.tv_sec;
366 ts.tv_nsec = tv.tv_usec * 1000;
367 }
368#endif
369
370 ret = 0;
Mark Salyzync33103c2016-03-28 16:20:29 -0700371 i = 1 << log_id;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800372 write_transport_for_each(node, &__android_log_transport_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700373 if (node->logMask & i) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800374 ssize_t retval;
375 retval = (*node->write)(log_id, &ts, vec, nr);
376 if (ret >= 0) {
377 ret = retval;
378 }
379 }
380 }
381
382 write_transport_for_each(node, &__android_log_persist_write) {
Mark Salyzync33103c2016-03-28 16:20:29 -0700383 if (node->logMask & i) {
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800384 (void)(*node->write)(log_id, &ts, vec, nr);
385 }
386 }
387
388 return ret;
389}
390
391static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr)
392{
393 __android_log_lock();
394
395 if (write_to_log == __write_to_log_init) {
396 int ret;
397
398 ret = __write_to_log_initialize();
399 if (ret < 0) {
400 __android_log_unlock();
401 if (!list_empty(&__android_log_persist_write)) {
402 __write_to_log_daemon(log_id, vec, nr);
403 }
404 return ret;
405 }
406
407 write_to_log = __write_to_log_daemon;
408 }
409
410 __android_log_unlock();
411
412 return write_to_log(log_id, vec, nr);
413}
414
415LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
416 const char *msg)
417{
418 return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
419}
420
421LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
422 const char *tag, const char *msg)
423{
424 struct iovec vec[3];
425 char tmp_tag[32];
426
427 if (!tag)
428 tag = "";
429
430 /* XXX: This needs to go! */
431 if ((bufID != LOG_ID_RADIO) &&
432 (!strcmp(tag, "HTC_RIL") ||
433 !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */
434 !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */
435 !strcmp(tag, "AT") ||
436 !strcmp(tag, "GSM") ||
437 !strcmp(tag, "STK") ||
438 !strcmp(tag, "CDMA") ||
439 !strcmp(tag, "PHONE") ||
440 !strcmp(tag, "SMS"))) {
441 bufID = LOG_ID_RADIO;
442 /* Inform third party apps/ril/radio.. to use Rlog or RLOG */
443 snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
444 tag = tmp_tag;
445 }
446
447#if __BIONIC__
448 if (prio == ANDROID_LOG_FATAL) {
449 android_set_abort_message(msg);
450 }
451#endif
452
Mark Salyzync33103c2016-03-28 16:20:29 -0700453 vec[0].iov_base = (unsigned char *)&prio;
454 vec[0].iov_len = 1;
455 vec[1].iov_base = (void *)tag;
456 vec[1].iov_len = strlen(tag) + 1;
457 vec[2].iov_base = (void *)msg;
458 vec[2].iov_len = strlen(msg) + 1;
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800459
460 return write_to_log(bufID, vec, 3);
461}
462
463LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
464 const char *fmt, va_list ap)
465{
466 char buf[LOG_BUF_SIZE];
467
468 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
469
470 return __android_log_write(prio, tag, buf);
471}
472
473LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
474 const char *fmt, ...)
475{
476 va_list ap;
477 char buf[LOG_BUF_SIZE];
478
479 va_start(ap, fmt);
480 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
481 va_end(ap);
482
483 return __android_log_write(prio, tag, buf);
484}
485
486LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
487 const char *tag,
488 const char *fmt, ...)
489{
490 va_list ap;
491 char buf[LOG_BUF_SIZE];
492
493 va_start(ap, fmt);
494 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
495 va_end(ap);
496
497 return __android_log_buf_write(bufID, prio, tag, buf);
498}
499
500LIBLOG_ABI_PUBLIC void __android_log_assert(const char *cond, const char *tag,
501 const char *fmt, ...)
502{
503 char buf[LOG_BUF_SIZE];
504
505 if (fmt) {
506 va_list ap;
507 va_start(ap, fmt);
508 vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
509 va_end(ap);
510 } else {
511 /* Msg not provided, log condition. N.B. Do not use cond directly as
512 * format string as it could contain spurious '%' syntax (e.g.
513 * "%d" in "blocks%devs == 0").
514 */
515 if (cond)
516 snprintf(buf, LOG_BUF_SIZE, "Assertion failed: %s", cond);
517 else
518 strcpy(buf, "Unspecified assertion failed");
519 }
520
Elliott Hughes5bae1b82017-02-06 10:54:00 -0800521 // Log assertion failures to stderr for the benefit of "adb shell" users
522 // and gtests (http://b/23675822).
523 struct iovec iov[2] = {
524 { buf, strlen(buf) },
525 { (char*) "\n", 1 },
526 };
527 TEMP_FAILURE_RETRY(writev(2, iov, 2));
528
Mark Salyzyn018a96d2016-03-01 13:45:42 -0800529 __android_log_write(ANDROID_LOG_FATAL, tag, buf);
530 abort(); /* abort so we have a chance to debug the situation */
531 /* NOTREACHED */
532}
533
534LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
535 const void *payload, size_t len)
536{
537 struct iovec vec[2];
538
539 vec[0].iov_base = &tag;
540 vec[0].iov_len = sizeof(tag);
541 vec[1].iov_base = (void*)payload;
542 vec[1].iov_len = len;
543
544 return write_to_log(LOG_ID_EVENTS, vec, 2);
545}
546
547LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
548 const void *payload,
549 size_t len)
550{
551 struct iovec vec[2];
552
553 vec[0].iov_base = &tag;
554 vec[0].iov_len = sizeof(tag);
555 vec[1].iov_base = (void*)payload;
556 vec[1].iov_len = len;
557
558 return write_to_log(LOG_ID_SECURITY, vec, 2);
559}
560
561/*
562 * Like __android_log_bwrite, but takes the type as well. Doesn't work
563 * for the general case where we're generating lists of stuff, but very
564 * handy if we just want to dump an integer into the log.
565 */
566LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
567 const void *payload, size_t len)
568{
569 struct iovec vec[3];
570
571 vec[0].iov_base = &tag;
572 vec[0].iov_len = sizeof(tag);
573 vec[1].iov_base = &type;
574 vec[1].iov_len = sizeof(type);
575 vec[2].iov_base = (void*)payload;
576 vec[2].iov_len = len;
577
578 return write_to_log(LOG_ID_EVENTS, vec, 3);
579}
580
581/*
582 * Like __android_log_bwrite, but used for writing strings to the
583 * event log.
584 */
585LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
586{
587 struct iovec vec[4];
588 char type = EVENT_TYPE_STRING;
589 uint32_t len = strlen(payload);
590
591 vec[0].iov_base = &tag;
592 vec[0].iov_len = sizeof(tag);
593 vec[1].iov_base = &type;
594 vec[1].iov_len = sizeof(type);
595 vec[2].iov_base = &len;
596 vec[2].iov_len = sizeof(len);
597 vec[3].iov_base = (void*)payload;
598 vec[3].iov_len = len;
599
600 return write_to_log(LOG_ID_EVENTS, vec, 4);
601}
602
603/*
604 * Like __android_log_security_bwrite, but used for writing strings to the
605 * security log.
606 */
607LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
608 const char *payload)
609{
610 struct iovec vec[4];
611 char type = EVENT_TYPE_STRING;
612 uint32_t len = strlen(payload);
613
614 vec[0].iov_base = &tag;
615 vec[0].iov_len = sizeof(tag);
616 vec[1].iov_base = &type;
617 vec[1].iov_len = sizeof(type);
618 vec[2].iov_base = &len;
619 vec[2].iov_len = sizeof(len);
620 vec[3].iov_base = (void*)payload;
621 vec[3].iov_len = len;
622
623 return write_to_log(LOG_ID_SECURITY, vec, 4);
624}
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800625
626static int __write_to_log_null(log_id_t log_id, struct iovec* vec, size_t nr)
627{
628 size_t len, i;
629
630 if ((log_id < LOG_ID_MIN) || (log_id >= LOG_ID_MAX)) {
631 return -EINVAL;
632 }
633
634 for (len = i = 0; i < nr; ++i) {
635 len += vec[i].iov_len;
636 }
637 if (!len) {
638 return -EINVAL;
639 }
640 return len;
641}
642
643/* Following functions need access to our internal write_to_log status */
644
Mark Salyzyn71002882016-03-08 16:18:26 -0800645LIBLOG_HIDDEN int __android_log_frontend;
646
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800647LIBLOG_ABI_PUBLIC int android_set_log_frontend(int frontend_flag)
648{
Mark Salyzyn71002882016-03-08 16:18:26 -0800649 int retval;
650
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800651 if (frontend_flag < 0) {
652 return -EINVAL;
653 }
654
Mark Salyzyn71002882016-03-08 16:18:26 -0800655 retval = LOGGER_NULL;
656
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800657 __android_log_lock();
658
659 if (frontend_flag & LOGGER_NULL) {
660 write_to_log = __write_to_log_null;
661
662 __android_log_unlock();
663
Mark Salyzyn71002882016-03-08 16:18:26 -0800664 return retval;
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800665 }
666
Mark Salyzyn4d99c982017-02-28 12:59:01 -0800667 __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800668
Mark Salyzyn4d99c982017-02-28 12:59:01 -0800669 frontend_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
Mark Salyzyn71002882016-03-08 16:18:26 -0800670
671 if (__android_log_frontend != frontend_flag) {
672 __android_log_frontend = frontend_flag;
673 __android_log_config_write_close();
674 __android_log_config_read_close();
675
676 write_to_log = __write_to_log_init;
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800677 /* generically we only expect these two values for write_to_log */
Mark Salyzyn71002882016-03-08 16:18:26 -0800678 } else if ((write_to_log != __write_to_log_init) &&
679 (write_to_log != __write_to_log_daemon)) {
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800680 write_to_log = __write_to_log_init;
681 }
682
Mark Salyzyn71002882016-03-08 16:18:26 -0800683 retval = __android_log_frontend;
684
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800685 __android_log_unlock();
686
Mark Salyzyn71002882016-03-08 16:18:26 -0800687 return retval;
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800688}
689
690LIBLOG_ABI_PUBLIC int android_get_log_frontend()
691{
692 int ret = LOGGER_DEFAULT;
693
694 __android_log_lock();
695 if (write_to_log == __write_to_log_null) {
696 ret = LOGGER_NULL;
Mark Salyzyn71002882016-03-08 16:18:26 -0800697 } else {
Mark Salyzyn4d99c982017-02-28 12:59:01 -0800698 __android_log_frontend &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
Mark Salyzyn71002882016-03-08 16:18:26 -0800699 ret = __android_log_frontend;
700 if ((write_to_log != __write_to_log_init) &&
701 (write_to_log != __write_to_log_daemon)) {
702 ret = -EINVAL;
703 }
Mark Salyzyn850d06e2015-02-04 12:39:57 -0800704 }
705 __android_log_unlock();
706
707 return ret;
708}