Beispiel #1
0
static bool is_valid_path(char const* path)
{
    if (is_unc_path(path))
    {
        if (path[2] != '\0' && !isalnum(path[2]))
        {
            return false;
        }
    }
    else
    {
        char const* colon_pos = strchr(path, ':');

        if (colon_pos != NULL)
        {
            if (colon_pos != path + 1 || !isalpha(path[0]))
            {
                return false;
            }

            path += 2;
        }
    }

    return strpbrk(path, "<>:\"|?*") == NULL;
}
Beispiel #2
0
char* tr_sys_path_dirname(char const* path, tr_error** error)
{
    if (path == NULL || path[0] == '\0')
    {
        return tr_strdup(".");
    }

    if (!is_valid_path(path))
    {
        set_system_error(error, ERROR_PATH_NOT_FOUND);
        return NULL;
    }

    bool const is_unc = is_unc_path(path);

    if (is_unc && path[2] == '\0')
    {
        return tr_strdup(path);
    }

    char const* end = path + strlen(path);

    while (end > path && is_slash(*(end - 1)))
    {
        --end;
    }

    if (end == path)
    {
        return tr_strdup("/");
    }

    char const* name = end;

    while (name > path && *(name - 1) != ':' && !is_slash(*(name - 1)))
    {
        --name;
    }

    while (name > path && is_slash(*(name - 1)))
    {
        --name;
    }

    if (name == path)
    {
        return tr_strdup(is_unc ? "\\\\" : ".");
    }

    if (name > path && *(name - 1) == ':' && *name != '\0' && !is_slash(*name))
    {
        return tr_strdup_printf("%c:.", path[0]);
    }

    return tr_strndup(path, name - path);
}
Beispiel #3
0
int
is_path_well_formed(const char *path)
{
#ifndef _WIN32
	return strchr(path, '/') != NULL;
#else
	return is_unc_path(path) || (strlen(path) >= 2 && path[1] == ':' &&
			drive_exists(path[0]));
#endif
}
Beispiel #4
0
static wchar_t* path_to_native_path_ex(char const* path, int extra_chars_after, int* real_result_size)
{
    /* Extending maximum path length limit up to ~32K. See "Naming Files, Paths, and Namespaces"
       (https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx) for more info */

    wchar_t const local_prefix[] = { '\\', '\\', '?', '\\' };
    wchar_t const unc_prefix[] = { '\\', '\\', '?', '\\', 'U', 'N', 'C', '\\' };

    bool const is_relative = tr_sys_path_is_relative(path);
    bool const is_unc = is_unc_path(path);

    /* `-2` for UNC since we overwrite existing prefix slashes */
    int const extra_chars_before = is_relative ? 0 : (is_unc ? TR_N_ELEMENTS(unc_prefix) - 2 : TR_N_ELEMENTS(local_prefix));

    /* TODO (?): TR_ASSERT(!is_relative); */

    wchar_t* const wide_path = tr_win32_utf8_to_native_ex(path, -1, extra_chars_before, extra_chars_after, real_result_size);

    if (wide_path == NULL)
    {
        return NULL;
    }

    /* Relative paths cannot be used with "\\?\" prefixes. This also means that relative paths are
       limited to ~260 chars... but we should rarely work with relative paths in the first place */
    if (!is_relative)
    {
        if (is_unc)
        {
            /* UNC path: "\\server\share" -> "\\?\UNC\server\share" */
            memcpy(wide_path, unc_prefix, sizeof(unc_prefix));
        }
        else
        {
            /* Local path: "C:" -> "\\?\C:" */
            memcpy(wide_path, local_prefix, sizeof(local_prefix));
        }
    }

    /* Automatic '/' to '\' conversion is disabled for "\\?\"-prefixed paths */
    wchar_t* p = wide_path + extra_chars_before;

    while ((p = wcschr(p, L'/')) != NULL)
    {
        *p++ = L'\\';
    }

    if (real_result_size != NULL)
    {
        *real_result_size += extra_chars_before;
    }

    return wide_path;
}
Beispiel #5
0
/* Implementation of :u filename modifier. */
static int
apply_u_mod(const char *path, char *buf, size_t buf_len)
{
	if(!is_unc_path(path))
	{
		DWORD size = buf_len - 2;
		snprintf(buf, buf_len, "//");
		GetComputerNameA(buf + 2, &size);
		return 0;
	}
	snprintf(buf, buf_len, "%s", path);
	break_at(buf + 2, '/');
	return 0;
}
Beispiel #6
0
int
is_unc_root(const char *path)
{
#ifdef _WIN32
	if(is_unc_path(path) && path[2] != '\0')
	{
		char *p = strchr(path + 2, '/');
		if(p == NULL || p[1] == '\0')
			return 1;
	}
	return 0;
#else
	return 0;
#endif
}
Beispiel #7
0
bool
tr_sys_path_is_relative (const char * path)
{
  assert (path != NULL);

  /* UNC path: `\\...`. */
  if (is_unc_path (path))
    return false;

  /* Local path: `X:` or `X:\...`. */
  if (isalpha (path[0]) && path[1] == ':' && (path[2] == '\0' || is_slash (path[2])))
    return false;

  return true;
}
Beispiel #8
0
static int open_file(FILE **f)
{
	if(f!=0 && ((*f)==0)){
		WCHAR tmp[SR_MAX_PATH];
		if(is_unc_path(fname))
			_snwprintf(tmp,sizeof(tmp)/sizeof(WCHAR),L"\\\\?\\UNC%s",fname+1);
		else
			_snwprintf(tmp,sizeof(tmp)/sizeof(WCHAR),L"\\\\?\\%s",fname);
		tmp[sizeof(tmp)/sizeof(WCHAR)-1]=0;
		*f=_wfopen(tmp,L"rb");
		if(*f!=0)
			_fseeki64(*f,last_offset,SEEK_SET);
	}
	return f!=0 ? TRUE:FALSE;
}
Beispiel #9
0
bool tr_sys_path_is_relative(char const* path)
{
    TR_ASSERT(path != NULL);

    /* UNC path: `\\...`. */
    if (is_unc_path(path))
    {
        return false;
    }

    /* Local path: `X:` or `X:\...`. */
    if (isalpha(path[0]) && path[1] == ':' && (path[2] == '\0' || is_slash(path[2])))
    {
        return false;
    }

    return true;
}
Beispiel #10
0
/* Runs command in a background and redirects its stdout and stderr streams to
 * file streams which are set.  Returns (pid_t)0 or (pid_t)-1 on error. */
