+ ret = write_uid_list();
+out:
+ close_all_tables();
+ return ret;
+}
+
+static int read_uid_file(void)
+{
+ size_t size;
+ uint32_t n;
+ char *filename = get_uid_list_name(), *map;
+ int ret = mmap_full_file(filename, O_RDONLY, (void **)&map, &size, NULL);
+
+ if (ret < 0) {
+ INFO_LOG("failed to map %s\n", filename);
+ free(filename);
+ return ret;
+ }
+ num_uids = size / 4;
+ INFO_LOG("found %u uids in %s\n", (unsigned)num_uids, filename);
+ free(filename);
+ /* hash table size should be a power of two and larger than the number of uids */
+ uid_hash_table_size = 4;
+ while (uid_hash_table_size < num_uids)
+ uid_hash_table_size *= 2;
+ create_hash_table();
+ for (n = 0; n < num_uids; n++) {
+ uint32_t uid = read_u32(map + n * sizeof(uid));
+ ret = search_uid(uid, OPEN_USER_TABLE, NULL);
+ if (ret < 0)
+ goto out;
+ }
+out:
+ para_munmap(map, size);
+ return ret;
+}
+
+static int com_select(void)
+{
+ int ret;
+
+ if (conf.count_unit_arg != count_unit_arg_h)
+ count_unit_buf[1] = count_unit_abbrevs[conf.count_unit_arg];
+ else
+ count_unit_buf[0] = '\0';
+ if (conf.size_unit_arg != size_unit_arg_h)
+ size_unit_buf[1] = size_unit_abbrevs[conf.size_unit_arg];
+ else
+ size_unit_buf[0] = '\0';
+
+ ret = open_dir_table();
+ if (ret < 0)
+ return ret;
+ ret = read_uid_file();
+ if (ret < 0)
+ return ret;
+ ret = print_statistics();
+ close_all_tables();
+ return ret;
+}
+
+static int check_args(void)
+{
+ int i, ret;
+
+ /* remove trailing slashes from base-dir arg */
+ if (conf.base_dir_given) {
+ size_t len = strlen(conf.base_dir_arg);
+ for (;;) {
+ if (!len) /* empty string */
+ return -ERRNO_TO_ERROR(EINVAL);
+ if (!--len) /* length 1 is always OK */
+ break;
+ if (conf.base_dir_arg[len] != '/')
+ break; /* no trailing slash, also OK */
+ conf.base_dir_arg[len] = '\0';
+ }
+ }
+ if (!conf.uid_given)
+ return 0;
+ admissible_uids = para_malloc(conf.uid_given * sizeof(*admissible_uids));
+ for (i = 0; i < conf.uid_given; i++) {
+ ret = parse_uid_range(conf.uid_arg[i], admissible_uids + i);
+ if (ret < 0)
+ goto err;
+ }
+ return 1;
+err:
+ free(admissible_uids);
+ admissible_uids = NULL;
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ struct cmdline_parser_params params = {
+ .override = 0,
+ .initialize = 1,
+ .check_required = 0,
+ .check_ambiguity = 0,
+ .print_errors = 1
+ };
+
+ cmdline_parser_ext(argc, argv, &conf, ¶ms); /* aborts on errors */
+ ret = check_args();