1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

commands: fix memory debug for cmd defs

Clean up the handling of memory used for cmd defs
so it doesn't trip up memory debugging.

Allocate memory for commands[] from libmem.

Free temporary memory used by define_commands()
at the end of the function.

Clear all the command def state in in lvm_fin().
This commit is contained in:
David Teigland 2017-04-28 16:27:19 -05:00
parent 54726a4950
commit 15eaf703fc
5 changed files with 76 additions and 44 deletions

View File

@ -40,14 +40,18 @@
*/
#ifdef MAN_PAGE_GENERATOR
struct cmd_context {
void *libmem;
};
#define log_error(fmt, args...) \
do { \
printf(fmt "\n", ##args); \
} while (0)
#define dm_malloc malloc
#define dm_free free
#define dm_strdup strdup
#define dm_free free
#define dm_snprintf snprintf
static int dm_strncpy(char *dest, const char *src, size_t n)
@ -61,6 +65,16 @@ static int dm_strncpy(char *dest, const char *src, size_t n)
return 0;
}
static char *dm_pool_strdup(void *p, const char *str)
{
return strdup(str);
}
static void *dm_pool_alloc(void *p, size_t size)
{
return malloc(size);
}
/* needed to include args.h */
#define ARG_COUNTABLE 0x00000001
#define ARG_GROUPABLE 0x00000002
@ -281,7 +295,7 @@ static struct oo_line oo_lines[MAX_OO_LINES];
*/
#include "command-lines-input.h"
static void add_optional_opt_line(struct command *cmd, int argc, char *argv[]);
static void add_optional_opt_line(struct cmd_context *cmdtool, struct command *cmd, int argc, char *argv[]);
/*
* modifies buf, replacing the sep characters with \0
@ -648,7 +662,7 @@ static void set_pos_def(struct command *cmd, char *str, struct arg_def *def)
* Parse str for anything that can follow --option.
*/
static void set_opt_def(struct command *cmd, char *str, struct arg_def *def)
static void set_opt_def(struct cmd_context *cmdtool, struct command *cmd, char *str, struct arg_def *def)
{
char *argv[MAX_LINE_ARGC];
int argc;
@ -686,7 +700,7 @@ static void set_opt_def(struct command *cmd, char *str, struct arg_def *def)
def->num = (uint64_t)atoi(name);
if (val_enum == conststr_VAL)
def->str = dm_strdup(name);
def->str = dm_pool_strdup(cmdtool->libmem, name);
if (val_enum == lv_VAL) {
if (strchr(name, '_'))
@ -789,7 +803,7 @@ static char *get_oo_line(const char *str)
* i.e. include common options from an OO_FOO definition.
*/
static void include_optional_opt_args(struct command *cmd, const char *str)
static void include_optional_opt_args(struct cmd_context *cmdtool, struct command *cmd, const char *str)
{
char *oo_line;
char *line;
@ -808,7 +822,7 @@ static void include_optional_opt_args(struct command *cmd, const char *str)
}
split_line(line, &line_argc, line_argv, ' ');
add_optional_opt_line(cmd, line_argc, line_argv);
add_optional_opt_line(cmdtool, cmd, line_argc, line_argv);
dm_free(line);
}
@ -873,7 +887,7 @@ skip:
* for the value that appears after --option.
*/
static void update_prev_opt_arg(struct command *cmd, char *str, int required)
static void update_prev_opt_arg(struct cmd_context *cmdtool, struct command *cmd, char *str, int required)
{
struct arg_def def = { 0 };
char *comma;
@ -890,7 +904,7 @@ static void update_prev_opt_arg(struct command *cmd, char *str, int required)
if ((comma = strchr(str, ',')))
*comma = '\0';
set_opt_def(cmd, str, &def);
set_opt_def(cmdtool, cmd, str, &def);
if (required > 0)
cmd->required_opt_args[cmd->ro_count-1].def = def;
@ -948,7 +962,7 @@ static void update_prev_pos_arg(struct command *cmd, char *str, int required)
/* Process what follows OO:, which are the optional opt args for the cmd def. */
static void add_optional_opt_line(struct command *cmd, int argc, char *argv[])
static void add_optional_opt_line(struct cmd_context *cmdtool, struct command *cmd, int argc, char *argv[])
{
int takes_arg = 0;
int already;
@ -963,9 +977,9 @@ static void add_optional_opt_line(struct command *cmd, int argc, char *argv[])
if (is_opt_name(argv[i]))
add_opt_arg(cmd, argv[i], &takes_arg, &already, OPTIONAL);
else if (!strncmp(argv[i], "OO_", 3))
include_optional_opt_args(cmd, argv[i]);
include_optional_opt_args(cmdtool, cmd, argv[i]);
else if (takes_arg)
update_prev_opt_arg(cmd, argv[i], OPTIONAL);
update_prev_opt_arg(cmdtool, cmd, argv[i], OPTIONAL);
else {
log_error("Parsing command defs: can't parse argc %d argv %s prev %s.",
i, argv[i], argv[i-1]);
@ -980,7 +994,7 @@ static void add_optional_opt_line(struct command *cmd, int argc, char *argv[])
/* Process what follows IO:, which are the ignore options for the cmd def. */
static void add_ignore_opt_line(struct command *cmd, int argc, char *argv[])
static void add_ignore_opt_line(struct cmd_context *cmdtool, struct command *cmd, int argc, char *argv[])
{
int takes_arg = 0;
int i;
@ -991,7 +1005,7 @@ static void add_ignore_opt_line(struct command *cmd, int argc, char *argv[])
if (is_opt_name(argv[i]))
add_opt_arg(cmd, argv[i], &takes_arg, NULL, IGNORE);
else if (takes_arg)
update_prev_opt_arg(cmd, argv[i], IGNORE);
update_prev_opt_arg(cmdtool, cmd, argv[i], IGNORE);
else {
log_error("Parsing command defs: can't parse argc %d argv %s prev %s.",
i, argv[i], argv[i-1]);
@ -1017,7 +1031,7 @@ static void add_optional_pos_line(struct command *cmd, int argc, char *argv[])
}
}
static void add_required_opt_line(struct command *cmd, int argc, char *argv[])
static void add_required_opt_line(struct cmd_context *cmdtool, struct command *cmd, int argc, char *argv[])
{
int takes_arg = 0;
int i;
@ -1026,7 +1040,7 @@ static void add_required_opt_line(struct command *cmd, int argc, char *argv[])
if (is_opt_name(argv[i]))
add_opt_arg(cmd, argv[i], &takes_arg, NULL, REQUIRED);
else if (takes_arg)
update_prev_opt_arg(cmd, argv[i], REQUIRED);
update_prev_opt_arg(cmdtool, cmd, argv[i], REQUIRED);
else {
log_error("Parsing command defs: can't parse argc %d argv %s prev %s.",
i, argv[i], argv[i-1]);
@ -1045,7 +1059,7 @@ static void add_required_opt_line(struct command *cmd, int argc, char *argv[])
* this special case.
*/
static void include_required_opt_args(struct command *cmd, char *str)
static void include_required_opt_args(struct cmd_context *cmdtool, struct command *cmd, char *str)
{
char *oo_line;
char *line;
@ -1064,13 +1078,13 @@ static void include_required_opt_args(struct command *cmd, char *str)
}
split_line(line, &line_argc, line_argv, ' ');
add_required_opt_line(cmd, line_argc, line_argv);
add_required_opt_line(cmdtool, cmd, line_argc, line_argv);
dm_free(line);
}
/* Process what follows command_name, which are required opt/pos args. */
static void add_required_line(struct command *cmd, int argc, char *argv[])
static void add_required_line(struct cmd_context *cmdtool, struct command *cmd, int argc, char *argv[])
{
int i;
int takes_arg;
@ -1088,7 +1102,7 @@ static void add_required_line(struct command *cmd, int argc, char *argv[])
} else if (prev_was_opt && takes_arg) {
/* set value for previous required_opt_arg */
update_prev_opt_arg(cmd, argv[i], REQUIRED);
update_prev_opt_arg(cmdtool, cmd, argv[i], REQUIRED);
prev_was_opt = 0;
prev_was_pos = 0;
@ -1101,7 +1115,7 @@ static void add_required_line(struct command *cmd, int argc, char *argv[])
} else if (!strncmp(argv[i], "OO_", 3)) {
/* one required_opt_arg is required, special case lv/vgchange */
cmd->cmd_flags |= CMD_FLAG_ONE_REQUIRED_OPT;
include_required_opt_args(cmd, argv[i]);
include_required_opt_args(cmdtool, cmd, argv[i]);
} else if (prev_was_pos) {
/* set property for previous required_pos_arg */
@ -1125,7 +1139,7 @@ static void add_flags(struct command *cmd, char *line)
#define MAX_RULE_OPTS 64
static void add_rule(struct command *cmd, char *line)
static void add_rule(struct cmd_context *cmdtool, struct command *cmd, char *line)
{
struct cmd_rule *rule;
char *line_argv[MAX_LINE_ARGC];
@ -1164,7 +1178,7 @@ static void add_rule(struct command *cmd, char *line)
else if (!strncmp(arg, "--", 2)) {
if (!rule->opts) {
if (!(rule->opts = dm_malloc(MAX_RULE_OPTS * sizeof(int)))) {
if (!(rule->opts = dm_pool_alloc(cmdtool->libmem, MAX_RULE_OPTS * sizeof(int)))) {
log_error("Parsing command defs: no mem.");
cmd->cmd_flags |= CMD_FLAG_PARSE_ERROR;
return;
@ -1173,7 +1187,7 @@ static void add_rule(struct command *cmd, char *line)
}
if (!rule->check_opts) {
if (!(rule->check_opts = dm_malloc(MAX_RULE_OPTS * sizeof(int)))) {
if (!(rule->check_opts = dm_pool_alloc(cmdtool->libmem, MAX_RULE_OPTS * sizeof(int)))) {
log_error("Parsing command defs: no mem.");
cmd->cmd_flags |= CMD_FLAG_PARSE_ERROR;
return;
@ -1348,7 +1362,7 @@ static int copy_line(char *line, int max_line, int *position)
return 1;
}
int define_commands(const char *run_name)
int define_commands(struct cmd_context *cmdtool, const char *run_name)
{
struct command *cmd = NULL;
char line[MAX_LINE];
@ -1400,7 +1414,7 @@ int define_commands(const char *run_name)
cmd = &commands[cmd_count];
cmd->command_index = cmd_count;
cmd_count++;
cmd->name = dm_strdup(name);
cmd->name = dm_pool_strdup(cmdtool->libmem, name);
if (run_name && strcmp(run_name, name)) {
skip = 1;
@ -1412,10 +1426,10 @@ int define_commands(const char *run_name)
skip = 0;
cmd->pos_count = 1;
add_required_line(cmd, line_argc, line_argv);
add_required_line(cmdtool, cmd, line_argc, line_argv);
/* Every cmd gets the OO_ALL options */
include_optional_opt_args(cmd, "OO_ALL:");
include_optional_opt_args(cmdtool, cmd, "OO_ALL:");
continue;
}
@ -1425,15 +1439,13 @@ int define_commands(const char *run_name)
*/
if (is_desc_line(line_argv[0]) && !skip && cmd) {
char *desc = dm_strdup(line_orig);
char *desc = dm_pool_strdup(cmdtool->libmem, line_orig);
if (cmd->desc) {
int newlen = strlen(cmd->desc) + strlen(desc) + 2;
char *newdesc = dm_malloc(newlen);
char *newdesc = dm_pool_alloc(cmdtool->libmem, newlen);
if (newdesc) {
memset(newdesc, 0, newlen);
snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
dm_free((char *)cmd->desc);
dm_free(desc);
cmd->desc = newdesc;
}
} else
@ -1447,12 +1459,12 @@ int define_commands(const char *run_name)
}
if (is_rule_line(line_argv[0]) && !skip && cmd) {
add_rule(cmd, line_orig);
add_rule(cmdtool, cmd, line_orig);
continue;
}
if (is_id_line(line_argv[0]) && cmd) {
cmd->command_id = dm_strdup(line_argv[1]);
cmd->command_id = dm_pool_strdup(cmdtool->libmem, line_argv[1]);
continue;
}
@ -1467,7 +1479,7 @@ int define_commands(const char *run_name)
/* OO: ... */
if (is_oo_line(line_argv[0]) && !skip && cmd) {
add_optional_opt_line(cmd, line_argc, line_argv);
add_optional_opt_line(cmdtool, cmd, line_argc, line_argv);
prev_was_oo_def = 0;
prev_was_oo = 1;
prev_was_op = 0;
@ -1485,7 +1497,7 @@ int define_commands(const char *run_name)
/* IO: ... */
if (is_io_line(line_argv[0]) && !skip && cmd) {
add_ignore_opt_line(cmd, line_argc, line_argv);
add_ignore_opt_line(cmdtool, cmd, line_argc, line_argv);
prev_was_oo = 0;
prev_was_op = 0;
continue;
@ -1499,7 +1511,7 @@ int define_commands(const char *run_name)
}
if (prev_was_oo && cmd) {
add_optional_opt_line(cmd, line_argc, line_argv);
add_optional_opt_line(cmdtool, cmd, line_argc, line_argv);
continue;
}
@ -1517,7 +1529,15 @@ int define_commands(const char *run_name)
return 0;
}
include_optional_opt_args(&lvm_all, "OO_ALL");
include_optional_opt_args(cmdtool, &lvm_all, "OO_ALL");
for (i = 0; i < oo_line_count; i++) {
struct oo_line *oo = &oo_lines[i];
dm_free(oo->name);
dm_free(oo->line);
}
memset(&oo_lines, 0, sizeof(oo_lines));
oo_line_count = 0;
return 1;
}
@ -3422,6 +3442,7 @@ static void _print_man_secondary(char *name)
int main(int argc, char *argv[])
{
struct cmd_context cmdtool;
char *cmdname = NULL;
char *desfile = NULL;
char *stdout_buf;
@ -3478,7 +3499,7 @@ int main(int argc, char *argv[])
if (optind < argc)
desfile = argv[optind++];
define_commands(NULL);
define_commands(&cmdtool, NULL);
configure_command_option_values(cmdname);

View File

@ -255,7 +255,7 @@ struct lv_type {
};
int define_commands(const char *run_name);
int define_commands(struct cmd_context *cmdtool, const char *run_name);
int command_id_to_enum(const char *str);
void print_usage(struct command *cmd, int longhelp, int desc_first);
void print_usage_common_cmd(struct command_name *cname, struct command *cmd);

View File

@ -32,7 +32,7 @@ void *cmdlib_lvm2_init(unsigned static_compile);
void lvm_fin(struct cmd_context *cmd);
struct cmd_context *init_lvm(unsigned set_connections, unsigned set_filters);
int lvm_register_commands(const char *name);
int lvm_register_commands(struct cmd_context *cmdtool, const char *name);
int lvm_split(char *str, int *argc, char **argv, int max);
int lvm_run_command(struct cmd_context *cmd, int argc, char **argv);
int lvm_return_code(int ret);

View File

@ -34,7 +34,7 @@ void *cmdlib_lvm2_init(unsigned static_compile)
if (!(cmd = init_lvm(1, 1)))
return NULL;
if (!lvm_register_commands(NULL))
if (!lvm_register_commands(cmd, NULL))
return NULL;
return (void *) cmd;

View File

@ -1241,7 +1241,16 @@ static const struct command_function *_find_command_id_function(int command_enum
return NULL;
}
int lvm_register_commands(const char *run_name)
static void _unregister_commands(void)
{
_cmdline.commands = NULL;
_cmdline.num_commands = 0;
_cmdline.command_names = NULL;
_cmdline.num_command_names = 0;
memset(&commands, 0, sizeof(commands));
}
int lvm_register_commands(struct cmd_context *cmd, const char *run_name)
{
int i;
@ -1255,7 +1264,7 @@ int lvm_register_commands(const char *run_name)
* populate commands[] array with command definitions
* by parsing command-lines.in/command-lines-input.h
*/
if (!define_commands(run_name)) {
if (!define_commands(cmd, run_name)) {
log_error(INTERNAL_ERROR "Failed to parse command definitions.");
return 0;
}
@ -1285,6 +1294,7 @@ int lvm_register_commands(const char *run_name)
}
_cmdline.command_names = command_names;
_cmdline.num_command_names = 0;
for (i = 0; i < MAX_COMMAND_NAMES; i++) {
if (!command_names[i].name)
@ -3268,6 +3278,7 @@ struct cmd_context *init_lvm(unsigned set_connections, unsigned set_filters)
void lvm_fin(struct cmd_context *cmd)
{
_unregister_commands();
destroy_toolcontext(cmd);
udev_fin_library_context();
}
@ -3448,7 +3459,7 @@ int lvm2_main(int argc, char **argv)
if (run_name && !find_command_name(run_name))
run_name = NULL;
if (!lvm_register_commands(run_name)) {
if (!lvm_register_commands(cmd, run_name)) {
ret = ECMD_FAILED;
goto out;
}