[Libguestfs] [PATCH nbdkit v3 3/6] common/utils: Add C string quoting function

Eric Blake eblake at redhat.com
Tue May 9 18:18:13 UTC 2023


On Tue, May 09, 2023 at 03:51:18PM +0100, Richard W.M. Jones wrote:
> eg. { '\r', '\n' } -> { '\\', 'n', '\\', 'r' }
> ---
>  common/utils/utils.h |  1 +
>  common/utils/quote.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 59 insertions(+)
> 

> +
> +/* Print str to fp, quoting in a way similar to C strings, for example
> + * '\n' -> "\n".
> + *
> + * Note that we do not emit quotes around the string, and double
> + * quotes within the string are not escaped.
> + */
> +void
> +c_string_quote (const char *str, FILE *fp)
> +{
> +  size_t i;
> +  char c;
> +
> +  for (i = 0; c = str[i], c != '\0'; ++i) {
> +    if (ascii_isprint (c))
> +      fputc (c, fp);

ascii_isprint('\\') returns true, which means you output just one
backslash; but that's one where you really want to output two.
Otherwise, you can't tell the difference on the output from the
C-string input of one-byte "\a" vs. two-byte "\\a".  :(

> +    else {
> +      switch (c) {
...
> +      default:
> +        fputc ('\\', fp);
> +        fputc ('x', fp);
> +        fputc (hexchar (c >> 4), fp);
> +        fputc (hexchar (c), fp);
> +      }

You mentioned in the commit message that not escaping " is
intentional; and I can live with that for this patch.  But if we need
to add it in the future, it will be easier to rejigger the loop as
(abbreviated, but you get the idea):

for (i = 0; c = str[i], c != '\0'; ++i) {
  switch (c) {
  case '\\': fputc ('\\'); fputc ('\\'); break;
  case '\a': fputc ('\\'); fputc ('a'); break;
  ...
  default:
    if (isprint (c)
      fputc (c);
    else {
      // output \xXX
    }
  }
}

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


More information about the Libguestfs mailing list