diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2015-09-17 09:58:38 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2015-09-17 10:11:38 -0400 |
commit | 0862ec2eb9529573ab46f3975defc0b7632bede4 (patch) | |
tree | d210c87e64c7b1059d1b426945904dd655ae2a8b | |
parent | 08df66301ec677f6cd98175a914dc933e2fb43a9 (diff) | |
download | libgit2-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.c | 11 | ||||
-rw-r--r-- | src/path.h | 6 | ||||
-rw-r--r-- | tests/core/mkdir.c | 34 |
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; |