vfs_path: Fixed broken relative paths processing.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2012-02-07 14:54:58 +03:00
parent 2f744e86a2
commit 05d220a9c6
8 changed files with 98 additions and 44 deletions

View File

@ -436,7 +436,7 @@ mc_opendir (const vfs_path_t * vpath)
path_element->dir.info = info;
path_element->dir.converter = (path_element->encoding != NULL) ?
str_crt_conv_from (path_element->encoding) : str_cnv_from_term;
str_crt_conv_from (path_element->encoding) : str_cnv_from_term;
if (path_element->dir.converter == INVALID_CONV)
path_element->dir.converter = str_cnv_from_term;
@ -612,7 +612,7 @@ mc_getlocalcopy (const vfs_path_t * pathname_vpath)
if (vfs_path_element_valid (path_element))
{
result = path_element->class->getlocalcopy != NULL ?
path_element->class-> getlocalcopy (pathname_vpath) :
path_element->class->getlocalcopy (pathname_vpath) :
mc_def_getlocalcopy (pathname_vpath);
if (result == NULL)
errno = vfs_ferrno (path_element->class);
@ -658,6 +658,7 @@ mc_chdir (const vfs_path_t * vpath)
vfsid old_vfsid;
int result;
const vfs_path_element_t *path_element;
vfs_path_t *abcolute_vpath;
if (vpath == NULL)
return -1;
@ -669,10 +670,13 @@ mc_chdir (const vfs_path_t * vpath)
return -1;
}
result = (*path_element->class->chdir) (vpath);
abcolute_vpath = vfs_path_to_absolute (vpath);
result = (*path_element->class->chdir) (abcolute_vpath);
if (result == -1)
{
vfs_path_free (abcolute_vpath);
errno = vfs_ferrno (path_element->class);
return -1;
}
@ -681,7 +685,8 @@ mc_chdir (const vfs_path_t * vpath)
old_vfs = current_vfs;
/* Actually change directory */
vfs_set_raw_current_dir (vfs_path_clone (vpath));
vfs_set_raw_current_dir (abcolute_vpath);
current_vfs = path_element->class;
/* This function uses the new current_dir implicitly */

View File

