Blame tests/clar/sandbox.h

Packit ae9e2a
static char _clar_path[4096];
Packit ae9e2a
Packit ae9e2a
static int
Packit ae9e2a
is_valid_tmp_path(const char *path)
Packit ae9e2a
{
Packit ae9e2a
	STAT_T st;
Packit ae9e2a
Packit ae9e2a
	if (stat(path, &st) != 0)
Packit ae9e2a
		return 0;
Packit ae9e2a
Packit ae9e2a
	if (!S_ISDIR(st.st_mode))
Packit ae9e2a
		return 0;
Packit ae9e2a
Packit ae9e2a
	return (access(path, W_OK) == 0);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int
Packit ae9e2a
find_tmp_path(char *buffer, size_t length)
Packit ae9e2a
{
Packit ae9e2a
#ifndef _WIN32
Packit ae9e2a
	static const size_t var_count = 5;
Packit ae9e2a
	static const char *env_vars[] = {
Packit ae9e2a
		"CLAR_TMP", "TMPDIR", "TMP", "TEMP", "USERPROFILE"
Packit ae9e2a
 	};
Packit ae9e2a
Packit ae9e2a
 	size_t i;
Packit ae9e2a
Packit ae9e2a
	for (i = 0; i < var_count; ++i) {
Packit ae9e2a
		const char *env = getenv(env_vars[i]);
Packit ae9e2a
		if (!env)
Packit ae9e2a
			continue;
Packit ae9e2a
Packit ae9e2a
		if (is_valid_tmp_path(env)) {
Packit ae9e2a
			strncpy(buffer, env, length);
Packit ae9e2a
			return 0;
Packit ae9e2a
		}
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	/* If the environment doesn't say anything, try to use /tmp */
Packit ae9e2a
	if (is_valid_tmp_path("/tmp")) {
Packit ae9e2a
		strncpy(buffer, "/tmp", length);
Packit ae9e2a
		return 0;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
#else
Packit ae9e2a
	DWORD env_len = GetEnvironmentVariable("CLAR_TMP", buffer, (DWORD)length);
Packit ae9e2a
	if (env_len > 0 && env_len < (DWORD)length)
Packit ae9e2a
		return 0;
Packit ae9e2a
Packit ae9e2a
	if (GetTempPath((DWORD)length, buffer))
Packit ae9e2a
		return 0;
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
	/* This system doesn't like us, try to use the current directory */
Packit ae9e2a
	if (is_valid_tmp_path(".")) {
Packit ae9e2a
		strncpy(buffer, ".", length);
Packit ae9e2a
		return 0;
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	return -1;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static void clar_unsandbox(void)
Packit ae9e2a
{
Packit ae9e2a
	if (_clar_path[0] == '\0')
Packit ae9e2a
		return;
Packit ae9e2a
Packit ae9e2a
	cl_must_pass(chdir(".."));
Packit ae9e2a
Packit ae9e2a
	fs_rm(_clar_path);
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int build_sandbox_path(void)
Packit ae9e2a
{
Packit ae9e2a
#ifdef CLAR_TMPDIR
Packit ae9e2a
	const char path_tail[] = CLAR_TMPDIR "_XXXXXX";
Packit ae9e2a
#else
Packit ae9e2a
	const char path_tail[] = "clar_tmp_XXXXXX";
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
	size_t len;
Packit ae9e2a
Packit ae9e2a
	if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
Packit ae9e2a
	len = strlen(_clar_path);
Packit ae9e2a
Packit ae9e2a
#ifdef _WIN32
Packit ae9e2a
	{ /* normalize path to POSIX forward slashes */
Packit ae9e2a
		size_t i;
Packit ae9e2a
		for (i = 0; i < len; ++i) {
Packit ae9e2a
			if (_clar_path[i] == '\\')
Packit ae9e2a
				_clar_path[i] = '/';
Packit ae9e2a
		}
Packit ae9e2a
	}
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
	if (_clar_path[len - 1] != '/') {
Packit ae9e2a
		_clar_path[len++] = '/';
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
	strncpy(_clar_path + len, path_tail, sizeof(_clar_path) - len);
Packit ae9e2a
Packit ae9e2a
#if defined(__MINGW32__)
Packit ae9e2a
	if (_mktemp(_clar_path) == NULL)
Packit ae9e2a
		return -1;
Packit ae9e2a
Packit ae9e2a
	if (mkdir(_clar_path, 0700) != 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
#elif defined(_WIN32)
Packit ae9e2a
	if (_mktemp_s(_clar_path, sizeof(_clar_path)) != 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
Packit ae9e2a
	if (mkdir(_clar_path, 0700) != 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
#else
Packit ae9e2a
	if (mkdtemp(_clar_path) == NULL)
Packit ae9e2a
		return -1;
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
	return 0;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
static int clar_sandbox(void)
Packit ae9e2a
{
Packit ae9e2a
	if (_clar_path[0] == '\0' && build_sandbox_path() < 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
Packit ae9e2a
	if (chdir(_clar_path) != 0)
Packit ae9e2a
		return -1;
Packit ae9e2a
Packit ae9e2a
	return 0;
Packit ae9e2a
}
Packit ae9e2a
Packit ae9e2a
const char *clar_sandbox_path(void)
Packit ae9e2a
{
Packit ae9e2a
	return _clar_path;
Packit ae9e2a
}
Packit ae9e2a