mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
dmstats: support group aliases with embedded whitespace
Creating a group with a name that contains whitespace causes an error in the @stats_set_aux message: device-mapper: message ioctl on (253:0) failed: Invalid argument Could not create regions from file /var/tmp/File With Spaces. Fix this by quoting the group alias and backslash escaping any embedded space characters.
This commit is contained in:
parent
33931431c3
commit
7d8981dd3f
@ -136,6 +136,36 @@ struct dm_stats {
|
|||||||
uint64_t cur_area;
|
uint64_t cur_area;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *_stats_escape_aux_data(const char *aux_data)
|
||||||
|
{
|
||||||
|
size_t aux_data_len = strlen(aux_data);
|
||||||
|
char *escaped = dm_malloc((3 * aux_data_len + 1) * sizeof(char));
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
if (!escaped) {
|
||||||
|
log_error("Could not allocate memory for escaped "
|
||||||
|
"aux_data string.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < aux_data_len; i++) {
|
||||||
|
if (aux_data[i] == ' ') {
|
||||||
|
escaped[index++] = '\\';
|
||||||
|
escaped[index++] = ' ';
|
||||||
|
} else if (aux_data[i] == '\\') {
|
||||||
|
escaped[index++] = '\\';
|
||||||
|
escaped[index++] = '\\';
|
||||||
|
} else if (aux_data[i] == '\t') {
|
||||||
|
escaped[index++] = '\\';
|
||||||
|
escaped[index++] = '\t';
|
||||||
|
} else {
|
||||||
|
escaped[index++] = aux_data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escaped[index] = '\0';
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
#define PROC_SELF_COMM "/proc/self/comm"
|
#define PROC_SELF_COMM "/proc/self/comm"
|
||||||
static char *_program_id_from_proc(void)
|
static char *_program_id_from_proc(void)
|
||||||
{
|
{
|
||||||
@ -697,6 +727,8 @@ static void _check_group_regions_present(struct dm_stats *dms,
|
|||||||
#define DMS_GROUP_TAG_LEN (sizeof(DMS_GROUP_TAG) - 1)
|
#define DMS_GROUP_TAG_LEN (sizeof(DMS_GROUP_TAG) - 1)
|
||||||
#define DMS_GROUP_SEP ':'
|
#define DMS_GROUP_SEP ':'
|
||||||
#define DMS_AUX_SEP "#"
|
#define DMS_AUX_SEP "#"
|
||||||
|
#define DMS_AUX_SEP_CHAR '#'
|
||||||
|
#define DMS_GROUP_QUOTE '"'
|
||||||
|
|
||||||
static int _parse_aux_data_group(struct dm_stats *dms,
|
static int _parse_aux_data_group(struct dm_stats *dms,
|
||||||
struct dm_stats_region *region,
|
struct dm_stats_region *region,
|
||||||
@ -713,7 +745,8 @@ static int _parse_aux_data_group(struct dm_stats *dms,
|
|||||||
if (!c)
|
if (!c)
|
||||||
return 1; /* no group is not an error */
|
return 1; /* no group is not an error */
|
||||||
|
|
||||||
alias = c + strlen(DMS_GROUP_TAG);
|
/* extract alias from quotes */
|
||||||
|
alias = c + strlen(DMS_GROUP_TAG) + 1;
|
||||||
|
|
||||||
c = strchr(c, DMS_GROUP_SEP);
|
c = strchr(c, DMS_GROUP_SEP);
|
||||||
|
|
||||||
@ -722,8 +755,9 @@ static int _parse_aux_data_group(struct dm_stats *dms,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate alias and advance to members */
|
/* terminate alias and advance to members accounting for closing quote */
|
||||||
*(c++) = '\0';
|
*(c - 1) = '\0';
|
||||||
|
c++;
|
||||||
|
|
||||||
log_debug("Read alias '%s' from aux_data", alias);
|
log_debug("Read alias '%s' from aux_data", alias);
|
||||||
|
|
||||||
@ -904,7 +938,7 @@ bad:
|
|||||||
static int _stats_parse_string_data(char *string_data, char **program_id,
|
static int _stats_parse_string_data(char *string_data, char **program_id,
|
||||||
char **aux_data, char **stats_args)
|
char **aux_data, char **stats_args)
|
||||||
{
|
{
|
||||||
char *p, *next_space, *empty_string = (char *)"";
|
char *p, *next_gap, *empty_string = (char *)"";
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -927,14 +961,26 @@ static int _stats_parse_string_data(char *string_data, char **program_id,
|
|||||||
*program_id = string_data;
|
*program_id = string_data;
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
next_space = strchr(p, ' ');
|
if (strstr(p, DMS_GROUP_TAG)) {
|
||||||
if (next_space) {
|
|
||||||
*next_space = '\0';
|
|
||||||
*aux_data = p;
|
*aux_data = p;
|
||||||
*stats_args = next_space + 1;
|
/* Skip over the group tag */
|
||||||
|
next_gap = strchr(p, DMS_AUX_SEP_CHAR);
|
||||||
|
next_gap = strchr(next_gap, ' ');
|
||||||
|
if (next_gap) {
|
||||||
|
*(next_gap++) = '\0';
|
||||||
|
*stats_args = next_gap++;
|
||||||
|
} else
|
||||||
|
*stats_args = empty_string;
|
||||||
} else {
|
} else {
|
||||||
*aux_data = p;
|
next_gap = strchr(p, ' ');
|
||||||
*stats_args = empty_string;
|
if (next_gap) {
|
||||||
|
*next_gap = '\0';
|
||||||
|
*aux_data = p;
|
||||||
|
*stats_args = next_gap + 1;
|
||||||
|
} else {
|
||||||
|
*aux_data = p;
|
||||||
|
*stats_args = empty_string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strncmp(*program_id, "-", 1))
|
if (!strncmp(*program_id, "-", 1))
|
||||||
@ -1864,7 +1910,7 @@ static char *_build_group_tag(struct dm_stats *dms, uint64_t group_id)
|
|||||||
return_0;
|
return_0;
|
||||||
|
|
||||||
buflen += DMS_GROUP_TAG_LEN;
|
buflen += DMS_GROUP_TAG_LEN;
|
||||||
buflen += 1 + (alias ? strlen(alias) : 0); /* 'alias:' */
|
buflen += 1 + (alias ? strlen(alias) + 2 : 0); /* 'alias:' */
|
||||||
|
|
||||||
buf = aux_string = dm_malloc(buflen);
|
buf = aux_string = dm_malloc(buflen);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
@ -1878,7 +1924,11 @@ static char *_build_group_tag(struct dm_stats *dms, uint64_t group_id)
|
|||||||
buf += DMS_GROUP_TAG_LEN;
|
buf += DMS_GROUP_TAG_LEN;
|
||||||
buflen -= DMS_GROUP_TAG_LEN;
|
buflen -= DMS_GROUP_TAG_LEN;
|
||||||
|
|
||||||
r = dm_snprintf(buf, buflen, "%s%c", alias ? alias : "", DMS_GROUP_SEP);
|
if (alias)
|
||||||
|
r = dm_snprintf(buf, buflen, "\"%s\"%c", alias, DMS_GROUP_SEP);
|
||||||
|
else
|
||||||
|
r = dm_snprintf(buf, buflen, "%c", DMS_GROUP_SEP);
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto_bad;
|
goto_bad;
|
||||||
|
|
||||||
@ -1907,6 +1957,7 @@ static int _stats_set_aux(struct dm_stats *dms,
|
|||||||
const char *group_tag = NULL;
|
const char *group_tag = NULL;
|
||||||
struct dm_task *dmt = NULL;
|
struct dm_task *dmt = NULL;
|
||||||
char msg[STATS_MSG_BUF_LEN];
|
char msg[STATS_MSG_BUF_LEN];
|
||||||
|
char *group_tag_escaped = NULL;
|
||||||
|
|
||||||
/* group data required? */
|
/* group data required? */
|
||||||
if (_stats_group_id_present(dms, region_id)) {
|
if (_stats_group_id_present(dms, region_id)) {
|
||||||
@ -1916,10 +1967,15 @@ static int _stats_set_aux(struct dm_stats *dms,
|
|||||||
"region ID " FMTu64, region_id);
|
"region ID " FMTu64, region_id);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
group_tag_escaped = _stats_escape_aux_data(group_tag);
|
||||||
|
if (!group_tag_escaped)
|
||||||
|
goto bad;
|
||||||
|
} else
|
||||||
|
group_tag_escaped = dm_strdup("");
|
||||||
|
|
||||||
if (dm_snprintf(msg, sizeof(msg), "@stats_set_aux " FMTu64 " %s%s%s ",
|
if (dm_snprintf(msg, sizeof(msg), "@stats_set_aux " FMTu64 " %s%s%s ",
|
||||||
region_id, (group_tag) ? group_tag : "",
|
region_id, (group_tag_escaped) ? group_tag_escaped : "",
|
||||||
(group_tag) ? DMS_AUX_SEP : "",
|
(group_tag_escaped) ? DMS_AUX_SEP : "",
|
||||||
(strlen(user_data)) ? user_data : "-") < 0) {
|
(strlen(user_data)) ? user_data : "-") < 0) {
|
||||||
log_error("Could not prepare @stats_set_aux message");
|
log_error("Could not prepare @stats_set_aux message");
|
||||||
goto bad;
|
goto bad;
|
||||||
@ -1929,6 +1985,7 @@ static int _stats_set_aux(struct dm_stats *dms,
|
|||||||
goto_bad;
|
goto_bad;
|
||||||
|
|
||||||
dm_free((char *) group_tag);
|
dm_free((char *) group_tag);
|
||||||
|
dm_free(group_tag_escaped);
|
||||||
|
|
||||||
/* no response to a @stats_set_aux message */
|
/* no response to a @stats_set_aux message */
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
@ -1953,6 +2010,7 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
|||||||
const char *err_fmt = "Could not prepare @stats_create %s.";
|
const char *err_fmt = "Could not prepare @stats_create %s.";
|
||||||
const char *precise_str = PRECISE_ARG;
|
const char *precise_str = PRECISE_ARG;
|
||||||
const char *resp, *opt_args = NULL;
|
const char *resp, *opt_args = NULL;
|
||||||
|
char *aux_data_escaped = NULL;
|
||||||
struct dm_task *dmt = NULL;
|
struct dm_task *dmt = NULL;
|
||||||
int r = 0, nr_opt = 0;
|
int r = 0, nr_opt = 0;
|
||||||
|
|
||||||
@ -1983,6 +2041,10 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id,
|
|||||||
else
|
else
|
||||||
hist_arg = "";
|
hist_arg = "";
|
||||||
|
|
||||||
|
aux_data_escaped = _stats_escape_aux_data(aux_data);
|
||||||
|
if (!aux_data_escaped)
|
||||||
|
return_0;
|
||||||
|
|
||||||
if (nr_opt) {
|
if (nr_opt) {
|
||||||
if ((dm_asprintf((char **)&opt_args, "%d %s %s%s", nr_opt,
|
if ((dm_asprintf((char **)&opt_args, "%d %s %s%s", nr_opt,
|
||||||
precise_str,
|
precise_str,
|
||||||
@ -2026,6 +2088,7 @@ out:
|
|||||||
if (dmt)
|
if (dmt)
|
||||||
dm_task_destroy(dmt);
|
dm_task_destroy(dmt);
|
||||||
dm_free((void *) opt_args);
|
dm_free((void *) opt_args);
|
||||||
|
dm_free(aux_data_escaped);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user