예제 #1
0
static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
{
	int error = 0;
	futils__rmdir_data *data = opaque;
	struct stat st;

	if (data->depth > FUTILS_MAX_DEPTH)
		error = futils__error_cannot_rmdir(
			path->ptr, "directory nesting too deep");

	else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) {
		if (errno == ENOENT)
			error = 0;
		else if (errno == ENOTDIR) {
			/* asked to remove a/b/c/d/e and a/b is a normal file */
			if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0)
				error = futils__rm_first_parent(path, data->base);
			else
				futils__error_cannot_rmdir(
					path->ptr, "parent is not directory");
		}
		else
			error = git_path_set_error(errno, path->ptr, "rmdir");
	}

	else if (S_ISDIR(st.st_mode)) {
		data->depth++;

		error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data);

		data->depth--;

		if (error < 0)
			return error;

		if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0)
			return error;

		if ((error = p_rmdir(path->ptr)) < 0) {
			if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 &&
				(errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY))
				error = 0;
			else
				error = git_path_set_error(errno, path->ptr, "rmdir");
		}
	}

	else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) {
		if (p_unlink(path->ptr) < 0)
			error = git_path_set_error(errno, path->ptr, "remove");
	}

	else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0)
		error = futils__error_cannot_rmdir(path->ptr, "still present");

	return error;
}
예제 #2
0
파일: fileops.c 프로젝트: 0CV0/libgit2
static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path)
{
	struct stat st;
	futils__rmdir_data *data = opaque;

	if ((data->error = p_lstat_posixly(path->ptr, &st)) < 0) {
		if (errno == ENOENT)
			data->error = 0;
		else if (errno == ENOTDIR) {
			/* asked to remove a/b/c/d/e and a/b is a normal file */
			if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0)
				data->error = futils__rm_first_parent(path, data->base);
			else
				futils__error_cannot_rmdir(
					path->ptr, "parent is not directory");
		}
		else
			futils__error_cannot_rmdir(path->ptr, "cannot access");
	}

	else if (S_ISDIR(st.st_mode)) {
		int error = git_path_direach(path, futils__rmdir_recurs_foreach, data);
		if (error < 0)
			return (error == GIT_EUSER) ? data->error : error;

		data->error = p_rmdir(path->ptr);

		if (data->error < 0) {
			if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 &&
				(errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY))
				data->error = 0;
			else
				futils__error_cannot_rmdir(path->ptr, NULL);
		}
	}

	else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) {
		data->error = p_unlink(path->ptr);

		if (data->error < 0)
			futils__error_cannot_rmdir(path->ptr, "cannot be removed");
	}

	else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0)
		data->error = futils__error_cannot_rmdir(path->ptr, "still present");

	return data->error;
}
예제 #3
0
파일: indexer.c 프로젝트: Arhzi/libgit2
static int find_tmp_file_recurs(void *opaque, git_buf *path)
{
	int error = 0;
	git_buf *first_tmp_file = opaque;
	struct stat st;

	if ((error = p_lstat_posixly(path->ptr, &st)) < 0)
		return error;

	if (S_ISDIR(st.st_mode))
		return git_path_direach(path, 0, find_tmp_file_recurs, opaque);

	/* This is the template that's used in git_futils_mktmp. */
	if (strstr(git_buf_cstr(path), "_git2_") != NULL)
		return git_buf_sets(first_tmp_file, git_buf_cstr(path));

	return 0;
}
예제 #4
0
static int futils__rm_first_parent(git_buf *path, const char *ceiling)
{
	int error = GIT_ENOTFOUND;
	struct stat st;

	while (error == GIT_ENOTFOUND) {
		git_buf_rtruncate_at_char(path, '/');

		if (!path->size || git__prefixcmp(path->ptr, ceiling) != 0)
			error = 0;
		else if (p_lstat_posixly(path->ptr, &st) == 0) {
			if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
				error = p_unlink(path->ptr);
			else if (!S_ISDIR(st.st_mode))
				error = -1; /* fail to remove non-regular file */
		} else if (errno != ENOTDIR)
			error = -1;
	}

	if (error)
		futils__error_cannot_rmdir(path->ptr, "cannot remove parent");

	return error;
}
예제 #5
0
파일: stat.c 프로젝트: 0CV0/libgit2
void test_core_stat__0(void)
{
	struct stat st;
	int err;

	cl_assert_equal_i(0, p_lstat("root", &st));
	cl_assert(S_ISDIR(st.st_mode));
	cl_assert_error(0);

	cl_assert_equal_i(0, p_lstat("root/", &st));
	cl_assert(S_ISDIR(st.st_mode));
	cl_assert_error(0);

	cl_assert_equal_i(0, p_lstat("root/file", &st));
	cl_assert(S_ISREG(st.st_mode));
	cl_assert_error(0);

	cl_assert_equal_i(0, p_lstat("root/d1", &st));
	cl_assert(S_ISDIR(st.st_mode));
	cl_assert_error(0);

	cl_assert_equal_i(0, p_lstat("root/d1/", &st));
	cl_assert(S_ISDIR(st.st_mode));
	cl_assert_error(0);

	cl_assert_equal_i(0, p_lstat("root/d1/file", &st));
	cl_assert(S_ISREG(st.st_mode));
	cl_assert_error(0);

	cl_assert(p_lstat("root/missing", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat("root/missing/but/could/be/created", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat_posixly("root/missing/but/could/be/created", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat("root/d1/missing", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat("root/d1/missing/deeper/path", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat_posixly("root/d1/missing/deeper/path", &st) < 0);
	cl_assert_error(ENOENT);

	cl_assert(p_lstat_posixly("root/d1/file/deeper/path", &st) < 0);
	cl_assert_error(ENOTDIR);

	cl_assert(p_lstat("root/file/invalid", &st) < 0);
#ifdef GIT_WIN32
	cl_assert_error(ENOENT);
#else
	cl_assert_error(ENOTDIR);
#endif

	cl_assert(p_lstat_posixly("root/file/invalid", &st) < 0);
	cl_assert_error(ENOTDIR);

	cl_assert(p_lstat("root/file/invalid/deeper_path", &st) < 0);
#ifdef GIT_WIN32
	cl_assert_error(ENOENT);
#else
	cl_assert_error(ENOTDIR);
#endif

	cl_assert(p_lstat_posixly("root/file/invalid/deeper_path", &st) < 0);
	cl_assert_error(ENOTDIR);

	cl_assert(p_lstat_posixly("root/d1/file/extra", &st) < 0);
	cl_assert_error(ENOTDIR);

	cl_assert(p_lstat_posixly("root/d1/file/further/invalid/items", &st) < 0);
	cl_assert_error(ENOTDIR);
}