Introduce select-mode and use pretty formating for the global lists.
authorAndre Noll <maan@systemlinux.org>
Sat, 1 Nov 2008 13:30:28 +0000 (14:30 +0100)
committerAndre Noll <maan@systemlinux.org>
Sat, 1 Nov 2008 13:30:28 +0000 (14:30 +0100)
This patch introduces the new --select-mode option which is used
to specify which of the four possible output formats should be used.
Only this table is being printed.

The other change to select.c is that the global list also uses the
functions from format.c to pretty-print the output. The new
--global-list-format option may be used to customize the output.

adu.h
select.c
select.ggo

diff --git a/adu.h b/adu.h
index 012fdde..62eaa7e 100644 (file)
--- a/adu.h
+++ b/adu.h
@@ -196,6 +196,7 @@ void sort_hash_table(int (*comp)(const void *, const void *));
 
 /* select.c */
 struct select_format_info {
+       struct format_info *global_list_fi;
        struct format_info *global_summary_fi;
        struct format_info *user_summary_fi;
 };
index 84e18d4..7b33383 100644 (file)
--- a/select.c
+++ b/select.c
@@ -27,6 +27,21 @@ static uint64_t num_bytes;
 /** The decimal representation of an uint64_t never exceeds that size. */
 #define FORMATED_VALUE_SIZE 25
 
+#define GLOBAL_LIST_ATOMS \
+       ATOM(size, SIZE) \
+       ATOM(files, COUNT) \
+       ATOM(dirname, STRING) \
+
+#define ATOM(x, y) { .name = #x, .type = AT_ ## y},
+struct atom global_list_atoms[] = {
+       GLOBAL_LIST_ATOMS
+       {.name = NULL}
+};
+#undef ATOM
+#define ATOM(x, y) gla_ ## x,
+enum global_list_atoms {GLOBAL_LIST_ATOMS};
+#undef ATOM
+
 #define GLOBAL_SUMMARY_ATOMS \
        ATOM(dirs, COUNT) \
        ATOM(files, COUNT) \
@@ -60,21 +75,15 @@ enum user_summary_atoms {USER_SUMMARY_ATOMS};
 #undef ATOM
 
 
+
 /* these get filled in by the select command. */
 static char count_unit_buf[4] = "( )", size_unit_buf[4] = "( )";
 
