logd_reader.c revision facf94c74a2cc44f294c4789d36d5c7281c7bc3f
1c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/*
2c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * Copyright (C) 2007-2016 The Android Open Source Project
3c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh *
4c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * Licensed under the Apache License, Version 2.0 (the "License");
5c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * you may not use this file except in compliance with the License.
6c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * You may obtain a copy of the License at
7c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh *
8c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh *      http://www.apache.org/licenses/LICENSE-2.0
9c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh *
10c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * Unless required by applicable law or agreed to in writing, software
11c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * distributed under the License is distributed on an "AS IS" BASIS,
12c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * See the License for the specific language governing permissions and
14c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * limitations under the License.
15c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
16c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
17c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <endian.h>
18c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <errno.h>
19c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <fcntl.h>
20c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <inttypes.h>
21c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <poll.h>
22c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <stdarg.h>
23c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <stdatomic.h>
24c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <stdio.h>
25c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <stdlib.h>
26c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <string.h>
27c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/stat.h>
28c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/types.h>
29c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/socket.h>
30c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/un.h>
31c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <time.h>
32c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <unistd.h>
33c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
34c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <cutils/sockets.h>
35c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <log/logd.h>
36c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <log/logger.h>
37c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <log/log_read.h>
38c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <private/android_filesystem_config.h>
39c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <private/android_logger.h>
40c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
41c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include "config_read.h"
42c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include "log_portability.h"
43c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include "logger.h"
44c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
45c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* branchless on many architectures. */
46c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
47c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
48c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdAvailable(log_id_t LogId);
49c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdVersion(struct android_log_logger *logger,
50c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                       struct android_log_transport_context *transp);
51c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdRead(struct android_log_logger_list *logger_list,
52c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct android_log_transport_context *transp,
53c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct log_msg *log_msg);
54c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdPoll(struct android_log_logger_list *logger_list,
55c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct android_log_transport_context *transp);
56c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic void logdClose(struct android_log_logger_list *logger_list,
57c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                      struct android_log_transport_context *transp);
58c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdClear(struct android_log_logger *logger,
59c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                     struct android_log_transport_context *transp);
60c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdSetSize(struct android_log_logger *logger,
61c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                           struct android_log_transport_context *transp,
62c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                           size_t size);
63c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetSize(struct android_log_logger *logger,
64c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                           struct android_log_transport_context *transp);
65c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetReadableSize(struct android_log_logger *logger,
66c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                   struct android_log_transport_context *transp);
67c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetPrune(struct android_log_logger_list *logger,
68c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            struct android_log_transport_context *transp,
69c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            char *buf, size_t len);
70c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdSetPrune(struct android_log_logger_list *logger,
71c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            struct android_log_transport_context *transp,
72c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            char *buf, size_t len);
73c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetStats(struct android_log_logger_list *logger,
74c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            struct android_log_transport_context *transp,
75c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            char *buf, size_t len);
76c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
77c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia YehLIBLOG_HIDDEN struct android_log_transport_read logdLoggerRead = {
78c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .node = { &logdLoggerRead.node, &logdLoggerRead.node },
79c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .name = "logd",
80c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .available = logdAvailable,
81c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .version = logdVersion,
82c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .read = logdRead,
83c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .poll = logdPoll,
84c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .close = logdClose,
85c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .clear = logdClear,
86c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .getSize = logdGetSize,
87c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .setSize = logdSetSize,
88c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .getReadableSize = logdGetSize,
89c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .getPrune = logdGetPrune,
90c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .setPrune = logdSetPrune,
91c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    .getStats = logdGetStats,
92c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh};
93c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
94c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdAvailable(log_id_t logId)
95c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
96c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logId > LOG_ID_KERNEL) {
97c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -EINVAL;
98c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
99c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logId == LOG_ID_SECURITY) {
100c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        uid_t uid = __android_log_uid();
101c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (uid != AID_SYSTEM) {
102c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            return -EPERM;
103c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
104c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
105c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (access("/dev/socket/logdw", W_OK) == 0) {
106c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return 0;
107c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
108c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return -EBADF;
109c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
110c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
111c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
112c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
113c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#if defined(_WIN32)
114c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
115c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia YehLIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
116c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
117c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    errno = ENOSYS;
118c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return -ENOSYS;
119c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
120c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
121c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#else /* !_WIN32 */
122c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
123c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/socket.h>
124c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/un.h>
125c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/select.h>
126c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#include <sys/types.h>
127c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
128c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* Private copy of ../libcutils/socket_local.h prevent library loops */
129c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#define FILESYSTEM_SOCKET_PREFIX "/tmp/"
130c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#define ANDROID_RESERVED_SOCKET_PREFIX "/dev/socket/"
131c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* End of ../libcutils/socket_local.h */
132c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
133c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#define LISTEN_BACKLOG 4
134c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
135c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* Documented in header file. */
136c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia YehLIBLOG_WEAK int socket_make_sockaddr_un(const char *name, int namespaceId,
137c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                        struct sockaddr_un *p_addr,
138c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                        socklen_t *alen)
139c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
140c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    memset (p_addr, 0, sizeof (*p_addr));
141c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    size_t namelen;
142c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
143c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    switch (namespaceId) {
144c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    case ANDROID_SOCKET_NAMESPACE_ABSTRACT:
145c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#if defined(__linux__)
146c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        namelen  = strlen(name);
147c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
148c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* Test with length +1 for the *initial* '\0'. */
149c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if ((namelen + 1) > sizeof(p_addr->sun_path)) {
150c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            goto error;
151c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
152c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
153c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /*
154c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh         * Note: The path in this case is *not* supposed to be
155c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh         * '\0'-terminated. ("man 7 unix" for the gory details.)
156c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh         */
157c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
158c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        p_addr->sun_path[0] = 0;
159c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        memcpy(p_addr->sun_path + 1, name, namelen);
160c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#else
161c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* this OS doesn't have the Linux abstract namespace */
162c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
163c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
164c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* unix_path_max appears to be missing on linux */
165c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (namelen > sizeof(*p_addr)
166c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                - offsetof(struct sockaddr_un, sun_path) - 1) {
167c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            goto error;
168c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
169c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
170c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        strcpy(p_addr->sun_path, FILESYSTEM_SOCKET_PREFIX);
171c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        strcat(p_addr->sun_path, name);
172c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#endif
173c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        break;
174c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
175c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    case ANDROID_SOCKET_NAMESPACE_RESERVED:
176c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
177c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* unix_path_max appears to be missing on linux */
178c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (namelen > sizeof(*p_addr)
179c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                - offsetof(struct sockaddr_un, sun_path) - 1) {
180c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            goto error;
181c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
182c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
183c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        strcpy(p_addr->sun_path, ANDROID_RESERVED_SOCKET_PREFIX);
184c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        strcat(p_addr->sun_path, name);
185c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        break;
186c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
187c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
188c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        namelen = strlen(name);
189c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* unix_path_max appears to be missing on linux */
190c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (namelen > sizeof(*p_addr)
191c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                - offsetof(struct sockaddr_un, sun_path) - 1) {
192c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            goto error;
193c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
194c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
195c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        strcpy(p_addr->sun_path, name);
196c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        break;
197c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
198c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    default:
199c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* invalid namespace id */
200c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -1;
201c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
202c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
203c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    p_addr->sun_family = AF_LOCAL;
204c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    *alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
205c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return 0;
206c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeherror:
207c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return -1;
208c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
209c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
210c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/**
211c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * connect to peer named "name" on fd
212c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * returns same fd or -1 on error.
213c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * fd is not closed on error. that's your job.
214c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh *
215c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * Used by AndroidSocketImpl
216c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
217c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia YehLIBLOG_WEAK int socket_local_client_connect(int fd, const char *name,
218c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                            int namespaceId, int type __unused)
219c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
220c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct sockaddr_un addr;
221c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    socklen_t alen;
222c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int err;
223c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
224c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    err = socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
225c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
226c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (err < 0) {
227c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        goto error;
228c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
229c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
230c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if(connect(fd, (struct sockaddr *) &addr, alen) < 0) {
231c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        goto error;
232c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
233c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
234c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return fd;
235c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
236c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeherror:
237c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return -1;
238c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
239c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
240c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/**
241c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * connect to peer named "name"
242c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * returns fd or -1 on error
243c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
244c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia YehLIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
245c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
246c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int s;
247c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
248c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    s = socket(AF_LOCAL, type, 0);
249c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if(s < 0) return -1;
250c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
251c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if ( 0 > socket_local_client_connect(s, name, namespaceId, type)) {
252c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        close(s);
253c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -1;
254c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
255c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
256c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return s;
257c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
258c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
259c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh#endif /* !_WIN32 */
260c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* End of ../libcutils/socket_local_client.c */
261c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
262c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* worker for sending the command to the logger */
263c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t send_log_msg(struct android_log_logger *logger,
264c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            const char *msg, char *buf, size_t buf_size)
265c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
266c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ssize_t ret;
267c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    size_t len;
268c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char *cp;
269c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int errno_save = 0;
270c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
271c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                   SOCK_STREAM);
272c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (sock < 0) {
273c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return sock;
274c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
275c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
276c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (msg) {
277c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        snprintf(buf, buf_size, msg, logger ? logger->logId : (unsigned) -1);
278c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
279c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
280c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    len = strlen(buf) + 1;
281c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ret = TEMP_FAILURE_RETRY(write(sock, buf, len));
282c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret <= 0) {
283c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        goto done;
284c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
285c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
286c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    len = buf_size;
287c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    cp = buf;
288c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    while ((ret = TEMP_FAILURE_RETRY(read(sock, cp, len))) > 0) {
289c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct pollfd p;
290c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
291c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (((size_t)ret == len) || (buf_size < PAGE_SIZE)) {
292c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            break;
293c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
294c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
295c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        len -= ret;
296c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += ret;
297c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
298c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        memset(&p, 0, sizeof(p));
299c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        p.fd = sock;
300c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        p.events = POLLIN;
301c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
302c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* Give other side 20ms to refill pipe */
303c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = TEMP_FAILURE_RETRY(poll(&p, 1, 20));
304c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
305c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (ret <= 0) {
306c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            break;
307c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
308c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
309c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (!(p.revents & POLLIN)) {
310c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            ret = 0;
311c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            break;
312c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
313c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
314c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
315c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret >= 0) {
316c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret += buf_size - len;
317c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
318c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
319c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehdone:
320c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if ((ret == -1) && errno) {
321c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        errno_save = errno;
322c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
323c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    close(sock);
324c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (errno_save) {
325c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        errno = errno_save;
326c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
327c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return ret;
328c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
329c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
330c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int check_log_success(char *buf, ssize_t ret)
331c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
332c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret < 0) {
333c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return ret;
334c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
335c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
336c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (strncmp(buf, "success", 7)) {
337c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        errno = EINVAL;
338c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -1;
339c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
340c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
341c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return 0;
342c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
343c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
344c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdClear(struct android_log_logger *logger,
345c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                     struct android_log_transport_context *transp __unused)
346c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
347c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char buf[512];
348c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
349c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return check_log_success(buf,
350c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        send_log_msg(logger, "clear %d", buf, sizeof(buf)));
351c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
352c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
353c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* returns the total size of the log's ring buffer */
354c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetSize(struct android_log_logger *logger,
355c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                           struct android_log_transport_context *transp __unused)
356c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
357c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char buf[512];
358c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
359c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ssize_t ret = send_log_msg(logger, "getLogSize %d", buf, sizeof(buf));
360c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret < 0) {
361c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return ret;
362c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
363c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
364c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if ((buf[0] < '0') || ('9' < buf[0])) {
365c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -1;
366c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
367c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
368c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return atol(buf);
369c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
370c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
371c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdSetSize(
372c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_logger *logger,
373c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_transport_context *transp __unused,
374c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        size_t size)
375c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
376c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char buf[512];
377c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
378c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
379c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
380c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
381c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
382c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
383c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/*
384c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * returns the readable size of the log's ring buffer (that is, amount of the
385c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * log consumed)
386c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
387c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetReadableSize(
388c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh       struct android_log_logger *logger,
389c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh       struct android_log_transport_context *transp __unused)
390c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
391c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char buf[512];
392c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
393c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
394c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret < 0) {
395c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return ret;
396c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
397c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
398c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if ((buf[0] < '0') || ('9' < buf[0])) {
399c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -1;
400c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
401c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
402c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return atol(buf);
403c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
404c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
405c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/*
406c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * returns the logger version
407c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
408c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdVersion(
409c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_logger *logger __unused,
410c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_transport_context *transp __unused)
411c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
412c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    uid_t uid = __android_log_uid();
413c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return ((uid != AID_ROOT) && (uid != AID_LOG) && (uid != AID_SYSTEM)) ? 3 : 4;
414c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
415c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
416c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/*
417c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh * returns statistics
418c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh */
419c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetStats(struct android_log_logger_list *logger_list,
420c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            struct android_log_transport_context *transp __unused,
421c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                            char *buf, size_t len)
422c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
423c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct android_log_logger *logger;
424c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char *cp = buf;
425c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    size_t remaining = len;
426c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    size_t n;
427c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
428c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    n = snprintf(cp, remaining, "getStatistics");
429c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    n = min(n, remaining);
430c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    remaining -= n;
431c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    cp += n;
432c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
433c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    logger_for_each(logger, logger_list) {
434c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        n = snprintf(cp, remaining, " %d", logger->logId);
435c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        n = min(n, remaining);
436c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        remaining -= n;
437c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += n;
438c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
439c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
440c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->pid) {
441c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        snprintf(cp, remaining, " pid=%u", logger_list->pid);
442c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
443c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
444c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return send_log_msg(NULL, NULL, buf, len);
445c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
446c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
447c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdGetPrune(
448c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_logger_list *logger_list __unused,
449c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_transport_context *transp __unused,
450c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        char *buf, size_t len)
451c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
452c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return send_log_msg(NULL, "getPruneList", buf, len);
453c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
454c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
455c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic ssize_t logdSetPrune(
456c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_logger_list *logger_list __unused,
457c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        struct android_log_transport_context *transp __unused,
458c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        char *buf, size_t len)
459c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
460c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    const char cmd[] = "setPruneList ";
461c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    const size_t cmdlen = sizeof(cmd) - 1;
462c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
463c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (strlen(buf) > (len - cmdlen)) {
464c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -ENOMEM; /* KISS */
465c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
466c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    memmove(buf + cmdlen, buf, len - cmdlen);
467c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    buf[len - 1] = '\0';
468c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    memcpy(buf, cmd, cmdlen);
469c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
470c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
471c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
472c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
473c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
474c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic void caught_signal(int signum __unused)
475c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
476c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
477c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
478c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdOpen(struct android_log_logger_list *logger_list,
479c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct android_log_transport_context *transp)
480c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
481c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct android_log_logger *logger;
482c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct sigaction ignore;
483c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct sigaction old_sigaction;
484c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    unsigned int old_alarm = 0;
485c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    char buffer[256], *cp, c;
486c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int e, ret, remaining;
487c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
488c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int sock = transp->context.sock;
489c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (sock > 0) {
490c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return sock;
491c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
492c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
493c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (!logger_list) {
494c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return -EINVAL;
495c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
496c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
497c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    sock = socket_local_client("logdr",
498c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                               ANDROID_SOCKET_NAMESPACE_RESERVED,
499c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                               SOCK_SEQPACKET);
500c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (sock == 0) {
501c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* Guarantee not file descriptor zero */
502c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        int newsock = socket_local_client("logdr",
503c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                   ANDROID_SOCKET_NAMESPACE_RESERVED,
504c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                                   SOCK_SEQPACKET);
505c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        close(sock);
506c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sock = newsock;
507c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
508c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (sock <= 0) {
509c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if ((sock == -1) && errno) {
510c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            return -errno;
511c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
512c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return sock;
513c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
514c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
515c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ?
516c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            "dumpAndClose" : "stream");
517c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    cp = buffer + strlen(buffer);
518c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
519c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    strcpy(cp, " lids");
520c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    cp += 5;
521c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    c = '=';
522c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    remaining = sizeof(buffer) - (cp - buffer);
523c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    logger_for_each(logger, logger_list) {
524c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = snprintf(cp, remaining, "%c%u", c, logger->logId);
525c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = min(ret, remaining);
526c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        remaining -= ret;
527c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += ret;
528c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        c = ',';
529c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
530c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
531c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->tail) {
532c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = snprintf(cp, remaining, " tail=%u", logger_list->tail);
533c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = min(ret, remaining);
534c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        remaining -= ret;
535c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += ret;
536c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
537c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
538c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
539c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (logger_list->mode & ANDROID_LOG_WRAP) {
540c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            // ToDo: alternate API to allow timeout to be adjusted.
541c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            ret = snprintf(cp, remaining, " timeout=%u",
542c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                           ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
543c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            ret = min(ret, remaining);
544c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            remaining -= ret;
545c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            cp += ret;
546c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
547c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
548c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                       logger_list->start.tv_sec,
549c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                       logger_list->start.tv_nsec);
550c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = min(ret, remaining);
551c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        remaining -= ret;
552c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += ret;
553c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
554c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
555c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->pid) {
556c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = snprintf(cp, remaining, " pid=%u", logger_list->pid);
557c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ret = min(ret, remaining);
558c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        cp += ret;
559c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
560c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
561c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
562c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* Deal with an unresponsive logd */
563c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        memset(&ignore, 0, sizeof(ignore));
564c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ignore.sa_handler = caught_signal;
565c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigemptyset(&ignore.sa_mask);
566c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* particularily useful if tombstone is reporting for logd */
567c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigaction(SIGALRM, &ignore, &old_sigaction);
568c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        old_alarm = alarm(30);
569c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
570c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ret = write(sock, buffer, cp - buffer);
571c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    e = errno;
572c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
573c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (e == EINTR) {
574c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            e = ETIMEDOUT;
575c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
576c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        alarm(old_alarm);
577c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigaction(SIGALRM, &old_sigaction, NULL);
578c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
579c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
580c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret <= 0) {
581c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        close(sock);
582c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if ((ret == -1) && e) {
583c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            return -e;
584c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
585c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if (ret == 0) {
586c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            return -EIO;
587c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
588c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return ret;
589c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
590c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
591c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    return transp->context.sock = sock;
592c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh}
593c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
594c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh/* Read from the selected logs */
595c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yehstatic int logdRead(struct android_log_logger_list *logger_list,
596c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct android_log_transport_context *transp,
597c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh                    struct log_msg *log_msg)
598c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh{
599c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    int ret, e;
600c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct sigaction ignore;
601c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    struct sigaction old_sigaction;
602c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    unsigned int old_alarm = 0;
603c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
604c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ret = logdOpen(logger_list, transp);
605c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (ret < 0) {
606c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        return ret;
607c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
608c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
609c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    memset(log_msg, 0, sizeof(*log_msg));
610c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
611c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
612c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        memset(&ignore, 0, sizeof(ignore));
613c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        ignore.sa_handler = caught_signal;
614c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigemptyset(&ignore.sa_mask);
615c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        /* particularily useful if tombstone is reporting for logd */
616c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigaction(SIGALRM, &ignore, &old_sigaction);
617c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        old_alarm = alarm(30);
618c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
619c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
620c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    /* NOTE: SOCK_SEQPACKET guarantees we read exactly one full entry */
621c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    ret = recv(ret, log_msg, LOGGER_ENTRY_MAX_LEN, 0);
622c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    e = errno;
623c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh
624c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    if (logger_list->mode & ANDROID_LOG_NONBLOCK) {
625c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        if ((ret == 0) || (e == EINTR)) {
626c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            e = EAGAIN;
627c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh            ret = -1;
628c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        }
629c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        alarm(old_alarm);
630c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh        sigaction(SIGALRM, &old_sigaction, NULL);
631c360382bf257d815b2a411152485d3c3b37a9f46Yin-Chia Yeh    }
632
633    if ((ret == -1) && e) {
634        return -e;
635    }
636    return ret;
637}
638
639static int logdPoll(struct android_log_logger_list *logger_list,
640                    struct android_log_transport_context *transp)
641{
642    struct pollfd p;
643
644    int ret = logdOpen(logger_list, transp);
645    if (ret < 0) {
646        return ret;
647    }
648
649    memset(&p, 0, sizeof(p));
650    p.fd = ret;
651    p.events = POLLIN;
652    ret = poll(&p, 1, 20);
653    if ((ret > 0) && !(p.revents & POLLIN)) {
654        ret = 0;
655    }
656    if ((ret == -1) && errno) {
657        return -errno;
658    }
659    return ret;
660}
661
662/* Close all the logs */
663static void logdClose(struct android_log_logger_list *logger_list __unused,
664                      struct android_log_transport_context *transp)
665{
666    if (transp->context.sock > 0) {
667        close (transp->context.sock);
668        transp->context.sock = -1;
669    }
670}
671