summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-11-28 13:36:47 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2019-01-18 23:01:37 +0000
commitd04c1aa0fc5ec2c38da5a0eed96a748d98f563f1 (patch)
tree9f5a39ea2d5d577959307a9b3979b4c662d8cd7e
parentac5879de88c606ba62fb0c490f2ba6712cfea457 (diff)
downloadlibgit2-d04c1aa0fc5ec2c38da5a0eed96a748d98f563f1.tar.gz
config: fix adding files if their parent directory is a file
When we try to add a configuration file with `git_config_add_file_ondisk`, we treat nonexisting files as empty. We do this by performing a stat call, ignoring ENOENT errors. This works just fine in case the file or any of its parents simply does not exist, but there is also the case where any of the parent directories is not a directory, but a file. So e.g. trying to add a configuration file "/dev/null/.gitconfig" will fail, as `errno` will be ENOTDIR instead of ENOENT. Catch ENOTDIR in addition to ENOENT to fix the issue. Add a test that verifies we are able to add configuration files with such an invalid path file just fine.
-rw-r--r--src/config.c2
-rw-r--r--tests/config/read.c20
2 files changed, 21 insertions, 1 deletions
diff --git a/src/config.c b/src/config.c
index 7e1e982e2..ba225297c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -109,7 +109,7 @@ int git_config_add_file_ondisk(
assert(cfg && path);
res = p_stat(path, &st);
- if (res < 0 && errno != ENOENT) {
+ if (res < 0 && errno != ENOENT && errno != ENOTDIR) {
giterr_set(GITERR_CONFIG, "failed to stat '%s'", path);
return -1;
}
diff --git a/tests/config/read.c b/tests/config/read.c
index 646567134..df745a567 100644
--- a/tests/config/read.c
+++ b/tests/config/read.c
@@ -524,6 +524,26 @@ void test_config_read__fallback_from_local_to_global_and_from_global_to_system(v
git_config_free(cfg);
}
+void test_config_read__parent_dir_is_file(void)
+{
+ git_config *cfg;
+ int count;
+
+ cl_git_pass(git_config_new(&cfg));
+ /*
+ * Verify we can add non-existing files when the parent directory is not
+ * a directory.
+ */
+ cl_git_pass(git_config_add_file_ondisk(cfg, "/dev/null/.gitconfig",
+ GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
+
+ count = 0;
+ cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count));
+ cl_assert_equal_i(0, count);
+
+ git_config_free(cfg);
+}
+
/*
* At the beginning of the test, config18 has:
* int32global = 28