blob: 11fe8486b58b939a03e877df543b66ba1a8b7309 [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>
26#include <unistd.h>
27
Mark Salyzyn42958412013-11-22 10:50:27 -080028#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080029#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080030#include <log/log.h>
31#include <log/logger.h>
32
Mark Salyzyn154f4602014-02-20 14:59:07 -080033/* branchless on many architectures. */
34#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080035
Mark Salyzyn154f4602014-02-20 14:59:07 -080036#define WEAK __attribute__((weak))
37#define UNUSED __attribute__((unused))
Mark Salyzyn1345f382014-01-14 08:41:27 -080038
Mark Salyzyn154f4602014-02-20 14:59:07 -080039/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080040
Mark Salyzyn154f4602014-02-20 14:59:07 -080041#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080042
Mark Salyzyn154f4602014-02-20 14:59:07 -080043int WEAK socket_local_client(const char *name, int namespaceId, int type)
44{
45 errno = ENOSYS;
46 return -ENOSYS;
47}
Mark Salyzyn42958412013-11-22 10:50:27 -080048
Mark Salyzyn154f4602014-02-20 14:59:07 -080049#else /* !HAVE_WINSOCK */
50
51#include <sys/socket.h>
52#include <sys/un.h>
53#include <sys/select.h>
54#include <sys/types.h>
55
56/* Private copy of ../libcutils/socket_local.h prevent library loops */
57#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
58#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
59/* End of ../libcutils/socket_local.h */
60
61#define LISTEN_BACKLOG 4
62
63/* Documented in header file. */
64int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
65 struct sockaddr_un *p_addr, socklen_t *alen)
66{
67 memset (p_addr, 0, sizeof (*p_addr));
68 size_t namelen;
69
70 switch (namespaceId) {
71 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
72#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
73 namelen = strlen(name);
74
75 /* Test with length +1 for the *initial* '\0'. */
76 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
77 goto error;
78 }
79
80 /*
81 * Note: The path in this case is *not* supposed to be
82 * '\0'-terminated. ("man 7 unix" for the gory details.)
83 */
84
85 p_addr->sun_path[0] = 0;
86 memcpy(p_addr->sun_path + 1, name, namelen);
87#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
88 /* this OS doesn't have the Linux abstract namespace */
89
90 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
91 /* unix_path_max appears to be missing on linux */
92 if (namelen > sizeof(*p_addr)
93 - offsetof(struct sockaddr_un, sun_path) - 1) {
94 goto error;
95 }
96
97 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
98 strcat(p_addr->sun_path, name);
99#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
100 break;
101
102 case ANDROID_SOCKET_NAMESPACE_RESERVED:
103 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
104 /* unix_path_max appears to be missing on linux */
105 if (namelen > sizeof(*p_addr)
106 - offsetof(struct sockaddr_un, sun_path) - 1) {
107 goto error;
108 }
109
110 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
111 strcat(p_addr->sun_path, name);
112 break;
113
114 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
115 namelen = strlen(name);
116 /* unix_path_max appears to be missing on linux */
117 if (namelen > sizeof(*p_addr)
118 - offsetof(struct sockaddr_un, sun_path) - 1) {
119 goto error;
120 }
121
122 strcpy(p_addr->sun_path, name);
123 break;
124
125 default:
126 /* invalid namespace id */
127 return -1;
128 }
129
130 p_addr->sun_family = AF_LOCAL;
131 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
132 return 0;
133error:
134 return -1;
135}
136
137/**
138 * connect to peer named "name" on fd
139 * returns same fd or -1 on error.
140 * fd is not closed on error. that's your job.
141 *
142 * Used by AndroidSocketImpl
143 */
144int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
145 int type UNUSED)
146{
147 struct sockaddr_un addr;
148 socklen_t alen;
149 size_t namelen;
150 int err;
151
152 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
153
154 if (err < 0) {
155 goto error;
156 }
157
158 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
159 goto error;
160 }
161
162 return fd;
163
164error:
165 return -1;
166}
167
168/**
169 * connect to peer named "name"
170 * returns fd or -1 on error
171 */
172int WEAK socket_local_client(const char *name, int namespaceId, int type)
173{
174 int s;
175
176 s = socket(AF_LOCAL, type, 0);
177 if(s < 0) return -1;
178
179 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
180 close(s);
181 return -1;
182 }
183
184 return s;
185}
186
187#endif /* !HAVE_WINSOCK */
188/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800189
190#define logger_for_each(logger, logger_list) \
191 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
192 logger != node_to_item(&(logger_list)->node, struct logger, node); \
193 logger = node_to_item((logger)->node.next, struct logger, node))
194
195/* In the future, we would like to make this list extensible */
196static const char *LOG_NAME[LOG_ID_MAX] = {
197 [LOG_ID_MAIN] = "main",
198 [LOG_ID_RADIO] = "radio",
199 [LOG_ID_EVENTS] = "events",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700200 [LOG_ID_SYSTEM] = "system",
201 [LOG_ID_CRASH] = "crash",
Mark Salyzyn42958412013-11-22 10:50:27 -0800202};
203
Mark Salyzyn154f4602014-02-20 14:59:07 -0800204const char *android_log_id_to_name(log_id_t log_id)
205{
Mark Salyzyn42958412013-11-22 10:50:27 -0800206 if (log_id >= LOG_ID_MAX) {
207 log_id = LOG_ID_MAIN;
208 }
209 return LOG_NAME[log_id];
210}
211
Mark Salyzyn154f4602014-02-20 14:59:07 -0800212log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800213{
Mark Salyzyn42958412013-11-22 10:50:27 -0800214 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800215 int ret;
216
217 if (!logName) {
218 return -1; /* NB: log_id_t is unsigned */
219 }
220 b = strrchr(logName, '/');
221 if (!b) {
222 b = logName;
223 } else {
224 ++b;
225 }
226
Mark Salyzyn42958412013-11-22 10:50:27 -0800227 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
228 const char *l = LOG_NAME[ret];
229 if (l && !strcmp(b, l)) {
230 return ret;
231 }
232 }
233 return -1; /* should never happen */
234}
235
236struct logger_list {
237 struct listnode node;
238 int mode;
239 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800240 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800241 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800242 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800243};
244
245struct logger {
246 struct listnode node;
247 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800248 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800249};
250
251/* android_logger_alloc unimplemented, no use case */
252/* android_logger_free not exported */
253static void android_logger_free(struct logger *logger)
254{
255 if (!logger) {
256 return;
257 }
258
Mark Salyzyn42958412013-11-22 10:50:27 -0800259 list_remove(&logger->node);
260
261 free(logger);
262}
263
Mark Salyzyn154f4602014-02-20 14:59:07 -0800264/* android_logger_alloc unimplemented, no use case */
265
266/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800267log_id_t android_logger_get_id(struct logger *logger)
268{
269 return logger->id;
270}
271
272/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800273static ssize_t send_log_msg(struct logger *logger,
274 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800275{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800276 ssize_t ret;
Mark Salyzyn696817d2014-04-18 14:49:28 -0700277 size_t len;
278 char *cp;
Greg Hackmann8084a532014-03-17 13:08:31 -0700279 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800280 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
281 SOCK_STREAM);
282 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700283 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800284 }
285
Mark Salyzyn154f4602014-02-20 14:59:07 -0800286 if (msg) {
287 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800288 }
289
Mark Salyzyn696817d2014-04-18 14:49:28 -0700290 len = strlen(buf) + 1;
291 ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
Mark Salyzyn154f4602014-02-20 14:59:07 -0800292 if (ret <= 0) {
293 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800294 }
295
Mark Salyzyn696817d2014-04-18 14:49:28 -0700296 len = buf_size;
297 cp = buf;
298 while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
299 struct pollfd p;
300
301 if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
302 break;
303 }
304
305 len -= ret;
306 cp += ret;
307
308 memset(&p, 0, sizeof(p));
309 p.fd = sock;
310 p.events = POLLIN;
311
312 /* Give other side 20ms to refill pipe */
313 ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
314
315 if (ret <= 0) {
316 break;
317 }
318
319 if (!(p.revents & POLLIN)) {
320 ret = 0;
321 break;
322 }
323 }
324
325 if (ret >= 0) {
326 ret += buf_size - len;
327 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800328
329done:
330 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700331 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800332 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800333 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700334 if (errno_save) {
335 errno = errno_save;
336 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800337 return ret;
338}
339
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800340static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800341{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800342 if (ret < 0) {
343 return ret;
344 }
345
346 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700347 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800348 return -1;
349 }
350
351 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800352}
353
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800354int android_logger_clear(struct logger *logger)
355{
356 char buf[512];
357
358 return check_log_success(buf,
359 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
360}
361
Mark Salyzyn42958412013-11-22 10:50:27 -0800362/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800363long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800364{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800365 char buf[512];
366
367 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
368 if (ret < 0) {
369 return ret;
370 }
371
372 if ((buf[0] < '0') || ('9' < buf[0])) {
373 return -1;
374 }
375
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800376 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800377}
378
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800379int android_logger_set_log_size(struct logger *logger, unsigned long size)
380{
381 char buf[512];
382
383 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
384 logger ? logger->id : (unsigned) -1, size);
385
386 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
387}
388
Mark Salyzyn42958412013-11-22 10:50:27 -0800389/*
390 * returns the readable size of the log's ring buffer (that is, amount of the
391 * log consumed)
392 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800393long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800394{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800395 char buf[512];
396
397 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
398 if (ret < 0) {
399 return ret;
400 }
401
402 if ((buf[0] < '0') || ('9' < buf[0])) {
403 return -1;
404 }
405
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800406 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800407}
408
409/*
410 * returns the logger version
411 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800412int android_logger_get_log_version(struct logger *logger UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800413{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800414 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800415}
416
Mark Salyzyn34facab2014-02-06 14:48:50 -0800417/*
418 * returns statistics
419 */
420ssize_t android_logger_get_statistics(struct logger_list *logger_list,
421 char *buf, size_t len)
422{
423 struct listnode *node;
424 struct logger *logger;
425 char *cp = buf;
426 size_t remaining = len;
427 size_t n;
428
429 n = snprintf(cp, remaining, "getStatistics");
430 n = min(n, remaining);
431 remaining -= n;
432 cp += n;
433
434 logger_for_each(logger, logger_list) {
435 n = snprintf(cp, remaining, " %d", logger->id);
436 n = min(n, remaining);
437 remaining -= n;
438 cp += n;
439 }
440 return send_log_msg(NULL, NULL, buf, len);
441}
442
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800443ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
444 char *buf, size_t len)
445{
446 return send_log_msg(NULL, "getPruneList", buf, len);
447}
448
449int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
450 char *buf, size_t len)
451{
452 const char cmd[] = "setPruneList ";
453 const size_t cmdlen = sizeof(cmd) - 1;
454
455 if (strlen(buf) > (len - cmdlen)) {
456 return -ENOMEM; /* KISS */
457 }
458 memmove(buf + cmdlen, buf, len - cmdlen);
459 buf[len - 1] = '\0';
460 memcpy(buf, cmd, cmdlen);
461
462 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
463}
464
Mark Salyzyn42958412013-11-22 10:50:27 -0800465struct logger_list *android_logger_list_alloc(int mode,
466 unsigned int tail,
467 pid_t pid)
468{
469 struct logger_list *logger_list;
470
471 logger_list = calloc(1, sizeof(*logger_list));
472 if (!logger_list) {
473 return NULL;
474 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800475
Mark Salyzyn42958412013-11-22 10:50:27 -0800476 list_init(&logger_list->node);
477 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800478 logger_list->start.tv_sec = 0;
479 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800480 logger_list->tail = tail;
481 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800482 logger_list->sock = -1;
483
Mark Salyzyn42958412013-11-22 10:50:27 -0800484 return logger_list;
485}
486
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800487struct logger_list *android_logger_list_alloc_time(int mode,
488 log_time start,
489 pid_t pid)
490{
491 struct logger_list *logger_list;
492
493 logger_list = calloc(1, sizeof(*logger_list));
494 if (!logger_list) {
495 return NULL;
496 }
497
498 list_init(&logger_list->node);
499 logger_list->mode = mode;
500 logger_list->start = start;
501 logger_list->tail = 0;
502 logger_list->pid = pid;
503 logger_list->sock = -1;
504
505 return logger_list;
506}
507
Mark Salyzyn42958412013-11-22 10:50:27 -0800508/* android_logger_list_register unimplemented, no use case */
509/* android_logger_list_unregister unimplemented, no use case */
510
511/* Open the named log and add it to the logger list */
512struct logger *android_logger_open(struct logger_list *logger_list,
513 log_id_t id)
514{
515 struct listnode *node;
516 struct logger *logger;
517 char *n;
518
519 if (!logger_list || (id >= LOG_ID_MAX)) {
520 goto err;
521 }
522
523 logger_for_each(logger, logger_list) {
524 if (logger->id == id) {
525 goto ok;
526 }
527 }
528
529 logger = calloc(1, sizeof(*logger));
530 if (!logger) {
531 goto err;
532 }
533
Mark Salyzyn42958412013-11-22 10:50:27 -0800534 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800535 list_add_tail(&logger_list->node, &logger->node);
536 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800537 goto ok;
538
Mark Salyzyn42958412013-11-22 10:50:27 -0800539err:
540 logger = NULL;
541ok:
542 return logger;
543}
544
545/* Open the single named log and make it part of a new logger list */
546struct logger_list *android_logger_list_open(log_id_t id,
547 int mode,
548 unsigned int tail,
549 pid_t pid)
550{
551 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
552 if (!logger_list) {
553 return NULL;
554 }
555
556 if (!android_logger_open(logger_list, id)) {
557 android_logger_list_free(logger_list);
558 return NULL;
559 }
560
561 return logger_list;
562}
563
Mark Salyzyn154f4602014-02-20 14:59:07 -0800564static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800565{
Mark Salyzyn42958412013-11-22 10:50:27 -0800566}
567
568/* Read from the selected logs */
569int android_logger_list_read(struct logger_list *logger_list,
570 struct log_msg *log_msg)
571{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800572 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800573 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800574 struct sigaction ignore;
575 struct sigaction old_sigaction;
576 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800577
578 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800579 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800580 }
581
Mark Salyzyn154f4602014-02-20 14:59:07 -0800582 if (logger_list->mode & O_NONBLOCK) {
583 memset(&ignore, 0, sizeof(ignore));
584 ignore.sa_handler = caught_signal;
585 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800586 }
587
Mark Salyzyn154f4602014-02-20 14:59:07 -0800588 if (logger_list->sock < 0) {
589 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800590
Mark Salyzyn154f4602014-02-20 14:59:07 -0800591 int sock = socket_local_client("logdr",
592 ANDROID_SOCKET_NAMESPACE_RESERVED,
593 SOCK_SEQPACKET);
594 if (sock < 0) {
595 if ((sock == -1) && errno) {
596 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800597 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800598 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800599 }
600
Mark Salyzyn154f4602014-02-20 14:59:07 -0800601 strcpy(buffer,
602 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
603 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800604
Mark Salyzyn154f4602014-02-20 14:59:07 -0800605 strcpy(cp, " lids");
606 cp += 5;
607 c = '=';
608 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800609 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800610 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
611 ret = min(ret, remaining);
612 remaining -= ret;
613 cp += ret;
614 c = ',';
615 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800616
Mark Salyzyn154f4602014-02-20 14:59:07 -0800617 if (logger_list->tail) {
618 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
619 ret = min(ret, remaining);
620 remaining -= ret;
621 cp += ret;
622 }
623
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800624 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
625 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
626 logger_list->start.tv_sec,
627 logger_list->start.tv_nsec);
628 ret = min(ret, remaining);
629 remaining -= ret;
630 cp += ret;
631 }
632
Mark Salyzyn154f4602014-02-20 14:59:07 -0800633 if (logger_list->pid) {
634 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
635 ret = min(ret, remaining);
636 remaining -= ret;
637 cp += ret;
638 }
639
640 if (logger_list->mode & O_NONBLOCK) {
641 /* Deal with an unresponsive logd */
642 sigaction(SIGALRM, &ignore, &old_sigaction);
643 old_alarm = alarm(30);
644 }
645 ret = write(sock, buffer, cp - buffer);
646 e = errno;
647 if (logger_list->mode & O_NONBLOCK) {
648 if (e == EINTR) {
649 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800650 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800651 alarm(old_alarm);
652 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800653 }
654
655 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800656 close(sock);
657 if ((ret == -1) && e) {
658 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800659 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800660 if (ret == 0) {
661 return -EIO;
662 }
663 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800664 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800665
666 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800667 }
668
Mark Salyzyn154f4602014-02-20 14:59:07 -0800669 ret = 0;
670 while(1) {
671 memset(log_msg, 0, sizeof(*log_msg));
672
673 if (logger_list->mode & O_NONBLOCK) {
674 /* particularily useful if tombstone is reporting for logd */
675 sigaction(SIGALRM, &ignore, &old_sigaction);
676 old_alarm = alarm(30);
677 }
678 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
679 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
680 e = errno;
681 if (logger_list->mode & O_NONBLOCK) {
682 if ((ret == 0) || (e == EINTR)) {
683 e = EAGAIN;
684 ret = -1;
685 }
686 alarm(old_alarm);
687 sigaction(SIGALRM, &old_sigaction, NULL);
688 }
689
690 if (ret <= 0) {
691 if ((ret == -1) && e) {
692 return -e;
693 }
694 return ret;
695 }
696
697 logger_for_each(logger, logger_list) {
698 if (log_msg->entry.lid == logger->id) {
699 return ret;
700 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800701 }
702 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800703 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800704 return ret;
705}
706
707/* Close all the logs */
708void android_logger_list_free(struct logger_list *logger_list)
709{
710 if (logger_list == NULL) {
711 return;
712 }
713
714 while (!list_empty(&logger_list->node)) {
715 struct listnode *node = list_head(&logger_list->node);
716 struct logger *logger = node_to_item(node, struct logger, node);
717 android_logger_free(logger);
718 }
719
Mark Salyzyn154f4602014-02-20 14:59:07 -0800720 if (logger_list->sock >= 0) {
721 close (logger_list->sock);
722 }
723
Mark Salyzyn42958412013-11-22 10:50:27 -0800724 free(logger_list);
725}