Fix user summary accounting if pattern is given.
[adu.git] / select.c
index 4ebfbbfa02b10903a3766b1855cbf950810af9e9..15ad7070844da6915970eb992df8d686f8408d81 100644 (file)
--- a/select.c
+++ b/select.c
@@ -72,18 +72,18 @@ enum user_list_atoms {USER_LIST_ATOMS};
 #undef ATOM
 
 /* user list header */
-#define USER_LIST_HEADER_ATOMS \
+#define USER_LIST_HEADER_TRAILER_ATOMS \
        ATOM(pw_name, STRING) \
        ATOM(uid, ID)
 
 #define ATOM(x, y) { .name = #x, .type = AT_ ## y},
-struct atom user_list_header_atoms[] = {
-       USER_LIST_HEADER_ATOMS
+struct atom user_list_header_trailer_atoms[] = {
+       USER_LIST_HEADER_TRAILER_ATOMS
        {.name = NULL}
 };
 #undef ATOM
 #define ATOM(x, y) ulha_ ## x,
-enum user_list_header_atoms {USER_LIST_HEADER_ATOMS};
+enum user_list_header_trailer_atoms {USER_LIST_HEADER_TRAILER_ATOMS};
 #undef ATOM
 
 /* user summary */
@@ -141,6 +141,7 @@ struct user_list_info {
 struct user_list_format_info {
        struct format_info *fi;
        struct format_info *header_fi;
+       struct format_info *trailer_fi;
 };
 
 struct user_summary_info {
@@ -430,9 +431,12 @@ static int print_global_summary(struct format_info *fi)
        buf = format_items(fi, values);
        ret = output("%s", buf);
        free(buf);
-       return ret;
+       if (ret < 0)
+               return ret;
+       return output("%s", select_conf.trailer_arg);
 }
 
+/* row: a pointer to a row of the *user* table */
 static int user_summary_loop_function(struct osl_row *row, void *data)
 {
        struct user_summary_info *usi = data;
@@ -441,7 +445,7 @@ static int user_summary_loop_function(struct osl_row *row, void *data)
 
        if (usi->preg) {
                char *dirname;
-               ret = get_dir_name_of_row(row, &dirname);
+               ret = get_dir_name_of_user_row(row, usi->ui, &dirname);
                if (ret < 0)
                        goto err;
                ret = dir_is_admissible(dirname, usi->preg, usi->inverse_matching);
@@ -590,8 +594,11 @@ static int print_user_summary(struct format_info *fi)
        for (i = 0; i < usld.num_admissible_users; i++) {
                if (select_conf.limit_arg >= 0 && i > select_conf.limit_arg)
                        break;
-               print_user_summary_line(usld.usis + i, usld.fi);
+               ret = print_user_summary_line(usld.usis + i, usld.fi);
+               if (ret < 0)
+                       goto out;
        }
+       ret = output("%s", select_conf.trailer_arg);
 out:
        free(usld.usis);
        return ret;
@@ -662,12 +669,12 @@ static int print_user_list(struct user_info *ui, void *data)
                .fi = ulfi->fi,
                .count = select_conf.limit_arg
        };
-       union atom_value header_values[] = {
+       union atom_value header_trailer_values[] = {
                [ulha_uid] = {.num_value = (long long unsigned)ui->uid},
                [ulha_pw_name] = {.string_value = ui->pw_name?
                        ui->pw_name : "?"}
        };
-       char *buf = format_items(ulfi->header_fi, header_values);
+       char *buf = format_items(ulfi->header_fi, header_trailer_values);
 
        ret = output("%s", buf);
        free(buf);
@@ -684,6 +691,11 @@ static int print_user_list(struct user_info *ui, void *data)
        ret = adu_loop_reverse(ui->table, sort_column, &uli,
                user_list_loop_function, &uli.ret, &uli.osl_errno);
        free_regex(uli.preg);
+       if (ret < 0)
+               return ret;
+       buf = format_items(ulfi->trailer_fi, header_trailer_values);
+       ret = output("%s", buf);
+       free(buf);
        return ret;
 }
 
@@ -692,12 +704,18 @@ static int print_user_lists(struct format_info *fi)
        struct user_list_format_info ulfi = {.fi = fi};
        char *header_fmt = select_conf.header_given?
                select_conf.header_arg : "uid %(uid)(%(pw_name)):\n";
+       char *trailer_fmt = select_conf.trailer_arg;
        int ret = parse_format_string(header_fmt,
-               user_list_header_atoms, &ulfi.header_fi);
+               user_list_header_trailer_atoms, &ulfi.header_fi);
+       if (ret < 0)
+               return ret;
+       ret = parse_format_string(trailer_fmt,
+               user_list_header_trailer_atoms, &ulfi.trailer_fi);
        if (ret < 0)
                return ret;
        ret = for_each_admissible_user(print_user_list, &ulfi);
        free_format_info(ulfi.header_fi);
+       free_format_info(ulfi.trailer_fi);
        return ret;
 }
 
@@ -778,7 +796,9 @@ static int print_global_list(struct format_info *fi)
        ret = adu_loop_reverse(dir_table, sort_column, &gli,
                global_list_loop_function, &gli.ret, &gli.osl_errno);
        free_regex(gli.preg);
-       return ret;
+       if (ret < 0)
+               return ret;
+       return output("%s", select_conf.trailer_arg);
 }
 
 static int print_statistics(struct format_info *fi)
