/** The decimal representation of an uint64_t never exceeds that size. */
#define FORMATED_VALUE_SIZE 25
+#define FOR_EACH_USER(ui) for (ui = uid_hash_table; ui && ui < uid_hash_table \
+ + uid_hash_table_size; ui++)
+
/**
* Contains info for each user that owns at least one regular file.
return ret;
}
-
/** 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)))
return 1;
}
+static void close_dir_table(void)
+{
+ int ret;
+
+ if (!dir_table)
+ return;
+ ret = osl(osl_close_table(dir_table, OSL_MARK_CLEAN));
+ if (ret < 0)
+ ERROR_LOG("failed to close dir table: %s\n", adu_strerror(-ret));
+ free((char *)dir_table_desc.dir);
+ dir_table = NULL;
+}
+
+static void close_user_table(struct user_info *ui)
+{
+ int ret;
+
+ if (!ui || !ui_used(ui) || !ui_admissible(ui))
+ return;
+ ret = osl(osl_close_table(ui->table, OSL_MARK_CLEAN));
+ if (ret < 0)
+ ERROR_LOG("failed to close user table %u: %s\n",
+ (unsigned) ui->uid, adu_strerror(-ret));
+ free((char *)ui->desc->name);
+ ui->desc->name = NULL;
+ free((char *)ui->desc->dir);
+ ui->desc->dir = NULL;
+ free(ui->desc);
+ ui->desc = NULL;
+ ui->table = NULL;
+ ui->flags = 0;
+}
+
+static void close_user_tables(void)
+{
+ struct user_info *ui;
+
+ FOR_EACH_USER(ui)
+ close_user_table(ui);
+}
+
+static void close_all_tables(void)
+{
+ close_dir_table();
+ close_user_tables();
+ free_hash_table();
+}
+
+static int signum;
+
+static void signal_handler(int s)
+{
+ signum = s;
+}
+
+static void check_signals(void)
+{
+ if (likely(!signum))
+ return;
+ EMERG_LOG("caught signal %d\n", signum);
+ close_all_tables();
+ exit(EXIT_FAILURE);
+}
+
+static int init_signals(void)
+{
+ if (signal(SIGINT, &signal_handler) == SIG_ERR)
+ return -E_SIGNAL_SIG_ERR;
+ if (signal(SIGTERM, &signal_handler) == SIG_ERR)
+ return -E_SIGNAL_SIG_ERR;
+ return 1;
+}
+
/*
* We use a hash table of size s=2^uid_hash_bits to map the uids into the
* interval [0..s]. Hash collisions are treated by open addressing, i.e.
% uid_hash_table_size;
}
-#define FOR_EACH_USER(ui) for (ui = uid_hash_table; ui && ui < uid_hash_table \
- + uid_hash_table_size; ui++)
-
enum search_uid_flags {
OPEN_USER_TABLE = 1,
CREATE_USER_TABLE = 2,
uint64_t dir_size = 0, dir_files = 0;
uint64_t this_dir_num = ++num_dirs;
+ check_signals();
DEBUG_LOG("----------------- %llu: %s\n", (long long unsigned)num_dirs, dirname);
ret = para_opendir(dirname, &dir, &cwd_fd);
if (ret < 0) {
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;
int ret, summary = usi->flags & GSF_COMPUTE_SUMMARY;
char formated_value[FORMATED_VALUE_SIZE];
+ check_signals();
if (!usi->count && !summary) {
ret = -E_LOOP_COMPLETE;
goto err;
dir_table_desc.dir = para_strdup(conf.database_dir_arg);
return osl(osl_open_table(&dir_table_desc, &dir_table));
}
-
-static void close_dir_table(void)
-{
- int ret;
-
- if (!dir_table)
- return;
- ret = osl(osl_close_table(dir_table, OSL_MARK_CLEAN));
- if (ret < 0)
- ERROR_LOG("failed to close dir table: %s\n", adu_strerror(-ret));
- free((char *)dir_table_desc.dir);
- dir_table = NULL;
-}
-
-static void close_user_table(struct user_info *ui)
-{
- int ret;
-
- if (!ui || !ui_used(ui) || !ui_admissible(ui))
- return;
- ret = osl(osl_close_table(ui->table, OSL_MARK_CLEAN));
- if (ret < 0)
- ERROR_LOG("failed to close user table %u: %s\n",
- (unsigned) ui->uid, adu_strerror(-ret));
- free((char *)ui->desc->name);
- ui->desc->name = NULL;
- free((char *)ui->desc->dir);
- ui->desc->dir = NULL;
- free(ui->desc);
- ui->desc = NULL;
- ui->table = NULL;
- ui->flags = 0;
-}
-
-static void close_user_tables(void)
-{
- struct user_info *ui;
-
- FOR_EACH_USER(ui)
- close_user_table(ui);
-}
-
-static void close_all_tables(void)
-{
- close_dir_table();
- close_user_tables();
- free_hash_table();
-}
-
static int com_create()
{
uint64_t zero = 0ULL;
if (ret < 0)
return ret;
+ check_signals();
ret = open_dir_table();
if (ret < 0)
return ret;
+ check_signals();
ret = scan_dir(conf.base_dir_arg, &zero);
if (ret < 0)
goto out;
ret = open_dir_table();
if (ret < 0)
return ret;
+ check_signals();
ret = read_uid_file();
if (ret < 0)
return ret;
+ check_signals();
ret = print_statistics();
close_all_tables();
return ret;
};
cmdline_parser_ext(argc, argv, &conf, ¶ms); /* aborts on errors */
+ ret = init_signals();
+ if (ret < 0)
+ goto out;
ret = check_args();
if (ret < 0)
goto out;