Use buffer traits over specific IDs
[platform/core/system/dlog.git] / src / log-redirect-stdout / internal.c
1 /* MIT License
2  *
3  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
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
21  * THE SOFTWARE. */
22
23 #include "internal.h"
24
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>
31 #include <logpipe.h>
32 #include <zero_copy_backend.h>
33
34 #include <stdint.h>
35
36 static int setup_single_pipe(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
37 {
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. */
42         pid_t pid = getpid();
43
44         char key[20];
45         snprintf(key, sizeof key, "%s_conn_sock", log_name_by_id(buffer));
46         const char *const conf_val = log_config_get(config, key);
47         if (!conf_val)
48                 return -ENOKEY;
49
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) {
53                 .length = len,
54                 .request = DLOG_REQ_STDOUT,
55                 .result = 0,
56         };
57         struct dlog_control_msg_stdout *data = (struct dlog_control_msg_stdout *)&req->data;
58         *data = (struct dlog_control_msg_stdout) {
59                 .pid = pid,
60                 .prio = prio,
61         };
62         memcpy(data->tag, tag, strlen(tag));
63
64         *fd = connect_pipe(conf_val, req, DEFAULT_WAIT_PIPE_MS);
65         if (*fd < 0)
66                 return *fd;
67
68         return 0;
69 }
70
71 static int apply_android_logger_ioctl(int fd, const char *tag, log_priority prio)
72 {
73         int r = ioctl(fd, LOGGER_SET_TAG, & (struct logger_set_tag) {
74                 .len = strlen(tag) + 1,
75                 .ptr = (uintptr_t) tag
76         });
77         if (r < 0)
78                 return -errno;
79
80         r = ioctl(fd, LOGGER_SET_PRIO, prio);
81         if (r < 0)
82                 return -errno;
83
84         return 0;
85 }
86
87 static int setup_single_android_logger(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
88 {
89         int r = logger_open_buffer_from_config(buffer, config, O_WRONLY, fd);
90         if (r < 0)
91                 return r;
92
93         r = apply_android_logger_ioctl(*fd, tag, prio);
94         if (r < 0)
95                 return r;
96
97         return 0;
98 }
99
100 static int apply_zero_copy_ioctl(int fd, const char *tag, log_priority prio)
101 {
102         int r = ioctl(fd, ZLOGGER_IOCTL_COMMAND_SET_DEFAULT_PRIORITY, (uint32_t)prio);
103         if (r < 0)
104                 return -errno;
105
106         r = ioctl(fd, ZLOGGER_IOCTL_COMMAND_SET_DEFAULT_TAG, tag);
107         if (r < 0)
108                 return -errno;
109
110         return 0;
111 }
112
113 static int setup_single_zero_copy(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
114 {
115         *fd = open(ZERO_COPY_DEVICE_NAME, O_WRONLY);
116         if (*fd < 0)
117                 return -errno;
118
119         int r = apply_zero_copy_ioctl(*fd, tag, prio);
120         if (r < 0)
121                 return r;
122
123         return 0;
124 }
125
126 static int setup_single_null(log_id_t buffer, const char *tag, log_priority prio, struct log_config *config, int *fd)
127 {
128         *fd = open("/dev/null", O_WRONLY);
129         if (*fd < 0)
130                 return -errno;
131
132         return 0;
133 }
134
135 int setup_single_unstructed(log_id_t buffer, const char *tag, log_priority prio, int *fd)
136 {
137         __attribute__((cleanup(log_config_free))) struct log_config config;
138
139         int r = log_config_read(&config);
140         if (r < 0)
141                 return r;
142
143         if (!is_buffer_enabled(buffer, &config))
144                 return -EPERM;
145
146         const char *const backend = log_config_claim_backend(&config);
147         if (!backend)
148                 return -ENOKEY;
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);
157         else
158                 return -ENOTSUP;
159 }