3 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is furnished
10 * to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include <backend_androidlogger.h>
26 #include <buffer_config.h>
27 #include <buffer_traits.h>
28 #include <sys/ioctl.h>
29 #include <linux/logger.h>
30 #include <logconfig.h>
32 #include <zero_copy_backend.h>
36 static int setup_single_pipe(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
38 /* We don't really have a way to get the PID correctly in
39 * the daemon, so we send it on connection. This means that
40 * fork() invalidates the value; there is little we can do
41 * about it but nevertheless it's still better than nothing. */
45 snprintf(key, sizeof key, "%s_conn_sock", log_name_by_id(buffer));
46 const char *const conf_val = log_config_get(config, key);
50 int len = sizeof(struct dlog_control_msg) + sizeof(struct dlog_control_msg_stdout) + strlen(tag);
51 struct dlog_control_msg *req = alloca(len);
52 *req = (struct dlog_control_msg) {
54 .request = DLOG_REQ_STDOUT,
57 struct dlog_control_msg_stdout *data = (struct dlog_control_msg_stdout *)&req->data;
58 *data = (struct dlog_control_msg_stdout) {
62 memcpy(data->tag, tag, strlen(tag));
64 *fd = connect_pipe(conf_val, req, DEFAULT_WAIT_PIPE_MS);
71 static int apply_android_logger_ioctl(int fd, const char *tag, log_priority prio)
73 int r = ioctl(fd, LOGGER_SET_TAG, & (struct logger_set_tag) {
74 .len = strlen(tag) + 1,
75 .ptr = (uintptr_t) tag
80 r = ioctl(fd, LOGGER_SET_PRIO, prio);
87 static int setup_single_android_logger(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
89 int r = logger_open_buffer_from_config(buffer, config, O_WRONLY, fd);
93 r = apply_android_logger_ioctl(*fd, tag, prio);
100 static int apply_zero_copy_ioctl(int fd, const char *tag, log_priority prio)
102 int r = ioctl(fd, ZLOGGER_IOCTL_COMMAND_SET_DEFAULT_PRIORITY, (uint32_t)prio);
106 r = ioctl(fd, ZLOGGER_IOCTL_COMMAND_SET_DEFAULT_TAG, tag);
113 static int setup_single_zero_copy(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
115 *fd = open(ZERO_COPY_DEVICE_NAME, O_WRONLY);
119 int r = apply_zero_copy_ioctl(*fd, tag, prio);
126 static int setup_single_null(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
128 *fd = open("/dev/null", O_WRONLY);
135 int setup_single_unstructed(log_id_t buffer, const char *tag, log_priority prio, int *fd)
137 __attribute__((cleanup(log_config_free))) struct log_config config;
139 int r = log_config_read(&config);
143 if (!is_buffer_enabled(buffer, &config))
146 const char *const backend = log_config_claim_backend(&config);
149 else if (!strcmp(backend, "logger"))
150 return setup_single_android_logger(buffer, tag, prio, &config, fd);
151 else if (!strcmp(backend, "pipe"))
152 return setup_single_pipe(buffer, tag, prio, &config, fd);
153 else if (!strcmp(backend, "zero-copy"))
154 return setup_single_zero_copy(buffer, tag, prio, &config, fd);
155 else if (!strcmp(backend, "null"))
156 return setup_single_null(buffer, tag, prio, &config, fd);