blob: 0b126cf4d763b6bb83e23018a5a7a1048fb64f55 [file] [log] [blame]
Mark Salyzyn42958412013-11-22 10:50:27 -08001/*
Mark Salyzynd0a83fd2014-01-09 07:45:30 -08002** Copyright 2013-2014, The Android Open Source Project
Mark Salyzyn42958412013-11-22 10:50:27 -08003**
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
Mark Salyzyn42958412013-11-22 10:50:27 -080017#include <errno.h>
18#include <fcntl.h>
Mark Salyzynfa3716b2014-02-14 16:05:05 -080019#include <inttypes.h>
Mark Salyzyn696817d2014-04-18 14:49:28 -070020#include <poll.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080021#include <signal.h>
22#include <stddef.h>
23#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
Mark Salyzyn42958412013-11-22 10:50:27 -080024#include <stdlib.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080025#include <string.h>
Mark Salyzyna04464a2014-04-30 08:50:53 -070026#include <sys/cdefs.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080027#include <unistd.h>
28
Mark Salyzyn42958412013-11-22 10:50:27 -080029#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080030#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080031#include <log/log.h>
32#include <log/logger.h>
33
Mark Salyzyn154f4602014-02-20 14:59:07 -080034/* branchless on many architectures. */
35#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080036
Mark Salyzyn95687052014-10-02 11:12:28 -070037#if (defined(USE_MINGW) || defined(HAVE_WINSOCK))
38#define WEAK static
39#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080040#define WEAK __attribute__((weak))
Mark Salyzyn95687052014-10-02 11:12:28 -070041#endif
Mark Salyzyna04464a2014-04-30 08:50:53 -070042#ifndef __unused
43#define __unused __attribute__((unused))
44#endif
Mark Salyzyn1345f382014-01-14 08:41:27 -080045
Mark Salyzyn154f4602014-02-20 14:59:07 -080046/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080047
Mark Salyzyn154f4602014-02-20 14:59:07 -080048#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080049
Mark Salyzyn154f4602014-02-20 14:59:07 -080050int WEAK socket_local_client(const char *name, int namespaceId, int type)
51{
52 errno = ENOSYS;
53 return -ENOSYS;
54}
Mark Salyzyn42958412013-11-22 10:50:27 -080055
Mark Salyzyn154f4602014-02-20 14:59:07 -080056#else /* !HAVE_WINSOCK */
57
58#include <sys/socket.h>
59#include <sys/un.h>
60#include <sys/select.h>
61#include <sys/types.h>
62
63/* Private copy of ../libcutils/socket_local.h prevent library loops */
64#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
65#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
66/* End of ../libcutils/socket_local.h */
67
68#define LISTEN_BACKLOG 4
69
70/* Documented in header file. */
71int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
72 struct sockaddr_un *p_addr, socklen_t *alen)
73{
74 memset (p_addr, 0, sizeof (*p_addr));
75 size_t namelen;
76
77 switch (namespaceId) {
78 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
Elliott Hughes9768d242014-11-21 22:50:20 -080079#if defined(__linux__)
Mark Salyzyn154f4602014-02-20 14:59:07 -080080 namelen = strlen(name);
81
82 /* Test with length +1 for the *initial* '\0'. */
83 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
84 goto error;
85 }
86
87 /*
88 * Note: The path in this case is *not* supposed to be
89 * '\0'-terminated. ("man 7 unix" for the gory details.)
90 */
91
92 p_addr->sun_path[0] = 0;
93 memcpy(p_addr->sun_path + 1, name, namelen);
Elliott Hughes9768d242014-11-21 22:50:20 -080094#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080095 /* this OS doesn't have the Linux abstract namespace */
96
97 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
98 /* unix_path_max appears to be missing on linux */
99 if (namelen > sizeof(*p_addr)
100 - offsetof(struct sockaddr_un, sun_path) - 1) {
101 goto error;
102 }
103
104 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
105 strcat(p_addr->sun_path, name);
Elliott Hughes9768d242014-11-21 22:50:20 -0800106#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -0800107 break;
108
109 case ANDROID_SOCKET_NAMESPACE_RESERVED:
110 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
111 /* unix_path_max appears to be missing on linux */
112 if (namelen > sizeof(*p_addr)
113 - offsetof(struct sockaddr_un, sun_path) - 1) {
114 goto error;
115 }
116
117 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
118 strcat(p_addr->sun_path, name);
119 break;
120
121 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
122 namelen = strlen(name);
123 /* unix_path_max appears to be missing on linux */
124 if (namelen > sizeof(*p_addr)
125 - offsetof(struct sockaddr_un, sun_path) - 1) {
126 goto error;
127 }
128
129 strcpy(p_addr->sun_path, name);
130 break;
131
132 default:
133 /* invalid namespace id */
134 return -1;
135 }
136
137 p_addr->sun_family = AF_LOCAL;
138 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
139 return 0;
140error:
141 return -1;
142}
143
144/**
145 * connect to peer named "name" on fd
146 * returns same fd or -1 on error.
147 * fd is not closed on error. that's your job.
148 *
149 * Used by AndroidSocketImpl
150 */
151int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
Mark Salyzyna04464a2014-04-30 08:50:53 -0700152 int type __unused)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800153{
154 struct sockaddr_un addr;
155 socklen_t alen;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800156 int err;
157
158 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
159
160 if (err < 0) {
161 goto error;
162 }
163
164 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
165 goto error;
166 }
167
168 return fd;
169
170error:
171 return -1;
172}
173
174/**
175 * connect to peer named "name"
176 * returns fd or -1 on error
177 */
178int WEAK socket_local_client(const char *name, int namespaceId, int type)
179{
180 int s;
181
182 s = socket(AF_LOCAL, type, 0);
183 if(s < 0) return -1;
184
185 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
186 close(s);
187 return -1;
188 }
189
190 return s;
191}
192
193#endif /* !HAVE_WINSOCK */
194/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800195
196#define logger_for_each(logger, logger_list) \
197 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
198 logger != node_to_item(&(logger_list)->node, struct logger, node); \
199 logger = node_to_item((logger)->node.next, struct logger, node))
200
201/* In the future, we would like to make this list extensible */
202static const char *LOG_NAME[LOG_ID_MAX] = {
203 [LOG_ID_MAIN] = "main",
204 [LOG_ID_RADIO] = "radio",
205 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700206 [LOG_ID_SYSTEM] = "system",
207 [LOG_ID_CRASH] = "crash",
Mark Salyzyn42958412013-11-22 10:50:27 -0800208};
209
Mark Salyzyn154f4602014-02-20 14:59:07 -0800210const char *android_log_id_to_name(log_id_t log_id)
211{
Mark Salyzyn42958412013-11-22 10:50:27 -0800212 if (log_id >= LOG_ID_MAX) {
213 log_id = LOG_ID_MAIN;
214 }
215 return LOG_NAME[log_id];
216}
217
Mark Salyzyn154f4602014-02-20 14:59:07 -0800218log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800219{
Mark Salyzyn42958412013-11-22 10:50:27 -0800220 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800221 int ret;
222
223 if (!logName) {
224 return -1; /* NB: log_id_t is unsigned */
225 }
226 b = strrchr(logName, '/');
227 if (!b) {
228 b = logName;
229 } else {
230 ++b;
231 }
232
Mark Salyzyn42958412013-11-22 10:50:27 -0800233 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
234 const char *l = LOG_NAME[ret];
235 if (l && !strcmp(b, l)) {
236 return ret;
237 }
238 }
239 return -1; /* should never happen */
240}
241
242struct logger_list {
243 struct listnode node;
244 int mode;
245 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800246 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800247 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800248 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800249};
250
251struct logger {
252 struct listnode node;
253 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800254 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800255};
256
257/* android_logger_alloc unimplemented, no use case */
258/* android_logger_free not exported */
259static void android_logger_free(struct logger *logger)
260{
261 if (!logger) {
262 return;
263 }
264
Mark Salyzyn42958412013-11-22 10:50:27 -0800265 list_remove(&logger->node);
266
267 free(logger);
268}
269
Mark Salyzyn154f4602014-02-20 14:59:07 -0800270/* android_logger_alloc unimplemented, no use case */
271
272/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800273log_id_t android_logger_get_id(struct logger *logger)
274{
275 return logger->id;
276}
277
278/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800279static ssize_t send_log_msg(struct logger *logger,
280 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800281{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800282 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700283 size_t len;
284 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700285 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800286 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
287 SOCK_STREAM);
288 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700289 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800290 }
291
Mark Salyzyn154f4602014-02-20 14:59:07 -0800292 if (msg) {
293 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800294 }
295
Mark Salyzyn696817d2014-04-18 14:49:28 -0700296 len = strlen(buf) + 1;
297 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800298 if (ret <= 0) {
299 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800300 }
301
Mark Salyzyn696817d2014-04-18 14:49:28 -0700302 len = buf_size;
303 cp = buf;
304 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
305 struct pollfd p;
306
307 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
308 break;
309 }
310
311 len -= ret;
312 cp += ret;
313
314 memset(&p, 0, sizeof(p));
315 p.fd = sock;
316 p.events = POLLIN;
317
318 /* Give other side 20ms to refill pipe */
319 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
320
321 if (ret <= 0) {
322 break;
323 }
324
325 if (!(p.revents & POLLIN)) {
326 ret = 0;
327 break;
328 }
329 }
330
331 if (ret >= 0) {
332 ret += buf_size - len;
333 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800334
335done:
336 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700337 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800338 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800339 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700340 if (errno_save) {
341 errno = errno_save;
342 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800343 return ret;
344}
345
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800346static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800347{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800348 if (ret < 0) {
349 return ret;
350 }
351
352 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700353 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800354 return -1;
355 }
356
357 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800358}
359
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800360int android_logger_clear(struct logger *logger)
361{
362 char buf[512];
363
364 return check_log_success(buf,
365 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
366}
367
Mark Salyzyn42958412013-11-22 10:50:27 -0800368/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800369long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800370{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800371 char buf[512];
372
373 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
374 if (ret < 0) {
375 return ret;
376 }
377
378 if ((buf[0] < '0') || ('9' < buf[0])) {
379 return -1;
380 }
381
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800382 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800383}
384
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800385int android_logger_set_log_size(struct logger *logger, unsigned long size)
386{
387 char buf[512];
388
389 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
390 logger ? logger->id : (unsigned) -1, size);
391
392 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
393}
394
Mark Salyzyn42958412013-11-22 10:50:27 -0800395/*
396 * returns the readable size of the log's ring buffer (that is, amount of the
397 * log consumed)
398 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800399long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800400{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800401 char buf[512];
402
403 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
404 if (ret < 0) {
405 return ret;
406 }
407
408 if ((buf[0] < '0') || ('9' < buf[0])) {
409 return -1;
410 }
411
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800412 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800413}
414
415/*
416 * returns the logger version
417 */
Mark Salyzyna04464a2014-04-30 08:50:53 -0700418int android_logger_get_log_version(struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800419{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800420 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800421}
422
Mark Salyzyn34facab2014-02-06 14:48:50 -0800423/*
424 * returns statistics
425 */
426ssize_t android_logger_get_statistics(struct logger_list *logger_list,
427 char *buf, size_t len)
428{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800429 struct logger *logger;
430 char *cp = buf;
431 size_t remaining = len;
432 size_t n;
433
434 n = snprintf(cp, remaining, "getStatistics");
435 n = min(n, remaining);
436 remaining -= n;
437 cp += n;
438
439 logger_for_each(logger, logger_list) {
440 n = snprintf(cp, remaining, " %d", logger->id);
441 n = min(n, remaining);
442 remaining -= n;
443 cp += n;
444 }
445 return send_log_msg(NULL, NULL, buf, len);
446}
447
Mark Salyzyna04464a2014-04-30 08:50:53 -0700448ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800449 char *buf, size_t len)
450{
451 return send_log_msg(NULL, "getPruneList", buf, len);
452}
453
Mark Salyzyna04464a2014-04-30 08:50:53 -0700454int android_logger_set_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800455 char *buf, size_t len)
456{
457 const char cmd[] = "setPruneList ";
458 const size_t cmdlen = sizeof(cmd) - 1;
459
460 if (strlen(buf) > (len - cmdlen)) {
461 return -ENOMEM; /* KISS */
462 }
463 memmove(buf + cmdlen, buf, len - cmdlen);
464 buf[len - 1] = '\0';
465 memcpy(buf, cmd, cmdlen);
466
467 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
468}
469
Mark Salyzyn42958412013-11-22 10:50:27 -0800470struct logger_list *android_logger_list_alloc(int mode,
471 unsigned int tail,
472 pid_t pid)
473{
474 struct logger_list *logger_list;
475
476 logger_list = calloc(1, sizeof(*logger_list));
477 if (!logger_list) {
478 return NULL;
479 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800480
Mark Salyzyn42958412013-11-22 10:50:27 -0800481 list_init(&logger_list->node);
482 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800483 logger_list->start.tv_sec = 0;
484 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800485 logger_list->tail = tail;
486 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800487 logger_list->sock = -1;
488
Mark Salyzyn42958412013-11-22 10:50:27 -0800489 return logger_list;
490}
491
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800492struct logger_list *android_logger_list_alloc_time(int mode,
493 log_time start,
494 pid_t pid)
495{
496 struct logger_list *logger_list;
497
498 logger_list = calloc(1, sizeof(*logger_list));
499 if (!logger_list) {
500 return NULL;
501 }
502
503 list_init(&logger_list->node);
504 logger_list->mode = mode;
505 logger_list->start = start;
506 logger_list->tail = 0;
507 logger_list->pid = pid;
508 logger_list->sock = -1;
509
510 return logger_list;
511}
512
Mark Salyzyn42958412013-11-22 10:50:27 -0800513/* android_logger_list_register unimplemented, no use case */
514/* android_logger_list_unregister unimplemented, no use case */
515
516/* Open the named log and add it to the logger list */
517struct logger *android_logger_open(struct logger_list *logger_list,
518 log_id_t id)
519{
Mark Salyzyn42958412013-11-22 10:50:27 -0800520 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800521
522 if (!logger_list || (id >= LOG_ID_MAX)) {
523 goto err;
524 }
525
526 logger_for_each(logger, logger_list) {
527 if (logger->id == id) {
528 goto ok;
529 }
530 }
531
532 logger = calloc(1, sizeof(*logger));
533 if (!logger) {
534 goto err;
535 }
536
Mark Salyzyn42958412013-11-22 10:50:27 -0800537 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800538 list_add_tail(&logger_list->node, &logger->node);
539 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800540 goto ok;
541
Mark Salyzyn42958412013-11-22 10:50:27 -0800542err:
543 logger = NULL;
544ok:
545 return logger;
546}
547
548/* Open the single named log and make it part of a new logger list */
549struct logger_list *android_logger_list_open(log_id_t id,
550 int mode,
551 unsigned int tail,
552 pid_t pid)
553{
554 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
555 if (!logger_list) {
556 return NULL;
557 }
558
559 if (!android_logger_open(logger_list, id)) {
560 android_logger_list_free(logger_list);
561 return NULL;
562 }
563
564 return logger_list;
565}
566
Mark Salyzyna04464a2014-04-30 08:50:53 -0700567static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800568{
Mark Salyzyn42958412013-11-22 10:50:27 -0800569}
570
571/* Read from the selected logs */
572int android_logger_list_read(struct logger_list *logger_list,
573 struct log_msg *log_msg)
574{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800575 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800576 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800577 struct sigaction ignore;
578 struct sigaction old_sigaction;
579 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800580
581 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800582 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800583 }
584
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800585 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800586 memset(&ignore, 0, sizeof(ignore));
587 ignore.sa_handler = caught_signal;
588 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800589 }
590
Mark Salyzyn154f4602014-02-20 14:59:07 -0800591 if (logger_list->sock < 0) {
592 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800593
Mark Salyzyn154f4602014-02-20 14:59:07 -0800594 int sock = socket_local_client("logdr",
595 ANDROID_SOCKET_NAMESPACE_RESERVED,
596 SOCK_SEQPACKET);
597 if (sock < 0) {
598 if ((sock == -1) && errno) {
599 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800600 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800601 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800602 }
603
Mark Salyzyn154f4602014-02-20 14:59:07 -0800604 strcpy(buffer,
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800605 (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
Mark Salyzyn154f4602014-02-20 14:59:07 -0800606 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800607
Mark Salyzyn154f4602014-02-20 14:59:07 -0800608 strcpy(cp, " lids");
609 cp += 5;
610 c = '=';
611 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800612 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800613 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
614 ret = min(ret, remaining);
615 remaining -= ret;
616 cp += ret;
617 c = ',';
618 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800619
Mark Salyzyn154f4602014-02-20 14:59:07 -0800620 if (logger_list->tail) {
621 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
622 ret = min(ret, remaining);
623 remaining -= ret;
624 cp += ret;
625 }
626
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800627 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
628 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
629 logger_list->start.tv_sec,
630 logger_list->start.tv_nsec);
631 ret = min(ret, remaining);
632 remaining -= ret;
633 cp += ret;
634 }
635
Mark Salyzyn154f4602014-02-20 14:59:07 -0800636 if (logger_list->pid) {
637 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
638 ret = min(ret, remaining);
639 remaining -= ret;
640 cp += ret;
641 }
642
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800643 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800644 /* Deal with an unresponsive logd */
645 sigaction(SIGALRM, &ignore, &old_sigaction);
646 old_alarm = alarm(30);
647 }
648 ret = write(sock, buffer, cp - buffer);
649 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800650 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800651 if (e == EINTR) {
652 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800653 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800654 alarm(old_alarm);
655 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800656 }
657
658 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800659 close(sock);
660 if ((ret == -1) && e) {
661 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800662 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800663 if (ret == 0) {
664 return -EIO;
665 }
666 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800667 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800668
669 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800670 }
671
Mark Salyzyn154f4602014-02-20 14:59:07 -0800672 ret = 0;
673 while(1) {
674 memset(log_msg, 0, sizeof(*log_msg));
675
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800676 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800677 /* particularily useful if tombstone is reporting for logd */
678 sigaction(SIGALRM, &ignore, &old_sigaction);
679 old_alarm = alarm(30);
680 }
681 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
682 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
683 e = errno;
Mark Salyzyn2d3f38a2015-01-26 10:46:44 -0800684 if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800685 if ((ret == 0) || (e == EINTR)) {
686 e = EAGAIN;
687 ret = -1;
688 }
689 alarm(old_alarm);
690 sigaction(SIGALRM, &old_sigaction, NULL);
691 }
692
693 if (ret <= 0) {
694 if ((ret == -1) && e) {
695 return -e;
696 }
697 return ret;
698 }
699
700 logger_for_each(logger, logger_list) {
701 if (log_msg->entry.lid == logger->id) {
702 return ret;
703 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800704 }
705 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800706 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800707 return ret;
708}
709
710/* Close all the logs */
711void android_logger_list_free(struct logger_list *logger_list)
712{
713 if (logger_list == NULL) {
714 return;
715 }
716
717 while (!list_empty(&logger_list->node)) {
718 struct listnode *node = list_head(&logger_list->node);
719 struct logger *logger = node_to_item(node, struct logger, node);
720 android_logger_free(logger);
721 }
722
Mark Salyzyn154f4602014-02-20 14:59:07 -0800723 if (logger_list->sock >= 0) {
724 close (logger_list->sock);
725 }
726
Mark Salyzyn42958412013-11-22 10:50:27 -0800727 free(logger_list);
728}