X-Git-Url: http://git.tuebingen.mpg.de/?p=adu.git;a=blobdiff_plain;f=adu.c;h=4c1c62c0d56bb3955dabd1cfb52499d6d6fca4a3;hp=c21c37f0f5e5c77b659ed9d50f15e6cdadccfded;hb=b542a1e3c66b7b01cd2dc91749c5154e25cbff1e;hpb=0356ff402eec5e75a2c9e24c2fcb5b2c3a1cb63d diff --git a/adu.c b/adu.c index c21c37f..4c1c62c 100644 --- a/adu.c +++ b/adu.c @@ -28,6 +28,9 @@ uint64_t num_bytes = 0; /** The number of different uids found so far. */ uint32_t num_uids = 0; +/** This is always a power of two. It is set in create_hash_table(). */ +static uint32_t uid_hash_table_size; + /** * Contains info for each user that owns at least one regular file. * @@ -35,7 +38,7 @@ uint32_t num_uids = 0; * option occupy a slot in this hash table. This allows to find out * quicky whether a uid is admissible. And yes, this has to be fast. */ -struct user_info *uid_hash_table = NULL; +static struct user_info *uid_hash_table; /** * The table containing the directory names and statistics. @@ -285,15 +288,34 @@ err: return ret; } -#define uid_hash_bits 8 -uint32_t uid_hash_table_size = 1 << uid_hash_bits; +int for_each_admissible_user(int (*func)(struct user_info *, void *), + void *data) +{ + struct user_info *ui = uid_hash_table; + + if (!ui) + return -ERRNO_TO_ERROR(EFAULT); + + for (; ui < uid_hash_table + uid_hash_table_size; ui++) { + int ret; + + if (!ui_used(ui) || !ui_admissible(ui)) + continue; + ret = func(ui, data); + if (ret < 0) + return ret; + } + return 1; +} + #define PRIME1 0x811c9dc5 #define PRIME2 0x01000193 -void create_hash_table(void) +void create_hash_table(unsigned bits) { - uid_hash_table = adu_calloc(uid_hash_table_size - * sizeof(struct user_info)); + uid_hash_table_size = 1 << bits; + uid_hash_table = adu_calloc(uid_hash_table_size * + sizeof(struct user_info)); } static void free_hash_table(void) @@ -315,12 +337,10 @@ static void close_dir_table(void) dir_table = NULL; } -static void close_user_table(struct user_info *ui) +static int close_user_table(struct user_info *ui, __a_unused void *data) { 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", @@ -335,14 +355,12 @@ static void close_user_table(struct user_info *ui) ui->desc = NULL; ui->table = NULL; ui->flags = 0; + return 1; } static void close_user_tables(void) { - struct user_info *ui; - - FOR_EACH_USER(ui) - close_user_table(ui); + for_each_admissible_user(close_user_table, NULL); } void close_all_tables(void) @@ -372,6 +390,8 @@ static int init_signals(void) return -E_SIGNAL_SIG_ERR; if (signal(SIGTERM, &signal_handler) == SIG_ERR) return -E_SIGNAL_SIG_ERR; + if (signal(SIGPIPE, &signal_handler) == SIG_ERR) + return -E_SIGNAL_SIG_ERR; return 1; } @@ -470,6 +490,10 @@ static int check_args(void) { int i, ret; + + if (conf.create_given && !conf.base_dir_given) + return -E_SYNTAX; + /* remove trailing slashes from base-dir arg */ if (conf.base_dir_given) { size_t len = strlen(conf.base_dir_arg); @@ -504,16 +528,16 @@ int main(int argc, char **argv) struct cmdline_parser_params params = { .override = 0, .initialize = 1, - .check_required = 0, - .check_ambiguity = 0, + .check_required = 1, + .check_ambiguity = 1, .print_errors = 1 }; cmdline_parser_ext(argc, argv, &conf, ¶ms); /* aborts on errors */ - ret = init_signals(); + ret = check_args(); if (ret < 0) goto out; - ret = check_args(); + ret = init_signals(); if (ret < 0) goto out; ret = -E_SYNTAX;