blob: 2dd07e6948d6668298af1d0bc47b2331d72d796c [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 Salyzyn154f4602014-02-20 14:59:07 -080020#include <signal.h>
21#include <stddef.h>
22#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
Mark Salyzyn42958412013-11-22 10:50:27 -080023#include <stdlib.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080024#include <string.h>
25#include <unistd.h>
26
Mark Salyzyn42958412013-11-22 10:50:27 -080027#include <cutils/list.h>
Mark Salyzyn154f4602014-02-20 14:59:07 -080028#include <cutils/sockets.h>
Mark Salyzyn42958412013-11-22 10:50:27 -080029#include <log/log.h>
30#include <log/logger.h>
31
Mark Salyzyn154f4602014-02-20 14:59:07 -080032/* branchless on many architectures. */
33#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
Mark Salyzyn1345f382014-01-14 08:41:27 -080034
Mark Salyzyn154f4602014-02-20 14:59:07 -080035#define WEAK __attribute__((weak))
36#define UNUSED __attribute__((unused))
Mark Salyzyn1345f382014-01-14 08:41:27 -080037
Mark Salyzyn154f4602014-02-20 14:59:07 -080038/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
Mark Salyzyn1345f382014-01-14 08:41:27 -080039
Mark Salyzyn154f4602014-02-20 14:59:07 -080040#ifdef HAVE_WINSOCK
Mark Salyzyn42958412013-11-22 10:50:27 -080041
Mark Salyzyn154f4602014-02-20 14:59:07 -080042int WEAK socket_local_client(const char *name, int namespaceId, int type)
43{
44 errno = ENOSYS;
45 return -ENOSYS;
46}
Mark Salyzyn42958412013-11-22 10:50:27 -080047
Mark Salyzyn154f4602014-02-20 14:59:07 -080048#else /* !HAVE_WINSOCK */
49
50#include <sys/socket.h>
51#include <sys/un.h>
52#include <sys/select.h>
53#include <sys/types.h>
54
55/* Private copy of ../libcutils/socket_local.h prevent library loops */
56#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
57#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
58/* End of ../libcutils/socket_local.h */
59
60#define LISTEN_BACKLOG 4
61
62/* Documented in header file. */
63int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
64 struct sockaddr_un *p_addr, socklen_t *alen)
65{
66 memset (p_addr, 0, sizeof (*p_addr));
67 size_t namelen;
68
69 switch (namespaceId) {
70 case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
71#ifdef HAVE_LINUX_LOCAL_SOCKET_NAMESPACE
72 namelen = strlen(name);
73
74 /* Test with length +1 for the *initial* '\0'. */
75 if ((namelen + 1) > sizeof(p_addr->sun_path)) {
76 goto error;
77 }
78
79 /*
80 * Note: The path in this case is *not* supposed to be
81 * '\0'-terminated. ("man 7 unix" for the gory details.)
82 */
83
84 p_addr->sun_path[0] = 0;
85 memcpy(p_addr->sun_path + 1, name, namelen);
86#else /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
87 /* this OS doesn't have the Linux abstract namespace */
88
89 namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
90 /* unix_path_max appears to be missing on linux */
91 if (namelen > sizeof(*p_addr)
92 - offsetof(struct sockaddr_un, sun_path) - 1) {
93 goto error;
94 }
95
96 strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
97 strcat(p_addr->sun_path, name);
98#endif /*HAVE_LINUX_LOCAL_SOCKET_NAMESPACE*/
99 break;
100
101 case ANDROID_SOCKET_NAMESPACE_RESERVED:
102 namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
103 /* unix_path_max appears to be missing on linux */
104 if (namelen > sizeof(*p_addr)
105 - offsetof(struct sockaddr_un, sun_path) - 1) {
106 goto error;
107 }
108
109 strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
110 strcat(p_addr->sun_path, name);
111 break;
112
113 case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
114 namelen = strlen(name);
115 /* unix_path_max appears to be missing on linux */
116 if (namelen > sizeof(*p_addr)
117 - offsetof(struct sockaddr_un, sun_path) - 1) {
118 goto error;
119 }
120
121 strcpy(p_addr->sun_path, name);
122 break;
123
124 default:
125 /* invalid namespace id */
126 return -1;
127 }
128
129 p_addr->sun_family = AF_LOCAL;
130 *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
131 return 0;
132error:
133 return -1;
134}
135
136/**
137 * connect to peer named "name" on fd
138 * returns same fd or -1 on error.
139 * fd is not closed on error. that's your job.
140 *
141 * Used by AndroidSocketImpl
142 */
143int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
144 int type UNUSED)
145{
146 struct sockaddr_un addr;
147 socklen_t alen;
148 size_t namelen;
149 int err;
150
151 err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
152
153 if (err < 0) {
154 goto error;
155 }
156
157 if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
158 goto error;
159 }
160
161 return fd;
162
163error:
164 return -1;
165}
166
167/**
168 * connect to peer named "name"
169 * returns fd or -1 on error
170 */
171int WEAK socket_local_client(const char *name, int namespaceId, int type)
172{
173 int s;
174
175 s = socket(AF_LOCAL, type, 0);
176 if(s < 0) return -1;
177
178 if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
179 close(s);
180 return -1;
181 }
182
183 return s;
184}
185
186#endif /* !HAVE_WINSOCK */
187/* End of ../libcutils/socket_local_client.c */
Mark Salyzyn42958412013-11-22 10:50:27 -0800188
189#define logger_for_each(logger, logger_list) \
190 for (logger = node_to_item((logger_list)->node.next, struct logger, node); \
191 logger != node_to_item(&(logger_list)->node, struct logger, node); \
192 logger = node_to_item((logger)->node.next, struct logger, node))
193
194/* In the future, we would like to make this list extensible */
195static const char *LOG_NAME[LOG_ID_MAX] = {
196 [LOG_ID_MAIN] = "main",
197 [LOG_ID_RADIO] = "radio",
198 [LOG_ID_EVENTS] = "events",
199 [LOG_ID_SYSTEM] = "system"
200};
201
Mark Salyzyn154f4602014-02-20 14:59:07 -0800202const char *android_log_id_to_name(log_id_t log_id)
203{
Mark Salyzyn42958412013-11-22 10:50:27 -0800204 if (log_id >= LOG_ID_MAX) {
205 log_id = LOG_ID_MAIN;
206 }
207 return LOG_NAME[log_id];
208}
209
Mark Salyzyn154f4602014-02-20 14:59:07 -0800210log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800211{
Mark Salyzyn42958412013-11-22 10:50:27 -0800212 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800213 int ret;
214
215 if (!logName) {
216 return -1; /* NB: log_id_t is unsigned */
217 }
218 b = strrchr(logName, '/');
219 if (!b) {
220 b = logName;
221 } else {
222 ++b;
223 }
224
Mark Salyzyn42958412013-11-22 10:50:27 -0800225 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
226 const char *l = LOG_NAME[ret];
227 if (l && !strcmp(b, l)) {
228 return ret;
229 }
230 }
231 return -1; /* should never happen */
232}
233
234struct logger_list {
235 struct listnode node;
236 int mode;
237 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800238 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800239 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800240 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800241};
242
243struct logger {
244 struct listnode node;
245 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800246 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800247};
248
249/* android_logger_alloc unimplemented, no use case */
250/* android_logger_free not exported */
251static void android_logger_free(struct logger *logger)
252{
253 if (!logger) {
254 return;
255 }
256
Mark Salyzyn42958412013-11-22 10:50:27 -0800257 list_remove(&logger->node);
258
259 free(logger);
260}
261
Mark Salyzyn154f4602014-02-20 14:59:07 -0800262/* android_logger_alloc unimplemented, no use case */
263
264/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800265log_id_t android_logger_get_id(struct logger *logger)
266{
267 return logger->id;
268}
269
270/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800271static ssize_t send_log_msg(struct logger *logger,
272 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800273{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800274 ssize_t ret;
Greg Hackmann8084a532014-03-17 13:08:31 -0700275 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800276 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
277 SOCK_STREAM);
278 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700279 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800280 }
281
Mark Salyzyn154f4602014-02-20 14:59:07 -0800282 if (msg) {
283 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800284 }
285
Mark Salyzyn154f4602014-02-20 14:59:07 -0800286 ret = write(sock, buf, strlen(buf) + 1);
287 if (ret <= 0) {
288 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800289 }
290
Mark Salyzyn154f4602014-02-20 14:59:07 -0800291 ret = read(sock, buf, buf_size);
292
293done:
294 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700295 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800296 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800297 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700298 if (errno_save) {
299 errno = errno_save;
300 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800301 return ret;
302}
303
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800304static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800305{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800306 if (ret < 0) {
307 return ret;
308 }
309
310 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700311 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800312 return -1;
313 }
314
315 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800316}
317
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800318int android_logger_clear(struct logger *logger)
319{
320 char buf[512];
321
322 return check_log_success(buf,
323 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
324}
325
Mark Salyzyn42958412013-11-22 10:50:27 -0800326/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800327long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800328{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800329 char buf[512];
330
331 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
332 if (ret < 0) {
333 return ret;
334 }
335
336 if ((buf[0] < '0') || ('9' < buf[0])) {
337 return -1;
338 }
339
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800340 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800341}
342
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800343#ifdef USERDEBUG_BUILD
344
345int android_logger_set_log_size(struct logger *logger, unsigned long size)
346{
347 char buf[512];
348
349 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
350 logger ? logger->id : (unsigned) -1, size);
351
352 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
353}
354
355#endif /* USERDEBUG_BUILD */
356
Mark Salyzyn42958412013-11-22 10:50:27 -0800357/*
358 * returns the readable size of the log's ring buffer (that is, amount of the
359 * log consumed)
360 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800361long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800362{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800363 char buf[512];
364
365 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
366 if (ret < 0) {
367 return ret;
368 }
369
370 if ((buf[0] < '0') || ('9' < buf[0])) {
371 return -1;
372 }
373
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800374 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800375}
376
377/*
378 * returns the logger version
379 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800380int android_logger_get_log_version(struct logger *logger UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800381{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800382 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800383}
384
Mark Salyzyn34facab2014-02-06 14:48:50 -0800385/*
386 * returns statistics
387 */
388ssize_t android_logger_get_statistics(struct logger_list *logger_list,
389 char *buf, size_t len)
390{
391 struct listnode *node;
392 struct logger *logger;
393 char *cp = buf;
394 size_t remaining = len;
395 size_t n;
396
397 n = snprintf(cp, remaining, "getStatistics");
398 n = min(n, remaining);
399 remaining -= n;
400 cp += n;
401
402 logger_for_each(logger, logger_list) {
403 n = snprintf(cp, remaining, " %d", logger->id);
404 n = min(n, remaining);
405 remaining -= n;
406 cp += n;
407 }
408 return send_log_msg(NULL, NULL, buf, len);
409}
410
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800411#ifdef USERDEBUG_BUILD
412
413ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
414 char *buf, size_t len)
415{
416 return send_log_msg(NULL, "getPruneList", buf, len);
417}
418
419int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
420 char *buf, size_t len)
421{
422 const char cmd[] = "setPruneList ";
423 const size_t cmdlen = sizeof(cmd) - 1;
424
425 if (strlen(buf) > (len - cmdlen)) {
426 return -ENOMEM; /* KISS */
427 }
428 memmove(buf + cmdlen, buf, len - cmdlen);
429 buf[len - 1] = '\0';
430 memcpy(buf, cmd, cmdlen);
431
432 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
433}
434
435#endif /* USERDEBUG_BUILD */
436
Mark Salyzyn42958412013-11-22 10:50:27 -0800437struct logger_list *android_logger_list_alloc(int mode,
438 unsigned int tail,
439 pid_t pid)
440{
441 struct logger_list *logger_list;
442
443 logger_list = calloc(1, sizeof(*logger_list));
444 if (!logger_list) {
445 return NULL;
446 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800447
Mark Salyzyn42958412013-11-22 10:50:27 -0800448 list_init(&logger_list->node);
449 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800450 logger_list->start.tv_sec = 0;
451 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800452 logger_list->tail = tail;
453 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800454 logger_list->sock = -1;
455
Mark Salyzyn42958412013-11-22 10:50:27 -0800456 return logger_list;
457}
458
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800459struct logger_list *android_logger_list_alloc_time(int mode,
460 log_time start,
461 pid_t pid)
462{
463 struct logger_list *logger_list;
464
465 logger_list = calloc(1, sizeof(*logger_list));
466 if (!logger_list) {
467 return NULL;
468 }
469
470 list_init(&logger_list->node);
471 logger_list->mode = mode;
472 logger_list->start = start;
473 logger_list->tail = 0;
474 logger_list->pid = pid;
475 logger_list->sock = -1;
476
477 return logger_list;
478}
479
Mark Salyzyn42958412013-11-22 10:50:27 -0800480/* android_logger_list_register unimplemented, no use case */
481/* android_logger_list_unregister unimplemented, no use case */
482
483/* Open the named log and add it to the logger list */
484struct logger *android_logger_open(struct logger_list *logger_list,
485 log_id_t id)
486{
487 struct listnode *node;
488 struct logger *logger;
489 char *n;
490
491 if (!logger_list || (id >= LOG_ID_MAX)) {
492 goto err;
493 }
494
495 logger_for_each(logger, logger_list) {
496 if (logger->id == id) {
497 goto ok;
498 }
499 }
500
501 logger = calloc(1, sizeof(*logger));
502 if (!logger) {
503 goto err;
504 }
505
Mark Salyzyn42958412013-11-22 10:50:27 -0800506 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800507 list_add_tail(&logger_list->node, &logger->node);
508 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800509 goto ok;
510
Mark Salyzyn42958412013-11-22 10:50:27 -0800511err:
512 logger = NULL;
513ok:
514 return logger;
515}
516
517/* Open the single named log and make it part of a new logger list */
518struct logger_list *android_logger_list_open(log_id_t id,
519 int mode,
520 unsigned int tail,
521 pid_t pid)
522{
523 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
524 if (!logger_list) {
525 return NULL;
526 }
527
528 if (!android_logger_open(logger_list, id)) {
529 android_logger_list_free(logger_list);
530 return NULL;
531 }
532
533 return logger_list;
534}
535
Mark Salyzyn154f4602014-02-20 14:59:07 -0800536static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800537{
Mark Salyzyn42958412013-11-22 10:50:27 -0800538}
539
540/* Read from the selected logs */
541int android_logger_list_read(struct logger_list *logger_list,
542 struct log_msg *log_msg)
543{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800544 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800545 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800546 struct sigaction ignore;
547 struct sigaction old_sigaction;
548 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800549
550 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800551 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800552 }
553
Mark Salyzyn154f4602014-02-20 14:59:07 -0800554 if (logger_list->mode & O_NONBLOCK) {
555 memset(&ignore, 0, sizeof(ignore));
556 ignore.sa_handler = caught_signal;
557 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800558 }
559
Mark Salyzyn154f4602014-02-20 14:59:07 -0800560 if (logger_list->sock < 0) {
561 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800562
Mark Salyzyn154f4602014-02-20 14:59:07 -0800563 int sock = socket_local_client("logdr",
564 ANDROID_SOCKET_NAMESPACE_RESERVED,
565 SOCK_SEQPACKET);
566 if (sock < 0) {
567 if ((sock == -1) && errno) {
568 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800569 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800570 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800571 }
572
Mark Salyzyn154f4602014-02-20 14:59:07 -0800573 strcpy(buffer,
574 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
575 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800576
Mark Salyzyn154f4602014-02-20 14:59:07 -0800577 strcpy(cp, " lids");
578 cp += 5;
579 c = '=';
580 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800581 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800582 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
583 ret = min(ret, remaining);
584 remaining -= ret;
585 cp += ret;
586 c = ',';
587 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800588
Mark Salyzyn154f4602014-02-20 14:59:07 -0800589 if (logger_list->tail) {
590 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
591 ret = min(ret, remaining);
592 remaining -= ret;
593 cp += ret;
594 }
595
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800596 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
597 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
598 logger_list->start.tv_sec,
599 logger_list->start.tv_nsec);
600 ret = min(ret, remaining);
601 remaining -= ret;
602 cp += ret;
603 }
604
Mark Salyzyn154f4602014-02-20 14:59:07 -0800605 if (logger_list->pid) {
606 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
607 ret = min(ret, remaining);
608 remaining -= ret;
609 cp += ret;
610 }
611
612 if (logger_list->mode & O_NONBLOCK) {
613 /* Deal with an unresponsive logd */
614 sigaction(SIGALRM, &ignore, &old_sigaction);
615 old_alarm = alarm(30);
616 }
617 ret = write(sock, buffer, cp - buffer);
618 e = errno;
619 if (logger_list->mode & O_NONBLOCK) {
620 if (e == EINTR) {
621 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800622 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800623 alarm(old_alarm);
624 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800625 }
626
627 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800628 close(sock);
629 if ((ret == -1) && e) {
630 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800631 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800632 if (ret == 0) {
633 return -EIO;
634 }
635 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800636 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800637
638 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800639 }
640
Mark Salyzyn154f4602014-02-20 14:59:07 -0800641 ret = 0;
642 while(1) {
643 memset(log_msg, 0, sizeof(*log_msg));
644
645 if (logger_list->mode & O_NONBLOCK) {
646 /* particularily useful if tombstone is reporting for logd */
647 sigaction(SIGALRM, &ignore, &old_sigaction);
648 old_alarm = alarm(30);
649 }
650 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
651 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
652 e = errno;
653 if (logger_list->mode & O_NONBLOCK) {
654 if ((ret == 0) || (e == EINTR)) {
655 e = EAGAIN;
656 ret = -1;
657 }
658 alarm(old_alarm);
659 sigaction(SIGALRM, &old_sigaction, NULL);
660 }
661
662 if (ret <= 0) {
663 if ((ret == -1) && e) {
664 return -e;
665 }
666 return ret;
667 }
668
669 logger_for_each(logger, logger_list) {
670 if (log_msg->entry.lid == logger->id) {
671 return ret;
672 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800673 }
674 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800675 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800676 return ret;
677}
678
679/* Close all the logs */
680void android_logger_list_free(struct logger_list *logger_list)
681{
682 if (logger_list == NULL) {
683 return;
684 }
685
686 while (!list_empty(&logger_list->node)) {
687 struct listnode *node = list_head(&logger_list->node);
688 struct logger *logger = node_to_item(node, struct logger, node);
689 android_logger_free(logger);
690 }
691
Mark Salyzyn154f4602014-02-20 14:59:07 -0800692 if (logger_list->sock >= 0) {
693 close (logger_list->sock);
694 }
695
Mark Salyzyn42958412013-11-22 10:50:27 -0800696 free(logger_list);
697}