]> git.tuebingen.mpg.de Git - adu.git/blobdiff - adu.c
Merge branch 'refs/heads/t/doc-improvements'
[adu.git] / adu.c
diff --git a/adu.c b/adu.c
index a586ade942d892312a7b8b552614b2cfe3fbc88e..fe0caa501a2ce35e5f83273af8dace42f420bde4 100644 (file)
--- a/adu.c
+++ b/adu.c
@@ -1,4 +1,20 @@
-/** \file adu.c The main functions used by all modes of operation. */
+/*
+ * Copyright (C) 2008 Andre Noll <maan@tuebingen.mpg.de>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file adu.c \brief The main functions used by all modes of operation. */
+
+/**
+ * \mainpage adu API reference
+ *
+ * - Modes of operation: \ref select.c, \ref create.c, \ref interactive.c
+ * - User handling: \ref user.c
+ * - Error handling: \ref error.h
+ * - Library-type functions: \ref fd.c, \ref format.c, \ref string.c, \ref portable_io.h, \ref bloom.c
+ */
+
 #include "adu.h"
 #include <dirent.h> /* readdir() */
 #include <pwd.h>
 #include "string.h"
 #include "error.h"
 
+/** Define the array of error descriptions. */
 DEFINE_ERRLIST;
+
+/**
+ * The error code of the last called osl library function.
+ *
+ * \sa osl().
+ */
 int osl_errno;
 
 /** In case a signal is received, its number is stored here. */
@@ -23,8 +46,8 @@ struct gengetopt_args_info conf;
 /** Options passed to --select-options. */
 struct select_args_info select_conf;
 
-/** The number of different uids found so far. */
-uint32_t num_uids = 0;
+/** Computed database dir */
+char *database_dir;
 
 /**
  * The table containing the directory names and statistics.
@@ -102,12 +125,32 @@ __printf_2_3 void __log(int ll, const char* fmt,...)
        va_end(argp);
 }
 
+/**
+ * adu's version of strerror(3).
+ *
+ * \param num The error number.
+ *
+ * \return The error text of \a num.
+ */
+const char *adu_strerror(int num)
+{
+       assert(num > 0);
+       if (num == E_OSL) {
+               assert(osl_errno > 0);
+               return osl_strerror((osl_errno));
+       }
+       if (IS_SYSTEM_ERROR(num))
+               return strerror((num) & ((1 << SYSTEM_ERROR_BIT) - 1));
+       return adu_errlist[num];
+}
+
 static void close_dir_table(void)
 {
        int ret;
 
        if (!dir_table)
                return;
+       NOTICE_LOG("closing dir table\n");
        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));
@@ -115,7 +158,7 @@ static void close_dir_table(void)
        dir_table = NULL;
 }
 
-void close_all_tables(void)
+static void close_all_tables(void)
 {
        close_dir_table();
        close_user_tables();
@@ -126,6 +169,12 @@ static void signal_handler(int s)
        signum = s;
 }
 
+/**
+ * Check whether to terminate adu.
+ *
+ * Check whether a signal was caught that should terminate the
+ * adu process. If yes, close all osl tables and exit gracefully.
+ */
 void check_signals(void)
 {
        if (likely(!signum))
@@ -135,29 +184,59 @@ void check_signals(void)
        exit(EXIT_FAILURE);
 }
 
+static int catch_signal(int sig)
+{
+       struct sigaction act;
+
+       act.sa_handler = signal_handler;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;
+       return sigaction(sig, &act, NULL);
+}
+
 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;
-       if (signal(SIGPIPE, &signal_handler) == SIG_ERR)
-               return -E_SIGNAL_SIG_ERR;
+       if (catch_signal(SIGINT) < 0)
+               return -E_SIGACTION;
+       if (catch_signal(SIGTERM) < 0)
+               return -E_SIGACTION;
+       if (catch_signal(SIGPIPE) < 0)
+               return -E_SIGACTION;
        return 1;
 }
 
