blob: 2f21a5d9bdacffb0b98c74065b86718ebb041126 [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 Salyzyn154f4602014-02-20 14:59:07 -080037#define WEAK __attribute__((weak))
Mark Salyzyna04464a2014-04-30 08:50:53 -070038#ifndef __unused
39#define __unused __attribute__((unused))
40#endif
Mark Salyzyn1345f382014-01-14 08:41:27 -080041
Mark Salyzyn154f4602014-02-20 14:59:07 -080042/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080043
Mark Salyzyn154f4602014-02-20 14:59:07 -080044#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080045
Mark Salyzyn154f4602014-02-20 14:59:07 -080046int WEAK socket_local_client(const char *name, int namespaceId, int type)
47{
48 errno = ENOSYS;
49 return -ENOSYS;
50}
Mark Salyzyn42958412013-11-22 10:50:27 -080051
Mark Salyzyn154f4602014-02-20 14:59:07 -080052#else /* !HAVE_WINSOCK */
53
54#include <sys/socket.h>
55#include <sys/un.h>
56#include <sys/select.h>
57#include <sys/types.h>
58
59/* Private copy of ../libcutils/socket_local.h prevent library loops */
60#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
61#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
62/* End of ../libcutils/socket_local.h */
63
64#define LISTEN_BACKLOG 4
65
66/* Documented in header file. */
67int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
68 struct sockaddr_un *p_addr, socklen_t *alen)
69{
70 memset (p_addr, 0, sizeof (*p_addr));
71 size_t namelen;
72
73 switch (namespaceId) {
74 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
Elliott Hughes9768d242014-11-21 22:50:20 -080075#if defined(__linux__)
Mark Salyzyn154f4602014-02-20 14:59:07 -080076 namelen = strlen(name);
77
78 /* Test with length +1 for the *initial* '\0'. */
79 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
80 goto error;
81 }
82
83 /*
84 * Note: The path in this case is *not* supposed to be
85 * '\0'-terminated. ("man 7 unix" for the gory details.)
86 */
87
88 p_addr->sun_path[0] = 0;
89 memcpy(p_addr->sun_path + 1, name, namelen);
Elliott Hughes9768d242014-11-21 22:50:20 -080090#else
Mark Salyzyn154f4602014-02-20 14:59:07 -080091 /* this OS doesn't have the Linux abstract namespace */
92
93 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
94 /* unix_path_max appears to be missing on linux */
95 if (namelen > sizeof(*p_addr)
96 - offsetof(struct sockaddr_un, sun_path) - 1) {
97 goto error;
98 }
99
100 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
101 strcat(p_addr->sun_path, name);
Elliott Hughes9768d242014-11-21 22:50:20 -0800102#endif
Mark Salyzyn154f4602014-02-20 14:59:07 -0800103 break;
104
105 case ANDROID_SOCKET_NAMESPACE_RESERVED:
106 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
107 /* unix_path_max appears to be missing on linux */
108 if (namelen > sizeof(*p_addr)
109 - offsetof(struct sockaddr_un, sun_path) - 1) {
110 goto error;
111 }
112
113 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
114 strcat(p_addr->sun_path, name);
115 break;
116
117 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
118 namelen = strlen(name);
119 /* unix_path_max appears to be missing on linux */
120 if (namelen > sizeof(*p_addr)
121 - offsetof(struct sockaddr_un, sun_path) - 1) {
122 goto error;
123 }
124
125 strcpy(p_addr->sun_path, name);
126 break;
127
128 default:
129 /* invalid namespace id */
130 return -1;
131 }
132
133 p_addr->sun_family = AF_LOCAL;
134 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
135 return 0;
136error:
137 return -1;
138}
139
140/**
141 * connect to peer named "name" on fd
142 * returns same fd or -1 on error.
143 * fd is not closed on error. that's your job.
144 *
145 * Used by AndroidSocketImpl
146 */
147int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
Mark Salyzyna04464a2014-04-30 08:50:53 -0700148 int type __unused)
Mark Salyzyn154f4602014-02-20 14:59:07 -0800149{
150 struct sockaddr_un addr;
151 socklen_t alen;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800152 int err;
153
154 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
155
156 if (err < 0) {
157 goto error;
158 }
159
160 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
161 goto error;
162 }
163
164 return fd;
165
166error:
167 return -1;
168}
169
170/**
171 * connect to peer named "name"
172 * returns fd or -1 on error
173 */
174int WEAK socket_local_client(const char *name, int namespaceId, int type)
175{
176 int s;
177
178 s = socket(AF_LOCAL, type, 0);
179 if(s < 0) return -1;
180
181 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
182 close(s);
183 return -1;
184 }
185
186 return s;
187}
188
189#endif /* !HAVE_WINSOCK */
190/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800191
192#define logger_for_each(logger, logger_list) \
193 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
194 logger != node_to_item(&(logger_list)->node, struct logger, node); \
195 logger = node_to_item((logger)->node.next, struct logger, node))
196
197/* In the future, we would like to make this list extensible */
198static const char *LOG_NAME[LOG_ID_MAX] = {
199 [LOG_ID_MAIN] = "main",
200 [LOG_ID_RADIO] = "radio",
201 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700202 [LOG_ID_SYSTEM] = "system",
203 [LOG_ID_CRASH] = "crash",
Mark Salyzyn42958412013-11-22 10:50:27 -0800204};
205
Mark Salyzyn154f4602014-02-20 14:59:07 -0800206const char *android_log_id_to_name(log_id_t log_id)
207{
Mark Salyzyn42958412013-11-22 10:50:27 -0800208 if (log_id >= LOG_ID_MAX) {
209 log_id = LOG_ID_MAIN;
210 }
211 return LOG_NAME[log_id];
212}
213
Mark Salyzyn154f4602014-02-20 14:59:07 -0800214log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800215{
Mark Salyzyn42958412013-11-22 10:50:27 -0800216 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800217 int ret;
218
219 if (!logName) {
220 return -1; /* NB: log_id_t is unsigned */
221 }
222 b = strrchr(logName, '/');
223 if (!b) {
224 b = logName;
225 } else {
226 ++b;
227 }
228
Mark Salyzyn42958412013-11-22 10:50:27 -0800229 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
230 const char *l = LOG_NAME[ret];
231 if (l && !strcmp(b, l)) {
232 return ret;
233 }
234 }
235 return -1; /* should never happen */
236}
237
238struct logger_list {
239 struct listnode node;
240 int mode;
241 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800242 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800243 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800244 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800245};
246
247struct logger {
248 struct listnode node;
249 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800250 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800251};
252
253/* android_logger_alloc unimplemented, no use case */
254/* android_logger_free not exported */
255static void android_logger_free(struct logger *logger)
256{
257 if (!logger) {
258 return;
259 }
260
Mark Salyzyn42958412013-11-22 10:50:27 -0800261 list_remove(&logger->node);
262
263 free(logger);
264}
265
Mark Salyzyn154f4602014-02-20 14:59:07 -0800266/* android_logger_alloc unimplemented, no use case */
267
268/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800269log_id_t android_logger_get_id(struct logger *logger)
270{
271 return logger->id;
272}
273
274/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800275static ssize_t send_log_msg(struct logger *logger,
276 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800277{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800278 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700279 size_t len;
280 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700281 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800282 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
283 SOCK_STREAM);
284 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700285 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800286 }
287
Mark Salyzyn154f4602014-02-20 14:59:07 -0800288 if (msg) {
289 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800290 }
291
Mark Salyzyn696817d2014-04-18 14:49:28 -0700292 len = strlen(buf) + 1;
293 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800294 if (ret <= 0) {
295 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800296 }
297
Mark Salyzyn696817d2014-04-18 14:49:28 -0700298 len = buf_size;
299 cp = buf;
300 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
301 struct pollfd p;
302
303 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
304 break;
305 }
306
307 len -= ret;
308 cp += ret;
309
310 memset(&p, 0, sizeof(p));
311 p.fd = sock;
312 p.events = POLLIN;
313
314 /* Give other side 20ms to refill pipe */
315 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
316
317 if (ret <= 0) {
318 break;
319 }
320
321 if (!(p.revents & POLLIN)) {
322 ret = 0;
323 break;
324 }
325 }
326
327 if (ret >= 0) {
328 ret += buf_size - len;
329 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800330
331done:
332 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700333 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800334 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800335 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700336 if (errno_save) {
337 errno = errno_save;
338 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800339 return ret;
340}
341
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800342static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800343{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800344 if (ret < 0) {
345 return ret;
346 }
347
348 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700349 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800350 return -1;
351 }
352
353 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800354}
355
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800356int android_logger_clear(struct logger *logger)
357{
358 char buf[512];
359
360 return check_log_success(buf,
361 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
362}
363
Mark Salyzyn42958412013-11-22 10:50:27 -0800364/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800365long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800366{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800367 char buf[512];
368
369 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
370 if (ret < 0) {
371 return ret;
372 }
373
374 if ((buf[0] < '0') || ('9' < buf[0])) {
375 return -1;
376 }
377
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800378 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800379}
380
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800381int android_logger_set_log_size(struct logger *logger, unsigned long size)
382{
383 char buf[512];
384
385 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
386 logger ? logger->id : (unsigned) -1, size);
387
388 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
389}
390
Mark Salyzyn42958412013-11-22 10:50:27 -0800391/*
392 * returns the readable size of the log's ring buffer (that is, amount of the
393 * log consumed)
394 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800395long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800396{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800397 char buf[512];
398
399 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
400 if (ret < 0) {
401 return ret;
402 }
403
404 if ((buf[0] < '0') || ('9' < buf[0])) {
405 return -1;
406 }
407
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800408 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800409}
410
411/*
412 * returns the logger version
413 */
Mark Salyzyna04464a2014-04-30 08:50:53 -0700414int android_logger_get_log_version(struct logger *logger __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800415{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800416 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800417}
418
Mark Salyzyn34facab2014-02-06 14:48:50 -0800419/*
420 * returns statistics
421 */
422ssize_t android_logger_get_statistics(struct logger_list *logger_list,
423 char *buf, size_t len)
424{
Mark Salyzyn34facab2014-02-06 14:48:50 -0800425 struct logger *logger;
426 char *cp = buf;
427 size_t remaining = len;
428 size_t n;
429
430 n = snprintf(cp, remaining, "getStatistics");
431 n = min(n, remaining);
432 remaining -= n;
433 cp += n;
434
435 logger_for_each(logger, logger_list) {
436 n = snprintf(cp, remaining, " %d", logger->id);
437 n = min(n, remaining);
438 remaining -= n;
439 cp += n;
440 }
441 return send_log_msg(NULL, NULL, buf, len);
442}
443
Mark Salyzyna04464a2014-04-30 08:50:53 -0700444ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800445 char *buf, size_t len)
446{
447 return send_log_msg(NULL, "getPruneList", buf, len);
448}
449
Mark Salyzyna04464a2014-04-30 08:50:53 -0700450int android_logger_set_prune_list(struct logger_list *logger_list __unused,
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800451 char *buf, size_t len)
452{
453 const char cmd[] = "setPruneList ";
454 const size_t cmdlen = sizeof(cmd) - 1;
455
456 if (strlen(buf) > (len - cmdlen)) {
457 return -ENOMEM; /* KISS */
458 }
459 memmove(buf + cmdlen, buf, len - cmdlen);
460 buf[len - 1] = '\0';
461 memcpy(buf, cmd, cmdlen);
462
463 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
464}
465
Mark Salyzyn42958412013-11-22 10:50:27 -0800466struct logger_list *android_logger_list_alloc(int mode,
467 unsigned int tail,
468 pid_t pid)
469{
470 struct logger_list *logger_list;
471
472 logger_list = calloc(1, sizeof(*logger_list));
473 if (!logger_list) {
474 return NULL;
475 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800476
Mark Salyzyn42958412013-11-22 10:50:27 -0800477 list_init(&logger_list->node);
478 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800479 logger_list->start.tv_sec = 0;
480 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800481 logger_list->tail = tail;
482 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800483 logger_list->sock = -1;
484
Mark Salyzyn42958412013-11-22 10:50:27 -0800485 return logger_list;
486}
487
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800488struct logger_list *android_logger_list_alloc_time(int mode,
489 log_time start,
490 pid_t pid)
491{
492 struct logger_list *logger_list;
493
494 logger_list = calloc(1, sizeof(*logger_list));
495 if (!logger_list) {
496 return NULL;
497 }
498
499 list_init(&logger_list->node);
500 logger_list->mode = mode;
501 logger_list->start = start;
502 logger_list->tail = 0;
503 logger_list->pid = pid;
504 logger_list->sock = -1;
505
506 return logger_list;
507}
508
Mark Salyzyn42958412013-11-22 10:50:27 -0800509/* android_logger_list_register unimplemented, no use case */
510/* android_logger_list_unregister unimplemented, no use case */
511
512/* Open the named log and add it to the logger list */
513struct logger *android_logger_open(struct logger_list *logger_list,
514 log_id_t id)
515{
Mark Salyzyn42958412013-11-22 10:50:27 -0800516 struct logger *logger;
Mark Salyzyn42958412013-11-22 10:50:27 -0800517
518 if (!logger_list || (id >= LOG_ID_MAX)) {
519 goto err;
520 }
521
522 logger_for_each(logger, logger_list) {
523 if (logger->id == id) {
524 goto ok;
525 }
526 }
527
528 logger = calloc(1, sizeof(*logger));
529 if (!logger) {
530 goto err;
531 }
532
Mark Salyzyn42958412013-11-22 10:50:27 -0800533 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800534 list_add_tail(&logger_list->node, &logger->node);
535 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800536 goto ok;
537
Mark Salyzyn42958412013-11-22 10:50:27 -0800538err:
539 logger = NULL;
540ok:
541 return logger;
542}
543
544/* Open the single named log and make it part of a new logger list */
545struct logger_list *android_logger_list_open(log_id_t id,
546 int mode,
547 unsigned int tail,
548 pid_t pid)
549{
550 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
551 if (!logger_list) {
552 return NULL;
553 }
554
555 if (!android_logger_open(logger_list, id)) {
556 android_logger_list_free(logger_list);
557 return NULL;
558 }
559
560 return logger_list;
561}
562
Mark Salyzyna04464a2014-04-30 08:50:53 -0700563static void caught_signal(int signum __unused)
Mark Salyzyn42958412013-11-22 10:50:27 -0800564{
Mark Salyzyn42958412013-11-22 10:50:27 -0800565}
566
567/* Read from the selected logs */
568int android_logger_list_read(struct logger_list *logger_list,
569 struct log_msg *log_msg)
570{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800571 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800572 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800573 struct sigaction ignore;
574 struct sigaction old_sigaction;
575 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800576
577 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800578 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800579 }
580
Mark Salyzyn154f4602014-02-20 14:59:07 -0800581 if (logger_list->mode & O_NONBLOCK) {
582 memset(&ignore, 0, sizeof(ignore));
583 ignore.sa_handler = caught_signal;
584 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800585 }
586
Mark Salyzyn154f4602014-02-20 14:59:07 -0800587 if (logger_list->sock < 0) {
588 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800589
Mark Salyzyn154f4602014-02-20 14:59:07 -0800590 int sock = socket_local_client("logdr",
591 ANDROID_SOCKET_NAMESPACE_RESERVED,
592 SOCK_SEQPACKET);
593 if (sock < 0) {
594 if ((sock == -1) && errno) {
595 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800596 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800597 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800598 }
599
Mark Salyzyn154f4602014-02-20 14:59:07 -0800600 strcpy(buffer,
601 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
602 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800603
Mark Salyzyn154f4602014-02-20 14:59:07 -0800604 strcpy(cp, " lids");
605 cp += 5;
606 c = '=';
607 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800608 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800609 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
610 ret = min(ret, remaining);
611 remaining -= ret;
612 cp += ret;
613 c = ',';
614 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800615
Mark Salyzyn154f4602014-02-20 14:59:07 -0800616 if (logger_list->tail) {
617 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
618 ret = min(ret, remaining);
619 remaining -= ret;
620 cp += ret;
621 }
622
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800623 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
624 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
625 logger_list->start.tv_sec,
626 logger_list->start.tv_nsec);
627 ret = min(ret, remaining);
628 remaining -= ret;
629 cp += ret;
630 }
631
Mark Salyzyn154f4602014-02-20 14:59:07 -0800632 if (logger_list->pid) {
633 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
634 ret = min(ret, remaining);
635 remaining -= ret;
636 cp += ret;
637 }
638
639 if (logger_list->mode & O_NONBLOCK) {
640 /* Deal with an unresponsive logd */
641 sigaction(SIGALRM, &ignore, &old_sigaction);
642 old_alarm = alarm(30);
643 }
644 ret = write(sock, buffer, cp - buffer);
645 e = errno;
646 if (logger_list->mode & O_NONBLOCK) {
647 if (e == EINTR) {
648 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800649 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800650 alarm(old_alarm);
651 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800652 }
653
654 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800655 close(sock);
656 if ((ret == -1) && e) {
657 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800658 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800659 if (ret == 0) {
660 return -EIO;
661 }
662 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800663 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800664
665 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800666 }
667
Mark Salyzyn154f4602014-02-20 14:59:07 -0800668 ret = 0;
669 while(1) {
670 memset(log_msg, 0, sizeof(*log_msg));
671
672 if (logger_list->mode & O_NONBLOCK) {
673 /* particularily useful if tombstone is reporting for logd */
674 sigaction(SIGALRM, &ignore, &old_sigaction);
675 old_alarm = alarm(30);
676 }
677 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
678 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
679 e = errno;
680 if (logger_list->mode & O_NONBLOCK) {
681 if ((ret == 0) || (e == EINTR)) {
682 e = EAGAIN;
683 ret = -1;
684 }
685 alarm(old_alarm);
686 sigaction(SIGALRM, &old_sigaction, NULL);
687 }
688
689 if (ret <= 0) {
690 if ((ret == -1) && e) {
691 return -e;
692 }
693 return ret;
694 }
695
696 logger_for_each(logger, logger_list) {
697 if (log_msg->entry.lid == logger->id) {
698 return ret;
699 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800700 }
701 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800702 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800703 return ret;
704}
705
706/* Close all the logs */
707void android_logger_list_free(struct logger_list *logger_list)
708{
709 if (logger_list == NULL) {
710 return;
711 }
712
713 while (!list_empty(&logger_list->node)) {
714 struct listnode *node = list_head(&logger_list->node);
715 struct logger *logger = node_to_item(node, struct logger, node);
716 android_logger_free(logger);
717 }
718
Mark Salyzyn154f4602014-02-20 14:59:07 -0800719 if (logger_list->sock >= 0) {
720 close (logger_list->sock);
721 }
722
Mark Salyzyn42958412013-11-22 10:50:27 -0800723 free(logger_list);
724}