@ -352,13 +352,14 @@ vfs_path_is_str_path_deprecated (const char *path_str)
*/
static vfs_path_t *
vfs_path_from_str_deprecated_parser (char *path)
vfs_path_from_str_deprecated_parser (char *path, vfs_path_flag_t flags)
{
vfs_path_t *vpath;
vfs_path_element_t *element;
struct vfs_class *class;
const char *local, *op;
(void) flags;
vpath = vfs_path_new ();
while ((class = _vfs_split_with_semi_skip_count (path, &local, &op, 0)) != NULL)
@ -411,7 +412,7 @@ vfs_path_from_str_deprecated_parser (char *path)
*/
static vfs_path_t *
vfs_path_from_str_uri_parser (char *path)
vfs_path_from_str_uri_parser (char *path, vfs_path_flag_t flags)
{
vfs_path_t *vpath;
vfs_path_element_t *element;
@ -419,6 +420,7 @@ vfs_path_from_str_uri_parser (char *path)
char *url_delimiter;
vpath = vfs_path_new ();
vpath->relative = (flags & VPF_NO_CANON) != 0;
while ((url_delimiter = g_strrstr (path, VFS_PATH_URL_DELIMITER)) != NULL)
{
@ -573,7 +575,7 @@ vfs_path_strip_home (const char *dir)
* @return pointer to newly created string.
*/
#define vfs_append_from_path(appendfrom) \
#define vfs_append_from_path(appendfrom, is_relative) \
{ \
if ((flags & VPF_STRIP_HOME) && element_index == 0 && (element->class->flags & VFSF_LOCAL) != 0) \
{ \
@ -584,8 +586,8 @@ vfs_path_strip_home (const char *dir)
} \
else \
{ \
if ((*appendfrom != PATH_SEP) && (*appendfrom != '\0') \
&& (buffer->str[buffer->len - 1] != PATH_SEP)) \
if ((!is_relative) && (*appendfrom != PATH_SEP) && (*appendfrom != '\0') \
&& (buffer->len == 0 || buffer->str[buffer->len - 1] != PATH_SEP)) \
g_string_append_c (buffer, PATH_SEP); \
g_string_append (buffer, appendfrom); \
} \
@ -613,14 +615,13 @@ vfs_path_to_str_flags (const vfs_path_t * vpath, int elements_count, vfs_path_fl
for (element_index = 0; element_index < elements_count; element_index++)
{
const vfs_path_element_t *element;
gboolean is_relative = vpath->relative && (element_index == 0);
element = vfs_path_get_by_index (vpath, element_index);
if (element->vfs_prefix != NULL)
{
char *url_str;
if (buffer->len == 0 || buffer->str[buffer->len - 1] != PATH_SEP)
if ((!is_relative) && (buffer->len == 0 || buffer->str[buffer->len - 1] != PATH_SEP))
g_string_append_c (buffer, PATH_SEP);
g_string_append (buffer, element->vfs_prefix);
@ -638,18 +639,19 @@ vfs_path_to_str_flags (const vfs_path_t * vpath, int elements_count, vfs_path_fl
{
if ((flags & VPF_HIDE_CHARSET) == 0)
{
if (buffer->len == 0 || buffer->str[buffer->len - 1] != PATH_SEP)
if ((!is_relative)
&& (buffer->len == 0 || buffer->str[buffer->len - 1] != PATH_SEP))
g_string_append (buffer, PATH_SEP_STR);
g_string_append (buffer, VFS_ENCODING_PREFIX);
g_string_append (buffer, element->encoding);
}
str_vfs_convert_from (element->dir.converter, element->path, recode_buffer);
vfs_append_from_path (recode_buffer->str);
vfs_append_from_path (recode_buffer->str, is_relative);
g_string_set_size (recode_buffer, 0);
}
else
{
vfs_append_from_path (element->path);
vfs_append_from_path (element->path, is_relative);
}
}
g_string_free (recode_buffer, TRUE);
@ -717,9 +719,9 @@ vfs_path_from_str_flags (const char *path_str, vfs_path_flag_t flags)
return NULL;
if ((flags & VPF_USE_DEPRECATED_PARSER) != 0 && vfs_path_is_str_path_deprecated (path))
vpath = vfs_path_from_str_deprecated_parser (path);
vpath = vfs_path_from_str_deprecated_parser (path, flags);
else
vpath = vfs_path_from_str_uri_parser (path);
vpath = vfs_path_from_str_uri_parser (path, flags);
g_free (path);
@ -884,14 +886,14 @@ vfs_path_clone (const vfs_path_t * vpath)
return NULL;
new_vpath = vfs_path_new ();
new_vpath->relative = vpath->relative;
for (vpath_element_index = 0; vpath_element_index < vfs_path_elements_count (vpath);
vpath_element_index++)
{
vfs_path_element_t *path_element;
path_element =
vfs_path_element_clone (vfs_path_get_by_index (vpath, vpath_element_index));
path_element = vfs_path_element_clone (vfs_path_get_by_index (vpath, vpath_element_index));
g_array_append_val (new_vpath->path, path_element);
}
@ -1217,8 +1219,7 @@ vfs_path_append_vpath_new (const vfs_path_t * first_vpath, ...)
{
vfs_path_element_t *path_element;
path_element =
vfs_path_element_clone (vfs_path_get_by_index (current_vpath, vindex));
path_element = vfs_path_element_clone (vfs_path_get_by_index (current_vpath, vindex));
g_array_append_val (ret_vpath->path, path_element);
}
current_vpath = va_arg (args, const vfs_path_t *);
@ -1512,3 +1513,27 @@ vfs_path_len (const vfs_path_t * vpath)
}
/* --------------------------------------------------------------------------------------------- */
/**
* Convert relative vpath object to absolute
*
* @param vpath path object
*
* @return absolute path object
*/
vfs_path_t *
vfs_path_to_absolute (const vfs_path_t * vpath)
{
vfs_path_t *absolute_vpath;
char *path_str;
if (!vpath->relative)
return vfs_path_clone (vpath);
path_str = vfs_path_to_str (vpath);
absolute_vpath = vfs_path_from_str (path_str);
g_free (path_str);
return absolute_vpath;
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -25,6 +25,7 @@ struct vfs_url_struct;
typedef struct
{
gboolean relative;
GArray *path;
} vfs_path_t;
@ -85,6 +86,7 @@ char *vfs_path_build_url_params_str (const vfs_path_element_t * element, gboolea
size_t vfs_path_len (const vfs_path_t * vpath);
int vfs_path_cmp (const vfs_path_t * vpath1, const vfs_path_t * vpath2);
int vfs_path_ncmp (const vfs_path_t * vpath1, const vfs_path_t * vpath2, size_t len);
vfs_path_t *vfs_path_to_absolute (const vfs_path_t * vpath);
/*** inline functions ****************************************************************************/

View File

@ -574,7 +574,7 @@ nice_cd (const char *text, const char *xtext, const char *help,
{
vfs_path_t *cd_vpath;
cd_vpath = vfs_path_from_str (cd_path);
cd_vpath = vfs_path_from_str_flags (cd_path, VPF_NO_CANON);
if (!do_panel_cd (MENU_PANEL, cd_vpath, cd_parse_command))
message (D_ERROR, MSG_ERROR, _("Cannot chdir to \"%s\""), cd_path);
vfs_path_free (cd_vpath);

View File

@ -426,7 +426,7 @@ do_cd_command (char *orig_cmd)
if (*path == '\0')
q_vpath = vfs_path_from_str (mc_config_get_home_dir());
else
q_vpath = vfs_path_from_str (path);
q_vpath = vfs_path_from_str_flags (path, VPF_NO_CANON);
ok = do_cd (q_vpath, cd_parse_command);
if (!ok)

View File

@ -366,7 +366,7 @@ exec_extension (const char *filename, const char *lc_data, int *move_dir, int st
q--;
q[1] = 0;
p_vpath = vfs_path_from_str (p);
p_vpath = vfs_path_from_str_flags (p, VPF_NO_CANON);
do_cd (p_vpath, cd_parse_command);
vfs_path_free (p_vpath);
}

View File

@ -2967,34 +2967,18 @@ static gboolean
_do_panel_cd (WPanel * panel, const vfs_path_t * new_dir_vpath, enum cd_enum cd_type)
{
char *olddir;
char temp[MC_MAXPATHLEN];
char *new_dir, *_new_dir;
_new_dir = new_dir = vfs_path_to_str (new_dir_vpath);
if (cd_type == cd_parse_command)
{
while (*new_dir == ' ')
new_dir++;
}
olddir = vfs_path_to_str (panel->cwd_vpath);
/* Convert *new_path to a suitable pathname, handle ~user */
if (cd_type == cd_parse_command)
{
if (strcmp (new_dir, "-") == 0)
{
char *tmp_path;
const vfs_path_element_t *element;
tmp_path = vfs_path_to_str (panel->lwd_vpath);
strcpy (temp, tmp_path);
new_dir = temp;
g_free (tmp_path);
}
element = vfs_path_get_by_index (new_dir_vpath, 0);
if (strcmp (element->path, "-") == 0)
new_dir_vpath = panel->lwd_vpath;
}
g_free (_new_dir);
if (mc_chdir (new_dir_vpath) == -1)
{

View File

@ -232,6 +232,43 @@ END_TEST
/* --------------------------------------------------------------------------------------------- */
START_TEST (test_vfs_path_relative)
{
vfs_path_t *vpath, *copy_vpath;
char *path_str;
vpath = vfs_path_from_str_flags("../bla-bla", VPF_NO_CANON);
fail_unless (vpath->relative, "relative flag fail!\n");
path_str = vfs_path_to_str (vpath);
fail_unless (strcmp(path_str, "../bla-bla") == 0, "relative fail!\nactual: [%s]\n", path_str);
g_free (path_str);
path_str = (char *) vfs_path_get_last_path_str (vpath);
fail_unless (strcmp(path_str, "../bla-bla") == 0, "relative fail!\nactual: element->path=[%s]\n", path_str);
copy_vpath = vfs_path_clone (vpath);
path_str = vfs_path_to_str (copy_vpath);
fail_unless (strcmp(path_str, "../bla-bla") == 0, "relative fail!\nactual: [%s]\n", path_str);
g_free (path_str);
vfs_path_free (copy_vpath);
vfs_path_free (vpath);
vpath = vfs_path_from_str_flags ("../path/test1://user:pass@some.host:12345/bla-bla/some/path/", VPF_NO_CANON);
path_str = vfs_path_to_str (vpath);
fail_unless (strcmp(path_str, "../path/test1://user:pass@some.host:12345/bla-bla/some/path/") == 0, "relative fail!\nactual: [%s]\n", path_str);
g_free (path_str);
vfs_path_free (vpath);
}
END_TEST
/* --------------------------------------------------------------------------------------------- */
int
main (void)
{
@ -247,6 +284,7 @@ main (void)
tcase_add_test (tc_core, test_vfs_path_tokens_count);
tcase_add_test (tc_core, test_vfs_path_tokens_get);
tcase_add_test (tc_core, test_vfs_path_append_vpath);
tcase_add_test (tc_core, test_vfs_path_relative);
/* *********************************** */
suite_add_tcase (s, tc_core);