aboutsummaryrefslogtreecommitdiffstats
path: root/src/mds-kbdc/make-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mds-kbdc/make-tree.c')
-rw-r--r--src/mds-kbdc/make-tree.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/mds-kbdc/make-tree.c b/src/mds-kbdc/make-tree.c
index fab402b..5c644b4 100644
--- a/src/mds-kbdc/make-tree.c
+++ b/src/mds-kbdc/make-tree.c
@@ -662,6 +662,9 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_parsed_t* restrict res
size_t line_i, line_n;
const char** keyword_stack = NULL;
mds_kbdc_tree_t*** tree_stack = NULL;
+ char* cwd = NULL;
+ char* old = NULL;
+ size_t cwd_size = 4096 >> 1;
size_t stack_ptr = 0;
int saved_errno, in_array = 0;
@@ -672,7 +675,29 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_parsed_t* restrict res
* can be misleading as the program can have changed working
* directory to be able to resolve filenames. */
result->pathname = realpath(filename, NULL); /* XXX use absolute path */
- fail_if (result->pathname == NULL);
+ if (result->pathname == NULL)
+ {
+ fail_if (errno != ENOENT);
+ saved_errno = errno;
+
+ /* Get the current working directory. */
+ /* glibc offers ways to do this in just one function call,
+ * but we will not assume that glibc is used here. */
+ for (;;)
+ {
+ fail_if (xxrealloc(old, cwd, cwd_size <<= 1, char));
+ if (getcwd(cwd, cwd_size))
+ break;
+ else
+ fail_if (errno != ERANGE);
+ }
+
+ result->pathname = strdup(filename);
+ fail_if (result->pathname == NULL);
+ NEW_ERROR_(result, ERROR, 0, 0, 0, 0, 1, "no such file or directory in ‘%s’", cwd);
+ free(cwd);
+ return 0;
+ }
/* Check that the file exists and can be read. */
if (access(result->pathname, R_OK) < 0)
@@ -1043,6 +1068,8 @@ int parse_to_tree(const char* restrict filename, mds_kbdc_parsed_t* restrict res
saved_errno = errno;
free(keyword_stack);
free(tree_stack);
+ free(cwd);
+ free(old);
return errno = saved_errno, -1;
}