]> git.tuebingen.mpg.de Git - adu.git/blobdiff - adu.c
Add create.c.
[adu.git] / adu.c
diff --git a/adu.c b/adu.c
index c21c37f0f5e5c77b659ed9d50f15e6cdadccfded..4c1c62c0d56bb3955dabd1cfb52499d6d6fca4a3 100644 (file)
--- 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, &params); /* 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;