[git] GPG-ERROR - branch, master, updated. libgpg-error-1.32-57-gbd8668c

by Werner Koch cvs at cvs.gnupg.org
Mon Nov 26 20:22:53 CET 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Error codes used by GnuPG et al.".

The branch, master has been updated
       via  bd8668c120ac0f725edb092b2c4ca49ffdb78ed2 (commit)
       via  ffb49b72f132d954a3d9fa11e45803c36a62fd25 (commit)
      from  a5d4a4b32b11814d673241d62624ecec1d577571 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit bd8668c120ac0f725edb092b2c4ca49ffdb78ed2
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Nov 26 20:22:24 2018 +0100

    core: New functions gpgrt_fprintf_sf anf gpgrt_fprintf_sf_unlocked.
    
    * src/gpg-error.h.in (gpgrt_string_filter_t): New type.
    (gpgrt_fprintf_sf, gpgrt_fprintf_sf_unlocked): New.
    * src/gpg-error.vers, src/gpg-error.def.in: Add them.
    * src/visibility.c (gpgrt_fprintf_sf): New.
    (gpgrt_fprintf_sf_unlocked): New.
    * src/estream-printf.c (pr_string): Add and use args sf, sfvalue and
    string_no.
    (do_format): Add args sf and sfvalue.  Keep a string format counter.
    (_gpgrt_estream_format): Add args sf and sfvalue.  Change all callers
    to provide NULL for them.
    * src/estream.c (_gpgrt_vfprintf_unlocked, _gpgrt_vfprintf): Add sf
    and sfvalue and adjust all callers.
    (do_print_stream): Ditto.
    
    * tests/t-printf.c (stream_to_string): New.
    (struct sfstate_s): New.
    (string_filter): New.
    (check_fprintf_sf): New.
    (main): Call new test.
    --
    
    The actual reason to implement these functions is to enhance the
    internal logging function with a filter to sanitized strings so that
    control values or other things can be quoted.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/NEWS b/NEWS
index f1facf4..5804819 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ Noteworthy changes in version 1.33 (unreleased) [C24/A24/R_]
  * Interface changes relative to the 1.28 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gpgrt_cmp_version               New.
+ gpgrt_ftruncate                 New but limited functionality.
+ gpgrt_string_filter_t           New.
+ gpgrt_fprintf_sf                New.
+ gpgrt_fprintf_sf_unlocked       New.
 
 
 Noteworthy changes in version 1.32 (2018-07-12) [C24/A24/R3]
