mkdir.c 5.83 KB
Newer Older
1 2 3 4 5 6 7 8
#include "clar_libgit2.h"
#include "fileops.h"
#include "path.h"
#include "posix.h"

static void cleanup_basic_dirs(void *ref)
{
	GIT_UNUSED(ref);
9 10 11 12 13
	git_futils_rmdir_r("d0", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
	git_futils_rmdir_r("d1", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
	git_futils_rmdir_r("d2", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
	git_futils_rmdir_r("d3", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
	git_futils_rmdir_r("d4", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
}

void test_core_mkdir__basic(void)
{
	cl_set_cleanup(cleanup_basic_dirs, NULL);

	/* make a directory */
	cl_assert(!git_path_isdir("d0"));
	cl_git_pass(git_futils_mkdir("d0", NULL, 0755, 0));
	cl_assert(git_path_isdir("d0"));

	/* make a path */
	cl_assert(!git_path_isdir("d1"));
	cl_git_pass(git_futils_mkdir("d1/d1.1/d1.2", NULL, 0755, GIT_MKDIR_PATH));
	cl_assert(git_path_isdir("d1"));
	cl_assert(git_path_isdir("d1/d1.1"));
	cl_assert(git_path_isdir("d1/d1.1/d1.2"));

	/* make a dir exclusively */
	cl_assert(!git_path_isdir("d2"));
	cl_git_pass(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL));
	cl_assert(git_path_isdir("d2"));

	/* make exclusive failure */
	cl_git_fail(git_futils_mkdir("d2", NULL, 0755, GIT_MKDIR_EXCL));

	/* make a path exclusively */
	cl_assert(!git_path_isdir("d3"));
	cl_git_pass(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
	cl_assert(git_path_isdir("d3"));
	cl_assert(git_path_isdir("d3/d3.1/d3.2"));

	/* make exclusive path failure */
	cl_git_fail(git_futils_mkdir("d3/d3.1/d3.2", NULL, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));
	/* ??? Should EXCL only apply to the last item in the path? */

	/* path with trailing slash? */
	cl_assert(!git_path_isdir("d4"));
	cl_git_pass(git_futils_mkdir("d4/d4.1/", NULL, 0755, GIT_MKDIR_PATH));
	cl_assert(git_path_isdir("d4/d4.1"));
}

static void cleanup_basedir(void *ref)
{
	GIT_UNUSED(ref);
59
	git_futils_rmdir_r("base", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
}

void test_core_mkdir__with_base(void)
{
#define BASEDIR "base/dir/here"

	cl_set_cleanup(cleanup_basedir, NULL);

	cl_git_pass(git_futils_mkdir(BASEDIR, NULL, 0755, GIT_MKDIR_PATH));

	cl_git_pass(git_futils_mkdir("a", BASEDIR, 0755, 0));
	cl_assert(git_path_isdir(BASEDIR "/a"));

	cl_git_pass(git_futils_mkdir("b/b1/b2", BASEDIR, 0755, GIT_MKDIR_PATH));
	cl_assert(git_path_isdir(BASEDIR "/b/b1/b2"));

	/* exclusive with existing base */
	cl_git_pass(git_futils_mkdir("c/c1/c2", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));

	/* fail: exclusive with duplicated suffix */
	cl_git_fail(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));

	/* fail: exclusive with any duplicated component */
	cl_git_fail(git_futils_mkdir("c/cz/cz", BASEDIR, 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));

	/* success: exclusive without path */
	cl_git_pass(git_futils_mkdir("c/c1/c3", BASEDIR, 0755, GIT_MKDIR_EXCL));

	/* path with shorter base and existing dirs */
	cl_git_pass(git_futils_mkdir("dir/here/d/", "base", 0755, GIT_MKDIR_PATH));
	cl_assert(git_path_isdir("base/dir/here/d"));

	/* fail: path with shorter base and existing dirs */
	cl_git_fail(git_futils_mkdir("dir/here/e/", "base", 0755, GIT_MKDIR_PATH | GIT_MKDIR_EXCL));

	/* fail: base with missing components */
	cl_git_fail(git_futils_mkdir("f/", "base/missing", 0755, GIT_MKDIR_PATH));

	/* success: shift missing component to path */
	cl_git_pass(git_futils_mkdir("missing/f/", "base/", 0755, GIT_MKDIR_PATH));
}

static void cleanup_chmod_root(void *ref)
{
	mode_t *mode = ref;
105 106

	if (*mode != 0) {
107
		(void)p_umask(*mode);
108 109
		git__free(mode);
	}
110

111
	git_futils_rmdir_r("r", NULL, GIT_RMDIR_EMPTY_HIERARCHY);
112 113
}

114 115 116 117
static void check_mode(mode_t expected, mode_t actual)
{
#ifdef GIT_WIN32
	/* chmod on Win32 doesn't support exec bit, not group/world bits */
118
	cl_assert_equal_i_fmt((expected & 0600), (actual & 0777), "%07o");
119
#else
120
	cl_assert_equal_i_fmt(expected, (actual & 0777), "%07o");
121 122 123
#endif
}

124 125 126
void test_core_mkdir__chmods(void)
{
	struct stat st;
127 128
	mode_t *old = git__malloc(sizeof(mode_t));
	*old = p_umask(022);
129

130
	cl_set_cleanup(cleanup_chmod_root, old);
131 132 133 134 135 136

	cl_git_pass(git_futils_mkdir("r", NULL, 0777, 0));

	cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH));

	cl_git_pass(git_path_lstat("r/mode", &st));
137
	check_mode(0755, st.st_mode);
138
	cl_git_pass(git_path_lstat("r/mode/is", &st));
139
	check_mode(0755, st.st_mode);
140
	cl_git_pass(git_path_lstat("r/mode/is/important", &st));
141
	check_mode(0755, st.st_mode);
142 143 144 145

	cl_git_pass(git_futils_mkdir("mode2/is2/important2", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD));

	cl_git_pass(git_path_lstat("r/mode2", &st));
146
	check_mode(0755, st.st_mode);
147
	cl_git_pass(git_path_lstat("r/mode2/is2", &st));
148
	check_mode(0755, st.st_mode);
149
	cl_git_pass(git_path_lstat("r/mode2/is2/important2", &st));
150
	check_mode(0777, st.st_mode);
151 152 153 154

	cl_git_pass(git_futils_mkdir("mode3/is3/important3", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH));

	cl_git_pass(git_path_lstat("r/mode3", &st));
155
	check_mode(0777, st.st_mode);
156
	cl_git_pass(git_path_lstat("r/mode3/is3", &st));
157
	check_mode(0777, st.st_mode);
158
	cl_git_pass(git_path_lstat("r/mode3/is3/important3", &st));
159
	check_mode(0777, st.st_mode);
160 161 162 163 164 165

	/* test that we chmod existing dir */

	cl_git_pass(git_futils_mkdir("mode/is/important", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD));

	cl_git_pass(git_path_lstat("r/mode", &st));
166
	check_mode(0755, st.st_mode);
167
	cl_git_pass(git_path_lstat("r/mode/is", &st));
168
	check_mode(0755, st.st_mode);
169
	cl_git_pass(git_path_lstat("r/mode/is/important", &st));
170
	check_mode(0777, st.st_mode);
171 172 173 174 175 176

	/* test that we chmod even existing dirs if CHMOD_PATH is set */

	cl_git_pass(git_futils_mkdir("mode2/is2/important2.1", "r", 0777, GIT_MKDIR_PATH | GIT_MKDIR_CHMOD_PATH));

	cl_git_pass(git_path_lstat("r/mode2", &st));
177
	check_mode(0777, st.st_mode);
178
	cl_git_pass(git_path_lstat("r/mode2/is2", &st));
179
	check_mode(0777, st.st_mode);
180
	cl_git_pass(git_path_lstat("r/mode2/is2/important2.1", &st));
181
	check_mode(0777, st.st_mode);
182
}