From 60d11eca6649700c1e39c19c36c903cad747e775 Mon Sep 17 00:00:00 2001 From: wangshilong Date: Wed, 19 Sep 2012 17:21:51 +0800 Subject: Btrfs-progs: introduce -g -c --sort options into btrfs subvol list command This patch introduces '-g' '-c' '--sort' options The option '-g' can help you filter the subvolumes by the generation, you may use it just like: btrfs subvol list -g +/-value '+' means the generation of the subvolumes should >= the value you specified. '-' means the generation should <= the value If you don't input either '+' nor '-', this command will list the subvolumes that their generation equals to the value. However if you want to find gengeration between value1 and value2 you may use the above like: btrfs sub list -g -value1 -g +value2 The option '-c' can help you filter the subvolumes by the ogeneration, you may use it just like: btrfs subvol list -c +/-value The usage is the same to '-g' You might want to list subvolumes in order of some items, such as root id, gen and so on, you can use '--sort'. Now you can sort the subvolumes by root id, gen, ogen and path. For example: If you want to list subvolumes in order of rootid, you can use the option like that: btrfs sub list --sort=+/-rooid Here, '+' means the result is sorted by ascending order. '-' is by descending order. If you don't specify either '+' nor '-', the result is sorted by default - ascending order. If you want to combine sort items, you do it like that: btrfs sub list --sort=-rootid,+path,ogen,gen Signed-off-by: Wang Shilong Signed-off-by: Miao Xie --- btrfs-list.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) (limited to 'btrfs-list.c') diff --git a/btrfs-list.c b/btrfs-list.c index 201f378..c6d9a18 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -215,12 +215,48 @@ static int comp_entry_with_ogen(struct root_info *entry1, return is_descending ? -ret : ret; } +static int comp_entry_with_path(struct root_info *entry1, + struct root_info *entry2, + int is_descending) +{ + int ret; + + if (strcmp(entry1->full_path, entry2->full_path) > 0) + ret = 1; + else if (strcmp(entry1->full_path, entry2->full_path) < 0) + ret = -1; + else + ret = 0; + + return is_descending ? -ret : ret; +} + static btrfs_list_comp_func all_comp_funcs[] = { [BTRFS_LIST_COMP_ROOTID] = comp_entry_with_rootid, [BTRFS_LIST_COMP_OGEN] = comp_entry_with_ogen, [BTRFS_LIST_COMP_GEN] = comp_entry_with_gen, + [BTRFS_LIST_COMP_PATH] = comp_entry_with_path, }; +static char *all_sort_items[] = { + [BTRFS_LIST_COMP_ROOTID] = "rootid", + [BTRFS_LIST_COMP_OGEN] = "ogen", + [BTRFS_LIST_COMP_GEN] = "gen", + [BTRFS_LIST_COMP_PATH] = "path", + [BTRFS_LIST_COMP_MAX] = NULL, +}; + +static int btrfs_list_get_sort_item(char *sort_name) +{ + int i; + + for (i = 0; i < BTRFS_LIST_COMP_MAX; i++) { + if (strcmp(sort_name, all_sort_items[i]) == 0) + return i; + } + return -1; +} + struct btrfs_list_comparer_set *btrfs_list_alloc_comparer_set(void) { struct btrfs_list_comparer_set *set; @@ -1091,10 +1127,46 @@ static int filter_flags(struct root_info *ri, u64 flags) return ri->flags & flags; } +static int filter_gen_more(struct root_info *ri, u64 data) +{ + return ri->gen >= data; +} + +static int filter_gen_less(struct root_info *ri, u64 data) +{ + return ri->gen <= data; +} + +static int filter_gen_equal(struct root_info *ri, u64 data) +{ + return ri->gen == data; +} + +static int filter_cgen_more(struct root_info *ri, u64 data) +{ + return ri->ogen >= data; +} + +static int filter_cgen_less(struct root_info *ri, u64 data) +{ + return ri->ogen <= data; +} + +static int filter_cgen_equal(struct root_info *ri, u64 data) +{ + return ri->ogen == data; +} + static btrfs_list_filter_func all_filter_funcs[] = { [BTRFS_LIST_FILTER_ROOTID] = filter_by_rootid, [BTRFS_LIST_FILTER_SNAPSHOT_ONLY] = filter_snapshot, [BTRFS_LIST_FILTER_FLAGS] = filter_flags, + [BTRFS_LIST_FILTER_GEN_MORE] = filter_gen_more, + [BTRFS_LIST_FILTER_GEN_LESS] = filter_gen_less, + [BTRFS_LIST_FILTER_GEN_EQUAL] = filter_gen_equal, + [BTRFS_LIST_FILTER_CGEN_MORE] = filter_cgen_more, + [BTRFS_LIST_FILTER_CGEN_LESS] = filter_cgen_less, + [BTRFS_LIST_FILTER_CGEN_EQUAL] = filter_cgen_equal, }; struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void) @@ -1534,3 +1606,99 @@ char *btrfs_list_path_for_root(int fd, u64 root) return ret_path; } + +int btrfs_list_parse_sort_string(char *optarg, + struct btrfs_list_comparer_set **comps) +{ + int order; + int flag; + char *p; + char **ptr_argv; + int what_to_sort; + + while ((p = strtok(optarg, ",")) != NULL) { + flag = 0; + ptr_argv = all_sort_items; + + while (*ptr_argv) { + if (strcmp(*ptr_argv, p) == 0) { + flag = 1; + break; + } else { + p++; + if (strcmp(*ptr_argv, p) == 0) { + flag = 1; + p--; + break; + } + p--; + } + ptr_argv++; + } + + if (flag == 0) + return -1; + + else { + if (*p == '+') { + order = 0; + p++; + } else if (*p == '-') { + order = 1; + p++; + } else + order = 0; + + what_to_sort = btrfs_list_get_sort_item(p); + btrfs_list_setup_comparer(comps, what_to_sort, order); + } + optarg = NULL; + } + + return 0; +} + +/* + * This function is used to parse the argument of filter condition. + * + * type is the filter object. + */ +int btrfs_list_parse_filter_string(char *optarg, + struct btrfs_list_filter_set **filters, + enum btrfs_list_filter_enum type) +{ + + u64 arg; + char *ptr_parse_end = NULL; + char *ptr_optarg_end = optarg + strlen(optarg); + + switch (*(optarg++)) { + case '+': + arg = (u64)strtol(optarg, &ptr_parse_end, 10); + type += 2; + if (ptr_parse_end != ptr_optarg_end) + return -1; + + btrfs_list_setup_filter(filters, type, arg); + break; + case '-': + arg = (u64)strtoll(optarg, &ptr_parse_end, 10); + type += 1; + if (ptr_parse_end != ptr_optarg_end) + return -1; + + btrfs_list_setup_filter(filters, type, arg); + break; + default: + optarg--; + arg = (u64)strtoll(optarg, &ptr_parse_end, 10); + + if (ptr_parse_end != ptr_optarg_end) + return -1; + btrfs_list_setup_filter(filters, type, arg); + break; + } + + return 0; +} + -- cgit v1.2.1