blob: 0ff94bff144233ba60b233ba0d4727b93a60a933 [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",
Mark Salyzyn99f47a92014-04-07 14:58:08 -0700199 [LOG_ID_SYSTEM] = "system",
200 [LOG_ID_CRASH] = "crash",
Mark Salyzyn42958412013-11-22 10:50:27 -0800201};
202
Mark Salyzyn154f4602014-02-20 14:59:07 -0800203const char *android_log_id_to_name(log_id_t log_id)
204{
Mark Salyzyn42958412013-11-22 10:50:27 -0800205 if (log_id >= LOG_ID_MAX) {
206 log_id = LOG_ID_MAIN;
207 }
208 return LOG_NAME[log_id];
209}
210
Mark Salyzyn154f4602014-02-20 14:59:07 -0800211log_id_t android_name_to_log_id(const char *logName)
Mark Salyzyn42958412013-11-22 10:50:27 -0800212{
Mark Salyzyn42958412013-11-22 10:50:27 -0800213 const char *b;
Mark Salyzyn42958412013-11-22 10:50:27 -0800214 int ret;
215
216 if (!logName) {
217 return -1; /* NB: log_id_t is unsigned */
218 }
219 b = strrchr(logName, '/');
220 if (!b) {
221 b = logName;
222 } else {
223 ++b;
224 }
225
Mark Salyzyn42958412013-11-22 10:50:27 -0800226 for(ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
227 const char *l = LOG_NAME[ret];
228 if (l && !strcmp(b, l)) {
229 return ret;
230 }
231 }
232 return -1; /* should never happen */
233}
234
235struct logger_list {
236 struct listnode node;
237 int mode;
238 unsigned int tail;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800239 log_time start;
Mark Salyzyn42958412013-11-22 10:50:27 -0800240 pid_t pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800241 int sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800242};
243
244struct logger {
245 struct listnode node;
246 struct logger_list *top;
Mark Salyzyn42958412013-11-22 10:50:27 -0800247 log_id_t id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800248};
249
250/* android_logger_alloc unimplemented, no use case */
251/* android_logger_free not exported */
252static void android_logger_free(struct logger *logger)
253{
254 if (!logger) {
255 return;
256 }
257
Mark Salyzyn42958412013-11-22 10:50:27 -0800258 list_remove(&logger->node);
259
260 free(logger);
261}
262
Mark Salyzyn154f4602014-02-20 14:59:07 -0800263/* android_logger_alloc unimplemented, no use case */
264
265/* method for getting the associated sublog id */
Mark Salyzyn42958412013-11-22 10:50:27 -0800266log_id_t android_logger_get_id(struct logger *logger)
267{
268 return logger->id;
269}
270
271/* worker for sending the command to the logger */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800272static ssize_t send_log_msg(struct logger *logger,
273 const char *msg, char *buf, size_t buf_size)
Mark Salyzyn42958412013-11-22 10:50:27 -0800274{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800275 ssize_t ret;
Greg Hackmann8084a532014-03-17 13:08:31 -0700276 int errno_save = 0;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800277 int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
278 SOCK_STREAM);
279 if (sock < 0) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700280 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800281 }
282
Mark Salyzyn154f4602014-02-20 14:59:07 -0800283 if (msg) {
284 snprintf(buf, buf_size, msg, logger ? logger->id : (unsigned) -1);
Mark Salyzyn42958412013-11-22 10:50:27 -0800285 }
286
Mark Salyzyn154f4602014-02-20 14:59:07 -0800287 ret = write(sock, buf, strlen(buf) + 1);
288 if (ret <= 0) {
289 goto done;
Mark Salyzyn42958412013-11-22 10:50:27 -0800290 }
291
Mark Salyzyn154f4602014-02-20 14:59:07 -0800292 ret = read(sock, buf, buf_size);
293
294done:
295 if ((ret == -1) && errno) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700296 errno_save = errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800297 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800298 close(sock);
Greg Hackmann8084a532014-03-17 13:08:31 -0700299 if (errno_save) {
300 errno = errno_save;
301 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800302 return ret;
303}
304
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800305static int check_log_success(char *buf, ssize_t ret)
Mark Salyzyn42958412013-11-22 10:50:27 -0800306{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800307 if (ret < 0) {
308 return ret;
309 }
310
311 if (strncmp(buf, "success", 7)) {
Greg Hackmann8084a532014-03-17 13:08:31 -0700312 errno = EINVAL;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800313 return -1;
314 }
315
316 return 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800317}
318
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800319int android_logger_clear(struct logger *logger)
320{
321 char buf[512];
322
323 return check_log_success(buf,
324 send_log_msg(logger, "clear %d", buf, sizeof(buf)));
325}
326
Mark Salyzyn42958412013-11-22 10:50:27 -0800327/* returns the total size of the log's ring buffer */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800328long android_logger_get_log_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800329{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800330 char buf[512];
331
332 ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
333 if (ret < 0) {
334 return ret;
335 }
336
337 if ((buf[0] < '0') || ('9' < buf[0])) {
338 return -1;
339 }
340
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800341 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800342}
343
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800344int android_logger_set_log_size(struct logger *logger, unsigned long size)
345{
346 char buf[512];
347
348 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
349 logger ? logger->id : (unsigned) -1, size);
350
351 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
352}
353
Mark Salyzyn42958412013-11-22 10:50:27 -0800354/*
355 * returns the readable size of the log's ring buffer (that is, amount of the
356 * log consumed)
357 */
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800358long android_logger_get_log_readable_size(struct logger *logger)
Mark Salyzyn42958412013-11-22 10:50:27 -0800359{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800360 char buf[512];
361
362 ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
363 if (ret < 0) {
364 return ret;
365 }
366
367 if ((buf[0] < '0') || ('9' < buf[0])) {
368 return -1;
369 }
370
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800371 return atol(buf);
Mark Salyzyn42958412013-11-22 10:50:27 -0800372}
373
374/*
375 * returns the logger version
376 */
Mark Salyzyn154f4602014-02-20 14:59:07 -0800377int android_logger_get_log_version(struct logger *logger UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800378{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800379 return 3;
Mark Salyzyn42958412013-11-22 10:50:27 -0800380}
381
Mark Salyzyn34facab2014-02-06 14:48:50 -0800382/*
383 * returns statistics
384 */
385ssize_t android_logger_get_statistics(struct logger_list *logger_list,
386 char *buf, size_t len)
387{
388 struct listnode *node;
389 struct logger *logger;
390 char *cp = buf;
391 size_t remaining = len;
392 size_t n;
393
394 n = snprintf(cp, remaining, "getStatistics");
395 n = min(n, remaining);
396 remaining -= n;
397 cp += n;
398
399 logger_for_each(logger, logger_list) {
400 n = snprintf(cp, remaining, " %d", logger->id);
401 n = min(n, remaining);
402 remaining -= n;
403 cp += n;
404 }
405 return send_log_msg(NULL, NULL, buf, len);
406}
407
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800408ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
409 char *buf, size_t len)
410{
411 return send_log_msg(NULL, "getPruneList", buf, len);
412}
413
414int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
415 char *buf, size_t len)
416{
417 const char cmd[] = "setPruneList ";
418 const size_t cmdlen = sizeof(cmd) - 1;
419
420 if (strlen(buf) > (len - cmdlen)) {
421 return -ENOMEM; /* KISS */
422 }
423 memmove(buf + cmdlen, buf, len - cmdlen);
424 buf[len - 1] = '\0';
425 memcpy(buf, cmd, cmdlen);
426
427 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
428}
429
Mark Salyzyn42958412013-11-22 10:50:27 -0800430struct logger_list *android_logger_list_alloc(int mode,
431 unsigned int tail,
432 pid_t pid)
433{
434 struct logger_list *logger_list;
435
436 logger_list = calloc(1, sizeof(*logger_list));
437 if (!logger_list) {
438 return NULL;
439 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800440
Mark Salyzyn42958412013-11-22 10:50:27 -0800441 list_init(&logger_list->node);
442 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800443 logger_list->start.tv_sec = 0;
444 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800445 logger_list->tail = tail;
446 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800447 logger_list->sock = -1;
448
Mark Salyzyn42958412013-11-22 10:50:27 -0800449 return logger_list;
450}
451
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800452struct logger_list *android_logger_list_alloc_time(int mode,
453 log_time start,
454 pid_t pid)
455{
456 struct logger_list *logger_list;
457
458 logger_list = calloc(1, sizeof(*logger_list));
459 if (!logger_list) {
460 return NULL;
461 }
462
463 list_init(&logger_list->node);
464 logger_list->mode = mode;
465 logger_list->start = start;
466 logger_list->tail = 0;
467 logger_list->pid = pid;
468 logger_list->sock = -1;
469
470 return logger_list;
471}
472
Mark Salyzyn42958412013-11-22 10:50:27 -0800473/* android_logger_list_register unimplemented, no use case */
474/* android_logger_list_unregister unimplemented, no use case */
475
476/* Open the named log and add it to the logger list */
477struct logger *android_logger_open(struct logger_list *logger_list,
478 log_id_t id)
479{
480 struct listnode *node;
481 struct logger *logger;
482 char *n;
483
484 if (!logger_list || (id >= LOG_ID_MAX)) {
485 goto err;
486 }
487
488 logger_for_each(logger, logger_list) {
489 if (logger->id == id) {
490 goto ok;
491 }
492 }
493
494 logger = calloc(1, sizeof(*logger));
495 if (!logger) {
496 goto err;
497 }
498
Mark Salyzyn42958412013-11-22 10:50:27 -0800499 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800500 list_add_tail(&logger_list->node, &logger->node);
501 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800502 goto ok;
503
Mark Salyzyn42958412013-11-22 10:50:27 -0800504err:
505 logger = NULL;
506ok:
507 return logger;
508}
509
510/* Open the single named log and make it part of a new logger list */
511struct logger_list *android_logger_list_open(log_id_t id,
512 int mode,
513 unsigned int tail,
514 pid_t pid)
515{
516 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
517 if (!logger_list) {
518 return NULL;
519 }
520
521 if (!android_logger_open(logger_list, id)) {
522 android_logger_list_free(logger_list);
523 return NULL;
524 }
525
526 return logger_list;
527}
528
Mark Salyzyn154f4602014-02-20 14:59:07 -0800529static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800530{
Mark Salyzyn42958412013-11-22 10:50:27 -0800531}
532
533/* Read from the selected logs */
534int android_logger_list_read(struct logger_list *logger_list,
535 struct log_msg *log_msg)
536{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800537 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800538 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800539 struct sigaction ignore;
540 struct sigaction old_sigaction;
541 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800542
543 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800544 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800545 }
546
Mark Salyzyn154f4602014-02-20 14:59:07 -0800547 if (logger_list->mode & O_NONBLOCK) {
548 memset(&ignore, 0, sizeof(ignore));
549 ignore.sa_handler = caught_signal;
550 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800551 }
552
Mark Salyzyn154f4602014-02-20 14:59:07 -0800553 if (logger_list->sock < 0) {
554 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800555
Mark Salyzyn154f4602014-02-20 14:59:07 -0800556 int sock = socket_local_client("logdr",
557 ANDROID_SOCKET_NAMESPACE_RESERVED,
558 SOCK_SEQPACKET);
559 if (sock < 0) {
560 if ((sock == -1) && errno) {
561 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800562 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800563 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800564 }
565
Mark Salyzyn154f4602014-02-20 14:59:07 -0800566 strcpy(buffer,
567 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
568 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800569
Mark Salyzyn154f4602014-02-20 14:59:07 -0800570 strcpy(cp, " lids");
571 cp += 5;
572 c = '=';
573 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800574 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800575 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
576 ret = min(ret, remaining);
577 remaining -= ret;
578 cp += ret;
579 c = ',';
580 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800581
Mark Salyzyn154f4602014-02-20 14:59:07 -0800582 if (logger_list->tail) {
583 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
584 ret = min(ret, remaining);
585 remaining -= ret;
586 cp += ret;
587 }
588
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800589 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
590 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
591 logger_list->start.tv_sec,
592 logger_list->start.tv_nsec);
593 ret = min(ret, remaining);
594 remaining -= ret;
595 cp += ret;
596 }
597
Mark Salyzyn154f4602014-02-20 14:59:07 -0800598 if (logger_list->pid) {
599 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
600 ret = min(ret, remaining);
601 remaining -= ret;
602 cp += ret;
603 }
604
605 if (logger_list->mode & O_NONBLOCK) {
606 /* Deal with an unresponsive logd */
607 sigaction(SIGALRM, &ignore, &old_sigaction);
608 old_alarm = alarm(30);
609 }
610 ret = write(sock, buffer, cp - buffer);
611 e = errno;
612 if (logger_list->mode & O_NONBLOCK) {
613 if (e == EINTR) {
614 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800615 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800616 alarm(old_alarm);
617 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800618 }
619
620 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800621 close(sock);
622 if ((ret == -1) && e) {
623 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800624 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800625 if (ret == 0) {
626 return -EIO;
627 }
628 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800629 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800630
631 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800632 }
633
Mark Salyzyn154f4602014-02-20 14:59:07 -0800634 ret = 0;
635 while(1) {
636 memset(log_msg, 0, sizeof(*log_msg));
637
638 if (logger_list->mode & O_NONBLOCK) {
639 /* particularily useful if tombstone is reporting for logd */
640 sigaction(SIGALRM, &ignore, &old_sigaction);
641 old_alarm = alarm(30);
642 }
643 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
644 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
645 e = errno;
646 if (logger_list->mode & O_NONBLOCK) {
647 if ((ret == 0) || (e == EINTR)) {
648 e = EAGAIN;
649 ret = -1;
650 }
651 alarm(old_alarm);
652 sigaction(SIGALRM, &old_sigaction, NULL);
653 }
654
655 if (ret <= 0) {
656 if ((ret == -1) && e) {
657 return -e;
658 }
659 return ret;
660 }
661
662 logger_for_each(logger, logger_list) {
663 if (log_msg->entry.lid == logger->id) {
664 return ret;
665 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800666 }
667 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800668 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800669 return ret;
670}
671
672/* Close all the logs */
673void android_logger_list_free(struct logger_list *logger_list)
674{
675 if (logger_list == NULL) {
676 return;
677 }
678
679 while (!list_empty(&logger_list->node)) {
680 struct listnode *node = list_head(&logger_list->node);
681 struct logger *logger = node_to_item(node, struct logger, node);
682 android_logger_free(logger);
683 }
684
Mark Salyzyn154f4602014-02-20 14:59:07 -0800685 if (logger_list->sock >= 0) {
686 close (logger_list->sock);
687 }
688
Mark Salyzyn42958412013-11-22 10:50:27 -0800689 free(logger_list);
690}