]> git.tuebingen.mpg.de Git - adu.git/commitdiff
Merge commit 'fml/master'
authorAndre Noll <maan@systemlinux.org>
Tue, 10 Feb 2009 22:08:20 +0000 (23:08 +0100)
committerAndre Noll <maan@systemlinux.org>
Tue, 10 Feb 2009 22:08:20 +0000 (23:08 +0100)
Conflicts:
adu.ggo
user.c

13 files changed:
Makefile
adu.c
adu.ggo
adu.h
create.c
error.h
fd.c
fd.h
interactive.c
select.c
string.c
user.c
user.h

index a4293c70855de02f0d9069ff3ec9e90ce4958886..880ba86952ca108d95de2b65b7be38d1263ed8b0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,8 @@ CPPFLAGS += -I/usr/local/include
 
 LDFLAGS += -L/usr/local/lib
 
+PREFIX ?= /usr/local
+
 
 ifeq (,$(findstring BSD,$(uname_S)))
        CPPFLAGS += -D_LARGEFILE64_SOURCE
@@ -82,3 +84,7 @@ index.html: adu.1.html index.html.in INSTALL README
        sed -e '1,/@INSTALL@/d' -e '/@MAN_PAGE@/,$$d' index.html.in >> $@
        sed -e '1,/Return to Main Contents/d' -e '/Index/,$$d' adu.1.html >> $@
        sed -e '1,/@MAN_PAGE@/d' index.html.in >> $@
+
+install: adu adu.1
+       install -s adu $(PREFIX)/bin
+       install -m 0644 adu.1 $(PREFIX)/man/man1
diff --git a/adu.c b/adu.c
index 82c876a96eb550956f60db458207c2777e67cb86..9fb70bed1446f41d4a6049db036e28c5bf6d971e 100644 (file)
--- a/adu.c
+++ b/adu.c
@@ -46,6 +46,8 @@ struct gengetopt_args_info conf;
 /** Options passed to --select-options. */
 struct select_args_info select_conf;
 