diff --git a/src/estream-printf.c b/src/estream-printf.c
index eb6fa3a..b9775a6 100644
--- a/src/estream-printf.c
+++ b/src/estream-printf.c
@@ -1196,7 +1196,8 @@ pr_char (estream_printf_out_t outfnc, void *outfncarg,
 /* "s" formatting.  */
 static int
 pr_string (estream_printf_out_t outfnc, void *outfncarg,
-            argspec_t arg, value_t value, size_t *nbytes)
+           argspec_t arg, value_t value, size_t *nbytes,
+           gpgrt_string_filter_t sf, void *sfvalue, int string_no)
 {
   int rc;
   size_t n;
@@ -1205,6 +1206,11 @@ pr_string (estream_printf_out_t outfnc, void *outfncarg,
   if (arg->vt != VALTYPE_STRING)
     return -1;
   string = value.a_string;
+  if (sf)
+    string = sf (value.a_string, string_no, sfvalue);
+  else
+    string = value.a_string;
+
   if (!string)
     string = "(null)";
   if (arg->precision >= 0)
@@ -1222,12 +1228,12 @@ pr_string (estream_printf_out_t outfnc, void *outfncarg,
     {
       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
       if (rc)
-        return rc;
+        goto leave;
     }
 
   rc = outfnc (outfncarg, string, n);
   if (rc)
-    return rc;
+    goto leave;
   *nbytes += n;
 
   if ((arg->flags & FLAG_LEFT_JUST)
@@ -1235,10 +1241,16 @@ pr_string (estream_printf_out_t outfnc, void *outfncarg,
     {
       rc = pad_out (outfnc, outfncarg, ' ', arg->width - n, nbytes);
       if (rc)
-        return rc;
+        goto leave;
     }
 
-  return 0;
+  rc = 0;
+
+ leave:
+  if (sf) /* Tell the filter to release resources.  */
+    sf (value.a_string, -1, sfvalue);
+
+  return rc;
 }
 
 
@@ -1337,14 +1349,18 @@ pr_bytes_so_far (estream_printf_out_t outfnc, void *outfncarg,
 
 
 /* Run the actual formatting.  OUTFNC and OUTFNCARG are the output
-   functions.  FORMAT is format string ARGSPECS is the parsed format
-   string, ARGSPECS_LEN the number of items in ARGSPECS.  VALUETABLE
-   holds the values and may be directly addressed using the position
-   arguments given by ARGSPECS.  MYERRNO is used for the "%m"
-   conversion. NBYTES well be updated to reflect the number of bytes
-   send to the output function. */
+ * functions.  FORMAT is format string ARGSPECS is the parsed format
+ * string, ARGSPECS_LEN the number of items in ARGSPECS.
+ * STRING_FILTER is an optional function to filter string (%s) args;
+ * it is called with the original string and the count of already
+ * processed %s arguments.  Its return value will be used instead of
+ * the original string.  VALUETABLE holds the values and may be
+ * directly addressed using the position arguments given by ARGSPECS.
+ * MYERRNO is used for the "%m" conversion. NBYTES well be updated to
+ * reflect the number of bytes send to the output function. */
 static int
 do_format (estream_printf_out_t outfnc, void *outfncarg,
+           gpgrt_string_filter_t sf, void *sfvalue,
            const char *format, argspec_t argspecs, size_t argspecs_len,
            valueitem_t valuetable, int myerrno, size_t *nbytes)
 {
@@ -1354,6 +1370,7 @@ do_format (estream_printf_out_t outfnc, void *outfncarg,
   int argidx = 0; /* Only used for assertion.  */
   size_t n;
   value_t value;
+  int string_no = 0;  /* Number of processed "%s" args.  */
 
   s = format;
   while ( *s )
@@ -1443,8 +1460,12 @@ do_format (estream_printf_out_t outfnc, void *outfncarg,
           rc = pr_char (outfnc, outfncarg, arg, value, nbytes);
           break;
         case CONSPEC_STRING:
+          rc = pr_string (outfnc, outfncarg, arg, value, nbytes,
+                          sf, sfvalue, string_no++);
+          break;
         case CONSPEC_STRERROR:
-          rc = pr_string (outfnc, outfncarg, arg, value, nbytes);
+          rc = pr_string (outfnc, outfncarg, arg, value, nbytes,
+                          NULL, NULL, 0);
           break;
         case CONSPEC_POINTER:
           rc = pr_pointer (outfnc, outfncarg, arg, value, nbytes);
@@ -1478,6 +1499,7 @@ do_format (estream_printf_out_t outfnc, void *outfncarg,
 int
 _gpgrt_estream_format (estream_printf_out_t outfnc,
                        void *outfncarg,
+                       gpgrt_string_filter_t sf, void *sfvalue,
                        const char *format, va_list vaargs)
 {
   /* Buffer to hold the argspecs and a pointer to it.*/
@@ -1489,10 +1511,10 @@ _gpgrt_estream_format (estream_printf_out_t outfnc,
   struct valueitem_s valuetable_buffer[DEFAULT_MAX_VALUES];
   valueitem_t valuetable = valuetable_buffer;
 
-  int rc;     /* Return code. */
+  int rc;        /* Return code. */
   size_t argidx; /* Used to index the argspecs array.  */
   size_t validx; /* Used to index the valuetable.  */
-  int max_pos;/* Highest argument position.  */
+  int max_pos;   /* Highest argument position.  */
 
   size_t nbytes = 0; /* Keep track of the number of bytes passed to
                         the output function.  */
@@ -1606,7 +1628,7 @@ _gpgrt_estream_format (estream_printf_out_t outfnc,
 /*     fprintf (stderr, "%2d: vt=%d\n", validx, valuetable[validx].vt); */
 
   /* Everything has been collected, go ahead with the formatting.  */
-  rc = do_format (outfnc, outfncarg, format,
+  rc = do_format (outfnc, outfncarg, sf, sfvalue, format,
                   argspecs, argspecs_len, valuetable, myerrno, &nbytes);
 
   goto leave;
@@ -1646,7 +1668,8 @@ _gpgrt_estream_printf (const char *format, ...)
   va_list arg_ptr;
 
   va_start (arg_ptr, format);
-  rc = _gpgrt_estream_format (plain_stdio_out, stderr, format, arg_ptr);
+  rc = _gpgrt_estream_format (plain_stdio_out, stderr, NULL, NULL,
+                              format, arg_ptr);
   va_end (arg_ptr);
 
   return rc;
@@ -1660,7 +1683,8 @@ _gpgrt_estream_fprintf (FILE *fp, const char *format, ...)
   va_list arg_ptr;
 
   va_start (arg_ptr, format);
-  rc = _gpgrt_estream_format (plain_stdio_out, fp, format, arg_ptr);
+  rc = _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL,
+                              format, arg_ptr);
   va_end (arg_ptr);
 
   return rc;
@@ -1670,7 +1694,8 @@ _gpgrt_estream_fprintf (FILE *fp, const char *format, ...)
 int
 _gpgrt_estream_vfprintf (FILE *fp, const char *format, va_list arg_ptr)
 {
-  return _gpgrt_estream_format (plain_stdio_out, fp, format, arg_ptr);
+  return _gpgrt_estream_format (plain_stdio_out, fp, NULL, NULL,
+                                format, arg_ptr);
 }
 
 
@@ -1725,7 +1750,8 @@ _gpgrt_estream_vsnprintf (char *buf, size_t bufsize,
   parm.count = 0;
   parm.used = 0;
   parm.buffer = bufsize?buf:NULL;
-  rc = _gpgrt_estream_format (fixed_buffer_out, &parm, format, arg_ptr);
+  rc = _gpgrt_estream_format (fixed_buffer_out, &parm, NULL, NULL,
+                              format, arg_ptr);
   if (!rc)
     rc = fixed_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
   if (rc == -1)
@@ -1820,7 +1846,8 @@ _gpgrt_estream_vasprintf (char **bufp, const char *format, va_list arg_ptr)
       return -1;
     }
 
-  rc = _gpgrt_estream_format (dynamic_buffer_out, &parm, format, arg_ptr);
+  rc = _gpgrt_estream_format (dynamic_buffer_out, &parm, NULL, NULL,
+                              format, arg_ptr);
   if (!rc)
     rc = dynamic_buffer_out (&parm, "", 1); /* Print terminating Nul.  */
   /* Fixme: Should we shrink the resulting buffer?  */
diff --git a/src/estream-printf.h b/src/estream-printf.h
index ae303a7..69c7052 100644
--- a/src/estream-printf.h
+++ b/src/estream-printf.h
@@ -124,8 +124,10 @@ typedef int (*estream_printf_out_t)
      (void *outfncarg,  const char *buf, size_t buflen);
 
 int _gpgrt_estream_format (estream_printf_out_t outfnc, void *outfncarg,
+                           char *(*string_filter)(const char *s,int n,void*st),
+                           void *string_filter_state,
                            const char *format, va_list vaargs)
-     _ESTREAM_GCC_A_PRINTF(3,0);
+     _ESTREAM_GCC_A_PRINTF(5,0);
 int _gpgrt_estream_printf (const char *format, ...)
      _ESTREAM_GCC_A_PRINTF(1,2);
 int _gpgrt_estream_fprintf (FILE *fp, const char *format, ... )
diff --git a/src/estream.c b/src/estream.c
index 72e93e0..3645dfe 100644
--- a/src/estream.c
+++ b/src/estream.c
@@ -2982,12 +2982,13 @@ print_writer (void *outfncarg, const char *buf, size_t buflen)
 /* The core of our printf function.  This is called in locked state. */
 static int
 do_print_stream (estream_t _GPGRT__RESTRICT stream,
+                 gpgrt_string_filter_t sf, void *sfvalue,
                  const char *_GPGRT__RESTRICT format, va_list ap)
 {
   int rc;
 
   stream->intern->print_ntotal = 0;
-  rc = _gpgrt_estream_format (print_writer, stream, format, ap);
+  rc = _gpgrt_estream_format (print_writer, stream, sf, sfvalue, format, ap);
   if (rc)
     return -1;
   return (int)stream->intern->print_ntotal;
@@ -4444,22 +4445,24 @@ _gpgrt_read_line (estream_t stream,
 
 int
 _gpgrt_vfprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
+                          gpgrt_string_filter_t sf, void *sfvalue,
                           const char *_GPGRT__RESTRICT format,
                           va_list ap)
 {
-  return do_print_stream (stream, format, ap);
+  return do_print_stream (stream, sf, sfvalue, format, ap);
 }
 
 
 int
 _gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream,
+                 gpgrt_string_filter_t sf, void *sfvalue,
                  const char *_GPGRT__RESTRICT format,
                  va_list ap)
 {
   int ret;
 
   lock_stream (stream);
-  ret = do_print_stream (stream, format, ap);
+  ret = do_print_stream (stream, sf, sfvalue, format, ap);
   unlock_stream (stream);
 
   return ret;
@@ -4474,7 +4477,7 @@ _gpgrt_fprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
 
   va_list ap;
   va_start (ap, format);
-  ret = do_print_stream (stream, format, ap);
+  ret = do_print_stream (stream, NULL, NULL, format, ap);
   va_end (ap);
 
   return ret;
@@ -4490,7 +4493,7 @@ _gpgrt_fprintf (estream_t _GPGRT__RESTRICT stream,
   va_list ap;
   va_start (ap, format);
   lock_stream (stream);
-  ret = do_print_stream (stream, format, ap);
+  ret = do_print_stream (stream, NULL, NULL, format, ap);
   unlock_stream (stream);
   va_end (ap);
 
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index 9b522ea..f03a7e3 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -221,5 +221,8 @@ EXPORTS
  gpgrt_cmp_version            @169
 
  gpgrt_ftruncate              @170
+ gpgrt_fprintf_sf             @171
+ gpgrt_fprintf_sf_unlocked    @172
+
 
 ;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index c0ac0eb..cb32c48 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -644,6 +644,11 @@ typedef struct _gpgrt_poll_s gpgrt_poll_t;
 typedef struct _gpgrt_poll_s es_poll_t;
 #endif
 
+/* The type of the string filter function as used by fprintf_sf et al.  */
+typedef char *(*gpgrt_string_filter_t) (const char *s, int n, void *opaque);
+
+
+
 gpgrt_stream_t gpgrt_fopen (const char *_GPGRT__RESTRICT path,
                             const char *_GPGRT__RESTRICT mode);
 gpgrt_stream_t gpgrt_mopen (void *_GPGRT__RESTRICT data,
@@ -783,6 +788,15 @@ int gpgrt_fprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream,
                             const char *_GPGRT__RESTRICT format, ...)
                             GPGRT_ATTR_PRINTF(2,3);
 
+int gpgrt_fprintf_sf (gpgrt_stream_t _GPGRT__RESTRICT stream,
+                      gpgrt_string_filter_t sf, void *sfvalue,
+                      const char *_GPGRT__RESTRICT format,
+                      ...) GPGRT_ATTR_PRINTF(4,5);
+int gpgrt_fprintf_sf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream,
+                               gpgrt_string_filter_t sf, void *sfvalue,
+                               const char *_GPGRT__RESTRICT format,
+                               ...) GPGRT_ATTR_PRINTF(4,5);
+
 int gpgrt_printf (const char *_GPGRT__RESTRICT format, ...)
                   GPGRT_ATTR_PRINTF(1,2);
 int gpgrt_printf_unlocked (const char *_GPGRT__RESTRICT format, ...)
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index f9524d7..105e3bb 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -193,6 +193,9 @@ GPG_ERROR_1.0 {
     gpgrt_cmp_version;
 
     gpgrt_ftruncate;
+    gpgrt_fprintf_sf;
+    gpgrt_fprintf_sf_unlocked;
+
   local:
     *;
 };
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index 09aad11..e326400 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -435,11 +435,13 @@ int _gpgrt_fprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream,
                              GPGRT_ATTR_PRINTF(2,3);
 
 int _gpgrt_vfprintf (gpgrt_stream_t _GPGRT__RESTRICT stream,
+                     gpgrt_string_filter_t sf, void *sfvalue,
                      const char *_GPGRT__RESTRICT format, va_list ap)
-                     GPGRT_ATTR_PRINTF(2,0);
+                     GPGRT_ATTR_PRINTF(4,0);
 int _gpgrt_vfprintf_unlocked (gpgrt_stream_t _GPGRT__RESTRICT stream,
+                              gpgrt_string_filter_t sf, void *sfvalue,
                               const char *_GPGRT__RESTRICT format, va_list ap)
-                              GPGRT_ATTR_PRINTF(2,0);
+                              GPGRT_ATTR_PRINTF(4,0);
 
 int _gpgrt_setvbuf (gpgrt_stream_t _GPGRT__RESTRICT stream,
                     char *_GPGRT__RESTRICT buf, int mode, size_t size);
diff --git a/src/logging.c b/src/logging.c
index d01f974..51e1362 100644
--- a/src/logging.c
+++ b/src/logging.c
@@ -839,7 +839,7 @@ _gpgrt_logv_internal (int level, int ignore_arg_ptr, const char *extrastring,
         }
       else
         {
-          rc = _gpgrt_vfprintf_unlocked (logstream, fmt, arg_ptr);
+          rc = _gpgrt_vfprintf_unlocked (logstream, NULL, NULL, fmt, arg_ptr);
           if (rc > 0)
             length += rc;
         }
diff --git a/src/visibility.c b/src/visibility.c
index 1947111..573a5a4 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -515,7 +515,7 @@ gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream,
                 const char *_GPGRT__RESTRICT format,
                 va_list ap)
 {
-  return _gpgrt_vfprintf (stream, format, ap);
+  return _gpgrt_vfprintf (stream, NULL, NULL, format, ap);
 }
 
 int
@@ -523,7 +523,7 @@ gpgrt_vfprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
                           const char *_GPGRT__RESTRICT format,
                           va_list ap)
 {
-  return _gpgrt_vfprintf_unlocked (stream, format, ap);
+  return _gpgrt_vfprintf_unlocked (stream, NULL, NULL, format, ap);
 }
 
 int
@@ -533,7 +533,7 @@ gpgrt_printf (const char *_GPGRT__RESTRICT format, ...)
   int rc;
 
   va_start (ap, format);
-  rc = _gpgrt_vfprintf (es_stdout, format, ap);
+  rc = _gpgrt_vfprintf (es_stdout, NULL, NULL, format, ap);
   va_end (ap);
 
   return rc;
@@ -546,7 +546,7 @@ gpgrt_printf_unlocked (const char *_GPGRT__RESTRICT format, ...)
   int rc;
 
   va_start (ap, format);
-  rc = _gpgrt_vfprintf_unlocked (es_stdout, format, ap);
+  rc = _gpgrt_vfprintf_unlocked (es_stdout, NULL, NULL, format, ap);
   va_end (ap);
 
   return rc;
@@ -560,7 +560,7 @@ gpgrt_fprintf (estream_t _GPGRT__RESTRICT stream,
   int rc;
 
   va_start (ap, format);
-  rc = _gpgrt_vfprintf (stream, format, ap);
+  rc = _gpgrt_vfprintf (stream, NULL, NULL, format, ap);
   va_end (ap);
 
   return rc;
@@ -574,7 +574,37 @@ gpgrt_fprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
   int rc;
 
   va_start (ap, format);
-  rc = _gpgrt_vfprintf_unlocked (stream, format, ap);
+  rc = _gpgrt_vfprintf_unlocked (stream, NULL, NULL, format, ap);
+  va_end (ap);
+
+  return rc;
+}
+
+int
+gpgrt_fprintf_sf (estream_t _GPGRT__RESTRICT stream,
+                  gpgrt_string_filter_t sf, void *sfvalue,
+                  const char *_GPGRT__RESTRICT format, ...)
+{
+  va_list ap;
+  int rc;
+
+  va_start (ap, format);
+  rc = _gpgrt_vfprintf (stream, sf, sfvalue, format, ap);
+  va_end (ap);
+
+  return rc;
+}
+
+int
+gpgrt_fprintf_sf_unlocked (estream_t _GPGRT__RESTRICT stream,
+                           gpgrt_string_filter_t sf, void *sfvalue,
+                           const char *_GPGRT__RESTRICT format, ...)
+{
+  va_list ap;
+  int rc;
+
+  va_start (ap, format);
+  rc = _gpgrt_vfprintf_unlocked (stream, sf, sfvalue, format, ap);
   va_end (ap);
 
   return rc;
diff --git a/src/visibility.h b/src/visibility.h
index 46383c7..2dde522 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -121,6 +121,8 @@ MARK_VISIBLE (gpgrt_getline)
 MARK_VISIBLE (gpgrt_read_line)
 MARK_VISIBLE (gpgrt_fprintf)
 MARK_VISIBLE (gpgrt_fprintf_unlocked)
+MARK_VISIBLE (gpgrt_fprintf_sf)
+MARK_VISIBLE (gpgrt_fprintf_sf_unlocked)
 MARK_VISIBLE (gpgrt_printf)
 MARK_VISIBLE (gpgrt_printf_unlocked)
 MARK_VISIBLE (gpgrt_vfprintf)
@@ -296,6 +298,8 @@ MARK_VISIBLE (gpgrt_cmp_version);
 #define gpgrt_read_line             _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_fprintf               _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_fprintf_unlocked      _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_fprintf_sf            _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_fprintf_sf_unlocked   _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_printf                _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_printf_unlocked       _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_vfprintf              _gpgrt_USE_UNDERSCORED_FUNCTION
diff --git a/tests/t-printf.c b/tests/t-printf.c
index 7fba012..1e4d393 100644
--- a/tests/t-printf.c
+++ b/tests/t-printf.c
@@ -40,6 +40,49 @@
 static char *one_test_buf1;
 static int   one_test_rc1;
 
+
+
+
+/* Read all data from STREAM into a new malloced buffer and return
+ * that buffer.  The buffer is always 0 terminated.  Either returns a
+ * string or dies.  The stream will be trunctaed to zero. */
+static char *
+stream_to_string (gpgrt_stream_t stream)
+{
+#define NCHUNK 1024
+  char *buffer;
+  size_t bufsize, buflen;
+  size_t nread;
+
+  gpgrt_rewind (stream);
+
+  buffer = NULL;
+  buflen = bufsize = 0;
+  do
+    {
+      bufsize += NCHUNK;
+      buffer = realloc (buffer, bufsize+1);
+      if (!buffer)
+        die ("malloc failed at line %d\n", __LINE__);
+
+      nread = gpgrt_fread (buffer + buflen, 1, NCHUNK, stream);
+      if (nread < NCHUNK && gpgrt_ferror (stream))
+        die ("fread failed at line %d: %s\n", __LINE__, strerror (errno));
+      buflen += nread;
+    }
+  while (nread == NCHUNK);
+  buffer[nread] = 0;
+
+  if (strlen (buffer) != buflen)
+    fail ("stream_to_string detected an embedded nul");
+
+  gpgrt_ftruncate (stream, 0);
+  return buffer;
+#undef NCHUNK
+}
+
+
+
 static void
 one_test_x0 (const char *format, ...)
 {
@@ -375,6 +418,74 @@ check_snprintf (void)
 }
 
 
+struct sfstate_s
+{
+  char *last_result;
+};
+
+static char *
+string_filter (const char *string, int no, void *opaque)
+{
+  struct sfstate_s *state = opaque;
+
+  free (state->last_result);
+  if (no == -1)
+    {
+      state->last_result = NULL;
+      return NULL;
+    }
+  if (no == 3)
+    state->last_result = NULL;
+  else
+    state->last_result = strdup (string? string : "[==>Niente<==]");
+
+  return state->last_result;
+}
+
+
+static void
+check_fprintf_sf (void)
+{
+  volatile char *nullptr = NULL; /* Avoid compiler warning.  */
+  struct sfstate_s sfstate = {NULL};
+  gpgrt_stream_t stream;
+  const char *expect;
+  char *result;
+
+  stream = gpgrt_fopenmem (0, "w+b");
+  if (!stream)
+    die ("fopenmem failed at line %d\n", __LINE__);
+
+  gpgrt_fprintf_sf (stream, string_filter, &sfstate,
+                    "%s a=%d b=%s c=%d d=%.8s null=%s\n",
+                    nullptr, 1, "foo\x01 bar", 2,
+                    "a longer string", nullptr);
+  expect = "[==>Niente<==] a=1 b=foo\x01 bar c=2 d=a longer null=(null)\n";
+  result = stream_to_string (stream);
+  if (strcmp (result, expect))
+    {
+      show ("expect: '%s'\n", expect);
+      show ("result: '%s'\n", result);
+      fail ("fprintf_sf failed at %d\n", __LINE__);
+    }
+  free (result);
+
+  gpgrt_fprintf_sf (stream, string_filter, &sfstate,
+                    "a=%d b=%s c=%d d=%.8s e=%s\n",
+                    1, "foo\n bar", 2, nullptr, "");
+  expect = "a=1 b=foo\n bar c=2 d=[==>Nien e=\n";
+  result = stream_to_string (stream);
+  if (strcmp (result, expect))
+    {
+      show ("expect: '%s'\n", expect);
+      show ("result: '%s'\n", result);
+      fail ("fprintf_sf failed at %d\n", __LINE__);
+    }
+  free (result);
+
+  gpgrt_fclose (stream);
+}
+
 
 int
 main (int argc, char **argv)
@@ -420,6 +531,7 @@ main (int argc, char **argv)
 
   run_tests ();
   check_snprintf ();
+  check_fprintf_sf ();
 
 #ifdef __GLIBC__
   return !!errorcount;

commit ffb49b72f132d954a3d9fa11e45803c36a62fd25
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Nov 26 20:06:36 2018 +0100

    core: Add a limited version of gpgrt_ftruncate.
    
    * src/gpg-error.h.in (gpgrt_ftruncate, es_ftruncate): New.
    * src/gpg-error.def.in, src/gpg-error.vers: Add gpgrt_ftruncate.
    * src/visibility.c (gpgrt_ftruncate): new.
    * src/gpgrt-int.h (COOKIE_IOCTL_TRUNCATE): New.
    * src/estream.c (func_mem_ioctl): Support new internal IOCTL.
    (_gpgrt_ftruncate): New.
    --
    
    Right now the ftruncate works only on memory streams.  Can easily be
    added to other stream times.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/src/estream.c b/src/estream.c
index 8ad664e..72e93e0 100644
--- a/src/estream.c
+++ b/src/estream.c
@@ -820,6 +820,14 @@ func_mem_ioctl (void *cookie, int cmd, void *ptr, size_t *len)
       mem_cookie->offset = 0;
       ret = 0;
     }
+  else if (cmd == COOKIE_IOCTL_TRUNCATE)
+    {
+      gpgrt_off_t length = *(gpgrt_off_t *)ptr;
+
+      ret = func_mem_seek (cookie, &length, SEEK_SET);
+      if (ret != -1)
+        mem_cookie->data_len = mem_cookie->offset;
+    }
   else
     {
       _set_errno (EINVAL);
@@ -4027,6 +4035,29 @@ _gpgrt_rewind (estream_t stream)
 
 
 int
+_gpgrt_ftruncate (estream_t stream, gpgrt_off_t length)
+{
+  cookie_ioctl_function_t func_ioctl;
+  int ret;
+
+  lock_stream (stream);
+  func_ioctl = stream->intern->func_ioctl;
+  if (!func_ioctl)
+    {
+      _set_errno (EOPNOTSUPP);
+      ret = -1;
+    }
+  else
+    {
+      ret = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_TRUNCATE,
+                        &length, NULL);
+    }
+  unlock_stream (stream);
+  return ret;
+}
+
+
+int
 _gpgrt__getc_underflow (estream_t stream)
 {
   int err;
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index c2fabb0..9b522ea 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -220,5 +220,6 @@ EXPORTS
 
  gpgrt_cmp_version            @169
 
+ gpgrt_ftruncate              @170
 
 ;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index 2bf6a6f..c0ac0eb 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -712,6 +712,7 @@ int _gpgrt_pending_unlocked (gpgrt_stream_t stream); /* (private) */
 int gpgrt_fflush (gpgrt_stream_t stream);
 int gpgrt_fseek (gpgrt_stream_t stream, long int offset, int whence);
 int gpgrt_fseeko (gpgrt_stream_t stream, gpgrt_off_t offset, int whence);
+int gpgrt_ftruncate (estream_t stream, gpgrt_off_t length);
 long int gpgrt_ftell (gpgrt_stream_t stream);
 gpgrt_off_t gpgrt_ftello (gpgrt_stream_t stream);
 void gpgrt_rewind (gpgrt_stream_t stream);
@@ -868,6 +869,7 @@ int gpgrt_vsnprintf (char *buf,size_t bufsize,
 # define es_fflush            gpgrt_fflush
 # define es_fseek             gpgrt_fseek
 # define es_fseeko            gpgrt_fseeko
+# define es_ftruncate         gpgrt_ftruncate
 # define es_ftell             gpgrt_ftell
 # define es_ftello            gpgrt_ftello
 # define es_rewind            gpgrt_rewind
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 8c50a15..f9524d7 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -192,6 +192,7 @@ GPG_ERROR_1.0 {
 
     gpgrt_cmp_version;
 
+    gpgrt_ftruncate;
   local:
     *;
 };
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index b5a4dd1..09aad11 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -208,12 +208,12 @@ void _gpgrt_internal_trace_end (void);
 
 /*
  * A private cookie function to implement an internal IOCTL service.
- * and ist IOCTL numbers.
  */
 typedef int (*cookie_ioctl_function_t) (void *cookie, int cmd,
 					void *ptr, size_t *len);
 #define COOKIE_IOCTL_SNATCH_BUFFER 1
 #define COOKIE_IOCTL_NONBLOCK      2
+#define COOKIE_IOCTL_TRUNCATE      3
 
 /* An internal variant of gpgrt_cookie_close_function_t with a slot
  * for the ioctl function.  */
@@ -366,6 +366,7 @@ int _gpgrt_fseeko (gpgrt_stream_t stream, gpgrt_off_t offset, int whence);
 long int _gpgrt_ftell (gpgrt_stream_t stream);
 gpgrt_off_t _gpgrt_ftello (gpgrt_stream_t stream);
 void _gpgrt_rewind (gpgrt_stream_t stream);
+int  _gpgrt_ftruncate (estream_t stream, gpgrt_off_t length);
 
 int _gpgrt_fgetc (gpgrt_stream_t stream);
 int _gpgrt_fputc (int c, gpgrt_stream_t stream);
diff --git a/src/visibility.c b/src/visibility.c
index ab5e383..1947111 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -390,6 +390,12 @@ gpgrt_rewind (estream_t stream)
 }
 
 int
+gpgrt_ftruncate (estream_t stream, gpgrt_off_t length)
+{
+  return _gpgrt_ftruncate (stream, length);
+}
+
+int
 gpgrt_fgetc (estream_t stream)
 {
   return _gpgrt_fgetc (stream);
diff --git a/src/visibility.h b/src/visibility.h
index d6933df..46383c7 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -102,6 +102,7 @@ MARK_VISIBLE (gpgrt_fseeko)
 MARK_VISIBLE (gpgrt_ftell)
 MARK_VISIBLE (gpgrt_ftello)
 MARK_VISIBLE (gpgrt_rewind)
+MARK_VISIBLE (gpgrt_ftruncate)
 MARK_VISIBLE (gpgrt_fgetc)
 MARK_VISIBLE (_gpgrt_getc_underflow)
 MARK_VISIBLE (gpgrt_fputc)
@@ -276,6 +277,7 @@ MARK_VISIBLE (gpgrt_cmp_version);
 #define gpgrt_ftell                 _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_ftello                _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_rewind                _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_ftruncate             _gpgrt_USE_UNDERSCORED_FUNCTION
 #define gpgrt_fgetc                 _gpgrt_USE_UNDERSCORED_FUNCTION
 #define _gpgrt_getc_underflow       _gpgrt_USE_DBLUNDERSCO_FUNCTION
 #define gpgrt_fputc                 _gpgrt_USE_UNDERSCORED_FUNCTION
diff --git a/tests/t-version.c b/tests/t-version.c
index 240d4b4..d71f360 100644
--- a/tests/t-version.c
+++ b/tests/t-version.c
@@ -164,6 +164,7 @@ main (int argc, char **argv)
       fprintf (stderr, "%s: gpg_error_check_version did not return an error"
                " for a newer version\n", logpfx);
       errorcount++;
+      show ("\n"); /* Reference this function to silence gcc. */
     }
   if (verbose || errorcount)
     {

-----------------------------------------------------------------------

Summary of changes:
 NEWS                 |   4 ++
 src/estream-printf.c |  67 +++++++++++++++++++++---------
 src/estream-printf.h |   4 +-
 src/estream.c        |  44 +++++++++++++++++---
 src/gpg-error.def.in |   4 ++
 src/gpg-error.h.in   |  16 ++++++++
 src/gpg-error.vers   |   4 ++
 src/gpgrt-int.h      |   9 +++--
 src/logging.c        |   2 +-
 src/visibility.c     |  48 +++++++++++++++++++---
 src/visibility.h     |   6 +++
 tests/t-printf.c     | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/t-version.c    |   1 +
 13 files changed, 285 insertions(+), 36 deletions(-)


hooks/post-receive
-- 
Error codes used by GnuPG et al.
http://git.gnupg.org




More information about the Gnupg-commits mailing list