Blame tests/core/mkdir.c

Packit Service 20376f
#include "clar_libgit2.h"
Packit Service 20376f
#include "fileops.h"
Packit Service 20376f
#include "path.h"
Packit Service 20376f
#include "posix.h"
Packit Service 20376f
Packit Service 20376f
static void cleanup_basic_dirs(void *ref)
Packit Service 20376f
{
Packit Service 20376f
	GIT_UNUSED(ref);
Packit Service 20376f
	git_futils_rmdir_r("d0", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
	git_futils_rmdir_r("d1", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
	git_futils_rmdir_r("d2", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
	git_futils_rmdir_r("d3", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
	git_futils_rmdir_r("d4", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__absolute(void)
Packit Service 20376f
{
Packit Service 20376f
	git_buf path = GIT_BUF_INIT;
Packit Service 20376f
Packit Service 20376f
	cl_set_cleanup(cleanup_basic_dirs, NULL);
Packit Service 20376f
Packit Service 20376f
	git_buf_joinpath(&path, clar_sandbox_path(), "d0");
Packit Service 20376f
Packit Service 20376f
	/* make a directory */
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir(path.ptr, 0755, 0));
Packit Service 20376f
	cl_assert(git_path_isdir(path.ptr));
Packit Service 20376f
Packit Service 20376f
	git_buf_joinpath(&path, path.ptr, "subdir");
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir(path.ptr, 0755, 0));
Packit Service 20376f
	cl_assert(git_path_isdir(path.ptr));
Packit Service 20376f
Packit Service 20376f
	/* ensure mkdir_r works for a single subdir */
Packit Service 20376f
	git_buf_joinpath(&path, path.ptr, "another");
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_r(path.ptr, 0755));
Packit Service 20376f
	cl_assert(git_path_isdir(path.ptr));
Packit Service 20376f
Packit Service 20376f
	/* ensure mkdir_r works */
Packit Service 20376f
	git_buf_joinpath(&path, clar_sandbox_path(), "d1/foo/bar/asdf");
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_r(path.ptr, 0755));
Packit Service 20376f
	cl_assert(git_path_isdir(path.ptr));
Packit Service 20376f
Packit Service 20376f
	/* ensure we don't imply recursive */
Packit Service 20376f
	git_buf_joinpath(&path, clar_sandbox_path(), "d2/foo/bar/asdf");
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
	cl_git_fail(git_futils_mkdir(path.ptr, 0755, 0));
Packit Service 20376f
	cl_assert(!git_path_isdir(path.ptr));
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&path);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__basic(void)
Packit Service 20376f
{
Packit Service 20376f
	cl_set_cleanup(cleanup_basic_dirs, NULL);
Packit Service 20376f
Packit Service 20376f
	/* make a directory */
Packit Service 20376f
	cl_assert(!git_path_isdir("d0"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d0", 0755, 0));
Packit Service 20376f
	cl_assert(git_path_isdir("d0"));
Packit Service 20376f
Packit Service 20376f
	/* make a path */
Packit Service 20376f
	cl_assert(!git_path_isdir("d1"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d1/d1.1/d1.2", 0755, GIT_MKDIR_PATH));
Packit Service 20376f
	cl_assert(git_path_isdir("d1"));
Packit Service 20376f
	cl_assert(git_path_isdir("d1/d1.1"));
Packit Service 20376f
	cl_assert(git_path_isdir("d1/d1.1/d1.2"));
Packit Service 20376f
Packit Service 20376f
	/* make a dir exclusively */
Packit Service 20376f
	cl_assert(!git_path_isdir("d2"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d2", 0755, GIT_MKDIR_EXCL));
Packit Service 20376f
	cl_assert(git_path_isdir("d2"));
Packit Service 20376f
Packit Service 20376f
	/* make exclusive failure */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir("d2", 0755, GIT_MKDIR_EXCL));
Packit Service 20376f
Packit Service 20376f
	/* make a path exclusively */
Packit Service 20376f
	cl_assert(!git_path_isdir("d3"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d3/d3.1/d3.2", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
Packit Service 20376f
	cl_assert(git_path_isdir("d3"));
Packit Service 20376f
	cl_assert(git_path_isdir("d3/d3.1/d3.2"));
Packit Service 20376f
Packit Service 20376f
	/* make exclusive path failure */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir("d3/d3.1/d3.2", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
Packit Service 20376f
	/* ??? Should EXCL only apply to the last item in the path? */
Packit Service 20376f
Packit Service 20376f
	/* path with trailing slash? */
Packit Service 20376f
	cl_assert(!git_path_isdir("d4"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d4/d4.1/", 0755, GIT_MKDIR_PATH));
Packit Service 20376f
	cl_assert(git_path_isdir("d4/d4.1"));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void cleanup_basedir(void *ref)
Packit Service 20376f
{
Packit Service 20376f
	GIT_UNUSED(ref);
Packit Service 20376f
	git_futils_rmdir_r("base", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__with_base(void)
Packit Service 20376f
{
Packit Service 20376f
#define BASEDIR "base/dir/here"
Packit Service 20376f
Packit Service 20376f
	cl_set_cleanup(cleanup_basedir, NULL);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir(BASEDIR, 0755, GIT_MKDIR_PATH));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("a", BASEDIR, 0755, 0, NULL));
Packit Service 20376f
	cl_assert(git_path_isdir(BASEDIR "/a"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("b/b1/b2", BASEDIR, 0755, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
	cl_assert(git_path_isdir(BASEDIR "/b/b1/b2"));
Packit Service 20376f
Packit Service 20376f
	/* exclusive with existing base */
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("c/c1/c2", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
Packit Service 20376f
Packit Service 20376f
	/* fail: exclusive with duplicated suffix */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir_relative("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
Packit Service 20376f
Packit Service 20376f
	/* fail: exclusive with any duplicated component */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir_relative("c/cz/cz", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
Packit Service 20376f
Packit Service 20376f
	/* success: exclusive without path */
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_EXCL, NULL));
Packit Service 20376f
Packit Service 20376f
	/* path with shorter base and existing dirs */
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("dir/here/d/", "base", 0755, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
	cl_assert(git_path_isdir("base/dir/here/d"));
Packit Service 20376f
Packit Service 20376f
	/* fail: path with shorter base and existing dirs */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir_relative("dir/here/e/", "base", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL, NULL));
Packit Service 20376f
Packit Service 20376f
	/* fail: base with missing components */
Packit Service 20376f
	cl_git_fail(git_futils_mkdir_relative("f/", "base/missing", 0755, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
Packit Service 20376f
	/* success: shift missing component to path */
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("missing/f/", "base/", 0755, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void cleanup_chmod_root(void *ref)
Packit Service 20376f
{
Packit Service 20376f
	mode_t *mode = ref;
Packit Service 20376f
Packit Service 20376f
	if (mode != NULL) {
Packit Service 20376f
		(void)p_umask(*mode);
Packit Service 20376f
		git__free(mode);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#define check_mode(X,A) check_mode_at_line((X), (A), __FILE__, __LINE__)
Packit Service 20376f
Packit Service 20376f
static void check_mode_at_line(
Packit Service 20376f
	mode_t expected, mode_t actual, const char *file, int line)
Packit Service 20376f
{
Packit Service 20376f
	/* FAT filesystems don't support exec bit, nor group/world bits */
Packit Service 20376f
	if (!cl_is_chmod_supported()) {
Packit Service 20376f
		expected &= 0600;
Packit Service 20376f
		actual &= 0600;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	clar__assert_equal(
Packit Service 20376f
		file, line, "expected_mode != actual_mode", 1,
Packit Service 20376f
		"%07o", (int)expected, (int)(actual & 0777));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__chmods(void)
Packit Service 20376f
{
Packit Service 20376f
	struct stat st;
Packit Service 20376f
	mode_t *old = git__malloc(sizeof(mode_t));
Packit Service 20376f
	*old = p_umask(022);
Packit Service 20376f
Packit Service 20376f
	cl_set_cleanup(cleanup_chmod_root, old);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("r", 0777, 0));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode/is", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode/is/important", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2/is2", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode3", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode3/is3", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	/* test that we chmod existing dir */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode/is", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode/is/important", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	/* test that we chmod even existing dirs if CHMOD_PATH is set */
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH, NULL));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2/is2", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st);;
Packit Service 20376f
	check_mode(0777, st.st_mode);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__keeps_parent_symlinks(void)
Packit Service 20376f
{
Packit Service 20376f
#ifndef GIT_WIN32
Packit Service 20376f
	git_buf path = GIT_BUF_INIT;
Packit Service 20376f
Packit Service 20376f
	cl_set_cleanup(cleanup_basic_dirs, NULL);
Packit Service 20376f
Packit Service 20376f
	/* make a directory */
Packit Service 20376f
	cl_assert(!git_path_isdir("d0"));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d0", 0755, 0));
Packit Service 20376f
	cl_assert(git_path_isdir("d0"));
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(symlink("d0", "d1"));
Packit Service 20376f
	cl_assert(git_path_islink("d1"));
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("d1/foo/bar", 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
Packit Service 20376f
	cl_assert(git_path_islink("d1"));
Packit Service 20376f
	cl_assert(git_path_isdir("d1/foo/bar"));
Packit Service 20376f
	cl_assert(git_path_isdir("d0/foo/bar"));
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(symlink("d0", "d2"));
Packit Service 20376f
	cl_assert(git_path_islink("d2"));
Packit Service 20376f
Packit Service 20376f
	git_buf_joinpath(&path, clar_sandbox_path(), "d2/other/dir");
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_PATH|GIT_MKDIR_REMOVE_SYMLINKS));
Packit Service 20376f
	cl_assert(git_path_islink("d2"));
Packit Service 20376f
	cl_assert(git_path_isdir("d2/other/dir"));
Packit Service 20376f
	cl_assert(git_path_isdir("d0/other/dir"));
Packit Service 20376f
Packit Service 20376f
	git_buf_free(&path);
Packit Service 20376f
#endif
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
void test_core_mkdir__mkdir_path_inside_unwriteable_parent(void)
Packit Service 20376f
{
Packit Service 20376f
	struct stat st;
Packit Service 20376f
	mode_t *old;
Packit Service 20376f
Packit Service 20376f
	/* FAT filesystems don't support exec bit, nor group/world bits */
Packit Service 20376f
	if (!cl_is_chmod_supported())
Packit Service 20376f
		return;
Packit Service 20376f
Packit Service 20376f
	cl_assert((old = git__malloc(sizeof(mode_t))) != NULL);
Packit Service 20376f
	*old = p_umask(022);
Packit Service 20376f
	cl_set_cleanup(cleanup_chmod_root, old);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(git_futils_mkdir("r", 0777, 0));
Packit Service 20376f
	cl_git_pass(git_futils_mkdir_relative("mode/is/important", "r", 0777, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_chmod("r/mode", 0111));
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode", &st);;
Packit Service 20376f
	check_mode(0111, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	cl_git_pass(
Packit Service 20376f
		git_futils_mkdir_relative("mode/is/okay/inside", "r", 0777, GIT_MKDIR_PATH, NULL));
Packit Service 20376f
	cl_git_pass(git_path_lstat("r/mode/is/okay/inside", &st);;
Packit Service 20376f
	check_mode(0755, st.st_mode);
Packit Service 20376f
Packit Service 20376f
	cl_must_pass(p_chmod("r/mode", 0777));
Packit Service 20376f
}