Ticket #2800: Garbage directory listing in ftpfs
Just open any non-anonymous FTP connection.
Этот коммит содержится в:
родитель
328abc24c8
Коммит
21d1f61b40
@ -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 */
|
/* Ook, these were functions around directory entries / inodes */
|
||||||
/* -------------------------------- superblock games -------------------------- */
|
/* -------------------------------- 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
|
* 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 *
|
const char *
|
||||||
vfs_s_get_path (const vfs_path_t * vpath, struct vfs_s_super **archive, int flags)
|
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;
|
int result = -1;
|
||||||
struct vfs_s_super *super;
|
struct vfs_s_super *super;
|
||||||
void *cookie = NULL;
|
|
||||||
const vfs_path_element_t *path_element;
|
const vfs_path_element_t *path_element;
|
||||||
vfs_path_t *vpath_archive;
|
|
||||||
struct vfs_s_subclass *subclass;
|
struct vfs_s_subclass *subclass;
|
||||||
|
|
||||||
path_element = vfs_path_get_by_index (vpath, -1);
|
path_element = vfs_path_get_by_index (vpath, -1);
|
||||||
subclass = ((struct vfs_s_subclass *) path_element->class->data);
|
|
||||||
|
|
||||||
if (subclass == NULL)
|
if (path_element->path != NULL)
|
||||||
return NULL;
|
retval = path_element->path;
|
||||||
|
|
||||||
vpath_archive = vfs_path_clone (vpath);
|
super = vfs_get_super_by_vpath(vpath);
|
||||||
vfs_path_remove_element_by_index (vpath_archive, -1);
|
if (super != NULL)
|
||||||
|
goto return_success;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & FL_NO_OPEN)
|
if (flags & FL_NO_OPEN)
|
||||||
{
|
{
|
||||||
path_element->class->verrno = EIO;
|
path_element->class->verrno = EIO;
|
||||||
vfs_path_free (vpath_archive);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
super = vfs_s_new_super (path_element->class);
|
super = vfs_s_new_super (path_element->class);
|
||||||
|
|
||||||
|
subclass = ((struct vfs_s_subclass *) path_element->class->data);
|
||||||
if (subclass->open_archive != NULL)
|
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);
|
result = subclass->open_archive (super, vpath_archive, path_element);
|
||||||
|
vfs_path_free (vpath_archive);
|
||||||
|
}
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
{
|
{
|
||||||
vfs_s_free_super (path_element->class, super);
|
vfs_s_free_super (path_element->class, super);
|
||||||
path_element->class->verrno = EIO;
|
path_element->class->verrno = EIO;
|
||||||
vfs_path_free (vpath_archive);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!super->name)
|
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:
|
return_success:
|
||||||
*archive = super;
|
*archive = super;
|
||||||
vfs_path_free (vpath_archive);
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,34 +699,25 @@ mc_chdir (const vfs_path_t * vpath)
|
|||||||
path_element = vfs_path_get_by_index (vfs_get_raw_current_dir (), -1);
|
path_element = vfs_path_get_by_index (vfs_get_raw_current_dir (), -1);
|
||||||
if (vfs_path_element_valid (path_element))
|
if (vfs_path_element_valid (path_element))
|
||||||
{
|
{
|
||||||
|
struct vfs_s_super *super;
|
||||||
|
|
||||||
if (*path_element->path != '\0')
|
if (*path_element->path != '\0')
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = strchr (path_element->path, 0) - 1;
|
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';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_VFS_NET
|
|
||||||
|
super = vfs_get_super_by_vpath (vpath);
|
||||||
|
if (super != NULL)
|
||||||
{
|
{
|
||||||
struct vfs_s_subclass *subclass;
|
g_free (super->path_element->path);
|
||||||
|
super->path_element->path = g_strdup (path_element->path);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_VFS_NET */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_end:
|
error_end:
|
||||||
|
@ -176,6 +176,7 @@ struct vfs_s_inode *vfs_s_find_root (struct vfs_class *me, struct vfs_s_entry *e
|
|||||||
/* outside interface */
|
/* outside interface */
|
||||||
void vfs_s_init_class (struct vfs_class *vclass, struct vfs_s_subclass *sub);
|
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);
|
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);
|
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);
|
char *vfs_s_fullpath (struct vfs_class *me, struct vfs_s_inode *ino);
|
||||||
|
@ -543,7 +543,6 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
|||||||
if (fish_info (me, super))
|
if (fish_info (me, super))
|
||||||
SUP->scr_env = fish_set_env (SUP->host_flags);
|
SUP->scr_env = fish_set_env (SUP->host_flags);
|
||||||
|
|
||||||
vfs_print_message (_("fish: Connected, home %s."), super->path_element->path);
|
|
||||||
#if 0
|
#if 0
|
||||||
super->name =
|
super->name =
|
||||||
g_strconcat ("sh://", super->path_element->user, "@", super->path_element->host, "/",
|
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;
|
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);
|
func (name);
|
||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,7 @@ typedef struct
|
|||||||
* "LIST" instead
|
* "LIST" instead
|
||||||
*/
|
*/
|
||||||
int ctl_connection_busy;
|
int ctl_connection_busy;
|
||||||
|
char *current_dir;
|
||||||
} ftp_super_data_t;
|
} ftp_super_data_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -262,6 +263,7 @@ static const char *netrcp;
|
|||||||
c) strip trailing "/."
|
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,
|
static int ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super,
|
||||||
const char *remote_path);
|
const char *remote_path);
|
||||||
static int ftpfs_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply,
|
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);
|
sock = ftpfs_open_socket (me, super);
|
||||||
if (sock != -1)
|
if (sock != -1)
|
||||||
{
|
{
|
||||||
char *cwdir = super->path_element->path;
|
char *cwdir = SUP->current_dir;
|
||||||
|
|
||||||
close (SUP->sock);
|
close (SUP->sock);
|
||||||
SUP->sock = sock;
|
SUP->sock = sock;
|
||||||
super->path_element->path = NULL;
|
SUP->current_dir = NULL;
|
||||||
|
|
||||||
|
|
||||||
if (ftpfs_login_server (me, super, super->path_element->password) != 0)
|
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;
|
return sock == COMPLETE ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
super->path_element->path = cwdir;
|
SUP->current_dir = cwdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -548,6 +550,7 @@ ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
|
|||||||
ftpfs_command (me, super, NONE, "QUIT");
|
ftpfs_command (me, super, NONE, "QUIT");
|
||||||
close (SUP->sock);
|
close (SUP->sock);
|
||||||
}
|
}
|
||||||
|
g_free (SUP->current_dir);
|
||||||
g_free (super->data);
|
g_free (super->data);
|
||||||
super->data = NULL;
|
super->data = NULL;
|
||||||
}
|
}
|
||||||
@ -960,6 +963,10 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
|
|||||||
}
|
}
|
||||||
while (retry_seconds != 0);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,6 +1018,55 @@ ftpfs_archive_same (const vfs_path_element_t * vpath_element, struct vfs_s_super
|
|||||||
return result;
|
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 */
|
/* 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;
|
(void) me;
|
||||||
|
|
||||||
if (super->path_element->path == NULL)
|
if (SUP->current_dir == NULL)
|
||||||
return FALSE;
|
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)
|
if (r != COMPLETE)
|
||||||
ftpfs_errno = EIO;
|
ftpfs_errno = EIO;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
g_free (SUP->current_dir);
|
||||||
|
SUP->current_dir = g_strdup (remote_path);
|
||||||
SUP->cwd_deferred = 0;
|
SUP->cwd_deferred = 0;
|
||||||
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2188,6 +2248,7 @@ ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
|
|||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
name = vfs_path_element_build_pretty_path_str (super->path_element);
|
name = vfs_path_element_build_pretty_path_str (super->path_element);
|
||||||
|
|
||||||
func (name);
|
func (name);
|
||||||
g_free (name);
|
g_free (name);
|
||||||
}
|
}
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user