blob: d93f630752823ce9365f26f3496b42d42b3005b1 [file] [log] [blame]
Andrew Geissler595f6302022-01-24 19:11:47 +00001From 3e0df2c22bfd37bc62bf09a01ec498e40d3599de Mon Sep 17 00:00:00 2001
William A. Kennington IIIac69b482021-06-02 12:28:27 -07002From: Alexander Kanavin <alex.kanavin@gmail.com>
3Date: Sat, 22 May 2021 20:26:24 +0200
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05004Subject: [PATCH] add fallback parse_printf_format implementation
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08005
6Upstream-Status: Inappropriate [musl specific]
7
8Signed-off-by: Emil Renner Berthing <systemd@esmil.dk>
9Signed-off-by: Khem Raj <raj.khem@gmail.com>
10Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Brad Bishopa34c0302019-09-23 22:34:48 -040011[rebased for systemd 243]
12Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Andrew Geisslerd159c7f2021-09-02 21:05:58 -050013
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080014---
William A. Kennington IIIac69b482021-06-02 12:28:27 -070015 meson.build | 1 +
16 src/basic/meson.build | 5 +
17 src/basic/parse-printf-format.c | 273 +++++++++++++++++++++++
18 src/basic/parse-printf-format.h | 57 +++++
19 src/basic/stdio-util.h | 2 +-
20 src/libsystemd/sd-journal/journal-send.c | 2 +-
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080021 6 files changed, 338 insertions(+), 2 deletions(-)
22 create mode 100644 src/basic/parse-printf-format.c
23 create mode 100644 src/basic/parse-printf-format.h
24
Andrew Geisslerd1e89492021-02-12 15:35:20 -060025--- a/meson.build
26+++ b/meson.build
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000027@@ -686,6 +686,7 @@ endif
Brad Bishopa34c0302019-09-23 22:34:48 -040028 foreach header : ['crypt.h',
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080029 'linux/memfd.h',
30 'linux/vm_sockets.h',
31+ 'printf.h',
32 'sys/auxv.h',
33 'valgrind/memcheck.h',
34 'valgrind/valgrind.h',
Andrew Geisslerd1e89492021-02-12 15:35:20 -060035--- a/src/basic/meson.build
36+++ b/src/basic/meson.build
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000037@@ -335,6 +335,11 @@ endforeach
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080038
Brad Bishop19323692019-04-05 15:28:33 -040039 basic_sources += generated_gperf_headers
William A. Kennington IIIac69b482021-06-02 12:28:27 -070040
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080041+if conf.get('HAVE_PRINTF_H') != 1
42+ basic_sources += [files('parse-printf-format.c')]
43+endif
44+
William A. Kennington IIIac69b482021-06-02 12:28:27 -070045+
46 ############################################################
47
48 arch_list = [
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080049--- /dev/null
Andrew Geisslerd1e89492021-02-12 15:35:20 -060050+++ b/src/basic/parse-printf-format.c
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080051@@ -0,0 +1,273 @@
52+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
53+
54+/***
55+ This file is part of systemd.
56+
57+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
58+
59+ With parts from the musl C library
60+ Copyright 2005-2014 Rich Felker, et al.
61+
62+ systemd is free software; you can redistribute it and/or modify it
63+ under the terms of the GNU Lesser General Public License as published by
64+ the Free Software Foundation; either version 2.1 of the License, or
65+ (at your option) any later version.
66+
67+ systemd is distributed in the hope that it will be useful, but
68+ WITHOUT ANY WARRANTY; without even the implied warranty of
69+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
70+ Lesser General Public License for more details.
71+
72+ You should have received a copy of the GNU Lesser General Public License
73+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
74+***/
75+
76+#include <stddef.h>
77+#include <string.h>
78+
79+#include "parse-printf-format.h"
80+
81+static const char *consume_nonarg(const char *fmt)
82+{
83+ do {
84+ if (*fmt == '\0')
85+ return fmt;
86+ } while (*fmt++ != '%');
87+ return fmt;
88+}
89+
90+static const char *consume_num(const char *fmt)
91+{
92+ for (;*fmt >= '0' && *fmt <= '9'; fmt++)
93+ /* do nothing */;
94+ return fmt;
95+}
96+
97+static const char *consume_argn(const char *fmt, size_t *arg)
98+{
99+ const char *p = fmt;
100+ size_t val = 0;
101+
102+ if (*p < '1' || *p > '9')
103+ return fmt;
104+ do {
105+ val = 10*val + (*p++ - '0');
106+ } while (*p >= '0' && *p <= '9');
107+
108+ if (*p != '$')
109+ return fmt;
110+ *arg = val;
111+ return p+1;
112+}
113+
114+static const char *consume_flags(const char *fmt)
115+{
116+ while (1) {
117+ switch (*fmt) {
118+ case '#':
119+ case '0':
120+ case '-':
121+ case ' ':
122+ case '+':
123+ case '\'':
124+ case 'I':
125+ fmt++;
126+ continue;
127+ }
128+ return fmt;
129+ }
130+}
131+
132+enum state {
133+ BARE,
134+ LPRE,
135+ LLPRE,
136+ HPRE,
137+ HHPRE,
138+ BIGLPRE,
139+ ZTPRE,
140+ JPRE,
141+ STOP
142+};
143+
144+enum type {
145+ NONE,
146+ PTR,
147+ INT,
148+ UINT,
149+ ULLONG,
150+ LONG,
151+ ULONG,
152+ SHORT,
153+ USHORT,
154+ CHAR,
155+ UCHAR,
156+ LLONG,
157+ SIZET,
158+ IMAX,
159+ UMAX,
160+ PDIFF,
161+ UIPTR,
162+ DBL,
163+ LDBL,
164+ MAXTYPE
165+};
166+
167+static const short pa_types[MAXTYPE] = {
168+ [NONE] = PA_INT,
169+ [PTR] = PA_POINTER,
170+ [INT] = PA_INT,
171+ [UINT] = PA_INT,
172+ [ULLONG] = PA_INT | PA_FLAG_LONG_LONG,
173+ [LONG] = PA_INT | PA_FLAG_LONG,
174+ [ULONG] = PA_INT | PA_FLAG_LONG,
175+ [SHORT] = PA_INT | PA_FLAG_SHORT,
176+ [USHORT] = PA_INT | PA_FLAG_SHORT,
177+ [CHAR] = PA_CHAR,
178+ [UCHAR] = PA_CHAR,
179+ [LLONG] = PA_INT | PA_FLAG_LONG_LONG,
180+ [SIZET] = PA_INT | PA_FLAG_LONG,
181+ [IMAX] = PA_INT | PA_FLAG_LONG_LONG,
182+ [UMAX] = PA_INT | PA_FLAG_LONG_LONG,
183+ [PDIFF] = PA_INT | PA_FLAG_LONG_LONG,
184+ [UIPTR] = PA_INT | PA_FLAG_LONG,
185+ [DBL] = PA_DOUBLE,
186+ [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE
187+};
188+
189+#define S(x) [(x)-'A']
190+#define E(x) (STOP + (x))
191+
192+static const unsigned char states[]['z'-'A'+1] = {
193+ { /* 0: bare types */
194+ S('d') = E(INT), S('i') = E(INT),
195+ S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT),
196+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
197+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
198+ S('c') = E(CHAR),S('C') = E(INT),
199+ S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR),
200+ S('m') = E(NONE),
201+ S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
202+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE
203+ }, { /* 1: l-prefixed */
204+ S('d') = E(LONG), S('i') = E(LONG),
205+ S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG),
206+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
207+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
208+ S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR),
209+ S('l') = LLPRE
210+ }, { /* 2: ll-prefixed */
211+ S('d') = E(LLONG), S('i') = E(LLONG),
212+ S('o') = E(ULLONG),S('u') = E(ULLONG),
213+ S('x') = E(ULLONG),S('X') = E(ULLONG),
214+ S('n') = E(PTR)
215+ }, { /* 3: h-prefixed */
216+ S('d') = E(SHORT), S('i') = E(SHORT),
217+ S('o') = E(USHORT),S('u') = E(USHORT),
218+ S('x') = E(USHORT),S('X') = E(USHORT),
219+ S('n') = E(PTR),
220+ S('h') = HHPRE
221+ }, { /* 4: hh-prefixed */
222+ S('d') = E(CHAR), S('i') = E(CHAR),
223+ S('o') = E(UCHAR),S('u') = E(UCHAR),
224+ S('x') = E(UCHAR),S('X') = E(UCHAR),
225+ S('n') = E(PTR)
226+ }, { /* 5: L-prefixed */
227+ S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL),
228+ S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL),
229+ S('n') = E(PTR)
230+ }, { /* 6: z- or t-prefixed (assumed to be same size) */
231+ S('d') = E(PDIFF),S('i') = E(PDIFF),
232+ S('o') = E(SIZET),S('u') = E(SIZET),
233+ S('x') = E(SIZET),S('X') = E(SIZET),
234+ S('n') = E(PTR)
235+ }, { /* 7: j-prefixed */
236+ S('d') = E(IMAX), S('i') = E(IMAX),
237+ S('o') = E(UMAX), S('u') = E(UMAX),
238+ S('x') = E(UMAX), S('X') = E(UMAX),
239+ S('n') = E(PTR)
240+ }
241+};
242+
243+size_t parse_printf_format(const char *fmt, size_t n, int *types)
244+{
245+ size_t i = 0;
246+ size_t last = 0;
247+
248+ memset(types, 0, n);
249+
250+ while (1) {
251+ size_t arg;
252+ unsigned int state;
253+
254+ fmt = consume_nonarg(fmt);
255+ if (*fmt == '\0')
256+ break;
257+ if (*fmt == '%') {
258+ fmt++;
259+ continue;
260+ }
261+ arg = 0;
262+ fmt = consume_argn(fmt, &arg);
263+ /* flags */
264+ fmt = consume_flags(fmt);
265+ /* width */
266+ if (*fmt == '*') {
267+ size_t warg = 0;
268+ fmt = consume_argn(fmt+1, &warg);
269+ if (warg == 0)
270+ warg = ++i;
271+ if (warg > last)
272+ last = warg;
273+ if (warg <= n && types[warg-1] == NONE)
274+ types[warg-1] = INT;
275+ } else
276+ fmt = consume_num(fmt);
277+ /* precision */
278+ if (*fmt == '.') {
279+ fmt++;
280+ if (*fmt == '*') {
281+ size_t parg = 0;
282+ fmt = consume_argn(fmt+1, &parg);
283+ if (parg == 0)
284+ parg = ++i;
285+ if (parg > last)
286+ last = parg;
287+ if (parg <= n && types[parg-1] == NONE)
288+ types[parg-1] = INT;
289+ } else {
290+ if (*fmt == '-')
291+ fmt++;
292+ fmt = consume_num(fmt);
293+ }
294+ }
295+ /* length modifier and conversion specifier */
296+ state = BARE;
297+ do {
298+ unsigned char c = *fmt++;
299+
300+ if (c < 'A' || c > 'z')
301+ continue;
302+ state = states[state]S(c);
303+ if (state == 0)
304+ continue;
305+ } while (state < STOP);
306+
307+ if (state == E(NONE))
308+ continue;
309+
310+ if (arg == 0)
311+ arg = ++i;
312+ if (arg > last)
313+ last = arg;
314+ if (arg <= n)
315+ types[arg-1] = state - STOP;
316+ }
317+
318+ if (last > n)
319+ last = n;
320+ for (i = 0; i < last; i++)
321+ types[i] = pa_types[types[i]];
322+
323+ return last;
324+}
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800325--- /dev/null
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600326+++ b/src/basic/parse-printf-format.h
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800327@@ -0,0 +1,57 @@
328+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
329+
330+/***
331+ This file is part of systemd.
332+
333+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
334+
335+ With parts from the GNU C Library
336+ Copyright 1991-2014 Free Software Foundation, Inc.
337+
338+ systemd is free software; you can redistribute it and/or modify it
339+ under the terms of the GNU Lesser General Public License as published by
340+ the Free Software Foundation; either version 2.1 of the License, or
341+ (at your option) any later version.
342+
343+ systemd is distributed in the hope that it will be useful, but
344+ WITHOUT ANY WARRANTY; without even the implied warranty of
345+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
346+ Lesser General Public License for more details.
347+
348+ You should have received a copy of the GNU Lesser General Public License
349+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
350+***/
351+
352+#pragma once
353+
354+#include "config.h"
355+
356+#if HAVE_PRINTF_H
357+#include <printf.h>
358+#else
359+
360+#include <stddef.h>
361+
362+enum { /* C type: */
363+ PA_INT, /* int */
364+ PA_CHAR, /* int, cast to char */
365+ PA_WCHAR, /* wide char */
366+ PA_STRING, /* const char *, a '\0'-terminated string */
367+ PA_WSTRING, /* const wchar_t *, wide character string */
368+ PA_POINTER, /* void * */
369+ PA_FLOAT, /* float */
370+ PA_DOUBLE, /* double */
371+ PA_LAST
372+};
373+
374+/* Flag bits that can be set in a type returned by `parse_printf_format'. */
375+#define PA_FLAG_MASK 0xff00
376+#define PA_FLAG_LONG_LONG (1 << 8)
377+#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
378+#define PA_FLAG_LONG (1 << 9)
379+#define PA_FLAG_SHORT (1 << 10)
380+#define PA_FLAG_PTR (1 << 11)
381+
382+size_t parse_printf_format(const char *fmt, size_t n, int *types);
383+
384+#endif /* HAVE_PRINTF_H */
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600385--- a/src/basic/stdio-util.h
386+++ b/src/basic/stdio-util.h
Brad Bishop19323692019-04-05 15:28:33 -0400387@@ -1,13 +1,13 @@
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600388 /* SPDX-License-Identifier: LGPL-2.1-or-later */
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800389 #pragma once
390
391-#include <printf.h>
392 #include <stdarg.h>
393 #include <stdio.h>
394 #include <sys/types.h>
395
396 #include "macro.h"
Brad Bishopc342db32019-05-15 21:57:59 -0400397 #include "memory-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800398+#include "parse-printf-format.h"
399
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000400 #define snprintf_ok(buf, len, fmt, ...) \
401 ({ \
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700402--- a/src/libsystemd/sd-journal/journal-send.c
403+++ b/src/libsystemd/sd-journal/journal-send.c
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800404@@ -2,7 +2,6 @@
405
406 #include <errno.h>
407 #include <fcntl.h>
408-#include <printf.h>
409 #include <stddef.h>
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800410 #include <sys/un.h>
Andrew Geissler82c905d2020-04-13 13:39:40 -0500411 #include <unistd.h>
Andrew Geissler635e0e42020-08-21 15:58:33 -0500412@@ -21,6 +20,7 @@
Brad Bishopc342db32019-05-15 21:57:59 -0400413 #include "stdio-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800414 #include "string-util.h"
Brad Bishop19323692019-04-05 15:28:33 -0400415 #include "tmpfile-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800416+#include "parse-printf-format.h"
417
418 #define SNDBUF_SIZE (8*1024*1024)
419