diff --git a/lib/vfs/direntry.c b/lib/vfs/direntry.c index 565878570..8ee544db4 100644 --- a/lib/vfs/direntry.c +++ b/lib/vfs/direntry.c @@ -1043,6 +1043,58 @@ vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super, /* --------------------------------------------------------------------------------------------- */ /* Ook, these were functions around directory entries / inodes */ /* -------------------------------- superblock games -------------------------- */ +/** + * get superlock object by vpath + * + * @param vpath path + * @return superlock object or NULL if not found + */ + +struct vfs_s_super * +vfs_get_super_by_vpath (const vfs_path_t * vpath) +{ + GList *iter; + void *cookie = NULL; + const vfs_path_element_t *path_element; + struct vfs_s_subclass *subclass; + struct vfs_s_super *super = NULL; + vfs_path_t *vpath_archive; + + path_element = vfs_path_get_by_index (vpath, -1); + subclass = ((struct vfs_s_subclass *) path_element->class->data); + if (subclass == NULL) + return NULL; + + vpath_archive = vfs_path_clone (vpath); + vfs_path_remove_element_by_index (vpath_archive, -1); + + if (subclass->archive_check != NULL) + { + cookie = subclass->archive_check (vpath_archive); + if (cookie == NULL) + goto ret; + } + + for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter)) + { + int i; + + super = (struct vfs_s_super *) iter->data; + + /* 0 == other, 1 == same, return it, 2 == other but stop scanning */ + i = subclass->archive_same (path_element, super, vpath_archive, cookie); + if (i == 1) + goto ret; + if (i != 0) + break; + } + + ret: + vfs_path_free (vpath_archive); + return super; +} + +/* --------------------------------------------------------------------------------------------- */ /** * get path from last VFS-element and create corresponding superblock * @@ -1055,67 +1107,44 @@ vfs_s_find_inode (struct vfs_class *me, const struct vfs_s_super *super, const char * vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flags) { - GList *iter; - const char *retval; + const char *retval = ""; int result = -1; struct vfs_s_super *super; - void *cookie = NULL; const vfs_path_element_t *path_element; - vfs_path_t *vpath_archive; struct vfs_s_subclass *subclass; path_element = vfs_path_get_by_index (vpath, -1); - subclass = ((struct vfs_s_subclass *) path_element->class->data); - if (subclass == NULL) - return NULL; + if (path_element->path != NULL) + retval = path_element->path; - vpath_archive = vfs_path_clone (vpath); - vfs_path_remove_element_by_index (vpath_archive, -1); - - retval = (path_element->path != NULL) ? path_element->path : ""; - - if (subclass->archive_check != NULL) - { - cookie = subclass->archive_check (vpath_archive); - if (cookie == NULL) - { - vfs_path_free (vpath_archive); - return NULL; - } - } - - for (iter = subclass->supers; iter != NULL; iter = g_list_next (iter)) - { - int i; - - super = (struct vfs_s_super *) iter->data; - - /* 0 == other, 1 == same, return it, 2 == other but stop scanning */ - i = subclass->archive_same (path_element, super, vpath_archive, cookie); - if (i != 0) - { - if (i == 1) - goto return_success; - break; - } - } + super = vfs_get_super_by_vpath(vpath); + if (super != NULL) + goto return_success; if (flags & FL_NO_OPEN) { path_element->class->verrno = EIO; - vfs_path_free (vpath_archive); return NULL; } super = vfs_s_new_super (path_element->class); + + subclass = ((struct vfs_s_subclass *) path_element->class->data); if (subclass->open_archive != NULL) + { + vfs_path_t *vpath_archive; + + vpath_archive = vfs_path_clone (vpath); + vfs_path_remove_element_by_index (vpath_archive, -1); + result = subclass->open_archive (super, vpath_archive, path_element); + vfs_path_free (vpath_archive); + } if (result == -1) { vfs_s_free_super (path_element->class, super); path_element->class->verrno = EIO; - vfs_path_free (vpath_archive); return NULL; } if (!super->name) @@ -1128,7 +1157,6 @@ vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flag return_success: *archive = super; - vfs_path_free (vpath_archive); return retval; } diff --git a/lib/vfs/interface.c b/lib/vfs/interface.c index 02b6628b3..294646532 100644 --- a/lib/vfs/interface.c +++ b/lib/vfs/interface.c @@ -699,34 +699,25 @@ mc_chdir (const vfs_path_t * vpath) path_element = vfs_path_get_by_index (vfs_get_raw_current_dir (), -1); if (vfs_path_element_valid (path_element)) { + struct vfs_s_super *super; + if (*path_element->path != '\0') { char *p; p = strchr (path_element->path, 0) - 1; - if (p != NULL && *p == PATH_SEP && p != path_element->path) + if (*p == PATH_SEP && p > path_element->path) *p = '\0'; } -#ifdef ENABLE_VFS_NET + + super = vfs_get_super_by_vpath (vpath); + if (super != NULL) { - struct vfs_s_subclass *subclass; - - subclass = (struct vfs_s_subclass *) path_element->class->data; - if (subclass != NULL) - { - struct vfs_s_super *super = NULL; - - (void) vfs_s_get_path (vpath, &super, 0); - if (super != NULL && super->path_element != NULL) - { - g_free (super->path_element->path); - super->path_element->path = g_strdup (path_element->path); - } - } + g_free (super->path_element->path); + super->path_element->path = g_strdup (path_element->path); } -#endif /* ENABLE_VFS_NET */ - } + return 0; error_end: diff --git a/lib/vfs/xdirentry.h b/lib/vfs/xdirentry.h index 2e63a7b29..7d44d04d5 100644 --- a/lib/vfs/xdirentry.h +++ b/lib/vfs/xdirentry.h @@ -176,6 +176,7 @@ struct vfs_s_inode *vfs_s_find_root (struct vfs_class *me, struct vfs_s_entry *e /* outside interface */ void vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub); const char *vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flags); +struct vfs_s_super *vfs_get_super_by_vpath(const vfs_path_t * vpath); void vfs_s_invalidate (struct vfs_class *me, struct vfs_s_super *super); char *vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino); diff --git a/src/vfs/fish/fish.c b/src/vfs/fish/fish.c index 5d1353d62..da5bcde7d 100644 --- a/src/vfs/fish/fish.c +++ b/src/vfs/fish/fish.c @@ -543,7 +543,6 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super) if (fish_info (me, super)) SUP->scr_env = fish_set_env (SUP->host_flags); - vfs_print_message (_("fish: Connected, home %s."), super->path_element->path); #if 0 super->name = g_strconcat ("sh://", super->path_element->user, "@", super->path_element->host, "/", @@ -1568,7 +1567,11 @@ fish_fill_names (struct vfs_class *me, fill_names_f func) } break; } - name = vfs_path_element_build_pretty_path_str (super->path_element); + + name = + g_strconcat (vfs_fish_ops.prefix, VFS_PATH_URL_DELIMITER, + super->path_element->user, "@", super->path_element->host, flags, "/", + super->path_element->path, (char *) NULL); func (name); g_free (name); } diff --git a/src/vfs/ftpfs/ftpfs.c b/src/vfs/ftpfs/ftpfs.c index 9e8d5ad3e..f84d388fe 100644 --- a/src/vfs/ftpfs/ftpfs.c +++ b/src/vfs/ftpfs/ftpfs.c @@ -219,6 +219,7 @@ typedef struct * "LIST" instead */ int ctl_connection_busy; + char *current_dir; } ftp_super_data_t; typedef struct @@ -262,6 +263,7 @@ static const char *netrcp; c) strip trailing "/." */ +static char *ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super); static int ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const char *remote_path); static int ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, @@ -424,11 +426,11 @@ ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super) sock = ftpfs_open_socket (me, super); if (sock != -1) { - char *cwdir = super->path_element->path; + char *cwdir = SUP->current_dir; close (SUP->sock); SUP->sock = sock; - super->path_element->path = NULL; + SUP->current_dir = NULL; if (ftpfs_login_server (me, super, super->path_element->password) != 0) @@ -440,7 +442,7 @@ ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super) return sock == COMPLETE ? 1 : 0; } - super->path_element->path = cwdir; + SUP->current_dir = cwdir; } return 0; @@ -548,6 +550,7 @@ ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super) ftpfs_command (me, super, NONE, "QUIT"); close (SUP->sock); } + g_free (SUP->current_dir); g_free (super->data); super->data = NULL; } @@ -960,6 +963,10 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super) } while (retry_seconds != 0); + SUP->current_dir = ftpfs_get_current_directory (me, super); + if (SUP->current_dir == NULL) + SUP->current_dir = g_strdup (PATH_SEP_STR); + return 0; } @@ -1011,6 +1018,55 @@ ftpfs_archive_same (const vfs_path_element_t * vpath_element, struct vfs_s_super return result; } +/* --------------------------------------------------------------------------------------------- */ +/* The returned directory should always contain a trailing slash */ + +static char * +ftpfs_get_current_directory (struct vfs_class *me, struct vfs_s_super *super) +{ + char buf[MC_MAXPATHLEN + 1]; + + if (ftpfs_command (me, super, NONE, "PWD") == COMPLETE && + ftpfs_get_reply (me, SUP->sock, buf, sizeof (buf)) == COMPLETE) + { + char *bufp = NULL; + char *bufq; + + for (bufq = buf; *bufq != '\0'; bufq++) + if (*bufq == '"') + { + if (bufp == NULL) + bufp = bufq + 1; + else + { + *bufq = '\0'; + + if (*bufp != '\0') + { + if (*(bufq - 1) != '/') + { + *bufq++ = '/'; + *bufq = '\0'; + } + + if (*bufp == '/') + return g_strdup (bufp); + + /* If the remote server is an Amiga a leading slash + might be missing. MC needs it because it is used + as separator between hostname and path internally. */ + return g_strconcat ("/", bufp, (char *) NULL); + } + + break; + } + } + } + + ftpfs_errno = EIO; + return NULL; +} + /* --------------------------------------------------------------------------------------------- */ /* Setup Passive PASV FTP connection */ @@ -1991,9 +2047,9 @@ ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char * { (void) me; - if (super->path_element->path == NULL) + if (SUP->current_dir == NULL) return FALSE; - return (strcmp (path, super->path_element->path) == 0); + return (strcmp (path, SUP->current_dir) == 0); } /* --------------------------------------------------------------------------------------------- */ @@ -2014,7 +2070,11 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha if (r != COMPLETE) ftpfs_errno = EIO; else + { + g_free (SUP->current_dir); + SUP->current_dir = g_strdup (remote_path); SUP->cwd_deferred = 0; + } return r; } @@ -2188,6 +2248,7 @@ ftpfs_fill_names (struct vfs_class *me, fill_names_f func) char *name; name = vfs_path_element_build_pretty_path_str (super->path_element); + func (name); g_free (name); }