blob: 1d61367da4b82fa54726b762de60556611849ffa [file] [log] [blame]
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001From b19f800e178516d4f4d344457647e4a018bd6855 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 -060025diff --git a/meson.build b/meson.build
Andrew Geisslerd159c7f2021-09-02 21:05:58 -050026index 738879eb21..1aa20b8246 100644
Andrew Geisslerd1e89492021-02-12 15:35:20 -060027--- a/meson.build
28+++ b/meson.build
Andrew Geisslerd159c7f2021-09-02 21:05:58 -050029@@ -656,6 +656,7 @@ endif
Brad Bishopa34c0302019-09-23 22:34:48 -040030 foreach header : ['crypt.h',
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080031 'linux/memfd.h',
32 'linux/vm_sockets.h',
33+ 'printf.h',
34 'sys/auxv.h',
35 'valgrind/memcheck.h',
36 'valgrind/valgrind.h',
Andrew Geisslerd1e89492021-02-12 15:35:20 -060037diff --git a/src/basic/meson.build b/src/basic/meson.build
Andrew Geisslerd159c7f2021-09-02 21:05:58 -050038index 9b016ce5e8..a9ce21b02e 100644
Andrew Geisslerd1e89492021-02-12 15:35:20 -060039--- a/src/basic/meson.build
40+++ b/src/basic/meson.build
Andrew Geisslerd159c7f2021-09-02 21:05:58 -050041@@ -322,6 +322,11 @@ endforeach
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080042
Brad Bishop19323692019-04-05 15:28:33 -040043 basic_sources += generated_gperf_headers
William A. Kennington IIIac69b482021-06-02 12:28:27 -070044
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080045+if conf.get('HAVE_PRINTF_H') != 1
46+ basic_sources += [files('parse-printf-format.c')]
47+endif
48+
William A. Kennington IIIac69b482021-06-02 12:28:27 -070049+
50 ############################################################
51
52 arch_list = [
Andrew Geisslerd1e89492021-02-12 15:35:20 -060053diff --git a/src/basic/parse-printf-format.c b/src/basic/parse-printf-format.c
54new file mode 100644
55index 0000000000..49437e5445
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080056--- /dev/null
Andrew Geisslerd1e89492021-02-12 15:35:20 -060057+++ b/src/basic/parse-printf-format.c
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080058@@ -0,0 +1,273 @@
59+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60+
61+/***
62+ This file is part of systemd.
63+
64+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
65+
66+ With parts from the musl C library
67+ Copyright 2005-2014 Rich Felker, et al.
68+
69+ systemd is free software; you can redistribute it and/or modify it
70+ under the terms of the GNU Lesser General Public License as published by
71+ the Free Software Foundation; either version 2.1 of the License, or
72+ (at your option) any later version.
73+
74+ systemd is distributed in the hope that it will be useful, but
75+ WITHOUT ANY WARRANTY; without even the implied warranty of
76+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
77+ Lesser General Public License for more details.
78+
79+ You should have received a copy of the GNU Lesser General Public License
80+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
81+***/
82+
83+#include <stddef.h>
84+#include <string.h>
85+
86+#include "parse-printf-format.h"
87+
88+static const char *consume_nonarg(const char *fmt)
89+{
90+ do {
91+ if (*fmt == '\0')
92+ return fmt;
93+ } while (*fmt++ != '%');
94+ return fmt;
95+}
96+
97+static const char *consume_num(const char *fmt)
98+{
99+ for (;*fmt >= '0' && *fmt <= '9'; fmt++)
100+ /* do nothing */;
101+ return fmt;
102+}
103+
104+static const char *consume_argn(const char *fmt, size_t *arg)
105+{
106+ const char *p = fmt;
107+ size_t val = 0;
108+
109+ if (*p < '1' || *p > '9')
110+ return fmt;
111+ do {
112+ val = 10*val + (*p++ - '0');
113+ } while (*p >= '0' && *p <= '9');
114+
115+ if (*p != '$')
116+ return fmt;
117+ *arg = val;
118+ return p+1;
119+}
120+
121+static const char *consume_flags(const char *fmt)
122+{
123+ while (1) {
124+ switch (*fmt) {
125+ case '#':
126+ case '0':
127+ case '-':
128+ case ' ':
129+ case '+':
130+ case '\'':
131+ case 'I':
132+ fmt++;
133+ continue;
134+ }
135+ return fmt;
136+ }
137+}
138+
139+enum state {
140+ BARE,
141+ LPRE,
142+ LLPRE,
143+ HPRE,
144+ HHPRE,
145+ BIGLPRE,
146+ ZTPRE,
147+ JPRE,
148+ STOP
149+};
150+
151+enum type {
152+ NONE,
153+ PTR,
154+ INT,
155+ UINT,
156+ ULLONG,
157+ LONG,
158+ ULONG,
159+ SHORT,
160+ USHORT,
161+ CHAR,
162+ UCHAR,
163+ LLONG,
164+ SIZET,
165+ IMAX,
166+ UMAX,
167+ PDIFF,
168+ UIPTR,
169+ DBL,
170+ LDBL,
171+ MAXTYPE
172+};
173+
174+static const short pa_types[MAXTYPE] = {
175+ [NONE] = PA_INT,
176+ [PTR] = PA_POINTER,
177+ [INT] = PA_INT,
178+ [UINT] = PA_INT,
179+ [ULLONG] = PA_INT | PA_FLAG_LONG_LONG,
180+ [LONG] = PA_INT | PA_FLAG_LONG,
181+ [ULONG] = PA_INT | PA_FLAG_LONG,
182+ [SHORT] = PA_INT | PA_FLAG_SHORT,
183+ [USHORT] = PA_INT | PA_FLAG_SHORT,
184+ [CHAR] = PA_CHAR,
185+ [UCHAR] = PA_CHAR,
186+ [LLONG] = PA_INT | PA_FLAG_LONG_LONG,
187+ [SIZET] = PA_INT | PA_FLAG_LONG,
188+ [IMAX] = PA_INT | PA_FLAG_LONG_LONG,
189+ [UMAX] = PA_INT | PA_FLAG_LONG_LONG,
190+ [PDIFF] = PA_INT | PA_FLAG_LONG_LONG,
191+ [UIPTR] = PA_INT | PA_FLAG_LONG,
192+ [DBL] = PA_DOUBLE,
193+ [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE
194+};
195+
196+#define S(x) [(x)-'A']
197+#define E(x) (STOP + (x))
198+
199+static const unsigned char states[]['z'-'A'+1] = {
200+ { /* 0: bare types */
201+ S('d') = E(INT), S('i') = E(INT),
202+ S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT),
203+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
204+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
205+ S('c') = E(CHAR),S('C') = E(INT),
206+ S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR),
207+ S('m') = E(NONE),
208+ S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
209+ S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE
210+ }, { /* 1: l-prefixed */
211+ S('d') = E(LONG), S('i') = E(LONG),
212+ S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG),
213+ S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
214+ S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
215+ S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR),
216+ S('l') = LLPRE
217+ }, { /* 2: ll-prefixed */
218+ S('d') = E(LLONG), S('i') = E(LLONG),
219+ S('o') = E(ULLONG),S('u') = E(ULLONG),
220+ S('x') = E(ULLONG),S('X') = E(ULLONG),
221+ S('n') = E(PTR)
222+ }, { /* 3: h-prefixed */
223+ S('d') = E(SHORT), S('i') = E(SHORT),
224+ S('o') = E(USHORT),S('u') = E(USHORT),
225+ S('x') = E(USHORT),S('X') = E(USHORT),
226+ S('n') = E(PTR),
227+ S('h') = HHPRE
228+ }, { /* 4: hh-prefixed */
229+ S('d') = E(CHAR), S('i') = E(CHAR),
230+ S('o') = E(UCHAR),S('u') = E(UCHAR),
231+ S('x') = E(UCHAR),S('X') = E(UCHAR),
232+ S('n') = E(PTR)
233+ }, { /* 5: L-prefixed */
234+ S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL),
235+ S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL),
236+ S('n') = E(PTR)
237+ }, { /* 6: z- or t-prefixed (assumed to be same size) */
238+ S('d') = E(PDIFF),S('i') = E(PDIFF),
239+ S('o') = E(SIZET),S('u') = E(SIZET),
240+ S('x') = E(SIZET),S('X') = E(SIZET),
241+ S('n') = E(PTR)
242+ }, { /* 7: j-prefixed */
243+ S('d') = E(IMAX), S('i') = E(IMAX),
244+ S('o') = E(UMAX), S('u') = E(UMAX),
245+ S('x') = E(UMAX), S('X') = E(UMAX),
246+ S('n') = E(PTR)
247+ }
248+};
249+
250+size_t parse_printf_format(const char *fmt, size_t n, int *types)
251+{
252+ size_t i = 0;
253+ size_t last = 0;
254+
255+ memset(types, 0, n);
256+
257+ while (1) {
258+ size_t arg;
259+ unsigned int state;
260+
261+ fmt = consume_nonarg(fmt);
262+ if (*fmt == '\0')
263+ break;
264+ if (*fmt == '%') {
265+ fmt++;
266+ continue;
267+ }
268+ arg = 0;
269+ fmt = consume_argn(fmt, &arg);
270+ /* flags */
271+ fmt = consume_flags(fmt);
272+ /* width */
273+ if (*fmt == '*') {
274+ size_t warg = 0;
275+ fmt = consume_argn(fmt+1, &warg);
276+ if (warg == 0)
277+ warg = ++i;
278+ if (warg > last)
279+ last = warg;
280+ if (warg <= n && types[warg-1] == NONE)
281+ types[warg-1] = INT;
282+ } else
283+ fmt = consume_num(fmt);
284+ /* precision */
285+ if (*fmt == '.') {
286+ fmt++;
287+ if (*fmt == '*') {
288+ size_t parg = 0;
289+ fmt = consume_argn(fmt+1, &parg);
290+ if (parg == 0)
291+ parg = ++i;
292+ if (parg > last)
293+ last = parg;
294+ if (parg <= n && types[parg-1] == NONE)
295+ types[parg-1] = INT;
296+ } else {
297+ if (*fmt == '-')
298+ fmt++;
299+ fmt = consume_num(fmt);
300+ }
301+ }
302+ /* length modifier and conversion specifier */
303+ state = BARE;
304+ do {
305+ unsigned char c = *fmt++;
306+
307+ if (c < 'A' || c > 'z')
308+ continue;
309+ state = states[state]S(c);
310+ if (state == 0)
311+ continue;
312+ } while (state < STOP);
313+
314+ if (state == E(NONE))
315+ continue;
316+
317+ if (arg == 0)
318+ arg = ++i;
319+ if (arg > last)
320+ last = arg;
321+ if (arg <= n)
322+ types[arg-1] = state - STOP;
323+ }
324+
325+ if (last > n)
326+ last = n;
327+ for (i = 0; i < last; i++)
328+ types[i] = pa_types[types[i]];
329+
330+ return last;
331+}
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600332diff --git a/src/basic/parse-printf-format.h b/src/basic/parse-printf-format.h
333new file mode 100644
334index 0000000000..47be7522d7
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800335--- /dev/null
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600336+++ b/src/basic/parse-printf-format.h
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800337@@ -0,0 +1,57 @@
338+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
339+
340+/***
341+ This file is part of systemd.
342+
343+ Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
344+
345+ With parts from the GNU C Library
346+ Copyright 1991-2014 Free Software Foundation, Inc.
347+
348+ systemd is free software; you can redistribute it and/or modify it
349+ under the terms of the GNU Lesser General Public License as published by
350+ the Free Software Foundation; either version 2.1 of the License, or
351+ (at your option) any later version.
352+
353+ systemd is distributed in the hope that it will be useful, but
354+ WITHOUT ANY WARRANTY; without even the implied warranty of
355+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
356+ Lesser General Public License for more details.
357+
358+ You should have received a copy of the GNU Lesser General Public License
359+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
360+***/
361+
362+#pragma once
363+
364+#include "config.h"
365+
366+#if HAVE_PRINTF_H
367+#include <printf.h>
368+#else
369+
370+#include <stddef.h>
371+
372+enum { /* C type: */
373+ PA_INT, /* int */
374+ PA_CHAR, /* int, cast to char */
375+ PA_WCHAR, /* wide char */
376+ PA_STRING, /* const char *, a '\0'-terminated string */
377+ PA_WSTRING, /* const wchar_t *, wide character string */
378+ PA_POINTER, /* void * */
379+ PA_FLOAT, /* float */
380+ PA_DOUBLE, /* double */
381+ PA_LAST
382+};
383+
384+/* Flag bits that can be set in a type returned by `parse_printf_format'. */
385+#define PA_FLAG_MASK 0xff00
386+#define PA_FLAG_LONG_LONG (1 << 8)
387+#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
388+#define PA_FLAG_LONG (1 << 9)
389+#define PA_FLAG_SHORT (1 << 10)
390+#define PA_FLAG_PTR (1 << 11)
391+
392+size_t parse_printf_format(const char *fmt, size_t n, int *types);
393+
394+#endif /* HAVE_PRINTF_H */
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600395diff --git a/src/basic/stdio-util.h b/src/basic/stdio-util.h
396index 6dc1e72312..cea76b36cf 100644
397--- a/src/basic/stdio-util.h
398+++ b/src/basic/stdio-util.h
Brad Bishop19323692019-04-05 15:28:33 -0400399@@ -1,13 +1,13 @@
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600400 /* SPDX-License-Identifier: LGPL-2.1-or-later */
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800401 #pragma once
402
403-#include <printf.h>
404 #include <stdarg.h>
405 #include <stdio.h>
406 #include <sys/types.h>
407
408 #include "macro.h"
Brad Bishopc342db32019-05-15 21:57:59 -0400409 #include "memory-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800410+#include "parse-printf-format.h"
411
412 #define snprintf_ok(buf, len, fmt, ...) \
413 ((size_t) snprintf(buf, len, fmt, __VA_ARGS__) < (len))
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700414diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600415index fd3fd7ef9c..e8e6ad555b 100644
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700416--- a/src/libsystemd/sd-journal/journal-send.c
417+++ b/src/libsystemd/sd-journal/journal-send.c
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800418@@ -2,7 +2,6 @@
419
420 #include <errno.h>
421 #include <fcntl.h>
422-#include <printf.h>
423 #include <stddef.h>
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800424 #include <sys/un.h>
Andrew Geissler82c905d2020-04-13 13:39:40 -0500425 #include <unistd.h>
Andrew Geissler635e0e42020-08-21 15:58:33 -0500426@@ -21,6 +20,7 @@
Brad Bishopc342db32019-05-15 21:57:59 -0400427 #include "stdio-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800428 #include "string-util.h"
Brad Bishop19323692019-04-05 15:28:33 -0400429 #include "tmpfile-util.h"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800430+#include "parse-printf-format.h"
431
432 #define SNDBUF_SIZE (8*1024*1024)
433