Richard W.M. Jones
2023-May-09 14:51 UTC
[Libguestfs] [PATCH nbdkit v3 3/6] common/utils: Add C string quoting function
eg. { '\r', '\n' } -> { '\\', 'n', '\\', 'r' } --- common/utils/utils.h | 1 + common/utils/quote.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/common/utils/utils.h b/common/utils/utils.h index 42288a5cd..1e6d8972b 100644 --- a/common/utils/utils.h +++ b/common/utils/utils.h @@ -35,6 +35,7 @@ extern void shell_quote (const char *str, FILE *fp); extern void uri_quote (const char *str, FILE *fp); +extern void c_string_quote (const char *str, FILE *fp); extern int exit_status_to_nbd_error (int status, const char *cmd); extern int set_cloexec (int fd); extern int set_nonblock (int fd); diff --git a/common/utils/quote.c b/common/utils/quote.c index 863e08a8e..877035387 100644 --- a/common/utils/quote.c +++ b/common/utils/quote.c @@ -37,6 +37,9 @@ #include <string.h> #include <unistd.h> +#include "ascii-ctype.h" +#include "hexdigit.h" + /* Print str to fp, shell quoting if necessary. This comes from * libguestfs, but was written by me so I'm relicensing it to a BSD * license for nbdkit. @@ -98,3 +101,58 @@ uri_quote (const char *str, FILE *fp) fprintf (fp, "%%%02X", str[i] & 0xff); } } + +/* 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); + else { + switch (c) { + case '\a': + fputc ('\\', fp); + fputc ('a', fp); + break; + case '\b': + fputc ('\\', fp); + fputc ('b', fp); + break; + case '\f': + fputc ('\\', fp); + fputc ('f', fp); + break; + case '\n': + fputc ('\\', fp); + fputc ('n', fp); + break; + case '\r': + fputc ('\\', fp); + fputc ('r', fp); + break; + case '\t': + fputc ('\\', fp); + fputc ('t', fp); + break; + case '\v': + fputc ('\\', fp); + fputc ('v', fp); + break; + default: + fputc ('\\', fp); + fputc ('x', fp); + fputc (hexchar (c >> 4), fp); + fputc (hexchar (c), fp); + } + } + } +} -- 2.39.2
Eric Blake
2023-May-09 18:18 UTC
[Libguestfs] [PATCH nbdkit v3 3/6] common/utils: Add C string quoting function
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
Laszlo Ersek
2023-May-10 06:40 UTC
[Libguestfs] [PATCH nbdkit v3 3/6] common/utils: Add C string quoting function
On 5/9/23 16:51, 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(+) > > diff --git a/common/utils/utils.h b/common/utils/utils.h > index 42288a5cd..1e6d8972b 100644 > --- a/common/utils/utils.h > +++ b/common/utils/utils.h > @@ -35,6 +35,7 @@ > > extern void shell_quote (const char *str, FILE *fp); > extern void uri_quote (const char *str, FILE *fp); > +extern void c_string_quote (const char *str, FILE *fp); > extern int exit_status_to_nbd_error (int status, const char *cmd); > extern int set_cloexec (int fd); > extern int set_nonblock (int fd); > diff --git a/common/utils/quote.c b/common/utils/quote.c > index 863e08a8e..877035387 100644 > --- a/common/utils/quote.c > +++ b/common/utils/quote.c > @@ -37,6 +37,9 @@ > #include <string.h> > #include <unistd.h> > > +#include "ascii-ctype.h" > +#include "hexdigit.h" > + > /* Print str to fp, shell quoting if necessary. This comes from > * libguestfs, but was written by me so I'm relicensing it to a BSD > * license for nbdkit. > @@ -98,3 +101,58 @@ uri_quote (const char *str, FILE *fp) > fprintf (fp, "%%%02X", str[i] & 0xff); > } > } > + > +/* 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); > + else { > + switch (c) { > + case '\a': > + fputc ('\\', fp); > + fputc ('a', fp); > + break; > + case '\b': > + fputc ('\\', fp); > + fputc ('b', fp); > + break; > + case '\f': > + fputc ('\\', fp); > + fputc ('f', fp); > + break; > + case '\n': > + fputc ('\\', fp); > + fputc ('n', fp); > + break; > + case '\r': > + fputc ('\\', fp); > + fputc ('r', fp); > + break; > + case '\t': > + fputc ('\\', fp); > + fputc ('t', fp); > + break; > + case '\v': > + fputc ('\\', fp); > + fputc ('v', fp); > + break; > + default: > + fputc ('\\', fp); > + fputc ('x', fp); > + fputc (hexchar (c >> 4), fp); > + fputc (hexchar (c), fp); > + } > + } > + } > +}Reviewed-by: Laszlo Ersek <lersek at redhat.com>