blob: d96f12985220923272bd505947fcdfcec9f88083 [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;
275 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
276 SOCK_STREAM);
277 if (sock < 0) {
278 ret = sock;
279 goto done;
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) {
295 ret = -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800296 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800297 close(sock);
Mark Salyzyn42958412013-11-22 10:50:27 -0800298 return ret;
299}
300
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800301static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800302{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800303 if (ret < 0) {
304 return ret;
305 }
306
307 if (strncmp(buf, "success", 7)) {
308 return -1;
309 }
310
311 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800312}
313
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800314int android_logger_clear(struct logger *logger)
315{
316 char buf[512];
317
318 return check_log_success(buf,
319 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
320}
321
Mark Salyzyn42958412013-11-22 10:50:27 -0800322/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800323long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800324{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800325 char buf[512];
326
327 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
328 if (ret < 0) {
329 return ret;
330 }
331
332 if ((buf[0] < '0') || ('9' < buf[0])) {
333 return -1;
334 }
335
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800336 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800337}
338
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800339#ifdef USERDEBUG_BUILD
340
341int android_logger_set_log_size(struct logger *logger, unsigned long size)
342{
343 char buf[512];
344
345 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
346 logger ? logger->id : (unsigned) -1, size);
347
348 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
349}
350
351#endif /* USERDEBUG_BUILD */
352
Mark Salyzyn42958412013-11-22 10:50:27 -0800353/*
354 * returns the readable size of the log's ring buffer (that is, amount of the
355 * log consumed)
356 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800357long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800358{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800359 char buf[512];
360
361 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
362 if (ret < 0) {
363 return ret;
364 }
365
366 if ((buf[0] < '0') || ('9' < buf[0])) {
367 return -1;
368 }
369
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800370 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800371}
372
373/*
374 * returns the logger version
375 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800376int android_logger_get_log_version(struct logger *logger UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800377{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800378 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800379}
380
Mark Salyzyn34facab2014-02-06 14:48:50 -0800381/*
382 * returns statistics
383 */
384ssize_t android_logger_get_statistics(struct logger_list *logger_list,
385 char *buf, size_t len)
386{
387 struct listnode *node;
388 struct logger *logger;
389 char *cp = buf;
390 size_t remaining = len;
391 size_t n;
392
393 n = snprintf(cp, remaining, "getStatistics");
394 n = min(n, remaining);
395 remaining -= n;
396 cp += n;
397
398 logger_for_each(logger, logger_list) {
399 n = snprintf(cp, remaining, " %d", logger->id);
400 n = min(n, remaining);
401 remaining -= n;
402 cp += n;
403 }
404 return send_log_msg(NULL, NULL, buf, len);
405}
406
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800407#ifdef USERDEBUG_BUILD
408
409ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
410 char *buf, size_t len)
411{
412 return send_log_msg(NULL, "getPruneList", buf, len);
413}
414
415int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
416 char *buf, size_t len)
417{
418 const char cmd[] = "setPruneList ";
419 const size_t cmdlen = sizeof(cmd) - 1;
420
421 if (strlen(buf) > (len - cmdlen)) {
422 return -ENOMEM; /* KISS */
423 }
424 memmove(buf + cmdlen, buf, len - cmdlen);
425 buf[len - 1] = '\0';
426 memcpy(buf, cmd, cmdlen);
427
428 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
429}
430
431#endif /* USERDEBUG_BUILD */
432
Mark Salyzyn42958412013-11-22 10:50:27 -0800433struct logger_list *android_logger_list_alloc(int mode,
434 unsigned int tail,
435 pid_t pid)
436{
437 struct logger_list *logger_list;
438
439 logger_list = calloc(1, sizeof(*logger_list));
440 if (!logger_list) {
441 return NULL;
442 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800443
Mark Salyzyn42958412013-11-22 10:50:27 -0800444 list_init(&logger_list->node);
445 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800446 logger_list->start.tv_sec = 0;
447 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800448 logger_list->tail = tail;
449 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800450 logger_list->sock = -1;
451
Mark Salyzyn42958412013-11-22 10:50:27 -0800452 return logger_list;
453}
454
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800455struct logger_list *android_logger_list_alloc_time(int mode,
456 log_time start,
457 pid_t pid)
458{
459 struct logger_list *logger_list;
460
461 logger_list = calloc(1, sizeof(*logger_list));
462 if (!logger_list) {
463 return NULL;
464 }
465
466 list_init(&logger_list->node);
467 logger_list->mode = mode;
468 logger_list->start = start;
469 logger_list->tail = 0;
470 logger_list->pid = pid;
471 logger_list->sock = -1;
472
473 return logger_list;
474}
475
Mark Salyzyn42958412013-11-22 10:50:27 -0800476/* android_logger_list_register unimplemented, no use case */
477/* android_logger_list_unregister unimplemented, no use case */
478
479/* Open the named log and add it to the logger list */
480struct logger *android_logger_open(struct logger_list *logger_list,
481 log_id_t id)
482{
483 struct listnode *node;
484 struct logger *logger;
485 char *n;
486
487 if (!logger_list || (id >= LOG_ID_MAX)) {
488 goto err;
489 }
490
491 logger_for_each(logger, logger_list) {
492 if (logger->id == id) {
493 goto ok;
494 }
495 }
496
497 logger = calloc(1, sizeof(*logger));
498 if (!logger) {
499 goto err;
500 }
501
Mark Salyzyn42958412013-11-22 10:50:27 -0800502 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800503 list_add_tail(&logger_list->node, &logger->node);
504 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800505 goto ok;
506
Mark Salyzyn42958412013-11-22 10:50:27 -0800507err:
508 logger = NULL;
509ok:
510 return logger;
511}
512
513/* Open the single named log and make it part of a new logger list */
514struct logger_list *android_logger_list_open(log_id_t id,
515 int mode,
516 unsigned int tail,
517 pid_t pid)
518{
519 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
520 if (!logger_list) {
521 return NULL;
522 }
523
524 if (!android_logger_open(logger_list, id)) {
525 android_logger_list_free(logger_list);
526 return NULL;
527 }
528
529 return logger_list;
530}
531
Mark Salyzyn154f4602014-02-20 14:59:07 -0800532static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800533{
Mark Salyzyn42958412013-11-22 10:50:27 -0800534}
535
536/* Read from the selected logs */
537int android_logger_list_read(struct logger_list *logger_list,
538 struct log_msg *log_msg)
539{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800540 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800541 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800542 struct sigaction ignore;
543 struct sigaction old_sigaction;
544 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800545
546 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800547 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800548 }
549
Mark Salyzyn154f4602014-02-20 14:59:07 -0800550 if (logger_list->mode & O_NONBLOCK) {
551 memset(&ignore, 0, sizeof(ignore));
552 ignore.sa_handler = caught_signal;
553 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800554 }
555
Mark Salyzyn154f4602014-02-20 14:59:07 -0800556 if (logger_list->sock < 0) {
557 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800558
Mark Salyzyn154f4602014-02-20 14:59:07 -0800559 int sock = socket_local_client("logdr",
560 ANDROID_SOCKET_NAMESPACE_RESERVED,
561 SOCK_SEQPACKET);
562 if (sock < 0) {
563 if ((sock == -1) && errno) {
564 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800565 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800566 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800567 }
568
Mark Salyzyn154f4602014-02-20 14:59:07 -0800569 strcpy(buffer,
570 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
571 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800572
Mark Salyzyn154f4602014-02-20 14:59:07 -0800573 strcpy(cp, " lids");
574 cp += 5;
575 c = '=';
576 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800577 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800578 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
579 ret = min(ret, remaining);
580 remaining -= ret;
581 cp += ret;
582 c = ',';
583 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800584
Mark Salyzyn154f4602014-02-20 14:59:07 -0800585 if (logger_list->tail) {
586 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
587 ret = min(ret, remaining);
588 remaining -= ret;
589 cp += ret;
590 }
591
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800592 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
593 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
594 logger_list->start.tv_sec,
595 logger_list->start.tv_nsec);
596 ret = min(ret, remaining);
597 remaining -= ret;
598 cp += ret;
599 }
600
Mark Salyzyn154f4602014-02-20 14:59:07 -0800601 if (logger_list->pid) {
602 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
603 ret = min(ret, remaining);
604 remaining -= ret;
605 cp += ret;
606 }
607
608 if (logger_list->mode & O_NONBLOCK) {
609 /* Deal with an unresponsive logd */
610 sigaction(SIGALRM, &ignore, &old_sigaction);
611 old_alarm = alarm(30);
612 }
613 ret = write(sock, buffer, cp - buffer);
614 e = errno;
615 if (logger_list->mode & O_NONBLOCK) {
616 if (e == EINTR) {
617 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800618 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800619 alarm(old_alarm);
620 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800621 }
622
623 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800624 close(sock);
625 if ((ret == -1) && e) {
626 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800627 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800628 if (ret == 0) {
629 return -EIO;
630 }
631 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800632 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800633
634 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800635 }
636
Mark Salyzyn154f4602014-02-20 14:59:07 -0800637 ret = 0;
638 while(1) {
639 memset(log_msg, 0, sizeof(*log_msg));
640
641 if (logger_list->mode & O_NONBLOCK) {
642 /* particularily useful if tombstone is reporting for logd */
643 sigaction(SIGALRM, &ignore, &old_sigaction);
644 old_alarm = alarm(30);
645 }
646 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
647 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
648 e = errno;
649 if (logger_list->mode & O_NONBLOCK) {
650 if ((ret == 0) || (e == EINTR)) {
651 e = EAGAIN;
652 ret = -1;
653 }
654 alarm(old_alarm);
655 sigaction(SIGALRM, &old_sigaction, NULL);
656 }
657
658 if (ret <= 0) {
659 if ((ret == -1) && e) {
660 return -e;
661 }
662 return ret;
663 }
664
665 logger_for_each(logger, logger_list) {
666 if (log_msg->entry.lid == logger->id) {
667 return ret;
668 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800669 }
670 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800671 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800672 return ret;
673}
674
675/* Close all the logs */
676void android_logger_list_free(struct logger_list *logger_list)
677{
678 if (logger_list == NULL) {
679 return;
680 }
681
682 while (!list_empty(&logger_list->node)) {
683 struct listnode *node = list_head(&logger_list->node);
684 struct logger *logger = node_to_item(node, struct logger, node);
685 android_logger_free(logger);
686 }
687
Mark Salyzyn154f4602014-02-20 14:59:07 -0800688 if (logger_list->sock >= 0) {
689 close (logger_list->sock);
690 }
691
Mark Salyzyn42958412013-11-22 10:50:27 -0800692 free(logger_list);
693}