diff options
author | David Teigland <teigland@redhat.com> | 2016-12-01 15:31:54 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2016-12-01 15:51:24 -0600 |
commit | d658ddfc703102409cf2f5c1519608941e0d3cf6 (patch) | |
tree | 4b57cc34c856219ba3ce1905350a1e8e9338e769 | |
parent | 268374c2354180573a631d4bca96f6e08d91dee5 (diff) | |
download | lvm2-d658ddfc703102409cf2f5c1519608941e0d3cf6.tar.gz |
process_each_lv: command def validation for LV in other position
Determine which position arg the LV being processed is.
Use this position to check the LV against the command def.
-rw-r--r-- | tools/toollib.c | 118 |
1 files changed, 78 insertions, 40 deletions
diff --git a/tools/toollib.c b/tools/toollib.c index 456216b43..55ac47ab7 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -2677,35 +2677,29 @@ static int _lv_props_match(struct cmd_context *cmd, struct logical_volume *lv, u return !found_a_mismatch; } -/* - * If the command definition specifies one required positional - * LV (possibly repeatable), and specifies accepted LV types, - * then verify that the LV being processed matches one of those - * types. - * - * process_each_lv() can only be used for commands that have - * one positional LV arg (optionally repeating, where each is - * processed independently.) It cannot work for commands that - * have different required LVs in designated positions, like - * 'lvrename LV1 LV2', where each LV is not processed - * independently. That means that this LV type check only - * needs to check the lv_type of the first positional arg. - */ - -static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv) +static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv, int pos) { int ret = 1; - if ((cmd->command->rp_count == 1) && - val_bit_is_set(cmd->command->required_pos_args[0].def.val_bits, lv_VAL) && - cmd->command->required_pos_args[0].def.lvt_bits) { - ret = _lv_types_match(cmd, lv, cmd->command->required_pos_args[0].def.lvt_bits, NULL, NULL); - if (!ret) { - int lvt_enum = _get_lvt_enum(lv); - struct lv_types *type = get_lv_type(lvt_enum); - log_warn("Operation on LV %s which has invalid type %s.", - display_lvname(lv), type ? type->name : "unknown"); - } + if (!pos) + return 1; + + if (!cmd->command->required_pos_args[pos-1].def.lvt_bits) + return 1; + + if (!val_bit_is_set(cmd->command->required_pos_args[pos-1].def.val_bits, lv_VAL)) { + log_error(INTERNAL_ERROR "Command (%s %d) arg position %d does not permit an LV (%llx)", + cmd->command->command_line_id, cmd->command->command_line_enum, + pos, (unsigned long long)cmd->command->required_pos_args[pos-1].def.val_bits); + return 0; + } + + ret = _lv_types_match(cmd, lv, cmd->command->required_pos_args[pos-1].def.lvt_bits, NULL, NULL); + if (!ret) { + int lvt_enum = _get_lvt_enum(lv); + struct lv_types *type = get_lv_type(lvt_enum); + log_warn("Operation on LV %s which has invalid type %s.", + display_lvname(lv), type ? type->name : "unknown"); } return ret; @@ -2869,6 +2863,59 @@ static int _check_lv_rules(struct cmd_context *cmd, struct logical_volume *lv) return ret; } +/* + * Return which arg position the given LV is at, + * where 1 represents the first position arg. + * When the first position arg is repeatable, + * return 1 for all. + * + * Return 0 when the command has no required + * position args. (optional position args are + * not considered.) + */ + +static int _find_lv_arg_position(struct cmd_context *cmd, struct logical_volume *lv) +{ + const char *sep, *lvname; + int i; + + if (cmd->command->rp_count == 0) + return 0; + + if (cmd->command->rp_count == 1) + return 1; + + for (i = 0; i < cmd->position_argc; i++) { + if (i == cmd->command->rp_count) + break; + + if (!val_bit_is_set(cmd->command->required_pos_args[i].def.val_bits, lv_VAL)) + continue; + + if ((sep = strstr(cmd->position_argv[i], "/"))) + lvname = sep + 1; + else + lvname = cmd->position_argv[i]; + + if (!strcmp(lvname, lv->name)) + return i + 1; + } + + /* + * If the last position arg is an LV and this + * arg is beyond that position, then the last + * LV position arg is repeatable, so return + * that position. + */ + if (i == cmd->command->rp_count) { + int last_pos = cmd->command->rp_count; + if (val_bit_is_set(cmd->command->required_pos_args[last_pos-1].def.val_bits, lv_VAL)) + return last_pos; + } + + return 0; +} + int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *arg_lvnames, const struct dm_list *tags_in, int stop_on_error, @@ -2888,6 +2935,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, unsigned process_all = 0; unsigned tags_supplied = 0; unsigned lvargs_supplied = 0; + int lv_arg_pos; struct lv_list *lvl; struct dm_str_list *sl; struct dm_list final_lvs; @@ -3047,42 +3095,32 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg, lv_is_named_arg = str_list_match_item(&found_arg_lvnames, lvl->lv->name); + lv_arg_pos = _find_lv_arg_position(cmd, lvl->lv); + /* * The command definition may include restrictions on the * types and properties of LVs that can be processed. */ - if (!_check_lv_types(cmd, lvl->lv)) { + if (!_check_lv_types(cmd, lvl->lv, lv_arg_pos)) { /* FIXME: include this result in report log? */ - /* FIXME: avoid duplicating message for each level */ - if (lv_is_named_arg) { log_error("Operation not permitted (%s %d) on LV %s.", cmd->command->command_line_id, cmd->command->command_line_enum, display_lvname(lvl->lv)); ret_max = ECMD_FAILED; - } else { - log_warn("Operation not permitted (%s %d) on LV %s.", - cmd->command->command_line_id, cmd->command->command_line_enum, - display_lvname(lvl->lv)); } continue; } if (!_check_lv_rules(cmd, lvl->lv)) { /* FIXME: include this result in report log? */ - /* FIXME: avoid duplicating message for each level */ - if (lv_is_named_arg) { log_error("Operation not permitted (%s %d) on LV %s.", cmd->command->command_line_id, cmd->command->command_line_enum, display_lvname(lvl->lv)); ret_max = ECMD_FAILED; - } else { - log_warn("Operation not permitted (%s %d) on LV %s.", - cmd->command->command_line_id, cmd->command->command_line_enum, - display_lvname(lvl->lv)); - } + } continue; } |