File: | build-scan/../src/journal/journal-send.c |
Warning: | line 502, column 16 Potential leak of memory pointed to by 'iov' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <errno(*__errno_location ()).h> | |||
4 | #include <fcntl.h> | |||
5 | #include <printf.h> | |||
6 | #include <stddef.h> | |||
7 | #include <sys/socket.h> | |||
8 | #include <sys/un.h> | |||
9 | #include <unistd.h> | |||
10 | ||||
11 | #define SD_JOURNAL_SUPPRESS_LOCATION | |||
12 | ||||
13 | #include "sd-journal.h" | |||
14 | ||||
15 | #include "alloc-util.h" | |||
16 | #include "fd-util.h" | |||
17 | #include "fileio.h" | |||
18 | #include "io-util.h" | |||
19 | #include "memfd-util.h" | |||
20 | #include "socket-util.h" | |||
21 | #include "stdio-util.h" | |||
22 | #include "string-util.h" | |||
23 | #include "util.h" | |||
24 | ||||
25 | #define SNDBUF_SIZE(8*1024*1024) (8*1024*1024) | |||
26 | ||||
27 | #define ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = & (f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10 ); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl ); } while (0) \ | |||
28 | do { \ | |||
29 | size_t _fl; \ | |||
30 | const char *_func = (func); \ | |||
31 | char **_f = &(f); \ | |||
32 | _fl = strlen(_func) + 1; \ | |||
33 | *_f = alloca(_fl + 10)__builtin_alloca (_fl + 10); \ | |||
34 | memcpy(*_f, "CODE_FUNC=", 10); \ | |||
35 | memcpy(*_f + 10, _func, _fl); \ | |||
36 | } while (false0) | |||
37 | ||||
38 | /* We open a single fd, and we'll share it with the current process, | |||
39 | * all its threads, and all its subprocesses. This means we need to | |||
40 | * initialize it atomically, and need to operate on it atomically | |||
41 | * never assuming we are the only user */ | |||
42 | ||||
43 | static int journal_fd(void) { | |||
44 | int fd; | |||
45 | static int fd_plus_one = 0; | |||
46 | ||||
47 | retry: | |||
48 | if (fd_plus_one > 0) | |||
49 | return fd_plus_one - 1; | |||
50 | ||||
51 | fd = socket(AF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC, 0); | |||
52 | if (fd < 0) | |||
53 | return -errno(*__errno_location ()); | |||
54 | ||||
55 | fd_inc_sndbuf(fd, SNDBUF_SIZE(8*1024*1024)); | |||
56 | ||||
57 | if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) { | |||
58 | safe_close(fd); | |||
59 | goto retry; | |||
60 | } | |||
61 | ||||
62 | return fd; | |||
63 | } | |||
64 | ||||
65 | _public___attribute__ ((visibility("default"))) int sd_journal_print(int priority, const char *format, ...) { | |||
66 | int r; | |||
67 | va_list ap; | |||
68 | ||||
69 | va_start(ap, format)__builtin_va_start(ap, format); | |||
70 | r = sd_journal_printv(priority, format, ap); | |||
71 | va_end(ap)__builtin_va_end(ap); | |||
72 | ||||
73 | return r; | |||
74 | } | |||
75 | ||||
76 | _public___attribute__ ((visibility("default"))) int sd_journal_printv(int priority, const char *format, va_list ap) { | |||
77 | ||||
78 | /* FIXME: Instead of limiting things to LINE_MAX we could do a | |||
79 | C99 variable-length array on the stack here in a loop. */ | |||
80 | ||||
81 | char buffer[8 + LINE_MAX2048], p[STRLEN("PRIORITY=")(sizeof("""PRIORITY=""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)]))) + 1]; | |||
82 | struct iovec iov[2]; | |||
83 | ||||
84 | assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0" ), "../src/journal/journal-send.c", 84, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
85 | assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7" ), "../src/journal/journal-send.c", 85, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
86 | assert_return(format, -EINVAL)do { if (!(((__builtin_expect(!!(format),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("format"), "../src/journal/journal-send.c" , 86, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
87 | ||||
88 | xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK)do { if ((__builtin_expect(!!(!(((size_t) snprintf(p, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0)) ), "PRIORITY=%i", priority & 0x07) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(p), typeof(&*(p))) , sizeof(p)/sizeof((p)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "p" "[] must be big enough" ), "../src/journal/journal-send.c", 88, __PRETTY_FUNCTION__); } while (0); | |||
89 | ||||
90 | memcpy(buffer, "MESSAGE=", 8); | |||
91 | vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); | |||
92 | ||||
93 | /* Strip trailing whitespace, keep prefix whitespace. */ | |||
94 | (void) strstrip(buffer); | |||
95 | ||||
96 | /* Suppress empty lines */ | |||
97 | if (isempty(buffer+8)) | |||
98 | return 0; | |||
99 | ||||
100 | iov[0] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen (buffer)) }; | |||
101 | iov[1] = IOVEC_MAKE_STRING(p)(struct iovec) { .iov_base = ((char*) p), .iov_len = (strlen( p)) }; | |||
102 | ||||
103 | return sd_journal_sendv(iov, 2); | |||
104 | } | |||
105 | ||||
106 | _printf_(1, 0)__attribute__ ((format (printf, 1, 0))) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) { | |||
107 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
108 | int r, n = 0, i = 0, j; | |||
109 | struct iovec *iov = NULL((void*)0); | |||
110 | ||||
111 | assert(_iov)do { if ((__builtin_expect(!!(!(_iov)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_iov"), "../src/journal/journal-send.c" , 111, __PRETTY_FUNCTION__); } while (0); | |||
112 | ||||
113 | if (extra
| |||
114 | n = MAX(extra * 2, extra + 4)__extension__ ({ const typeof((extra * 2)) __unique_prefix_A7 = ((extra * 2)); const typeof((extra + 4)) __unique_prefix_B8 = ((extra + 4)); __unique_prefix_A7 > __unique_prefix_B8 ? __unique_prefix_A7 : __unique_prefix_B8; }); | |||
115 | iov = malloc0(n * sizeof(struct iovec))(calloc(1, (n * sizeof(struct iovec)))); | |||
116 | if (!iov) { | |||
117 | r = -ENOMEM12; | |||
118 | goto fail; | |||
119 | } | |||
120 | ||||
121 | i = extra; | |||
122 | } | |||
123 | ||||
124 | while (format) { | |||
125 | struct iovec *c; | |||
126 | char *buffer; | |||
127 | va_list aq; | |||
128 | ||||
129 | if (i >= n) { | |||
130 | n = MAX(i*2, 4)__extension__ ({ const typeof((i*2)) __unique_prefix_A9 = ((i *2)); const typeof((4)) __unique_prefix_B10 = ((4)); __unique_prefix_A9 > __unique_prefix_B10 ? __unique_prefix_A9 : __unique_prefix_B10 ; }); | |||
131 | c = realloc(iov, n * sizeof(struct iovec)); | |||
132 | if (!c) { | |||
133 | r = -ENOMEM12; | |||
134 | goto fail; | |||
135 | } | |||
136 | ||||
137 | iov = c; | |||
138 | } | |||
139 | ||||
140 | va_copy(aq, ap)__builtin_va_copy(aq, ap); | |||
141 | if (vasprintf(&buffer, format, aq) < 0) { | |||
142 | va_end(aq)__builtin_va_end(aq); | |||
143 | r = -ENOMEM12; | |||
144 | goto fail; | |||
145 | } | |||
146 | va_end(aq)__builtin_va_end(aq); | |||
147 | ||||
148 | VA_FORMAT_ADVANCE(format, ap)do { int _argtypes[128]; size_t _i, _k; _k = parse_printf_format ((format), __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_argtypes), typeof(&*(_argtypes))), sizeof(_argtypes )/sizeof((_argtypes)[0]), ((void)0))), _argtypes); do { if (( __builtin_expect(!!(!(_k < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_argtypes), typeof(& *(_argtypes))), sizeof(_argtypes)/sizeof((_argtypes)[0]), ((void )0))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_k < ELEMENTSOF(_argtypes)" ), "../src/journal/journal-send.c", 148, __PRETTY_FUNCTION__) ; } while (0); for (_i = 0; _i < _k; _i++) { if (_argtypes [_i] & (1 << 11)) { (void) __builtin_va_arg(ap, void *); continue; } switch (_argtypes[_i]) { case PA_INT: case PA_INT |(1 << 10): case PA_CHAR: (void) __builtin_va_arg(ap, int ); break; case PA_INT|(1 << 9): (void) __builtin_va_arg (ap, long int); break; case PA_INT|(1 << 8): (void) __builtin_va_arg (ap, long long int); break; case PA_WCHAR: (void) __builtin_va_arg (ap, wchar_t); break; case PA_WSTRING: case PA_STRING: case PA_POINTER : (void) __builtin_va_arg(ap, void*); break; case PA_FLOAT: case PA_DOUBLE: (void) __builtin_va_arg(ap, double); break; case PA_DOUBLE |(1 << 8): (void) __builtin_va_arg(ap, long double); break ; default: do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD , ("Unknown format string argument."), "../src/journal/journal-send.c" , 148, __PRETTY_FUNCTION__); } while (0); } } } while (0); | |||
149 | ||||
150 | (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */ | |||
151 | ||||
152 | iov[i++] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen (buffer)) }; | |||
153 | ||||
154 | format = va_arg(ap, char *)__builtin_va_arg(ap, char *); | |||
155 | } | |||
156 | ||||
157 | *_iov = iov; | |||
158 | ||||
159 | return i; | |||
160 | ||||
161 | fail: | |||
162 | for (j = 0; j < i; j++) | |||
163 | free(iov[j].iov_base); | |||
164 | ||||
165 | free(iov); | |||
166 | ||||
167 | return r; | |||
168 | } | |||
169 | ||||
170 | _public___attribute__ ((visibility("default"))) int sd_journal_send(const char *format, ...) { | |||
171 | int r, i, j; | |||
172 | va_list ap; | |||
173 | struct iovec *iov = NULL((void*)0); | |||
174 | ||||
175 | va_start(ap, format)__builtin_va_start(ap, format); | |||
176 | i = fill_iovec_sprintf(format, ap, 0, &iov); | |||
177 | va_end(ap)__builtin_va_end(ap); | |||
178 | ||||
179 | if (_unlikely_(i < 0)(__builtin_expect(!!(i < 0),0))) { | |||
180 | r = i; | |||
181 | goto finish; | |||
182 | } | |||
183 | ||||
184 | r = sd_journal_sendv(iov, i); | |||
185 | ||||
186 | finish: | |||
187 | for (j = 0; j < i; j++) | |||
188 | free(iov[j].iov_base); | |||
189 | ||||
190 | free(iov); | |||
191 | ||||
192 | return r; | |||
193 | } | |||
194 | ||||
195 | _public___attribute__ ((visibility("default"))) int sd_journal_sendv(const struct iovec *iov, int n) { | |||
196 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
197 | int fd, r; | |||
198 | _cleanup_close___attribute__((cleanup(closep))) int buffer_fd = -1; | |||
199 | struct iovec *w; | |||
200 | uint64_t *l; | |||
201 | int i, j = 0; | |||
202 | static const union sockaddr_union sa = { | |||
203 | .un.sun_family = AF_UNIX1, | |||
204 | .un.sun_path = "/run/systemd/journal/socket", | |||
205 | }; | |||
206 | struct msghdr mh = { | |||
207 | .msg_name = (struct sockaddr*) &sa.sa, | |||
208 | .msg_namelen = SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journal-send.c" , 208, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof( struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen (_sa->sun_path, sizeof(_sa->sun_path))); }), | |||
209 | }; | |||
210 | ssize_t k; | |||
211 | bool_Bool have_syslog_identifier = false0; | |||
212 | bool_Bool seal = true1; | |||
213 | ||||
214 | assert_return(iov, -EINVAL)do { if (!(((__builtin_expect(!!(iov),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("iov"), "../src/journal/journal-send.c", 214, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
215 | assert_return(n > 0, -EINVAL)do { if (!(((__builtin_expect(!!(n > 0),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("n > 0"), "../src/journal/journal-send.c" , 215, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
216 | ||||
217 | w = newa(struct iovec, n * 5 + 3)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (struct iovec), n * 5 + 3))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(struct iovec), n * 5 + 3)" ), "../src/journal/journal-send.c", 217, __PRETTY_FUNCTION__) ; } while (0); (struct iovec*) __builtin_alloca (sizeof(struct iovec)*(n * 5 + 3)); }); | |||
218 | l = newa(uint64_t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (uint64_t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(uint64_t), n)"), "../src/journal/journal-send.c" , 218, __PRETTY_FUNCTION__); } while (0); (uint64_t*) __builtin_alloca (sizeof(uint64_t)*(n)); }); | |||
219 | ||||
220 | for (i = 0; i < n; i++) { | |||
221 | char *c, *nl; | |||
222 | ||||
223 | if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1)(__builtin_expect(!!(!iov[i].iov_base || iov[i].iov_len <= 1),0))) | |||
224 | return -EINVAL22; | |||
225 | ||||
226 | c = memchr(iov[i].iov_base, '=', iov[i].iov_len); | |||
227 | if (_unlikely_(!c || c == iov[i].iov_base)(__builtin_expect(!!(!c || c == iov[i].iov_base),0))) | |||
228 | return -EINVAL22; | |||
229 | ||||
230 | have_syslog_identifier = have_syslog_identifier || | |||
231 | (c == (char *) iov[i].iov_base + 17 && | |||
232 | startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER")); | |||
233 | ||||
234 | nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len); | |||
235 | if (nl) { | |||
236 | if (_unlikely_(nl < c)(__builtin_expect(!!(nl < c),0))) | |||
237 | return -EINVAL22; | |||
238 | ||||
239 | /* Already includes a newline? Bummer, then | |||
240 | * let's write the variable name, then a | |||
241 | * newline, then the size (64bit LE), followed | |||
242 | * by the data and a final newline */ | |||
243 | ||||
244 | w[j++] = IOVEC_MAKE(iov[i].iov_base, c - (char*) iov[i].iov_base)(struct iovec) { .iov_base = (iov[i].iov_base), .iov_len = (c - (char*) iov[i].iov_base) }; | |||
245 | w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen ("\n")) }; | |||
246 | ||||
247 | l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1)__uint64_identity (iov[i].iov_len - (c - (char*) iov[i].iov_base ) - 1); | |||
248 | w[j++] = IOVEC_MAKE(&l[i], sizeof(uint64_t))(struct iovec) { .iov_base = (&l[i]), .iov_len = (sizeof( uint64_t)) }; | |||
249 | ||||
250 | w[j++] = IOVEC_MAKE(c + 1, iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1)(struct iovec) { .iov_base = (c + 1), .iov_len = (iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1) }; | |||
251 | } else | |||
252 | /* Nothing special? Then just add the line and | |||
253 | * append a newline */ | |||
254 | w[j++] = iov[i]; | |||
255 | ||||
256 | w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen ("\n")) }; | |||
257 | } | |||
258 | ||||
259 | if (!have_syslog_identifier && | |||
260 | string_is_safe(program_invocation_short_name)) { | |||
261 | ||||
262 | /* Implicitly add program_invocation_short_name, if it | |||
263 | * is not set explicitly. We only do this for | |||
264 | * program_invocation_short_name, and nothing else | |||
265 | * since everything else is much nicer to retrieve | |||
266 | * from the outside. */ | |||
267 | ||||
268 | w[j++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=")(struct iovec) { .iov_base = ((char*) "SYSLOG_IDENTIFIER="), . iov_len = (strlen("SYSLOG_IDENTIFIER=")) }; | |||
269 | w[j++] = IOVEC_MAKE_STRING(program_invocation_short_name)(struct iovec) { .iov_base = ((char*) program_invocation_short_name ), .iov_len = (strlen(program_invocation_short_name)) }; | |||
270 | w[j++] = IOVEC_MAKE_STRING("\n")(struct iovec) { .iov_base = ((char*) "\n"), .iov_len = (strlen ("\n")) }; | |||
271 | } | |||
272 | ||||
273 | fd = journal_fd(); | |||
274 | if (_unlikely_(fd < 0)(__builtin_expect(!!(fd < 0),0))) | |||
275 | return fd; | |||
276 | ||||
277 | mh.msg_iov = w; | |||
278 | mh.msg_iovlen = j; | |||
279 | ||||
280 | k = sendmsg(fd, &mh, MSG_NOSIGNALMSG_NOSIGNAL); | |||
281 | if (k >= 0) | |||
282 | return 0; | |||
283 | ||||
284 | /* Fail silently if the journal is not available */ | |||
285 | if (errno(*__errno_location ()) == ENOENT2) | |||
286 | return 0; | |||
287 | ||||
288 | if (!IN_SET(errno, EMSGSIZE, ENOBUFS)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){90, 105})/sizeof(int)]; switch((*__errno_location ())) { case 90: case 105: _found = 1; break; default: break; } _found; })) | |||
289 | return -errno(*__errno_location ()); | |||
290 | ||||
291 | /* Message doesn't fit... Let's dump the data in a memfd or | |||
292 | * temporary file and just pass a file descriptor of it to the | |||
293 | * other side. | |||
294 | * | |||
295 | * For the temporary files we use /dev/shm instead of /tmp | |||
296 | * here, since we want this to be a tmpfs, and one that is | |||
297 | * available from early boot on and where unprivileged users | |||
298 | * can create files. */ | |||
299 | buffer_fd = memfd_new(NULL((void*)0)); | |||
300 | if (buffer_fd < 0) { | |||
301 | if (buffer_fd == -ENOSYS38) { | |||
302 | buffer_fd = open_tmpfile_unlinkable("/dev/shm", O_RDWR02 | O_CLOEXEC02000000); | |||
303 | if (buffer_fd < 0) | |||
304 | return buffer_fd; | |||
305 | ||||
306 | seal = false0; | |||
307 | } else | |||
308 | return buffer_fd; | |||
309 | } | |||
310 | ||||
311 | n = writev(buffer_fd, w, j); | |||
312 | if (n < 0) | |||
313 | return -errno(*__errno_location ()); | |||
314 | ||||
315 | if (seal) { | |||
316 | r = memfd_set_sealed(buffer_fd); | |||
317 | if (r < 0) | |||
318 | return r; | |||
319 | } | |||
320 | ||||
321 | r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0); | |||
322 | if (r == -ENOENT2) | |||
323 | /* Fail silently if the journal is not available */ | |||
324 | return 0; | |||
325 | return r; | |||
326 | } | |||
327 | ||||
328 | static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) { | |||
329 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
330 | size_t n, k; | |||
331 | ||||
332 | k = isempty(message) ? 0 : strlen(message) + 2; | |||
333 | n = 8 + k + 256 + 1; | |||
334 | ||||
335 | for (;;) { | |||
336 | char buffer[n]; | |||
337 | char* j; | |||
338 | ||||
339 | errno(*__errno_location ()) = 0; | |||
340 | j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k); | |||
341 | if (errno(*__errno_location ()) == 0) { | |||
342 | char error[STRLEN("ERRNO=")(sizeof("""ERRNO=""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)]))) + 1]; | |||
343 | ||||
344 | if (j != buffer + 8 + k) | |||
345 | memmove(buffer + 8 + k, j, strlen(j)+1); | |||
346 | ||||
347 | memcpy(buffer, "MESSAGE=", 8); | |||
348 | ||||
349 | if (k > 0) { | |||
350 | memcpy(buffer + 8, message, k - 2); | |||
351 | memcpy(buffer + 8 + k - 2, ": ", 2); | |||
352 | } | |||
353 | ||||
354 | xsprintf(error, "ERRNO=%i", _saved_errno_)do { if ((__builtin_expect(!!(!(((size_t) snprintf(error, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (error), typeof(&*(error))), sizeof(error)/sizeof((error) [0]), ((void)0))), "ERRNO=%i", _saved_errno_) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (error), typeof(&*(error))), sizeof(error)/sizeof((error) [0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "error" "[] must be big enough"), "../src/journal/journal-send.c" , 354, __PRETTY_FUNCTION__); } while (0); | |||
355 | ||||
356 | assert_cc(3 == LOG_ERR)GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_11 { char x[(3 == 3) ? 0 : -1]; }; GCC diagnostic pop ; | |||
357 | iov[skip+0] = IOVEC_MAKE_STRING("PRIORITY=3")(struct iovec) { .iov_base = ((char*) "PRIORITY=3"), .iov_len = (strlen("PRIORITY=3")) }; | |||
358 | iov[skip+1] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen (buffer)) }; | |||
359 | iov[skip+2] = IOVEC_MAKE_STRING(error)(struct iovec) { .iov_base = ((char*) error), .iov_len = (strlen (error)) }; | |||
360 | ||||
361 | return sd_journal_sendv(iov, skip + 3); | |||
362 | } | |||
363 | ||||
364 | if (errno(*__errno_location ()) != ERANGE34) | |||
365 | return -errno(*__errno_location ()); | |||
366 | ||||
367 | n *= 2; | |||
368 | } | |||
369 | } | |||
370 | ||||
371 | _public___attribute__ ((visibility("default"))) int sd_journal_perror(const char *message) { | |||
372 | struct iovec iovec[3]; | |||
373 | ||||
374 | return fill_iovec_perror_and_send(message, 0, iovec); | |||
375 | } | |||
376 | ||||
377 | _public___attribute__ ((visibility("default"))) int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) { | |||
378 | static const union sockaddr_union sa = { | |||
379 | .un.sun_family = AF_UNIX1, | |||
380 | .un.sun_path = "/run/systemd/journal/stdout", | |||
381 | }; | |||
382 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
383 | char *header; | |||
384 | size_t l; | |||
385 | int r; | |||
386 | ||||
387 | assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0" ), "../src/journal/journal-send.c", 387, __PRETTY_FUNCTION__) , 0))) return (-22); } while (0); | |||
388 | assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7" ), "../src/journal/journal-send.c", 388, __PRETTY_FUNCTION__) , 0))) return (-22); } while (0); | |||
389 | ||||
390 | fd = socket(AF_UNIX1, SOCK_STREAMSOCK_STREAM|SOCK_CLOEXECSOCK_CLOEXEC, 0); | |||
391 | if (fd < 0) | |||
392 | return -errno(*__errno_location ()); | |||
393 | ||||
394 | r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journal-send.c" , 394, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof( struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen (_sa->sun_path, sizeof(_sa->sun_path))); })); | |||
395 | if (r < 0) | |||
396 | return -errno(*__errno_location ()); | |||
397 | ||||
398 | if (shutdown(fd, SHUT_RDSHUT_RD) < 0) | |||
399 | return -errno(*__errno_location ()); | |||
400 | ||||
401 | (void) fd_inc_sndbuf(fd, SNDBUF_SIZE(8*1024*1024)); | |||
402 | ||||
403 | identifier = strempty(identifier); | |||
404 | ||||
405 | l = strlen(identifier); | |||
406 | header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2)__builtin_alloca (l + 1 + 1 + 2 + 2 + 2 + 2 + 2); | |||
407 | ||||
408 | memcpy(header, identifier, l); | |||
409 | header[l++] = '\n'; | |||
410 | header[l++] = '\n'; /* unit id */ | |||
411 | header[l++] = '0' + priority; | |||
412 | header[l++] = '\n'; | |||
413 | header[l++] = '0' + !!level_prefix; | |||
414 | header[l++] = '\n'; | |||
415 | header[l++] = '0'; | |||
416 | header[l++] = '\n'; | |||
417 | header[l++] = '0'; | |||
418 | header[l++] = '\n'; | |||
419 | header[l++] = '0'; | |||
420 | header[l++] = '\n'; | |||
421 | ||||
422 | r = loop_write(fd, header, l, false0); | |||
423 | if (r < 0) | |||
424 | return r; | |||
425 | ||||
426 | return TAKE_FD(fd)({ int _fd_ = (fd); (fd) = -1; _fd_; }); | |||
427 | } | |||
428 | ||||
429 | _public___attribute__ ((visibility("default"))) int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) { | |||
430 | int r; | |||
431 | va_list ap; | |||
432 | ||||
433 | va_start(ap, format)__builtin_va_start(ap, format); | |||
434 | r = sd_journal_printv_with_location(priority, file, line, func, format, ap); | |||
435 | va_end(ap)__builtin_va_end(ap); | |||
436 | ||||
437 | return r; | |||
438 | } | |||
439 | ||||
440 | _public___attribute__ ((visibility("default"))) int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) { | |||
441 | char buffer[8 + LINE_MAX2048], p[STRLEN("PRIORITY=")(sizeof("""PRIORITY=""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)]))) + 1]; | |||
442 | struct iovec iov[5]; | |||
443 | char *f; | |||
444 | ||||
445 | assert_return(priority >= 0, -EINVAL)do { if (!(((__builtin_expect(!!(priority >= 0),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority >= 0" ), "../src/journal/journal-send.c", 445, __PRETTY_FUNCTION__) , 0))) return (-22); } while (0); | |||
446 | assert_return(priority <= 7, -EINVAL)do { if (!(((__builtin_expect(!!(priority <= 7),1))) ? (1) : (log_assert_failed_return_realm(LOG_REALM_SYSTEMD, ("priority <= 7" ), "../src/journal/journal-send.c", 446, __PRETTY_FUNCTION__) , 0))) return (-22); } while (0); | |||
447 | assert_return(format, -EINVAL)do { if (!(((__builtin_expect(!!(format),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("format"), "../src/journal/journal-send.c" , 447, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
448 | ||||
449 | xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK)do { if ((__builtin_expect(!!(!(((size_t) snprintf(p, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (p), typeof(&*(p))), sizeof(p)/sizeof((p)[0]), ((void)0)) ), "PRIORITY=%i", priority & 0x07) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(p), typeof(&*(p))) , sizeof(p)/sizeof((p)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "p" "[] must be big enough" ), "../src/journal/journal-send.c", 449, __PRETTY_FUNCTION__) ; } while (0); | |||
450 | ||||
451 | memcpy(buffer, "MESSAGE=", 8); | |||
452 | vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap); | |||
453 | ||||
454 | /* Strip trailing whitespace, keep prefixing whitespace */ | |||
455 | (void) strstrip(buffer); | |||
456 | ||||
457 | /* Suppress empty lines */ | |||
458 | if (isempty(buffer+8)) | |||
459 | return 0; | |||
460 | ||||
461 | /* func is initialized from __func__ which is not a macro, but | |||
462 | * a static const char[], hence cannot easily be prefixed with | |||
463 | * CODE_FUNC=, hence let's do it manually here. */ | |||
464 | ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = & (f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10 ); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl ); } while (0); | |||
465 | ||||
466 | iov[0] = IOVEC_MAKE_STRING(buffer)(struct iovec) { .iov_base = ((char*) buffer), .iov_len = (strlen (buffer)) }; | |||
467 | iov[1] = IOVEC_MAKE_STRING(p)(struct iovec) { .iov_base = ((char*) p), .iov_len = (strlen( p)) }; | |||
468 | iov[2] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen (file)) }; | |||
469 | iov[3] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen (line)) }; | |||
470 | iov[4] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen( f)) }; | |||
471 | ||||
472 | return sd_journal_sendv(iov, ELEMENTSOF(iov)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(iov), typeof(&*(iov))), sizeof(iov)/sizeof((iov)[ 0]), ((void)0)))); | |||
473 | } | |||
474 | ||||
475 | _public___attribute__ ((visibility("default"))) int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) { | |||
476 | _cleanup_free___attribute__((cleanup(freep))) struct iovec *iov = NULL((void*)0); | |||
477 | int r, i, j; | |||
478 | va_list ap; | |||
479 | char *f; | |||
480 | ||||
481 | va_start(ap, format)__builtin_va_start(ap, format); | |||
482 | i = fill_iovec_sprintf(format, ap, 3, &iov); | |||
| ||||
483 | va_end(ap)__builtin_va_end(ap); | |||
484 | ||||
485 | if (_unlikely_(i < 0)(__builtin_expect(!!(i < 0),0))) { | |||
486 | r = i; | |||
487 | goto finish; | |||
488 | } | |||
489 | ||||
490 | ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = & (f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10 ); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl ); } while (0); | |||
491 | ||||
492 | iov[0] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen (file)) }; | |||
493 | iov[1] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen (line)) }; | |||
494 | iov[2] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen( f)) }; | |||
495 | ||||
496 | r = sd_journal_sendv(iov, i); | |||
497 | ||||
498 | finish: | |||
499 | for (j = 3; j < i; j++) | |||
500 | free(iov[j].iov_base); | |||
501 | ||||
502 | return r; | |||
| ||||
503 | } | |||
504 | ||||
505 | _public___attribute__ ((visibility("default"))) int sd_journal_sendv_with_location( | |||
506 | const char *file, const char *line, | |||
507 | const char *func, | |||
508 | const struct iovec *iov, int n) { | |||
509 | ||||
510 | struct iovec *niov; | |||
511 | char *f; | |||
512 | ||||
513 | assert_return(iov, -EINVAL)do { if (!(((__builtin_expect(!!(iov),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("iov"), "../src/journal/journal-send.c", 513, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
514 | assert_return(n > 0, -EINVAL)do { if (!(((__builtin_expect(!!(n > 0),1))) ? (1) : (log_assert_failed_return_realm (LOG_REALM_SYSTEMD, ("n > 0"), "../src/journal/journal-send.c" , 514, __PRETTY_FUNCTION__), 0))) return (-22); } while (0); | |||
515 | ||||
516 | niov = newa(struct iovec, n + 3)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (struct iovec), n + 3))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(struct iovec), n + 3)"), "../src/journal/journal-send.c" , 516, __PRETTY_FUNCTION__); } while (0); (struct iovec*) __builtin_alloca (sizeof(struct iovec)*(n + 3)); }); | |||
517 | memcpy(niov, iov, sizeof(struct iovec) * n); | |||
518 | ||||
519 | ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = & (f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10 ); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl ); } while (0); | |||
520 | ||||
521 | niov[n++] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen (file)) }; | |||
522 | niov[n++] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen (line)) }; | |||
523 | niov[n++] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen( f)) }; | |||
524 | ||||
525 | return sd_journal_sendv(niov, n); | |||
526 | } | |||
527 | ||||
528 | _public___attribute__ ((visibility("default"))) int sd_journal_perror_with_location( | |||
529 | const char *file, const char *line, | |||
530 | const char *func, | |||
531 | const char *message) { | |||
532 | ||||
533 | struct iovec iov[6]; | |||
534 | char *f; | |||
535 | ||||
536 | ALLOCA_CODE_FUNC(f, func)do { size_t _fl; const char *_func = (func); char **_f = & (f); _fl = strlen(_func) + 1; *_f = __builtin_alloca (_fl + 10 ); memcpy(*_f, "CODE_FUNC=", 10); memcpy(*_f + 10, _func, _fl ); } while (0); | |||
537 | ||||
538 | iov[0] = IOVEC_MAKE_STRING(file)(struct iovec) { .iov_base = ((char*) file), .iov_len = (strlen (file)) }; | |||
539 | iov[1] = IOVEC_MAKE_STRING(line)(struct iovec) { .iov_base = ((char*) line), .iov_len = (strlen (line)) }; | |||
540 | iov[2] = IOVEC_MAKE_STRING(f)(struct iovec) { .iov_base = ((char*) f), .iov_len = (strlen( f)) }; | |||
541 | ||||
542 | return fill_iovec_perror_and_send(message, 3, iov); | |||
543 | } |