From 9808428d6048fc0826e01d37017c89b4b4ffb9e6 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 1 Jun 2008 23:21:13 +0200 Subject: [PATCH] Make user summary sortable by user defined column. This adds the user-summary-sort option --- adu.c | 8 ++++++-- adu.ggo | 12 ++++++++++++ adu.h | 4 ++++ select.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/adu.c b/adu.c index 3eec0b4..27c0267 100644 --- a/adu.c +++ b/adu.c @@ -53,8 +53,6 @@ struct osl_table *dir_table = NULL; */ struct uid_range *admissible_uids; -/** Evaluates to 1 if x < y, to -1 if x > y and to 0 if x == y. */ -#define NUM_COMPARE(x, y) ((int)((x) < (y)) - (int)((x) > (y))) /** * Compare the size of two directories @@ -475,6 +473,12 @@ char *get_uid_list_name(void) return make_message("%s/uid_list", conf.database_dir_arg); } +void sort_hash_table(int (*comp)(const void *, const void *)) +{ + qsort(uid_hash_table, uid_hash_table_size, sizeof(struct user_info), + comp); +} + int open_dir_table(int create) { dir_table_desc.dir = adu_strdup(conf.database_dir_arg); diff --git a/adu.ggo b/adu.ggo index f2d14c9..0be213d 100644 --- a/adu.ggo +++ b/adu.ggo @@ -201,3 +201,15 @@ details=" number/10^15. The default is to print numbers in human-readable format. " + +option "user-summary-sort" - +#~~~~~~~~~~~~~~~~~~~~~~~~~~~ +"how to sort the user-summary" +enum typestr="col_spec" +values="name","uid","dir_count","file_count","size" +default="size" +optional +details=" + It is enough to specify the first letter of the column specifier, + e.g. \"--user-summary-sort f\" sorts by file count. +" diff --git a/adu.h b/adu.h index 67607fd..f1d4fba 100644 --- a/adu.h +++ b/adu.h @@ -118,6 +118,9 @@ } \ } +/** Evaluates to 1 if x < y, to -1 if x > y and to 0 if x == y. */ +#define NUM_COMPARE(x, y) ((int)((x) < (y)) - (int)((x) > (y))) + /** The columns of the directory table. */ enum dir_table_columns { /** The name of the directory. */ @@ -189,6 +192,7 @@ int search_uid(uint32_t uid, enum search_uid_flags flags, struct user_info **ui_ptr); int for_each_admissible_user(int (*func)(struct user_info *, void *), void *data); +void sort_hash_table(int (*comp)(const void *, const void *)); /* select.c */ int com_select(void); diff --git a/select.c b/select.c index 094ab72..515bbc4 100644 --- a/select.c +++ b/select.c @@ -389,11 +389,62 @@ static int print_user_summary_line(struct user_info *ui, __a_unused void *data) return 1; } +static int name_comp(const void *a, const void *b) +{ + char *x = ((struct user_info *)a)->pw_name; + char *y = ((struct user_info *)b)->pw_name; + + if (!x) + return 1; + if (!y) + return -1; + return strcmp(x, y); +} + +static int uid_comp(const void *a, const void *b) +{ + return -NUM_COMPARE(((struct user_info *)a)->uid, + ((struct user_info *)b)->uid); +} + +static int dir_count_comp(const void *a, const void *b) +{ + return NUM_COMPARE(((struct user_info *)a)->dirs, + ((struct user_info *)b)->dirs); +} + +static int file_count_comp(const void *a, const void *b) +{ + return NUM_COMPARE(((struct user_info *)a)->files, + ((struct user_info *)b)->files); +} + +static int size_comp(const void *a, const void *b) +{ + return NUM_COMPARE(((struct user_info *)a)->bytes, + ((struct user_info *)b)->bytes); +} + +/* + * The comparators for sorting the user summary. + * + * This is an array of pointers to functions taking two constant void * + * pointers and returning an int. + */ +static int (*summary_comparators[])(const void *, const void *) = { + [user_summary_sort_arg_name] = name_comp, + [user_summary_sort_arg_uid] = uid_comp, + [user_summary_sort_arg_dir_count] = dir_count_comp, + [user_summary_sort_arg_file_count] = file_count_comp, + [user_summary_sort_arg_size] = size_comp, +}; + static void print_user_summary(void) { printf("User summary " "(pw_name/uid/dirs%s/files%s/size%s):\n", count_unit_buf, count_unit_buf, size_unit_buf); + sort_hash_table(summary_comparators[conf.user_summary_sort_arg]); for_each_admissible_user(print_user_summary_line, NULL); } -- 2.30.2