From 1136bdfc82272850474eacba37cf87d01f6a1b7f Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Fri, 21 Aug 2009 13:25:04 +0200 Subject: [PATCH] Transform the database_dir/database_root arg into an absolute path. 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 | 28 ++++++++++++++++++++++------ string.c | 32 ++++++++++++++++++++++++++++++++ string.h | 1 + 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/adu.c b/adu.c index 68a48de..7d8c9ab 100644 --- 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) diff --git a/string.c b/string.c index 946faab..1355555 100644 --- 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; +} diff --git a/string.h b/string.h index 1283769..68ad746 100644 --- 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); -- 2.39.5