+/** Computed database dir */
+char *database_dir;
 
 /**
  * The table containing the directory names and statistics.
@@ -183,21 +185,27 @@ static int init_signals(void)
  */
 int open_dir_table(int create)
 {
+       int ret;
 
        if (dir_table)
                return 1;
-       dir_table_desc.dir = adu_strdup(conf.database_dir_arg);
 
+       dir_table_desc.dir = adu_strdup(database_dir);
        if (create) {
+               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");
-               int ret = osl(osl_create_table(&dir_table_desc));
-               if (ret < 0) {
-                       free((char *)dir_table_desc.dir);
-                       return ret;
-               }
+               ret = osl(osl_create_table(&dir_table_desc));
+               if (ret < 0)
+                       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)
@@ -293,6 +301,11 @@ int main(int argc, char **argv)
        if (ret < 0)
                goto out;
        ret = -E_SYNTAX;
+       if (conf.database_dir_given)
+               database_dir = adu_strdup(conf.database_dir_arg);
+       else
+               database_dir = make_message("%s%s",
+                       conf.database_root_arg, conf.base_dir_arg);
        if (conf.select_given)
                ret = com_select();
        else if (conf.create_given)
@@ -307,6 +320,7 @@ out:
                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;
diff --git a/adu.ggo b/adu.ggo
index 5da5908d7b9d7c467eac1044f0b3a75306028822..2ddc34e234acd87538fcfbc49abe9f53a83c1fbf 100644 (file)
--- a/adu.ggo
+++ b/adu.ggo
@@ -14,17 +14,18 @@ usage patterns of subdirectories and/or files owned by a given user id.
 section "General options"
 #########################
 
-option "database-dir" d
-#~~~~~~~~~~~~~~~~~~~~~~
-"directory containing the osl tables"
-string typestr="path"
-required
+option "config-file" c
+#~~~~~~~~~~~~~~~~~~~~~
+"(default='~/.adurc')"
+string typestr="filename"
+optional
 details="
-       Full path to the directory containing the osl tables. This
-       directory must exist. It must be writable for the user running
-       adu in --create mode and readable in --select mode.
-
+       Options may be given at the command line or in the
+       configuration file. As usual, if an option is given both at
+       the command line and in the configuration file, the command
+       line option takes precedence.
 "
+
 option "loglevel" l
 #~~~~~~~~~~~~~~~~~~
 "Set loglevel (0-6)"
@@ -36,6 +37,46 @@ details="
        goes to stdout. Lower values mean more verbose logging.
 "
 
+defgroup "database"
+#==================
+groupdesc="
+       There are two ways to specify a database directory. You can either
+       specify a full path using the database-dir option or a root path
+       using the database-root option. In the latter case, a directory
+       structure matching that of the base-dir argument is created
+       below the given full path.
+
+       The advantage of using database-root is that the base-dir is
+       used to find the relevant database both in create and select mode
+       and you do not have to care for setting the database-dir explicitly.
+"
+
+groupoption "database-dir" d
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"directory containing the osl tables"
+group="database"
+string typestr="path"
+details="
+       Full path to the directory containing the osl tables. This
+       directory is created if it does not exist. It must be writable for the
+       user running adu in --create mode and readable in --select mode.
+"
+
+groupoption "database-root" r
+#~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+"directory containing directories containing the osl tables"
+group="database"
+string typestr="path"
+default="/var/lib/adu"
+dependon="base-dir"
+optional
+details="
+       Base path to the directory containing the osl tables. The real
+       database-dir is generated by appending base-dir. This
+       directory is created if it does not exist. When used in select
+       mode you have to specify the base-dir as well.
+"
+
 ###############
 section "Modes"
 ###############
@@ -46,7 +87,6 @@ groupdesc="
        adu may be started in one of three possible modes, each of
        which corresponds to a different command line option. Exactly
        one of these options must be given.
-
 "
 required
 
@@ -93,7 +133,6 @@ option "base-dir" b
 #~~~~~~~~~~~~~~~~~~
 "directory to traverse"
 string typestr="path"
-dependon="create"
 optional
 details="
        The base directory to be traversed recursively. A warning
diff --git a/adu.h b/adu.h
index 5e99709c3679571b70ccaf5db5bc70c62957eb83..42b9471ee251e0ccf28ffd185628bfdd3d315634 100644 (file)
--- a/adu.h
+++ b/adu.h
@@ -139,6 +139,9 @@ extern struct osl_table *dir_table;
 /** The adu command line options. */
 extern struct gengetopt_args_info conf;
 
+/** Computed database dir. */
+extern char *database_dir;
+
 /**
  * The select command line options.
  *
index 2925d570d862b150b5786531c6a5dce51f5cb0e5..87b0b9a0198a471e0a5a886dbce84a09c49f4901 100644 (file)
--- a/create.c
+++ b/create.c
@@ -131,7 +131,7 @@ static int scan_dir(char *dirname, uint64_t *parent_dir_num)
                dir_size += size;
                dir_files++;
                uid = s.st_uid;
-               ret = create_user_table(conf.database_dir_arg, uid, &ui);
+               ret = create_user_table(uid, &ui);
                if (ret < 0)
                        goto out;
                ret = update_user_row(ui->table, this_dir_num, &size);
@@ -173,7 +173,7 @@ int com_create(void)
        ret = scan_dir(conf.base_dir_arg, &zero);
        if (ret < 0)
                goto out;
-       ret = write_uid_file(conf.database_dir_arg);
+       ret = write_uid_file();
 out:
        return ret;
 }
diff --git a/error.h b/error.h
index 00bdede471394e7a051a81674bdda18aa4d1c4cd..5a5aefb987dad5f4946844e3153f2c8f12d0f282 100644 (file)
--- a/error.h
+++ b/error.h
@@ -42,7 +42,8 @@
        _ERROR(BAD_UNIT, "invalid unit specifier") \
        _ERROR(BAD_ATOM, "invalid atom") \
        _ERROR(BAD_OUTPUT_ARG, "invalid name for output") \
-       _ERROR(REGEX, "regular expression error")
+       _ERROR(REGEX, "regular expression error") \
+       _ERROR(MKDIR, "could not create directory")
 
 
 /**
diff --git a/fd.c b/fd.c
index e1d243e1e8f34006326bdfab72f24455ad801eff..e661e71fa32d2c20d92f558f9f40f62f576b9ba1 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -9,9 +9,11 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <sys/mman.h>
+#include <string.h>
 
 #include "adu.h"
 #include "error.h"
+#include "string.h"
 
 /**
  * Wrapper for the write system call.
@@ -273,3 +275,54 @@ int adu_munmap(void *start, size_t length)
                strerror(err));
        return -ERRNO_TO_ERROR(err);
 }
+
+__must_check __malloc static char *adu_dirname(const char *name)
+{
+       char *p, *ret;
+
+       if (!name || !*name)
+               return NULL;
+       ret = adu_strdup(name);
+       p = strrchr(ret, '/');
+       if (!p)
+               *ret = '\0';
+       else
+               *p = '\0';
+       return ret;
+}
+
+/**
+ * Recursive mkdir
+ *
+ * \param p Full path that should be created.
+ *
+ * \param mode Use this mode when creating directories.
+ *
+ * \return 0 if successful, -E_MKDIR on errors.
+ */
+int mkpath(const char *p, mode_t mode)
+{
+       char *parent, *path;
+       int ret = -E_MKDIR;
+
+       DEBUG_LOG("%s\n", p);
+       if (strcmp(p, ".") == 0 || strcmp(p, "/") == 0 || strcmp(p, "") == 0) {
+               DEBUG_LOG("reached beginning of path\n");
+               return 0;
+       }
+       path = adu_strdup(p);
+       parent = adu_dirname(p);
+       if (!parent)
+               goto out;
+       ret = mkpath(parent, mode);
+       if (ret < 0)
+               goto out;
+       INFO_LOG("making dir %s\n", path);
+       ret = 0;
+       if ((mkdir(path, mode) == -1) && (errno != EEXIST))
+               ret = -E_MKDIR;
+out:
+       free(parent);
+       free(path);
+       return ret;
+}
diff --git a/fd.h b/fd.h
index 6ebd9c90cb67f5917b50c923491d8f5a8fe9d1a1..32a3ad3df108e297dbe3c22c1fae520c6a835ba9 100644 (file)
--- a/fd.h
+++ b/fd.h
@@ -12,3 +12,4 @@ int mmap_full_file(const char *filename, int open_mode, void **map,
        size_t *size, int *fd_ptr);
 int adu_munmap(void *start, size_t length);
 int adu_write_file(const char *filename, const void *buf, size_t size);
+int mkpath(const char *p, mode_t mode);
index 08f700f7a6cd2d423d0a37e84e9ee09727536745..1c7562271a0948941c8b5e5ba41f8826dec1d7e9 100644 (file)
@@ -214,13 +214,14 @@ int com_interactive(void)
        ret = parse_select_options(NULL, NULL, &admissible_uids, &fi);
        if (ret< 0)
                return ret;
-       ret = read_uid_file(conf.database_dir_arg);
+       ret = read_uid_file();
        if (ret < 0)
                return ret;
        while (read_input_line(line, sizeof(line)) >= 0) {
                ret = exec_interactive_command(line);
                if (ret < 0)
                        printf("%s\n", adu_strerror(-ret));
+               fflush(NULL);
        }
        return ret;
 }
