summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2015-09-17 09:58:38 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2015-09-17 10:11:38 -0400
commit0862ec2eb9529573ab46f3975defc0b7632bede4 (patch)
treed210c87e64c7b1059d1b426945904dd655ae2a8b
parent08df66301ec677f6cd98175a914dc933e2fb43a9 (diff)
downloadlibgit2-0862ec2eb9529573ab46f3975defc0b7632bede4.tar.gz
core::mkdir tests: ensure we don't stomp symlinks in mkdir
In `mkdir` and `mkdir_r`, ensure that we don't try to remove symlinks that are in our way.
-rw-r--r--src/path.c11
-rw-r--r--src/path.h6
-rw-r--r--tests/core/mkdir.c34
3 files changed, 51 insertions, 0 deletions
diff --git a/src/path.c b/src/path.c
index cb11acee3..72cb289e0 100644
--- a/src/path.c
+++ b/src/path.c
@@ -526,6 +526,17 @@ bool git_path_isfile(const char *path)
return S_ISREG(st.st_mode) != 0;
}
+bool git_path_islink(const char *path)
+{
+ struct stat st;
+
+ assert(path);
+ if (p_lstat(path, &st) < 0)
+ return false;
+
+ return S_ISLNK(st.st_mode) != 0;
+}
+
#ifdef GIT_WIN32
bool git_path_is_empty_dir(const char *path)
diff --git a/src/path.h b/src/path.h
index 971603ea7..c76e90343 100644
--- a/src/path.h
+++ b/src/path.h
@@ -169,6 +169,12 @@ extern bool git_path_isdir(const char *path);
extern bool git_path_isfile(const char *path);
/**
+ * Check if the given path points to a symbolic link.
+ * @return true or false
+ */
+extern bool git_path_islink(const char *path);
+
+/**
* Check if the given path is a directory, and is empty.
*/
extern bool git_path_is_empty_dir(const char *path);
diff --git a/tests/core/mkdir.c b/tests/core/mkdir.c
index 11fecb118..8d487e594 100644
--- a/tests/core/mkdir.c
+++ b/tests/core/mkdir.c
@@ -222,6 +222,40 @@ void test_core_mkdir__chmods(void)
check_mode(0777, st.st_mode);
}
+void test_core_mkdir__keeps_parent_symlinks(void)
+{
+#ifndef GIT_WIN32
+ git_buf path = GIT_BUF_INIT;
+
+ cl_set_cleanup(cleanup_basic_dirs, NULL);
+
+ /* make a directory */
+ cl_assert(!git_path_isdir("d0"));
+ cl_git_pass(git_futils_mkdir("d0", 0755, 0));
+ cl_assert(git_path_isdir("d0"));
+
+ cl_must_pass(symlink("d0", "d1"));
+ cl_assert(git_path_islink("d1"));
+
+ cl_git_pass(git_futils_mkdir("d1/foo/bar", 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
+ cl_assert(git_path_islink("d1"));
+ cl_assert(git_path_isdir("d1/foo/bar"));
+ cl_assert(git_path_isdir("d0/foo/bar"));
+
+ cl_must_pass(symlink("d0", "d2"));
+ cl_assert(git_path_islink("d2"));
+
+ git_buf_joinpath(&path, clar_sandbox_path(), "d2/other/dir");
+
+ cl_git_pass(git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
+ cl_assert(git_path_islink("d2"));
+ cl_assert(git_path_isdir("d2/other/dir"));
+ cl_assert(git_path_isdir("d0/other/dir"));
+
+ git_buf_free(&path);
+#endif
+}
+
void test_core_mkdir__mkdir_path_inside_unwriteable_parent(void)
{
struct stat st;