+/**
+ * Open the directory table.
+ *
+ * \param create If non-zero, create the table first.
+ *
+ * \return Standard.
+ */
 int open_dir_table(int create)
 {
-       dir_table_desc.dir = adu_strdup(conf.database_dir_arg);
+       int ret;
+
+       if (dir_table)
+               return 1;
 
+       dir_table_desc.dir = adu_strdup(database_dir);
        if (create) {
-               int ret = osl(osl_create_table(&dir_table_desc));
+               INFO_LOG("creating database directory structure\n");
+               ret = mkpath(dir_table_desc.dir, 0777);
+               if (ret < 0)
+                       goto out;
+               NOTICE_LOG("creating dir table\n");
+               ret = osl(osl_create_table(&dir_table_desc));
                if (ret < 0) {
-                       free((char *)dir_table_desc.dir);
-                       return ret;
+                       ERROR_LOG("could not create %s\n", dir_table_desc.dir);
+                       goto out;
                }
        }
+       INFO_LOG("opening dir table\n");
        return osl(osl_open_table(&dir_table_desc, &dir_table));
+out:
+       free((char *)dir_table_desc.dir);
+       return ret;
 }
 
 static int check_args(void)
@@ -181,10 +260,9 @@ static int check_args(void)
        return 1;
 }
 
-static int print_complete_help_and_die(void)
+static void print_complete_help_and_die(void)
 {
        const char **line;
-       select_cmdline_parser_init(&select_conf);
 
        printf("%s-%s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
        printf("%s\n\n", gengetopt_args_info_purpose);
@@ -207,23 +285,66 @@ static int print_complete_help_and_die(void)
 
        printf("Interactive commands:\n");
        print_interactive_help();
+       cmdline_parser_free(&conf);
+       select_cmdline_parser_free(&select_conf);
        exit(EXIT_FAILURE);
 }
 
+static void get_database_dir_or_die(void)
+{
+       char *tmp;
+
+       if (conf.database_dir_given)
+               tmp = adu_strdup(conf.database_dir_arg);
+       else {
+               if (!conf.base_dir_arg) {
+                       EMERG_LOG("fatal: neither database dir "
+                               "nor base dir given\n");
+                       exit(EXIT_FAILURE);
+               }
+               tmp = make_message("%s%s",
+                       conf.database_root_arg, conf.base_dir_arg);
+       }
+       /*
+        * As we change the cwd during database creation, database_dir
+        * must be an absolute path.
+        */
+       database_dir = absolute_path(tmp);
+       free(tmp);
+       if (database_dir)
+               return;
+       EMERG_LOG("failed to get absolute path of database dir\n");
+       exit(EXIT_FAILURE);
+}
+
+/**
+ * The main function of adu.
+ *
+ * \param argc Usual argument count.
+ * \param argv Usual argument vector.
+ *
+ * Check command line options, init the signal handlers and
+ * call the main function of the selected mode.
+ *
+ * \return \p EXIT_SUCCESS on success, \p EXIT_FAILURE otherwise.
+ */
 int main(int argc, char **argv)
 {
        int ret;
        struct cmdline_parser_params params = {
-               .override = 0,
+               .override = 1,
                .initialize = 1,
                .check_required = 0,
                .check_ambiguity = 0,
                .print_errors = 0
        };
+       select_cmdline_parser_init(&select_conf);
+       cmdline_parser_init(&conf);
        /* ignore errors and print complete help if --help was given */
        cmdline_parser_ext(argc, argv, &conf, &params);
        if (conf.help_given || conf.detailed_help_given)
                print_complete_help_and_die();
+       cmdline_parser_free(&conf);
        params.check_required = 1;
        params.check_ambiguity = 1;
        params.print_errors = 1;
@@ -237,7 +358,7 @@ int main(int argc, char **argv)
        ret = init_signals();
        if (ret < 0)
                goto out;
-       ret = -E_SYNTAX;
+       get_database_dir_or_die();
        if (conf.select_given)
                ret = com_select();
        else if (conf.create_given)
@@ -247,9 +368,13 @@ int main(int argc, char **argv)
        if (ret < 0)
                goto out;
 out:
+       close_all_tables();
        if (ret < 0) {
                ERROR_LOG("%s\n", adu_strerror(-ret));
                return -EXIT_FAILURE;
        }
+       free(database_dir);
+       cmdline_parser_free(&conf);
+       select_cmdline_parser_free(&select_conf);
        return EXIT_SUCCESS;
 }