Transform the database_dir/database_root arg into an absolute path.
authorAndre Noll <maan@systemlinux.org>
Fri, 21 Aug 2009 11:25:04 +0000 (13:25 +0200)
committerAndre Noll <maan@systemlinux.org>
Fri, 21 Aug 2009 11:25:04 +0000 (13:25 +0200)
adu --create failed badly if called with --database_dir or
--database_root being relative path. This patch fixes the bug.

Unfortunately, it's not completely trivial to obtain the cwd
in a portable and secure manner. The method used in the
new absolute_path() function, while still not bullet-proof, is
the best what one can do if portability is an issue.

adu.c
string.c
string.h

diff --git a/adu.c b/adu.c
index 68a48deea7a8a186511a1023fc7ee3bdba044977..7d8c9abd0191b6d4c84036bcc70e7e91d2cf03f3 100644 (file)
--- a/adu.c
+++ b/adu.c
@@ -259,6 +259,27 @@ static void print_complete_help_and_die(void)
        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
+               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.
  *
@@ -300,12 +321,7 @@ int main(int argc, char **argv)
        ret = init_signals();
        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);
+       get_database_dir_or_die();
        if (conf.select_given)
                ret = com_select();
        else if (conf.create_given)
index 946faabdfd09ce688059c5d8ce15e140af282a29..13555550efb6e1e567f66ca6f03158b79645ed7e 100644 (file)
--- a/string.c
+++ b/string.c
@@ -373,3 +373,35 @@ err:
        free(argv);
        return ret;
 }
+
+char *absolute_path(const char *path)
+{
+       char *cwd, *ap;
+       long int path_max;
+
+       if (!path || !path[0])
+               return NULL;
+       if (path[0] == '/')
+               return adu_strdup(path);
+
+#ifdef PATH_MAX
+       path_max = PATH_MAX;
+#else
+       /*
+        * The result of pathconf(3) may be huge and unsuitable for mallocing
+        * memory. OTOH pathconf(3) may return -1 to signify that PATH_MAX is
+        * not bounded.
+        */
+       path_max = pathconf(name, _PC_PATH_MAX);
+       if (path_max <= 0 || path_max >= 4096)
+               path_max = 4096;
+#endif
+       cwd = adu_malloc(path_max);
+       if (!getcwd(cwd, path_max)) {
+               free(cwd);
+               return NULL;
+       }
+       ap = make_message("%s/%s", cwd, path);
+       free(cwd);
+       return ap;
+}
index 128376995c0b45c1b565ba4527a8fdec0fd0aa2a..68ad7462e2f5fea0dd43642cbaf00825717e41ed 100644 (file)
--- a/string.h
+++ b/string.h
@@ -12,6 +12,7 @@ __must_check __malloc void *adu_calloc(size_t size);
 __must_check __malloc char *adu_strdup(const char *s);
 __must_check __malloc char *adu_strcat(char *a, const char *b);
 __must_check __malloc __printf_1_2 char *make_message(const char *fmt, ...);
+__must_check __malloc char *absolute_path(const char *path);
 __must_check int atoi64(const char *str, int64_t *result);
 __must_check unsigned split_args(char *args, char *** const argv_ptr, const char *delim);
 int create_argv(const char *line, char ***result);