1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

Escape double quotes and backslashes in external metadata and config data.

Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
This commit is contained in:
Alasdair Kergon 2008-03-12 16:03:22 +00:00
parent bcacf9d0e3
commit d4ce89d9da
6 changed files with 155 additions and 25 deletions

View File

@ -1,5 +1,8 @@
Version 2.02.34 - Version 2.02.34 -
=================================== ===================================
Escape double quotes and backslashes in external metadata and config data.
Add functions for escaping double quotes in strings.
Rename count_chars_len to count_chars.
Use return_0 in a couple more places. Use return_0 in a couple more places.
Correct a function name typo in _line_append error message. Correct a function name typo in _line_append error message.
Include limits.h in clvmd so it compiles with newer headers. Include limits.h in clvmd so it compiles with newer headers.

View File

@ -34,7 +34,8 @@
enum { enum {
TOK_INT, TOK_INT,
TOK_FLOAT, TOK_FLOAT,
TOK_STRING, TOK_STRING, /* Single quotes */
TOK_STRING_ESCAPED, /* Double quotes */
TOK_EQ, TOK_EQ,
TOK_SECTION_B, TOK_SECTION_B,
TOK_SECTION_E, TOK_SECTION_E,
@ -401,9 +402,16 @@ static int _line_end(struct output_line *outline)
static int _write_value(struct output_line *outline, struct config_value *v) static int _write_value(struct output_line *outline, struct config_value *v)
{ {
char *buf;
switch (v->type) { switch (v->type) {
case CFG_STRING: case CFG_STRING:
line_append("\"%s\"", v->v.str); if (!(buf = alloca(escaped_len(v->v.str)))) {
log_error("temporary stack allocation for a config "
"string failed");
return 0;
}
line_append("\"%s\"", escape_double_quotes(buf, v->v.str));
break; break;
case CFG_FLOAT: case CFG_FLOAT:
@ -644,6 +652,17 @@ static struct config_value *_type(struct parser *p)
match(TOK_STRING); match(TOK_STRING);
break; break;
case TOK_STRING_ESCAPED:
v->type = CFG_STRING;
p->tb++, p->te--; /* strip "'s */
if (!(v->v.str = _dup_tok(p)))
return_0;
unescape_double_quotes(v->v.str);
p->te++;
match(TOK_STRING_ESCAPED);
break;
default: default:
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value", log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
p->tb - p->fb + 1, p->line); p->tb - p->fb + 1, p->line);
@ -714,7 +733,7 @@ static void _get_token(struct parser *p, int tok_prev)
break; break;
case '"': case '"':
p->t = TOK_STRING; p->t = TOK_STRING_ESCAPED;
p->te++; p->te++;
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) { while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
if ((*p->te == '\\') && (p->te + 1 != p->fe) && if ((*p->te == '\\') && (p->te + 1 != p->fe) &&
@ -1232,7 +1251,7 @@ static unsigned _count_tokens(const char *str, unsigned len, int type)
c = _token_type_to_char(type); c = _token_type_to_char(type);
return count_chars_len(str, len, c); return count_chars(str, len, c);
} }
/* /*

View File

@ -18,6 +18,7 @@
#include "dev-cache.h" #include "dev-cache.h"
#include "filter-persistent.h" #include "filter-persistent.h"
#include "lvm-file.h" #include "lvm-file.h"
#include "lvm-string.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -142,6 +143,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
{ {
void *d; void *d;
int first = 1; int first = 1;
char *buf, *str;
struct dm_hash_node *n; struct dm_hash_node *n;
for (n = dm_hash_get_first(pf->devices); n; for (n = dm_hash_get_first(pf->devices); n;
@ -158,7 +160,13 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
first = 0; first = 0;
} }
fprintf(fp, "\t\t\"%s\"", dm_hash_get_key(pf->devices, n)); str = dm_hash_get_key(pf->devices, n);
if (!(buf = alloca(escaped_len(str)))) {
log_error("persistent filter device path stack "
"allocation failed");
return;
}
fprintf(fp, "\t\t\"%s\"", escape_double_quotes(buf, str));
} }
if (!first) if (!first)

View File

@ -296,6 +296,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
static int _print_header(struct formatter *f, static int _print_header(struct formatter *f,
const char *desc) const char *desc)
{ {
char *buf;
time_t t; time_t t;
t = time(NULL); t = time(NULL);
@ -305,7 +306,12 @@ static int _print_header(struct formatter *f,
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE); outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
outnl(f); outnl(f);
outf(f, "description = \"%s\"", desc); if (!(buf = alloca(escaped_len(desc)))) {
log_error("temporary stack allocation for description"
"string failed");
return 0;
}
outf(f, "description = \"%s\"", escape_double_quotes(buf, desc));
outnl(f); outnl(f);
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename, outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_utsname.sysname, _utsname.nodename, _utsname.release, _utsname.sysname, _utsname.nodename, _utsname.release,
@ -370,6 +376,7 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
struct pv_list *pvl; struct pv_list *pvl;
struct physical_volume *pv; struct physical_volume *pv;
char buffer[4096]; char buffer[4096];
char *buf;
const char *name; const char *name;
outf(f, "physical_volumes {"); outf(f, "physical_volumes {");
@ -389,7 +396,15 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
return_0; return_0;
outf(f, "id = \"%s\"", buffer); outf(f, "id = \"%s\"", buffer);
if (!out_hint(f, "device = \"%s\"", pv_dev_name(pv)))
if (!(buf = alloca(escaped_len(pv_dev_name(pv))))) {
log_error("temporary stack allocation for device name"
"string failed");
return 0;
}
if (!out_hint(f, "device = \"%s\"",
escape_double_quotes(buf, pv_dev_name(pv))))
return_0; return_0;
outnl(f); outnl(f);

View File

@ -39,16 +39,16 @@ int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
* Count occurences of 'c' in 'str' until we reach a null char. * Count occurences of 'c' in 'str' until we reach a null char.
* *
* Returns: * Returns:
* len - incremented for each char we encounter, whether 'c' or not. * len - incremented for each char we encounter.
* count - number of occurrences of 'c' * count - number of occurrences of 'c' and 'c2'.
*/ */
void count_chars(const char *str, size_t *len, int *count, static void _count_chars(const char *str, size_t *len, int *count,
const int c) const int c1, const int c2)
{ {
const char *ptr; const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++) for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == c) if (*ptr == c1 || *ptr == c2)
(*count)++; (*count)++;
} }
@ -58,7 +58,7 @@ void count_chars(const char *str, size_t *len, int *count,
* Returns: * Returns:
* Number of occurrences of 'c' * Number of occurrences of 'c'
*/ */
unsigned count_chars_len(const char *str, size_t len, const int c) unsigned count_chars(const char *str, size_t len, const int c)
{ {
size_t i; size_t i;
unsigned count = 0; unsigned count = 0;
@ -70,17 +70,62 @@ unsigned count_chars_len(const char *str, size_t len, const int c)
return count; return count;
} }
/*
* Length of string after escaping double quotes and backslashes.
*/
size_t escaped_len(const char *str)
{
size_t len = 1;
int count = 0;
_count_chars(str, &len, &count, '\"', '\\');
return count + len;
}
/*
* Copies a string, quoting orig_char with quote_char.
* Optionally also quote quote_char.
*/
static void _quote_characters(char **out, const char *src,
const int orig_char, const int quote_char,
int quote_quote_char)
{
while (*src) {
if (*src == orig_char ||
(*src == quote_char && quote_quote_char))
*(*out)++ = quote_char;
*(*out)++ = *src++;
}
}
/*
* Unquote orig_char in string.
* Also unquote quote_char.
*/
static void _unquote_characters(char *src, const int orig_char,
const int quote_char)
{
char *out = src;
while (*src) {
if (*src == quote_char &&
(*(src + 1) == orig_char || *(src + 1) == quote_char))
src++;
*out++ = *src++;
}
*out = '\0';
}
/* /*
* Copies a string, quoting hyphens with hyphens. * Copies a string, quoting hyphens with hyphens.
*/ */
static void _quote_hyphens(char **out, const char *src) static void _quote_hyphens(char **out, const char *src)
{ {
while (*src) { return _quote_characters(out, src, '-', '-', 0);
if (*src == '-')
*(*out)++ = '-';
*(*out)++ = *src++;
}
} }
/* /*
@ -93,11 +138,11 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
int hyphens = 1; int hyphens = 1;
char *r, *out; char *r, *out;
count_chars(vgname, &len, &hyphens, '-'); _count_chars(vgname, &len, &hyphens, '-', 0);
count_chars(lvname, &len, &hyphens, '-'); _count_chars(lvname, &len, &hyphens, '-', 0);
if (layer && *layer) { if (layer && *layer) {
count_chars(layer, &len, &hyphens, '-'); _count_chars(layer, &len, &hyphens, '-', 0);
hyphens++; hyphens++;
} }
@ -125,6 +170,27 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
return r; return r;
} }
/*
* Copies a string, quoting double quotes with backslashes.
*/
char *escape_double_quotes(char *out, const char *src)
{
char *buf = out;
_quote_characters(&buf, src, '\"', '\\', 1);
*buf = '\0';
return out;
}
/*
* Undo quoting in situ.
*/
void unescape_double_quotes(char *src)
{
_unquote_characters(src, '\"', '\\');
}
/* /*
* Device layer names are all of the form <vg>-<lv>-<layer>, any * Device layer names are all of the form <vg>-<lv>-<layer>, any
* other hyphens that appear in these names are quoted with yet * other hyphens that appear in these names are quoted with yet

View File

@ -31,8 +31,27 @@ char *build_dm_name(struct dm_pool *mem, const char *vg,
int validate_name(const char *n); int validate_name(const char *n);
void count_chars(const char *str, size_t *len, int *count, /*
const int c); * Returns number of occurrences of c in first len characters of str.
unsigned count_chars_len(const char *str, size_t len, const int c); */
unsigned count_chars(const char *str, size_t len, const int c);
/*
* Returns what length of escaped string would be including terminating NUL.
*/
size_t escaped_len(const char *str);
/*
* Copies a string from src to out.
* Double quotation marks and backslashes are quoted with a backslash.
* Caller must ensure *out has enough space - see escaped_len().
* Returns *out.
*/
char *escape_double_quotes(char *out, const char *src);
/*
* Removes quoting of double quotation marks and backslashes in situ.
*/
void unescape_double_quotes(char *src);
#endif #endif