Introduce log write buffering
[platform/core/system/dlog.git] / src / logger / dlogutil_line.c
1 #include "dlogutil_line.h"
2 #include "logger_internal.h"
3 #include <getopt.h>
4
5 void reset_getopt_internals(void *fake)
6 {
7         optarg = NULL;
8         optind = 0;
9         optopt = 0;
10 }
11
12 bool initialize_dlogutil_line_params(struct dlogutil_line_params *params, struct buf_params buf)
13 {
14         assert(params);
15
16         logfile_init(&params->file); // TODO: add flush
17         logfile_init_buffer(&params->file, buf.bytes);
18         params->monitor = false;
19         params->is_dumping = false;
20         params->buf_id = LOG_ID_INVALID;
21         params->file_path = NULL;
22
23         params->filter = log_filter_new();
24         if (!params->filter)
25                 return false;
26
27         return true;
28 }
29
30 void free_dlogutil_line_params(struct dlogutil_line_params *params)
31 {
32         logfile_free(&params->file);
33         log_filter_free(params->filter);
34         free(params->file_path);
35 }
36
37 static int make_argc_argv_from_dlogutil_line(const char *cmdl, size_t buf_size, char buffer[buf_size], int *argc, char **argv)
38 {
39         assert(cmdl);
40         assert(argc);
41         assert(argv);
42
43         snprintf(buffer, buf_size, "%s", cmdl); // strtok is destructive
44
45         char *tok_sv;
46         char *tok = strtok_r(buffer, DELIMITER, &tok_sv);
47
48         /* Legacy requirement: emulate `dlogutil`
49          * invocations right up to the binary name */
50         if (!tok || strcmp(tok, "dlogutil"))
51                 return -EINVAL;
52
53         int curr_argc = 0;
54         const int argv_size = *argc - 1; // for NULL at the end
55         while (tok && (curr_argc < argv_size)) {
56                 argv[curr_argc++] = tok;
57                 tok = strtok_r(NULL, DELIMITER, &tok_sv);
58         }
59
60         argv[curr_argc] = NULL;
61         *argc = curr_argc;
62
63         return 0;
64 }
65
66 static int get_dlogutil_params_from_argc_argv(int argc, char **argv, struct dlogutil_line_params *params)
67 {
68         assert(argc >= 0);
69         assert(argv);
70         assert(params);
71
72         bool silence = false;
73
74         static const struct option long_options[] = {
75                 {"tid", required_argument, NULL, 0},
76                 {"pid", required_argument, NULL, 1},
77                 {0}
78         };
79
80         __attribute__((cleanup(reset_getopt_internals))) int option;
81         while ((option = getopt_long(argc, argv, "cdt:gsf:r:n:v:b:mu:", long_options, NULL)) != -1) {
82                 switch (option) {
83                         break;
84                 case 'd':
85                 case 't':
86                         params->is_dumping = true;
87                         break;
88                 case 'm':
89                         params->monitor = true;
90                         break;
91                 case 'f':
92                         free(params->file_path);
93                         params->file_path = strdup(optarg);
94                         if (!params->file_path)
95                                 return -ENOMEM;
96                         break;
97                 case 'b':
98                         params->buf_id = log_id_by_name(optarg);
99                         if (params->buf_id == LOG_ID_INVALID)
100                                 return -EINVAL;
101                         break;
102                 case 'r':
103                         if (sscanf(optarg, "%zu", &params->file.rotate_size_kbytes) != 1)
104                                 return -EINVAL;
105                         break;
106                 case 'n':
107                         if (sscanf(optarg, "%zu", &params->file.max_rotated) != 1)
108                                 return -EINVAL;
109                         break;
110                 case 'v':
111                         params->file.format.format = log_format_from_string(optarg);
112                         break;
113                 case 's':
114                         silence = true;
115                         dlogutil_filter_options_set_filterspec(params->filter, "*:s");
116                         break;
117                 case 0: {
118                         pid_t tid;
119                         if (sscanf(optarg, "%d", &tid) != 1 || dlogutil_filter_options_set_tid(params->filter, tid))
120                                 return -EINVAL;
121                         break;
122                 }
123                 case 1: {
124                         pid_t pid;
125                         if (sscanf(optarg, "%d", &pid) != 1 || dlogutil_filter_options_set_pid(params->filter, pid))
126                                 return -EINVAL;
127                         break;
128                 }
129                 case '?': // invalid option or missing argument
130                         return -EINVAL;
131                 default:
132                         // everything else gets handled in util directly
133                         break;
134                 }
135         }
136
137         // dump + monitor = continuous
138         if (params->monitor && params->is_dumping) {
139                 params->is_dumping = false;
140                 params->monitor = false;
141         }
142
143         if (optind < argc)
144                 while (optind < argc)
145                         dlogutil_filter_options_set_filterspec(params->filter, argv[optind++]);
146         else if (!silence)
147                 dlogutil_filter_options_set_filterspec(params->filter, "*:D");
148
149         return 0;
150 }
151
152 int get_dlogutil_line_params(const char *cmdl, struct dlogutil_line_params *params)
153 {
154         assert(params);
155         assert(cmdl);
156         char buffer[1024];
157         char *argv[64]; // size arbitrary, should reasonably fit all args
158         int argc = NELEMS(argv);
159         int ret = make_argc_argv_from_dlogutil_line(cmdl, sizeof buffer, buffer, &argc, argv);
160         if (ret < 0)
161                 return ret;
162
163         return get_dlogutil_params_from_argc_argv(argc, argv, params);
164 }