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:
parent
bcacf9d0e3
commit
d4ce89d9da
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user