index 4ebfbbfa02b10903a3766b1855cbf950810af9e9..e30697ee9f0dc51d629d6ccbfaa789b6428e996a 100644 (file)
--- a/select.c
+++ b/select.c
@@ -912,8 +912,7 @@ int run_select_query(struct uid_range *admissible_uids, struct format_info *fi)
        if (ret < 0)
                goto out;
        check_signals();
-       ret = open_admissible_user_tables(conf.database_dir_arg,
-               admissible_uids);
+       ret = open_admissible_user_tables(admissible_uids);
        if (ret < 0)
                goto out;
        check_signals();
@@ -1063,7 +1062,7 @@ int com_select(void)
        ret = parse_select_options(conf.select_options_arg, &params,
                &admissible_uids, &fi);
        if (ret > 0) {
-               ret = read_uid_file(conf.database_dir_arg);
+               ret = read_uid_file();
                if (ret < 0)
                        goto out;
                ret = run_select_query(admissible_uids, fi);
index 77c90cb3bcee036565751f68ee9b3ff23726bab6..946faabdfd09ce688059c5d8ce15e140af282a29 100644 (file)
--- a/string.c
+++ b/string.c
@@ -138,7 +138,7 @@ __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
  * Append \p b to \p a.
  *
  * \return If \a a is \p NULL, return a pointer to a copy of \a b, i.e.
- * para_strcat(NULL, b) is equivalent to para_strdup(b). If \a b is \p NULL,
+ * adu_strcat(NULL, b) is equivalent to adu_strdup(b). If \a b is \p NULL,
  * return \a a without making a copy of \a a.  Otherwise, construct the
  * concatenation \a c, free \a a (but not \a b) and return \a c.
  *
diff --git a/user.c b/user.c
index dfa1c103a9211e1a78e5e0502b0537e4a22cb885..0ae4a6c9af04fe3eab521f38f9c14b74e4f69a8c 100644 (file)
--- a/user.c
+++ b/user.c
@@ -257,7 +257,7 @@ static inline int ui_admissible(struct user_info *ui)
        return ui->flags & UI_FL_ADMISSIBLE;
 }
 
