blob: 15be748f4973be38eb841fae0a116f527338c75d [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 -0800343int android_logger_set_log_size(struct logger *logger, unsigned long size)
344{
345 char buf[512];
346
347 snprintf(buf, sizeof(buf), "setLogSize %d %lu",
348 logger ? logger->id : (unsigned) -1, size);
349
350 return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
351}
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 -0800407ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
408 char *buf, size_t len)
409{
410 return send_log_msg(NULL, "getPruneList", buf, len);
411}
412
413int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
414 char *buf, size_t len)
415{
416 const char cmd[] = "setPruneList ";
417 const size_t cmdlen = sizeof(cmd) - 1;
418
419 if (strlen(buf) > (len - cmdlen)) {
420 return -ENOMEM; /* KISS */
421 }
422 memmove(buf + cmdlen, buf, len - cmdlen);
423 buf[len - 1] = '\0';
424 memcpy(buf, cmd, cmdlen);
425
426 return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
427}
428
Mark Salyzyn42958412013-11-22 10:50:27 -0800429struct logger_list *android_logger_list_alloc(int mode,
430 unsigned int tail,
431 pid_t pid)
432{
433 struct logger_list *logger_list;
434
435 logger_list = calloc(1, sizeof(*logger_list));
436 if (!logger_list) {
437 return NULL;
438 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800439
Mark Salyzyn42958412013-11-22 10:50:27 -0800440 list_init(&logger_list->node);
441 logger_list->mode = mode;
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800442 logger_list->start.tv_sec = 0;
443 logger_list->start.tv_nsec = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800444 logger_list->tail = tail;
445 logger_list->pid = pid;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800446 logger_list->sock = -1;
447
Mark Salyzyn42958412013-11-22 10:50:27 -0800448 return logger_list;
449}
450
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800451struct logger_list *android_logger_list_alloc_time(int mode,
452 log_time start,
453 pid_t pid)
454{
455 struct logger_list *logger_list;
456
457 logger_list = calloc(1, sizeof(*logger_list));
458 if (!logger_list) {
459 return NULL;
460 }
461
462 list_init(&logger_list->node);
463 logger_list->mode = mode;
464 logger_list->start = start;
465 logger_list->tail = 0;
466 logger_list->pid = pid;
467 logger_list->sock = -1;
468
469 return logger_list;
470}
471
Mark Salyzyn42958412013-11-22 10:50:27 -0800472/* android_logger_list_register unimplemented, no use case */
473/* android_logger_list_unregister unimplemented, no use case */
474
475/* Open the named log and add it to the logger list */
476struct logger *android_logger_open(struct logger_list *logger_list,
477 log_id_t id)
478{
479 struct listnode *node;
480 struct logger *logger;
481 char *n;
482
483 if (!logger_list || (id >= LOG_ID_MAX)) {
484 goto err;
485 }
486
487 logger_for_each(logger, logger_list) {
488 if (logger->id == id) {
489 goto ok;
490 }
491 }
492
493 logger = calloc(1, sizeof(*logger));
494 if (!logger) {
495 goto err;
496 }
497
Mark Salyzyn42958412013-11-22 10:50:27 -0800498 logger->id = id;
Mark Salyzyn42958412013-11-22 10:50:27 -0800499 list_add_tail(&logger_list->node, &logger->node);
500 logger->top = logger_list;
Mark Salyzyn42958412013-11-22 10:50:27 -0800501 goto ok;
502
Mark Salyzyn42958412013-11-22 10:50:27 -0800503err:
504 logger = NULL;
505ok:
506 return logger;
507}
508
509/* Open the single named log and make it part of a new logger list */
510struct logger_list *android_logger_list_open(log_id_t id,
511 int mode,
512 unsigned int tail,
513 pid_t pid)
514{
515 struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
516 if (!logger_list) {
517 return NULL;
518 }
519
520 if (!android_logger_open(logger_list, id)) {
521 android_logger_list_free(logger_list);
522 return NULL;
523 }
524
525 return logger_list;
526}
527
Mark Salyzyn154f4602014-02-20 14:59:07 -0800528static void caught_signal(int signum UNUSED)
Mark Salyzyn42958412013-11-22 10:50:27 -0800529{
Mark Salyzyn42958412013-11-22 10:50:27 -0800530}
531
532/* Read from the selected logs */
533int android_logger_list_read(struct logger_list *logger_list,
534 struct log_msg *log_msg)
535{
Mark Salyzyn154f4602014-02-20 14:59:07 -0800536 int ret, e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800537 struct logger *logger;
Mark Salyzyn154f4602014-02-20 14:59:07 -0800538 struct sigaction ignore;
539 struct sigaction old_sigaction;
540 unsigned int old_alarm = 0;
Mark Salyzyn42958412013-11-22 10:50:27 -0800541
542 if (!logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800543 return -EINVAL;
Mark Salyzyn42958412013-11-22 10:50:27 -0800544 }
545
Mark Salyzyn154f4602014-02-20 14:59:07 -0800546 if (logger_list->mode & O_NONBLOCK) {
547 memset(&ignore, 0, sizeof(ignore));
548 ignore.sa_handler = caught_signal;
549 sigemptyset(&ignore.sa_mask);
Mark Salyzyn42958412013-11-22 10:50:27 -0800550 }
551
Mark Salyzyn154f4602014-02-20 14:59:07 -0800552 if (logger_list->sock < 0) {
553 char buffer[256], *cp, c;
Mark Salyzyn42958412013-11-22 10:50:27 -0800554
Mark Salyzyn154f4602014-02-20 14:59:07 -0800555 int sock = socket_local_client("logdr",
556 ANDROID_SOCKET_NAMESPACE_RESERVED,
557 SOCK_SEQPACKET);
558 if (sock < 0) {
559 if ((sock == -1) && errno) {
560 return -errno;
Mark Salyzyn42958412013-11-22 10:50:27 -0800561 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800562 return sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800563 }
564
Mark Salyzyn154f4602014-02-20 14:59:07 -0800565 strcpy(buffer,
566 (logger_list->mode & O_NONBLOCK) ? "dumpAndClose" : "stream");
567 cp = buffer + strlen(buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800568
Mark Salyzyn154f4602014-02-20 14:59:07 -0800569 strcpy(cp, " lids");
570 cp += 5;
571 c = '=';
572 int remaining = sizeof(buffer) - (cp - buffer);
Mark Salyzyn42958412013-11-22 10:50:27 -0800573 logger_for_each(logger, logger_list) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800574 ret = snprintf(cp, remaining, "%c%u", c, logger->id);
575 ret = min(ret, remaining);
576 remaining -= ret;
577 cp += ret;
578 c = ',';
579 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800580
Mark Salyzyn154f4602014-02-20 14:59:07 -0800581 if (logger_list->tail) {
582 ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
583 ret = min(ret, remaining);
584 remaining -= ret;
585 cp += ret;
586 }
587
Mark Salyzynfa3716b2014-02-14 16:05:05 -0800588 if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
589 ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
590 logger_list->start.tv_sec,
591 logger_list->start.tv_nsec);
592 ret = min(ret, remaining);
593 remaining -= ret;
594 cp += ret;
595 }
596
Mark Salyzyn154f4602014-02-20 14:59:07 -0800597 if (logger_list->pid) {
598 ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
599 ret = min(ret, remaining);
600 remaining -= ret;
601 cp += ret;
602 }
603
604 if (logger_list->mode & O_NONBLOCK) {
605 /* Deal with an unresponsive logd */
606 sigaction(SIGALRM, &ignore, &old_sigaction);
607 old_alarm = alarm(30);
608 }
609 ret = write(sock, buffer, cp - buffer);
610 e = errno;
611 if (logger_list->mode & O_NONBLOCK) {
612 if (e == EINTR) {
613 e = ETIMEDOUT;
Mark Salyzyn42958412013-11-22 10:50:27 -0800614 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800615 alarm(old_alarm);
616 sigaction(SIGALRM, &old_sigaction, NULL);
Mark Salyzyn42958412013-11-22 10:50:27 -0800617 }
618
619 if (ret <= 0) {
Mark Salyzyn154f4602014-02-20 14:59:07 -0800620 close(sock);
621 if ((ret == -1) && e) {
622 return -e;
Mark Salyzyn42958412013-11-22 10:50:27 -0800623 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800624 if (ret == 0) {
625 return -EIO;
626 }
627 return ret;
Mark Salyzyn42958412013-11-22 10:50:27 -0800628 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800629
630 logger_list->sock = sock;
Mark Salyzyn42958412013-11-22 10:50:27 -0800631 }
632
Mark Salyzyn154f4602014-02-20 14:59:07 -0800633 ret = 0;
634 while(1) {
635 memset(log_msg, 0, sizeof(*log_msg));
636
637 if (logger_list->mode & O_NONBLOCK) {
638 /* particularily useful if tombstone is reporting for logd */
639 sigaction(SIGALRM, &ignore, &old_sigaction);
640 old_alarm = alarm(30);
641 }
642 /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
643 ret = recv(logger_list->sock, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
644 e = errno;
645 if (logger_list->mode & O_NONBLOCK) {
646 if ((ret == 0) || (e == EINTR)) {
647 e = EAGAIN;
648 ret = -1;
649 }
650 alarm(old_alarm);
651 sigaction(SIGALRM, &old_sigaction, NULL);
652 }
653
654 if (ret <= 0) {
655 if ((ret == -1) && e) {
656 return -e;
657 }
658 return ret;
659 }
660
661 logger_for_each(logger, logger_list) {
662 if (log_msg->entry.lid == logger->id) {
663 return ret;
664 }
Mark Salyzyn42958412013-11-22 10:50:27 -0800665 }
666 }
Mark Salyzyn154f4602014-02-20 14:59:07 -0800667 /* NOTREACH */
Mark Salyzyn42958412013-11-22 10:50:27 -0800668 return ret;
669}
670
671/* Close all the logs */
672void android_logger_list_free(struct logger_list *logger_list)
673{
674 if (logger_list == NULL) {
675 return;
676 }
677
678 while (!list_empty(&logger_list->node)) {
679 struct listnode *node = list_head(&logger_list->node);
680 struct logger *logger = node_to_item(node, struct logger, node);
681 android_logger_free(logger);
682 }
683
Mark Salyzyn154f4602014-02-20 14:59:07 -0800684 if (logger_list->sock >= 0) {
685 close (logger_list->sock);
686 }
687
Mark Salyzyn42958412013-11-22 10:50:27 -0800688 free(logger_list);
689}