Make user summary sortable by user defined column.
authorAndre Noll <maan@systemlinux.org>
Sun, 1 Jun 2008 21:21:13 +0000 (23:21 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 1 Jun 2008 21:21:13 +0000 (23:21 +0200)
This adds the user-summary-sort option

adu.c
adu.ggo
adu.h
select.c

diff --git a/adu.c b/adu.c
index 3eec0b4..27c0267 100644 (file)
--- 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 (file)
--- 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 (file)
--- a/adu.h
+++ b/adu.h
        } \
 }
 
+/** 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);
index 094ab72..515bbc4 100644 (file)
--- 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);
 }