@@ -792,14 +812,15 @@ static int print_statistics(struct format_info *fi)
                return print_user_lists(fi);
        case select_mode_arg_user_summary:
                return print_user_summary(fi);
+       default:
+               ERROR_LOG("bad select mode\n");
+               return -ERRNO_TO_ERROR(EINVAL);
        };
-       ERROR_LOG("bad select mode\n");
-       return -ERRNO_TO_ERROR(EINVAL);
 }
 
 static int open_pipe(char *path)
 {
-       int p[2], ret, argc;
+       int p[2], ret;
        char **argv;
 
        ret = pipe(p);
@@ -820,7 +841,7 @@ static int open_pipe(char *path)
        if (p[0] != STDIN_FILENO)
                dup2(p[0], STDIN_FILENO);
        DEBUG_LOG("executing %s\n", path);
-       argc = split_args(path, &argv, " \t");
+       split_args(path, &argv, " \t");
        execvp(argv[0], argv);
        ERROR_LOG("error executing %s: %s\n", path,
                adu_strerror(ERRNO_TO_ERROR(errno)));
@@ -912,8 +933,7 @@ int run_select_query(struct uid_range *admissible_uids, struct format_info *fi)
        if (ret < 0)
                goto out;
        check_signals();
-       ret = open_admissible_user_tables(conf.database_dir_arg,
-               admissible_uids);
+       ret = open_admissible_user_tables(admissible_uids);
        if (ret < 0)
                goto out;
        check_signals();
@@ -929,11 +949,11 @@ out:
 /** Default format string for global_list mode. */
 #define GLOBAL_LIST_DFLT_FMT "%(size:r:8) %(files:r:8) %(dirname)\n"
 /** Default format string for global_summary mode. */
-#define GLOBAL_SUMMARY_DFLT_FMT "#directories: %(dirs), #files: %(files), size: %(size)\n\n"
+#define GLOBAL_SUMMARY_DFLT_FMT "#directories: %(dirs), #files: %(files), size: %(size)\n"
 /** Default format string for user_list mode. */
 #define USER_LIST_DFLT_FMT "%(size:r:5) %(files:r:5) %(dirname)\n"
 /** Default format string for user_summary mode. */
-#define USER_SUMMARY_DFLT_FMT "%(pw_name:l:16) %(uid:r:5) %(dirs:r:5) %(files:r:5) %(size:r:5)\n"
+#define USER_SUMMARY_DFLT_FMT "%(pw_name:l:16) %(uid:r:6) %(dirs:r:5) %(files:r:5) %(size:r:5)\n"
 
 static int setup_format_string(char *fmt, struct format_info **fi)
 {
@@ -1063,7 +1083,7 @@ int com_select(void)
        ret = parse_select_options(conf.select_options_arg, &params,
                &admissible_uids, &fi);
        if (ret > 0) {
-               ret = read_uid_file(conf.database_dir_arg);
+               ret = read_uid_file();
                if (ret < 0)
                        goto out;
                ret = run_select_query(admissible_uids, fi);