-static int open_user_table(const char *dirname, struct user_info *ui, int create)
+static int open_user_table(struct user_info *ui, int create)
 {
        int ret;
        struct passwd *pw;
@@ -266,7 +266,7 @@ static int open_user_table(const char *dirname, struct user_info *ui, int create
        ui->desc->num_columns = NUM_UT_COLUMNS;
        ui->desc->flags = 0;
        ui->desc->column_descriptions = user_table_cols;
-       ui->desc->dir = adu_strdup(dirname);
+       ui->desc->dir = adu_strdup(database_dir);
        ui->desc->name = make_message("%u", (unsigned)ui->uid);
        pw = getpwuid(ui->uid);
        if (pw && pw->pw_name)
@@ -435,8 +435,7 @@ static struct user_info *lookup_uid(uint32_t uid)
  *
  * \return Standard.
  */
-int create_user_table(const char *dirname, uint32_t uid,
-               struct user_info **ui_ptr)
+int create_user_table(uint32_t uid, struct user_info **ui_ptr)
 {
        struct user_info *ui = lookup_uid(uid);
 
@@ -447,12 +446,12 @@ int create_user_table(const char *dirname, uint32_t uid,
                return 1;
        ui->uid = uid;
        ui->flags |= UI_FL_SLOT_USED;
-       return open_user_table(dirname, ui, 1);
+       return open_user_table(ui, 1);
 }
 
-static char *get_uid_list_name(const char *dirname)
+static char *get_uid_list_name(void)
 {
-       return make_message("%s/uid_list", dirname);
+       return make_message("%s/uid_list", database_dir);
 }
 /**
  * Open the osl tables for all admissible uids.
@@ -469,8 +468,7 @@ static char *get_uid_list_name(const char *dirname)
  *
  * \return Stamdard.
  */
-int open_admissible_user_tables(const char *dirname,
-               struct uid_range *admissible_uids)
+int open_admissible_user_tables(struct uid_range *admissible_uids)
 {
        struct user_info *ui;
 
@@ -489,7 +487,7 @@ int open_admissible_user_tables(const char *dirname,
                ui->flags |= UI_FL_ADMISSIBLE;
                if (ui->table)
                        continue;
-               ret = open_user_table(dirname, ui, 0);
+               ret = open_user_table(ui, 0);
                if (ret < 0)
                        return ret;
        }
@@ -508,11 +506,11 @@ int open_admissible_user_tables(const char *dirname,
  *
  * \return Standard.
  */
-int read_uid_file(const char *dirname)
+int read_uid_file(void)
 {
        size_t size;
        uint32_t n;
-       char *filename = get_uid_list_name(dirname), *map;
+       char *filename = get_uid_list_name(), *map;
        int ret = mmap_full_file(filename, O_RDONLY, (void **)&map, &size, NULL);
        unsigned bits;
 
@@ -562,7 +560,7 @@ out:
  *
  * \return Standard.
  */
-int write_uid_file(const char *dirname)
+int write_uid_file(void)
 {
        char *buf, *p, *filename;
        size_t size = num_uids * sizeof(uint32_t);
@@ -578,7 +576,7 @@ int write_uid_file(const char *dirname)
                write_u32(p, ui->uid);
                p += sizeof(uint32_t);
        }
-       filename = get_uid_list_name(dirname);
+       filename = get_uid_list_name();
        ret = adu_write_file(filename, buf, size);
        free(filename);
        free(buf);
diff --git a/user.h b/user.h
index c64983e251c6aa4fec56016f0f42c6dccfa0e367..a6fbbf6381953140e2cac54464988917bd38aa07 100644 (file)
--- a/user.h
+++ b/user.h
@@ -35,10 +35,9 @@ struct user_info {
 /** An opaque struct that contains info about which users are admissible. */
 struct uid_range;
 
-int create_user_table(const char *dirname, uint32_t uid,
-               struct user_info **ui_ptr);
-int read_uid_file(const char *dirname);
-int write_uid_file(const char *dirname);
+int create_user_table(uint32_t uid, struct user_info **ui_ptr);
+int read_uid_file(void);
+int write_uid_file(void);
 
 void create_hash_table(unsigned bits);
 int for_each_admissible_user(int (*func)(struct user_info *, void *),
@@ -47,5 +46,4 @@ int parse_uid_arg(const char *orig_arg, struct uid_range **ur);
 int append_users(char **users, int num_users,
                struct uid_range **admissible_uids, int num_uid_ranges);
 void close_user_tables(void);
-int open_admissible_user_tables(const char *dirname,
-               struct uid_range *admissible_uids);
+int open_admissible_user_tables(struct uid_range *admissible_uids);