From 248ce289f789eda18142f1e6003491bb11061e60 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 30 Jun 2024 17:17:14 +0200 Subject: [PATCH] dzprintf: New module. * lib/stdio.in.h (dzprintf): New declaration. * lib/dzprintf.c: New file, based on lib/vdzprintf.c. * m4/stdio_h.m4 (gl_STDIO_H_REQUIRE_DEFAULTS): Initialize GNULIB_DZPRINTF. * modules/stdio (Makefile.am): Substitute GNULIB_DZPRINTF. * modules/dzprintf: New file. --- ChangeLog | 10 +++++++ lib/dzprintf.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/stdio.in.h | 16 +++++++++++ m4/stdio_h.m4 | 3 +- modules/dzprintf | 29 +++++++++++++++++++ modules/stdio | 1 + 6 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 lib/dzprintf.c create mode 100644 modules/dzprintf diff --git a/ChangeLog b/ChangeLog index 72ecdad3d5..9b8a205204 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2024-06-30 Bruno Haible + + dzprintf: New module. + * lib/stdio.in.h (dzprintf): New declaration. + * lib/dzprintf.c: New file, based on lib/vdzprintf.c. + * m4/stdio_h.m4 (gl_STDIO_H_REQUIRE_DEFAULTS): Initialize + GNULIB_DZPRINTF. + * modules/stdio (Makefile.am): Substitute GNULIB_DZPRINTF. + * modules/dzprintf: New file. + 2024-06-30 Bruno Haible vdprintf: Use vdzprintf. diff --git a/lib/dzprintf.c b/lib/dzprintf.c new file mode 100644 index 0000000000..ee8b276a53 --- /dev/null +++ b/lib/dzprintf.c @@ -0,0 +1,72 @@ +/* Formatted output to a file descriptor. + Copyright (C) 2009-2024 Free Software Foundation, Inc. + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include + +#include +#include +#include + +#include "full-write.h" +#include "intprops.h" +#include "vasnprintf.h" + +off64_t +dzprintf (int fd, const char *format, ...) +{ + va_list args; + char buf[2000]; + char *output; + size_t len; + size_t lenbuf = sizeof (buf); + + va_start (args, format); + output = vasnprintf (buf, &lenbuf, format, args); + len = lenbuf; + va_end (args); + + if (!output) + return -1; + + if (len > TYPE_MAXIMUM (off64_t)) + { + /* We could write the (huge) output, but then could not return len, as it + would be negative. Since we want to use the error code ENOMEM, it is + better to treat this case as if vasnprintf had already encountered an + out-of-memory situation. */ + if (output != buf) + free (output); + errno = ENOMEM; + return -1; + } + + if (full_write (fd, output, len) < len) + { + if (output != buf) + free (output); + return -1; + } + + if (output != buf) + free (output); + + return len; +} diff --git a/lib/stdio.in.h b/lib/stdio.in.h index 03e4cf9ca6..5fac912db2 100644 --- a/lib/stdio.in.h +++ b/lib/stdio.in.h @@ -280,6 +280,22 @@ #endif +#if @GNULIB_DZPRINTF@ +/* Prints formatted output to file descriptor FD. + Returns the number of bytes written to the file descriptor. Upon + failure, returns -1 with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure codes are ENOMEM + and the possible failure codes from write(), excluding EINTR. */ +_GL_FUNCDECL_SYS (dzprintf, off64_t, + (int fd, const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_SYS (dzprintf, off64_t, + (int fd, const char *restrict format, ...)); +#endif + #if @GNULIB_DPRINTF@ # if @REPLACE_DPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4 index 8073f6fa5b..126e395fae 100644 --- a/m4/stdio_h.m4 +++ b/m4/stdio_h.m4 @@ -1,5 +1,5 @@ # stdio_h.m4 -# serial 70 +# serial 71 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -133,6 +133,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], [ m4_defun(GL_MODULE_INDICATOR_PREFIX[_STDIO_H_MODULE_INDICATOR_DEFAULTS], [ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_DPRINTF]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_DZPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FCLOSE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FDOPEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FFLUSH]) diff --git a/modules/dzprintf b/modules/dzprintf new file mode 100644 index 0000000000..ea3dc9d033 --- /dev/null +++ b/modules/dzprintf @@ -0,0 +1,29 @@ +Description: +dzprintf() function: print formatted output (without INT_MAX limitation) +to a file descriptor + +Files: +lib/dzprintf.c + +Depends-on: +stdio +vasnprintf +intprops +free-posix +full-write +errno + +configure.ac: +gl_STDIO_MODULE_INDICATOR([dzprintf]) + +Makefile.am: +lib_SOURCES += dzprintf.c + +Include: + + +License: +LGPL + +Maintainer: +all diff --git a/modules/stdio b/modules/stdio index dcc2bfbbf2..22008a2b90 100644 --- a/modules/stdio +++ b/modules/stdio @@ -68,6 +68,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ -e 's/@''GNULIB_DPRINTF''@/$(GNULIB_DPRINTF)/g' \ + -e 's/@''GNULIB_DZPRINTF''@/$(GNULIB_DZPRINTF)/g' \ -e 's/@''GNULIB_FCLOSE''@/$(GNULIB_FCLOSE)/g' \ -e 's/@''GNULIB_FDOPEN''@/$(GNULIB_FDOPEN)/g' \ -e 's/@''GNULIB_FFLUSH''@/$(GNULIB_FFLUSH)/g' \ -- 2.39.5