static pid_t
background_and_capture_internal(char cmd[], int user_sh, FILE **out, FILE **err,
		int out_pipe[2], int err_pipe[2])
{
	wchar_t *args[4];
	char cwd[PATH_MAX];
	int code;
	wchar_t *final_wide_cmd;
	wchar_t *wide_sh = NULL;

	if(_dup2(out_pipe[1], _fileno(stdout)) != 0)
		return (pid_t)-1;
	if(_dup2(err_pipe[1], _fileno(stderr)) != 0)
		return (pid_t)-1;

	cwd[0] = '\0';
	if(get_cwd(cwd, sizeof(cwd)) != NULL)
	{
		if(is_unc_path(cwd))
		{
			(void)chdir(get_tmpdir());
		}
	}

	final_wide_cmd = to_wide(cmd);

	wide_sh = to_wide(user_sh ? cfg.shell : "cmd");
	if(!user_sh || curr_stats.shell_type == ST_CMD)
	{
		args[0] = wide_sh;
		args[1] = L"/C";
		args[2] = final_wide_cmd;
		args[3] = NULL;
	}
	else
	{
		args[0] = wide_sh;
		args[1] = L"-c";
		args[2] = final_wide_cmd;
		args[3] = NULL;
	}

	code = _wspawnvp(P_NOWAIT, args[0], (const wchar_t **)args);

	free(wide_sh);
	free(final_wide_cmd);

	if(is_unc_path(cwd))
	{
		(void)chdir(cwd);
	}

	if(code == 0)
	{
		return (pid_t)-1;
	}

	if((*out = _fdopen(out_pipe[0], "r")) == NULL)
		return (pid_t)-1;
	if((*err = _fdopen(err_pipe[0], "r")) == NULL)
	{
		fclose(*out);
		return (pid_t)-1;
	}

	return 0;
}
Beispiel #11
0
/*
 * type: CT_*
 */
void
filename_completion(const char *str, CompletionType type)
{
	/* TODO refactor filename_completion(...) function */
	DIR * dir;
	char * dirname;
	char * filename;
	char * temp;

	if(str[0] == '~' && strchr(str, '/') == NULL)
	{
		char *const tilde_expanded = expand_tilde(str);
		vle_compl_add_path_match(tilde_expanded);
		free(tilde_expanded);
		return;
	}

	dirname = expand_tilde(str);
	filename = strdup(dirname);

	temp = cmds_expand_envvars(dirname);
	free(dirname);
	dirname = temp;

	temp = strrchr(dirname, '/');
	if(temp != NULL && type != CT_FILE && type != CT_FILE_WOE)
	{
		strcpy(filename, ++temp);
		*temp = '\0';
	}
	else
	{
		dirname = realloc(dirname, 2);
		strcpy(dirname, ".");
	}

#ifdef _WIN32
	if(is_unc_root(dirname) ||
			(stroscmp(dirname, ".") == 0 && is_unc_root(curr_view->curr_dir)) ||
			(stroscmp(dirname, "/") == 0 && is_unc_path(curr_view->curr_dir)))
	{
		char buf[PATH_MAX];
		if(!is_unc_root(dirname))
			snprintf(buf,
					strchr(curr_view->curr_dir + 2, '/') - curr_view->curr_dir + 1, "%s",
					curr_view->curr_dir);
		else
			snprintf(buf, sizeof(buf), "%s", dirname);

		complete_with_shared(buf, filename);
		free(filename);
		free(dirname);
		return;
	}
	if(is_unc_path(curr_view->curr_dir))
	{
		char buf[PATH_MAX];
		if(is_path_absolute(dirname) && !is_unc_root(curr_view->curr_dir))
			snprintf(buf,
					strchr(curr_view->curr_dir + 2, '/') - curr_view->curr_dir + 2, "%s",
					curr_view->curr_dir);
		else
			snprintf(buf, sizeof(buf), "%s", curr_view->curr_dir);
		strcat(buf, dirname);
		chosp(buf);
		(void)replace_string(&dirname, buf);
	}
#endif

	dir = opendir(dirname);

	if(dir == NULL || vifm_chdir(dirname) != 0)
	{
		vle_compl_add_path_match(filename);
	}
	else
	{
		filename_completion_internal(dir, dirname, filename, type);
		(void)vifm_chdir(curr_view->curr_dir);
	}

	free(filename);
	free(dirname);

	if(dir != NULL)
	{
		closedir(dir);
	}
}