From 05d220a9c6f31134373e4326608a6d7e9cbb20f1 Mon Sep 17 00:00:00 2001 From: Slava Zanko Date: Tue, 7 Feb 2012 14:54:58 +0300 Subject: [PATCH] vfs_path: Fixed broken relative paths processing. Signed-off-by: Slava Zanko --- lib/vfs/interface.c | 13 ++++++--- lib/vfs/path.c | 59 +++++++++++++++++++++++++++----------- lib/vfs/path.h | 2 ++ src/filemanager/cmd.c | 2 +- src/filemanager/command.c | 2 +- src/filemanager/ext.c | 2 +- src/filemanager/panel.c | 24 +++------------- tests/lib/vfs/path_manipulations.c | 38 ++++++++++++++++++++++++ 8 files changed, 98 insertions(+), 44 deletions(-) diff --git a/lib/vfs/interface.c b/lib/vfs/interface.c index a0a2de166..2f583495c 100644 --- a/lib/vfs/interface.c +++ b/lib/vfs/interface.c @@ -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 */ diff --git a/lib/vfs/path.c b/lib/vfs/path.c index 0c983979f..d758d6a9e 100644 --- a/lib/vfs/path.c +++ b/lib/vfs/path.c @@ -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; +} + +/* --------------------------------------------------------------------------------------------- */ diff --git a/lib/vfs/path.h b/lib/vfs/path.h index 4c7956dcd..30f6298ed 100644 --- a/lib/vfs/path.h +++ b/lib/vfs/path.h @@ -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 ****************************************************************************/ diff --git a/src/filemanager/cmd.c b/src/filemanager/cmd.c index b86ea5c4b..0eba78544 100644 --- a/src/filemanager/cmd.c +++ b/src/filemanager/cmd.c @@ -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); diff --git a/src/filemanager/command.c b/src/filemanager/command.c index e7d5735fe..fa5de13ad 100644 --- a/src/filemanager/command.c +++ b/src/filemanager/command.c @@ -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) diff --git a/src/filemanager/ext.c b/src/filemanager/ext.c index aae71f103..6fb991420 100644 --- a/src/filemanager/ext.c +++ b/src/filemanager/ext.c @@ -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); } diff --git a/src/filemanager/panel.c b/src/filemanager/panel.c index 0d44b38d4..976ad3d81 100644 --- a/src/filemanager/panel.c +++ b/src/filemanager/panel.c @@ -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) { diff --git a/tests/lib/vfs/path_manipulations.c b/tests/lib/vfs/path_manipulations.c index b4823196a..795704ccb 100644 --- a/tests/lib/vfs/path_manipulations.c +++ b/tests/lib/vfs/path_manipulations.c @@ -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); -- 2.11.4.GIT