1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +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 -
===================================
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.
Correct a function name typo in _line_append error message.
Include limits.h in clvmd so it compiles with newer headers.

View File

@ -34,7 +34,8 @@
enum {
TOK_INT,
TOK_FLOAT,
TOK_STRING,
TOK_STRING, /* Single quotes */
TOK_STRING_ESCAPED, /* Double quotes */
TOK_EQ,
TOK_SECTION_B,
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)
{
char *buf;
switch (v->type) {
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;
case CFG_FLOAT:
@ -644,6 +652,17 @@ static struct config_value *_type(struct parser *p)
match(TOK_STRING);
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:
log_error("Parse error at byte %" PRIptrdiff_t " (line %d): expected a value",
p->tb - p->fb + 1, p->line);
@ -714,7 +733,7 @@ static void _get_token(struct parser *p, int tok_prev)
break;
case '"':
p->t = TOK_STRING;
p->t = TOK_STRING_ESCAPED;
p->te++;
while ((p->te != p->fe) && (*p->te) && (*p->te != '"')) {
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);
return count_chars_len(str, len, c);
return count_chars(str, len, c);
}
/*

View File

@ -18,6 +18,7 @@
#include "dev-cache.h"
#include "filter-persistent.h"
#include "lvm-file.h"
#include "lvm-string.h"
#include <sys/stat.h>
#include <fcntl.h>
@ -142,6 +143,7 @@ static void _write_array(struct pfilter *pf, FILE *fp, const char *path,
{
void *d;
int first = 1;
char *buf, *str;
struct dm_hash_node *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;
}
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)

View File

@ -296,6 +296,7 @@ int out_text(struct formatter *f, const char *fmt, ...)
static int _print_header(struct formatter *f,
const char *desc)
{
char *buf;
time_t t;
t = time(NULL);
@ -305,7 +306,12 @@ static int _print_header(struct formatter *f,
outf(f, FORMAT_VERSION_FIELD " = %d", FORMAT_VERSION_VALUE);
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);
outf(f, "creation_host = \"%s\"\t# %s %s %s %s %s", _utsname.nodename,
_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 physical_volume *pv;
char buffer[4096];
char *buf;
const char *name;
outf(f, "physical_volumes {");
@ -389,7 +396,15 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
return_0;
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;
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.
*
* Returns:
* len - incremented for each char we encounter, whether 'c' or not.
* count - number of occurrences of 'c'
* len - incremented for each char we encounter.
* count - number of occurrences of 'c' and 'c2'.
*/
void count_chars(const char *str, size_t *len, int *count,
const int c)
static void _count_chars(const char *str, size_t *len, int *count,
const int c1, const int c2)
{
const char *ptr;
for (ptr = str; *ptr; ptr++, (*len)++)
if (*ptr == c)
if (*ptr == c1 || *ptr == c2)
(*count)++;
}
@ -58,7 +58,7 @@ void count_chars(const char *str, size_t *len, int *count,
* Returns:
* 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;
unsigned count = 0;
@ -70,17 +70,62 @@ unsigned count_chars_len(const char *str, size_t len, const int c)
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.
*/
static void _quote_hyphens(char **out, const char *src)
{
while (*src) {
if (*src == '-')
*(*out)++ = '-';
*(*out)++ = *src++;
}
return _quote_characters(out, src, '-', '-', 0);
}
/*
@ -93,11 +138,11 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
int hyphens = 1;
char *r, *out;
count_chars(vgname, &len, &hyphens, '-');
count_chars(lvname, &len, &hyphens, '-');
_count_chars(vgname, &len, &hyphens, '-', 0);
_count_chars(lvname, &len, &hyphens, '-', 0);
if (layer && *layer) {
count_chars(layer, &len, &hyphens, '-');
_count_chars(layer, &len, &hyphens, '-', 0);
hyphens++;
}
@ -125,6 +170,27 @@ char *build_dm_name(struct dm_pool *mem, const char *vgname,
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
* 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);
void count_chars(const char *str, size_t *len, int *count,
const int c);
unsigned count_chars_len(const char *str, size_t len, const int c);
/*
* Returns number of occurrences of c in first len characters of str.
*/
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