-enum global_stats_flags {
-       GSF_PRINT_DIRNAME = 1,
-       GSF_PRINT_BYTES = 2,
-       GSF_PRINT_FILES = 4,
-       GSF_COMPUTE_SUMMARY = 8,
-};
-
-struct global_stats_info {
+struct global_list_info {
        uint32_t count;
        int ret;
        int osl_errno;
-       enum global_stats_flags flags;
+       struct format_info *fi;
 };
 
 enum user_stats_flags {
@@ -288,80 +297,6 @@ err:
        return -1;
 }
 
-static int global_stats_loop_function(struct osl_row *row, void *data)
-{
-       struct global_stats_info *gsi = data;
-       struct osl_object obj;
-       char *dirname, formated_value[FORMATED_VALUE_SIZE];
-       int ret, summary = gsi->flags & GSF_COMPUTE_SUMMARY;
-
-       check_signals();
-       if (!gsi->count && !summary) {
-               ret = -E_LOOP_COMPLETE;
-               goto err;
-       }
-       if (summary || (gsi->count && (gsi->flags & GSF_PRINT_FILES))) {
-               uint64_t files;
-               ret = osl(osl_get_object(dir_table, row, DT_FILES, &obj));
-               if (ret < 0)
-                       goto err;
-               files = *(uint64_t *)obj.data;
-               if (gsi->count && (gsi->flags & GSF_PRINT_FILES)) {
-                       format_count_value(select_conf.count_unit_arg, files,
-                               select_conf.count_unit_arg == count_unit_arg_h,
-                               formated_value);
-                       ret = output("\t%s%s", formated_value,
-                               (gsi->flags & (GSF_PRINT_BYTES | GSF_PRINT_DIRNAME))?
-                               "\t" : "\n");
-                       if (ret < 0)
-                               goto err;
-               }
-               if (summary)
-                       num_files += files;
-       }
-       if (summary || (gsi->count && (gsi->flags & GSF_PRINT_BYTES))) {
-               uint64_t bytes;
-               ret = osl(osl_get_object(dir_table, row, DT_BYTES, &obj));
-               if (ret < 0)
-                       goto err;
-               bytes = *(uint64_t *)obj.data;
-               if (gsi->count && (gsi->flags & GSF_PRINT_BYTES)) {
-                       format_size_value(select_conf.size_unit_arg, bytes,
-                               select_conf.size_unit_arg == size_unit_arg_h,
-                               formated_value);
-                       ret = output("%s%s%s",
-                               (gsi->flags & GSF_PRINT_FILES)? "" : "\t",
-                               formated_value,
-                               (gsi->flags & GSF_PRINT_DIRNAME)? "\t" : "\n"
-                       );
-                       if (ret < 0)
-                               goto err;
-               }
-               if (summary) {
-                       num_bytes += bytes;
-                       num_dirs++;
-               }
-       }
-       if (gsi->count && (gsi->flags & GSF_PRINT_DIRNAME)) {
-               ret = get_dir_name_of_row(row, &dirname);
-               if (ret < 0)
-                       goto err;
-               ret = output("%s%s\n",
-                       (gsi->flags & (GSF_PRINT_BYTES | GSF_PRINT_FILES))? "" : "\t",
-                       dirname);
-               free(dirname);
-               if (ret < 0)
-                       goto err;
-       }
-       if (gsi->count > 0)
-               gsi->count--;
-       return 1;
-err:
-       gsi->ret = ret;
-       gsi->osl_errno = (ret == -E_OSL)? osl_errno : 0;
-       return -1;
-}
-
 static int check_loop_return(int ret, int loop_ret, int loop_osl_errno)
 {
        if (ret >= 0)
@@ -554,79 +489,114 @@ static int print_user_lists(void)
        return for_each_admissible_user(print_user_list, NULL);
 }
 
-static int print_global_lists(void)
+static int get_num_files_of_row(struct osl_row *row, uint64_t *num_files)
+{
+       struct osl_object obj;
+       int ret = osl(osl_get_object(dir_table, row, DT_FILES, &obj));
+       if (ret < 0)
+               return ret;
+       *num_files = *(uint64_t *)obj.data;
+       return 1;
+}
+
+static int get_num_bytes_of_row(struct osl_row *row, uint64_t *num_bytes)
+{
+       struct osl_object obj;
+       int ret = osl(osl_get_object(dir_table, row, DT_BYTES, &obj));
+       if (ret < 0)
+               return ret;
+       *num_bytes = *(uint64_t *)obj.data;
+       return 1;
+}
+
+static int global_list_loop_function(struct osl_row *row, void *data)
 {
-       struct global_stats_info gsi;
+       struct global_list_info *gli = data;
+       union atom_value values[] = {
+               [gla_size] = {.num_value = 0ULL},
+               [gla_files] = {.num_value =  0ULL},
+               [gla_dirname] = {.string_value = NULL}
+       };
+       uint64_t num_files, num_bytes;
+       char *dirname, *buf;
        int ret;
-       enum enum_global_list gla = select_conf.global_list_arg;
-       int print_size_list = (gla == global_list_arg_size
-               || gla == global_list_arg_both);
 
-       if (print_size_list) {
-               gsi.count = select_conf.limit_arg;
-               gsi.flags = GSF_PRINT_DIRNAME | GSF_PRINT_BYTES | GSF_COMPUTE_SUMMARY;
-               if (!select_conf.no_headers_given) {
-                       ret = output("By size%s:\n", size_unit_buf);
-                       if (ret < 0)
-                               return ret;
-               }
-               ret = adu_loop_reverse(dir_table, DT_BYTES, &gsi,
-                       global_stats_loop_function, &gsi.ret, &gsi.osl_errno);
-               if (ret < 0)
-                       return ret;
-               ret = output("\n");
-               if (ret < 0)
-                       return ret;
-       }
-       if (gla == global_list_arg_file_count || gla == global_list_arg_both) {
-               gsi.count = select_conf.limit_arg;
-               gsi.flags = GSF_PRINT_DIRNAME | GSF_PRINT_FILES;
-               if (!print_size_list)
-                       gsi.flags |= GSF_COMPUTE_SUMMARY;
-               if (!select_conf.no_headers_given) {
-                       ret = output("By file count%s:\n", count_unit_buf);
-                       if (ret < 0)
-                               return ret;
-               }
-               ret = adu_loop_reverse(dir_table, DT_FILES, &gsi,
-                       global_stats_loop_function, &gsi.ret, &gsi.osl_errno);
-               if (ret < 0)
-                       return ret;
-               ret = output("\n");
-               if (ret < 0)
-                       return ret;
-       }
-       if (gla == global_list_arg_none && !select_conf.no_global_summary_given) {
-               /* must compute summary */
-               gsi.count = select_conf.limit_arg;
-               gsi.flags = GSF_COMPUTE_SUMMARY;
-               ret = adu_loop_reverse(dir_table, DT_FILES, &gsi,
-                       global_stats_loop_function, &gsi.ret, &gsi.osl_errno);
+       check_signals();
+       ret = -E_LOOP_COMPLETE;
+       if (!gli->count)
+               goto err;
+
+       ret = get_num_files_of_row(row, &num_files);
+       if (ret < 0)
+               goto err;
+       values[gla_files].num_value = (long long unsigned)num_files;
+
+       ret = get_num_bytes_of_row(row, &num_bytes);
+       if (ret < 0)
+               goto err;
+       values[gla_size].num_value = (long long unsigned)num_bytes;
+
+       ret = get_dir_name_of_row(row, &dirname);
+       if (ret < 0)
+               goto err;
+       values[gla_dirname].string_value = dirname;
+
+       buf = format_items(gli->fi, values);
+       free(dirname);
+       ret = output("%s", buf);
+       free(buf);
+       if (gli->count > 0)
+               gli->count--;
+       return ret;
+err:
+       gli->ret = ret;
+       gli->osl_errno = (ret == -E_OSL)? osl_errno : 0;
+       return -1;
+}
+
+static int print_global_list(struct format_info *fi)
+{
+       int ret;
+       enum dir_table_columns sort_column = DT_BYTES;
+       struct global_list_info gli = {
+               .fi = fi,
+               .count = select_conf.limit_arg
+       };
+
+       if (!select_conf.no_headers_given) {
+               ret = output("Global list\n");
                if (ret < 0)
                        return ret;
        }
-       return 1;
+       if (select_conf.sort_arg == sort_arg_files)
+               sort_column = DT_FILES;
+       return adu_loop_reverse(dir_table, sort_column, &gli,
+               global_list_loop_function, &gli.ret, &gli.osl_errno);
 }
 
 static int print_statistics(struct select_format_info *sli)
 {
        int ret;
 
-       ret = print_global_lists();
-       if (ret < 0)
-               return ret;
-       ret = print_global_summary(sli->global_summary_fi);
-       free_format_info(sli->global_summary_fi);
-       if (ret < 0)
-               return ret;
-       ret = print_user_lists();
-       if (ret < 0)
-               return ret;
-       ret = print_user_summary(sli->user_summary_fi);
-       free_format_info(sli->user_summary_fi);
-       if (ret < 0)
-               return ret;
-       return 1;
+       switch (select_conf.select_mode_arg) {
+               case select_mode_arg_global_list:
+                       ret = print_global_list(sli->global_list_fi);
+                       free_format_info(sli->global_list_fi);
+                       return ret;
+               case select_mode_arg_global_summary:
+                       ret = print_global_summary(sli->global_summary_fi);
+                       free_format_info(sli->global_summary_fi);
+                       return ret;
+               case select_mode_arg_user_list:
+                       ret = print_user_lists();
+                       return ret;
+               case select_mode_arg_user_summary:
+                       ret = print_user_summary(sli->user_summary_fi);
+                       free_format_info(sli->user_summary_fi);
+                       return ret;
+       };
+       ERROR_LOG("bad select mode\n");
+       return ERRNO_TO_ERROR(-EINVAL);
 }
 
 static int read_uid_file(struct uid_range *admissible_uids)
@@ -733,11 +703,18 @@ int parse_select_options(char *string, struct select_cmdline_parser_params *para
                return ret;
        ret = parse_format_string(select_conf.global_summary_format_arg,
                global_summary_atoms, &sfi->global_summary_fi);
-       if (ret < 0) {
-               free_format_info(sfi->user_summary_fi);
-               return ret;
-       }
+       if (ret < 0)
+               goto global_summary_err;
+       ret = parse_format_string(select_conf.global_list_format_arg,
+               global_list_atoms, &sfi->global_list_fi);
+       if (ret < 0)
+               goto global_list_err;
        return 1;
+global_list_err:
+       free_format_info(sfi->global_summary_fi);
+global_summary_err:
+       free_format_info(sfi->user_summary_fi);
+       return ret;
 help:
        line = select_conf.detailed_help_given?
                select_args_info_detailed_help : select_args_info_help;
index d8f3ae3..b0b1daa 100644 (file)
@@ -33,6 +33,20 @@ details="
        This is mostly useful to feed the output of adu to scripts.
 "
 
+option "select-mode" m
+#~~~~~~~~~~~~~~~~~~~~~
+"How to print the results of the query"
+enum typestr="<key>"
+values="global_list","global_summary","user_list","user_summary"
+default="global_list"
+optional
+details="
+       global_list: List of directories, regardless of owner.
+       global_summary: Only print totals.
+       user_list: Print a list for each admissible uid.
+       user_summary Print totals for each admissible uid.
+"
+
 option "sort" s
 #~~~~~~~~~~~~~~~
 "how to sort the output"
@@ -145,6 +159,18 @@ details="
 section "Format strings"
 ########################
 
+option "global-list-format" -
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"How to format the global list"
+string typestr="<format>"
+default="%(size:r:8) %(files:r:8) %(dirname)\n"
+details="
+       size: Total size of all files
+       files: The number of files
+       dirname: The name of the directory
+"
+
+optional
 option "global-summary-format" -
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "How to format the global summary"