Ticket #2361: VFS URI reimplementation

Created vfs_url_t structure

...and use it to parse and store network VFS options.

vfs_s_super structure now has a special member for network VFS options.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Andrew Borodin 2011-03-29 10:20:34 +03:00 committed by Slava Zanko
parent fcfa76be3d
commit 42bc3171c3
7 changed files with 325 additions and 362 deletions

View File

@ -384,6 +384,9 @@ vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
MEDATA->supers = g_list_remove (MEDATA->supers, super);
CALL (free_archive) (me, super);
#ifdef ENABLE_VFS_NET
vfs_url_free (super->url);
#endif
g_free (super->name);
g_free (super);
}

View File

@ -373,85 +373,82 @@ vfs_mkstemps (char **pname, const char *prefix, const char *param_basename)
* ftp://joe:password@foo.se
*
* @param path is an input string to be parsed
* @param host is an outptun g_malloc()ed hostname
* @param user is an outptut g_malloc()ed username
* (NULL if not specified)
* @param port is an outptut integer port number
* @param pass is an outptut g_malloc()ed password
* @param default_port is an input default port
* @param flags are parsing modifier flags (@see VFS_URL_FLAGS)
* @param flags are parsing modifier flags (@see vfs_url_flags_t)
*
* @return g_malloc()ed host, user and pass if they are present.
* @return g_malloc()ed url info.
* If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
* is not set, then the current login name is supplied.
* Return value is a g_malloc()ed string with the pathname relative to the
* Return value is a g_malloc()ed structure with the pathname relative to the
* host.
*/
char *
vfs_split_url (const char *path, char **host, char **user, int *port,
char **pass, int default_port, enum VFS_URL_FLAGS flags)
vfs_url_t *
vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags)
{
vfs_url_t *url;
char *pcopy;
const char *pend;
char *dir, *colon, *inner_colon, *at, *rest;
char *retval;
char *const pcopy = g_strdup (path);
const char *pend = pcopy + strlen (pcopy);
if (pass)
*pass = NULL;
*port = default_port;
*user = NULL;
retval = NULL;
url = g_new0 (vfs_url_t, 1);
url->port = default_port;
pcopy = g_strdup (path);
pend = pcopy + strlen (pcopy);
dir = pcopy;
if (!(flags & URL_NOSLASH))
if ((flags & URL_NOSLASH) == 0)
{
/* locate path component */
while (*dir != PATH_SEP && *dir)
while (*dir != PATH_SEP && *dir != '\0')
dir++;
if (*dir)
{
retval = g_strdup (dir);
*dir = 0;
}
if (*dir == '\0')
url->path = g_strdup (PATH_SEP_STR);
else
retval = g_strdup (PATH_SEP_STR);
{
url->path = g_strdup (dir);
*dir = '\0';
}
}
/* search for any possible user */
at = strrchr (pcopy, '@');
/* We have a username */
if (at)
if (at == NULL)
rest = pcopy;
else
{
*at = 0;
*at = '\0';
inner_colon = strchr (pcopy, ':');
if (inner_colon)
if (inner_colon != NULL)
{
*inner_colon = 0;
*inner_colon = '\0';
inner_colon++;
if (pass)
*pass = g_strdup (inner_colon);
url->password = g_strdup (inner_colon);
}
if (*pcopy != 0)
*user = g_strdup (pcopy);
if (*pcopy != '\0')
url->user = g_strdup (pcopy);
if (pend == at + 1)
rest = at;
else
rest = at + 1;
}
else
rest = pcopy;
if (!*user && !(flags & URL_USE_ANONYMOUS))
*user = vfs_get_local_username ();
if ((flags & URL_USE_ANONYMOUS) == 0)
url->user = vfs_get_local_username ();
/* Check if the host comes with a port spec, if so, chop it */
if ('[' == *rest)
if (*rest != '[')
colon = strchr (rest, ':');
else
{
colon = strchr (++rest, ']');
if (colon)
if (colon != NULL)
{
colon[0] = '\0';
colon[1] = '\0';
@ -459,45 +456,52 @@ vfs_split_url (const char *path, char **host, char **user, int *port,
}
else
{
g_free (pcopy);
g_free (retval);
*host = NULL;
*port = 0;
vfs_url_free (url);
return NULL;
}
}
else
colon = strchr (rest, ':');
if (colon)
if (colon != NULL)
{
*colon = 0;
if (sscanf (colon + 1, "%d", port) == 1)
*colon = '\0';
if (sscanf (colon + 1, "%d", &url->port) == 1)
{
if (*port <= 0 || *port >= 65536)
*port = default_port;
if (url->port <= 0 || url->port >= 65536)
url->port = default_port;
}
else
{
while (*(++colon))
while (*(++colon) != '\0')
{
switch (*colon)
{
case 'C':
*port = 1;
url->port = 1;
break;
case 'r':
*port = 2;
url->port = 2;
break;
}
}
}
}
if (host)
*host = g_strdup (rest);
g_free (pcopy);
return retval;
url->host = g_strdup (rest);
return url;
}
/* --------------------------------------------------------------------------------------------- */
void
vfs_url_free (vfs_url_t * url)
{
if (url != NULL)
{
g_free (url->user);
g_free (url->password);
g_free (url->host);
g_free (url->path);
g_free (url);
}
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -17,19 +17,29 @@
/*** enums ***************************************************************************************/
/** Bit flags for vfs_split_url()
/** Bit flags for vfs_url_split()
*
* Modify parsing parameters according to flag meaning.
* @see vfs_split_url()
* @see vfs_url_split()
*/
enum VFS_URL_FLAGS
typedef enum
{
URL_FLAGS_NONE = 0,
URL_USE_ANONYMOUS = 1, /**< if set, empty *user will contain NULL instead of current */
URL_NOSLASH = 2 /**< if set, 'proto://' part in url is not searched */
};
} vfs_url_flags_t;
/*** structures declarations (and typedefs of structures)*****************************************/
typedef struct
{
char *user;
char *password;
char *host;
int port;
char *path;
} vfs_url_t;
/*** global variables defined in .c file *********************************************************/
/*** declarations of public functions ************************************************************/
@ -37,8 +47,8 @@ enum VFS_URL_FLAGS
int vfs_finduid (const char *name);
int vfs_findgid (const char *name);
char *vfs_split_url (const char *path, char **host, char **user, int *port,
char **pass, int default_port, enum VFS_URL_FLAGS flags);
vfs_url_t *vfs_url_split (const char *path, int default_port, vfs_url_flags_t flags);
void vfs_url_free (vfs_url_t * url);
int vfs_split_text (char *p);
int vfs_mkstemps (char **pname, const char *prefix, const char *basename);

View File

@ -60,6 +60,10 @@ struct vfs_s_super
int fd_usage; /* Number of open files */
int ino_usage; /* Usage count of this superblock */
int want_stale; /* If set, we do not flush cache properly */
#ifdef ENABLE_VFS_NET
vfs_url_t *url;
#endif /* ENABLE_VFS_NET */
void *data; /* This is for filesystem-specific use */
};

View File

@ -2,7 +2,7 @@
shell connections.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007 Free Software Foundation, Inc.
2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Written by: 1998 Pavel Machek
Spaces fix: 2000 Michal Svec
@ -134,11 +134,8 @@ int fish_directory_timeout = 900;
typedef struct
{
int sockr, sockw;
char *cwdir;
char *host, *user;
char *password;
int flags;
int sockr;
int sockw;
char *scr_ls;
char *scr_chmod;
char *scr_exists;
@ -253,7 +250,7 @@ fish_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, c
{
va_list ap;
char *str;
int status;
ssize_t status;
FILE *logfile = MEDATA->logfile;
va_start (ap, fmt);
@ -297,10 +294,6 @@ fish_free_archive (struct vfs_class *me, struct vfs_s_super *super)
close (SUP->sockr);
SUP->sockw = SUP->sockr = -1;
}
g_free (SUP->host);
g_free (SUP->user);
g_free (SUP->cwdir);
g_free (SUP->password);
g_free (SUP->scr_ls);
g_free (SUP->scr_exists);
g_free (SUP->scr_mkdir);
@ -437,17 +430,17 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
{
char gbuf[10];
const char *argv[10]; /* All of 10 is used now */
const char *xsh = (SUP->flags == FISH_FLAG_RSH ? "rsh" : "ssh");
const char *xsh = (super->url->port == FISH_FLAG_RSH ? "rsh" : "ssh");
int i = 0;
argv[i++] = xsh;
if (SUP->flags == FISH_FLAG_COMPRESSED)
if (super->url->port == FISH_FLAG_COMPRESSED)
argv[i++] = "-C";
if (SUP->flags > FISH_FLAG_RSH)
if (super->url->port > FISH_FLAG_RSH)
{
argv[i++] = "-p";
g_snprintf (gbuf, sizeof (gbuf), "%d", SUP->flags);
g_snprintf (gbuf, sizeof (gbuf), "%d", super->url->port);
argv[i++] = gbuf;
}
@ -458,18 +451,18 @@ fish_open_archive_pipeopen (struct vfs_s_super *super)
* option breaks it for some)
*/
if (SUP->user)
if (super->url->user != NULL)
{
argv[i++] = "-l";
argv[i++] = SUP->user;
argv[i++] = super->url->user;
}
else
{
/* The rest of the code assumes it to be a valid username */
SUP->user = vfs_get_local_username ();
super->url->user = vfs_get_local_username ();
}
argv[i++] = SUP->host;
argv[i++] = super->url->host;
argv[i++] = "echo FISH:; /bin/sh";
argv[i++] = NULL;
@ -488,7 +481,7 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
if (!vfs_s_get_line (me, SUP->sockr, answer, sizeof (answer), ':'))
return FALSE;
if (strstr (answer, "assword"))
if (strstr (answer, "assword") != NULL)
{
/* Currently, this does not work. ssh reads passwords from
/dev/tty, not from stdin :-(. */
@ -497,25 +490,27 @@ fish_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
return FALSE;
#if 0
if (!SUP->password)
if (super->url->password == NULL)
{
char *p, *op;
p = g_strdup_printf (_("fish: Password is required for %s"), SUP->user);
p = g_strdup_printf (_("fish: Password is required for %s"), super->url->user);
op = vfs_get_password (p);
g_free (p);
if (op == NULL)
return FALSE;
SUP->password = op;
super->url->password = op;
}
printf ("\n%s\n", _("fish: Sending password..."));
{
size_t str_len;
str_len = strlen (SUP->password);
if ((write (SUP->sockw, SUP->password, str_len) != (ssize_t) str_len)
str_len = strlen (super->url->password);
if ((write (SUP.sockw, super->url->password, str_len) != (ssize_t) str_len)
|| (write (SUP->sockw, "\n", 1) != 1))
{
return FALSE;
}
}
#endif
}
@ -569,12 +564,14 @@ fish_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
SUP->scr_env = fish_set_env (SUP->host_flags);
vfs_print_message (_("fish: Setting up current directory..."));
SUP->cwdir = fish_getcwd (me, super);
vfs_print_message (_("fish: Connected, home %s."), SUP->cwdir);
super->url->path = fish_getcwd (me, super);
vfs_print_message (_("fish: Connected, home %s."), super->url->path);
#if 0
super->name = g_strconcat ("/#sh:", SUP->user, "@", SUP->host, "/", (char *) NULL);
#endif
super->name =
g_strconcat ("/#sh:", super->url->user, "@", super->url->host, "/", (char *) NULL);
#else
super->name = g_strdup (PATH_SEP_STR);
#endif
super->root = vfs_s_new_inode (me, super, vfs_s_default_stat (me, S_IFDIR | 0755));
return 0;
@ -586,41 +583,41 @@ static int
fish_open_archive (struct vfs_class *me, struct vfs_s_super *super,
const char *archive_name, char *op)
{
char *host, *user, *password, *p;
int flags;
(void) archive_name;
super->data = g_new0 (fish_super_data_t, 1);
p = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags,
&password, 0, URL_NOSLASH | URL_USE_ANONYMOUS);
super->url = vfs_url_split (strchr (op, ':') + 1, 0, URL_NOSLASH | URL_USE_ANONYMOUS);
g_free (p);
super->data = g_new0 (fish_super_data_t, 1);
SUP->host = host;
SUP->user = user;
SUP->flags = flags;
if (strncmp (op, "rsh:", 4) == 0)
SUP->flags = FISH_FLAG_RSH;
SUP->cwdir = NULL;
if (password != NULL)
SUP->password = password;
SUP->scr_ls = fish_load_script_from_file (host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
SUP->scr_exists = fish_load_script_from_file (host, FISH_EXISTS_FILE, FISH_EXISTS_DEF_CONTENT);
SUP->scr_mkdir = fish_load_script_from_file (host, FISH_MKDIR_FILE, FISH_MKDIR_DEF_CONTENT);
SUP->scr_unlink = fish_load_script_from_file (host, FISH_UNLINK_FILE, FISH_UNLINK_DEF_CONTENT);
SUP->scr_chown = fish_load_script_from_file (host, FISH_CHOWN_FILE, FISH_CHOWN_DEF_CONTENT);
SUP->scr_chmod = fish_load_script_from_file (host, FISH_CHMOD_FILE, FISH_CHMOD_DEF_CONTENT);
SUP->scr_rmdir = fish_load_script_from_file (host, FISH_RMDIR_FILE, FISH_RMDIR_DEF_CONTENT);
SUP->scr_ln = fish_load_script_from_file (host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
SUP->scr_mv = fish_load_script_from_file (host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
super->url->port = FISH_FLAG_RSH;
SUP->scr_ls = fish_load_script_from_file (super->url->host, FISH_LS_FILE, FISH_LS_DEF_CONTENT);
SUP->scr_exists =
fish_load_script_from_file (super->url->host, FISH_EXISTS_FILE, FISH_EXISTS_DEF_CONTENT);
SUP->scr_mkdir =
fish_load_script_from_file (super->url->host, FISH_MKDIR_FILE, FISH_MKDIR_DEF_CONTENT);
SUP->scr_unlink =
fish_load_script_from_file (super->url->host, FISH_UNLINK_FILE, FISH_UNLINK_DEF_CONTENT);
SUP->scr_chown =
fish_load_script_from_file (super->url->host, FISH_CHOWN_FILE, FISH_CHOWN_DEF_CONTENT);
SUP->scr_chmod =
fish_load_script_from_file (super->url->host, FISH_CHMOD_FILE, FISH_CHMOD_DEF_CONTENT);
SUP->scr_rmdir =
fish_load_script_from_file (super->url->host, FISH_RMDIR_FILE, FISH_RMDIR_DEF_CONTENT);
SUP->scr_ln = fish_load_script_from_file (super->url->host, FISH_LN_FILE, FISH_LN_DEF_CONTENT);
SUP->scr_mv = fish_load_script_from_file (super->url->host, FISH_MV_FILE, FISH_MV_DEF_CONTENT);
SUP->scr_hardlink =
fish_load_script_from_file (host, FISH_HARDLINK_FILE, FISH_HARDLINK_DEF_CONTENT);
SUP->scr_get = fish_load_script_from_file (host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
SUP->scr_send = fish_load_script_from_file (host, FISH_SEND_FILE, FISH_SEND_DEF_CONTENT);
SUP->scr_append = fish_load_script_from_file (host, FISH_APPEND_FILE, FISH_APPEND_DEF_CONTENT);
SUP->scr_info = fish_load_script_from_file (host, FISH_INFO_FILE, FISH_INFO_DEF_CONTENT);
fish_load_script_from_file (super->url->host, FISH_HARDLINK_FILE,
FISH_HARDLINK_DEF_CONTENT);
SUP->scr_get =
fish_load_script_from_file (super->url->host, FISH_GET_FILE, FISH_GET_DEF_CONTENT);
SUP->scr_send =
fish_load_script_from_file (super->url->host, FISH_SEND_FILE, FISH_SEND_DEF_CONTENT);
SUP->scr_append =
fish_load_script_from_file (super->url->host, FISH_APPEND_FILE, FISH_APPEND_DEF_CONTENT);
SUP->scr_info =
fish_load_script_from_file (super->url->host, FISH_INFO_FILE, FISH_INFO_DEF_CONTENT);
return fish_open_archive_int (me, super);
}
@ -630,27 +627,23 @@ static int
fish_archive_same (struct vfs_class *me, struct vfs_s_super *super,
const char *archive_name, char *op, void *cookie)
{
char *host, *user;
int flags;
vfs_url_t *url;
int result;
(void) me;
(void) archive_name;
(void) cookie;
op = vfs_split_url (strchr (op, ':') + 1, &host, &user, &flags, 0, 0,
URL_NOSLASH | URL_USE_ANONYMOUS);
url = vfs_url_split (strchr (op, ':') + 1, 0, URL_NOSLASH | URL_USE_ANONYMOUS);
g_free (op);
if (url->user == NULL)
url->user = vfs_get_local_username ();
if (user == NULL)
user = vfs_get_local_username ();
result = ((strcmp (url->host, super->url->host) == 0)
&& (strcmp (url->user, super->url->user) == 0)
&& (url->port == super->url->port)) ? 1 : 0;
result = ((strcmp (host, SUP->host) == 0)
&& (strcmp (user, SUP->user) == 0) && (flags == SUP->flags));
g_free (host);
g_free (user);
vfs_url_free (url);
return result;
}
@ -843,19 +836,13 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
reply_code = fish_decode_reply (buffer + 4, 0);
if (reply_code == COMPLETE)
{
g_free (SUP->cwdir);
SUP->cwdir = g_strdup (remote_path);
g_free (super->url->path);
super->url->path = g_strdup (remote_path);
vfs_print_message (_("%s: done."), me->name);
return 0;
}
else if (reply_code == ERROR)
{
me->verrno = EACCES;
}
else
{
me->verrno = E_REMOTE;
}
me->verrno = reply_code == ERROR ? EACCES : E_REMOTE;
error:
vfs_print_message (_("%s: failure"), me->name);
@ -865,7 +852,7 @@ fish_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path)
/* --------------------------------------------------------------------------------------------- */
static int
fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
fish_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
gchar *shell_commands = NULL;
@ -878,7 +865,6 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
char *quoted_name;
h = open (localname, O_RDONLY);
if (h == -1)
ERRNOR (EIO, -1);
if (fstat (h, &s) < 0)
@ -925,6 +911,7 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
shell_commands =
g_strconcat (SUP->scr_env, "FISH_FILENAME=%s FISH_FILESIZE=%" PRIuMAX ";\n",
SUP->scr_append, (char *) NULL);
n = fish_command (me, super, WAIT_REPLY, shell_commands, quoted_name,
(uintmax_t) s.st_size);
g_free (shell_commands);
@ -978,9 +965,11 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
}
close (h);
g_free (quoted_name);
if ((fish_get_reply (me, SUP->sockr, NULL, 0) != COMPLETE) || was_error)
ERRNOR (E_REMOTE, -1);
return 0;
error_return:
close (h);
fish_get_reply (me, SUP->sockr, NULL, 0);
@ -991,7 +980,7 @@ fish_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
/* --------------------------------------------------------------------------------------------- */
static int
fish_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
fish_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
{
fish_fh_data_t *fish;
gchar *shell_commands = NULL;
@ -1042,7 +1031,7 @@ fish_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
/* --------------------------------------------------------------------------------------------- */
static void
fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
fish_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
struct vfs_s_super *super = FH_SUPER;
@ -1050,6 +1039,7 @@ fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
int n;
vfs_print_message (_("Aborting transfer..."));
do
{
n = MIN (sizeof (buffer), (size_t) (fish->total - fish->got));
@ -1072,7 +1062,7 @@ fish_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
/* --------------------------------------------------------------------------------------------- */
static int
fish_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
fish_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
struct vfs_s_super *super = FH_SUPER;
@ -1101,7 +1091,7 @@ fish_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_
/* --------------------------------------------------------------------------------------------- */
static void
fish_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
fish_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
{
fish_fh_data_t *fish = (fish_fh_data_t *) fh->data;
@ -1304,6 +1294,7 @@ fish_chown (struct vfs_class *me, const char *path, uid_t owner, gid_t group)
sowner = pw->pw_name;
sgroup = gr->gr_name;
{
gchar *shell_commands = NULL;
@ -1357,7 +1348,6 @@ fish_exists (struct vfs_class *me, const char *path)
return (fish_send_command (me, super, buf, OPT_FLUSH) == 0) ? 1 : 0;
}
/* --------------------------------------------------------------------------------------------- */
static int
@ -1382,9 +1372,7 @@ fish_mkdir (struct vfs_class *me, const char *path, mode_t mode)
return ret_code;
if (!fish_exists (me, path))
{
ERRNOR (EACCES, -1);
}
return 0;
}
@ -1408,7 +1396,7 @@ fish_rmdir (struct vfs_class *me, const char *path)
/* --------------------------------------------------------------------------------------------- */
static int
fish_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
fish_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
{
fish_fh_data_t *fish;
@ -1445,7 +1433,7 @@ fish_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mo
/* --------------------------------------------------------------------------------------------- */
static int
fish_fh_close (struct vfs_class *me, vfs_file_handler_t *fh)
fish_fh_close (struct vfs_class *me, vfs_file_handler_t * fh)
{
(void) me;
@ -1468,7 +1456,7 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
char gbuf[10];
const char *flags = "";
switch (SUP->flags)
switch (super->url->port)
{
case FISH_FLAG_RSH:
flags = ":r";
@ -1477,16 +1465,16 @@ fish_fill_names (struct vfs_class *me, fill_names_f func)
flags = ":C";
break;
default:
if (SUP->flags > FISH_FLAG_RSH)
if (super->url->port > FISH_FLAG_RSH)
{
g_snprintf (gbuf, sizeof (gbuf), ":%d", SUP->flags);
g_snprintf (gbuf, sizeof (gbuf), ":%d", super->url->port);
flags = gbuf;
}
break;
}
name =
g_strconcat ("/#sh:", SUP->user, "@", SUP->host, flags, "/", SUP->cwdir, (char *) NULL);
name = g_strconcat ("/#sh:", super->url->user, "@", super->url->host, flags, "/",
super->url->path, (char *) NULL);
func (name);
g_free (name);
}

View File

@ -1,6 +1,6 @@
/* Virtual File System: FTP file system.
Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007 Free Software Foundation, Inc.
2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Written by:
1995 Ching Hui
@ -9,6 +9,8 @@
1997 Norbert Warmuth
1998 Pavel Machek
2010 Yury V. Zaytsev
2010 Slava Zanko
2010 Andrew Borodin
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License
@ -197,11 +199,6 @@ typedef enum
typedef struct
{
int sock;
char *cwdir;
char *host;
char *user;
char *password;
int port;
char *proxy; /* proxy server, NULL if no proxy */
int failed_on_login; /* used to pass the failure reason to upper levels */
@ -322,43 +319,42 @@ ftpfs_translate_path (struct vfs_class *me, struct vfs_s_super *super, const cha
* ftp://joe@foo.edu:11321/private
* If the user is empty, e.g. ftp://@roxanne/private, then your login name
* is supplied.
*
*/
static void
ftpfs_split_url (char *path, char **host, char **user, int *port, char **pass)
static vfs_url_t *
ftpfs_split_url (const char *path)
{
char *p;
vfs_url_t *p;
p = vfs_split_url (path, host, user, port, pass, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
p = vfs_url_split (path, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
if (!*user)
if (p->user != NULL)
{
/* Look up user and password in netrc */
if (ftpfs_use_netrc)
ftpfs_netrc_lookup (*host, user, pass);
if (!*user)
*user = g_strdup ("anonymous");
ftpfs_netrc_lookup (p->host, &p->user, &p->password);
}
if (p->user == NULL)
p->user = g_strdup ("anonymous");
/* Look up password in netrc for known user */
if (ftpfs_use_netrc && *user && pass && !*pass)
if (ftpfs_use_netrc && p->user != NULL && p->password != NULL)
{
char *new_user;
char *new_user = NULL;
ftpfs_netrc_lookup (*host, &new_user, pass);
ftpfs_netrc_lookup (p->host, &new_user, &p->password);
/* If user is different, remove password */
if (new_user && strcmp (*user, new_user))
if (new_user != NULL && strcmp (p->user, new_user) != 0)
{
g_free (*pass);
*pass = NULL;
g_free (p->password);
p->password = NULL;
}
g_free (new_user);
}
g_free (p);
return p;
}
/* --------------------------------------------------------------------------------------------- */
@ -414,23 +410,30 @@ ftpfs_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_le
static int
ftpfs_reconnect (struct vfs_class *me, struct vfs_s_super *super)
{
int sock = ftpfs_open_socket (me, super);
int sock;
sock = ftpfs_open_socket (me, super);
if (sock != -1)
{
char *cwdir = SUP->cwdir;
char *cwdir = super->url->path;
close (SUP->sock);
SUP->sock = sock;
SUP->cwdir = NULL;
if (ftpfs_login_server (me, super, SUP->password))
super->url->path = NULL;
if (ftpfs_login_server (me, super, super->url->password) != 0)
{
if (!cwdir)
if (cwdir == NULL)
return 1;
sock = ftpfs_chdir_internal (me, super, cwdir);
g_free (cwdir);
return sock == COMPLETE;
return sock == COMPLETE ? 1 : 0;
}
SUP->cwdir = cwdir;
super->url->path = cwdir;
}
return 0;
}
@ -532,14 +535,10 @@ ftpfs_free_archive (struct vfs_class *me, struct vfs_s_super *super)
{
if (SUP->sock != -1)
{
vfs_print_message (_("ftpfs: Disconnecting from %s"), SUP->host);
vfs_print_message (_("ftpfs: Disconnecting from %s"), super->url->host);
ftpfs_command (me, super, NONE, "QUIT");
close (SUP->sock);
}
g_free (SUP->host);
g_free (SUP->user);
g_free (SUP->cwdir);
g_free (SUP->password);
g_free (super->data);
super->data = NULL;
}
@ -572,13 +571,13 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
SUP->isbinary = TYPE_UNKNOWN;
if (SUP->password != NULL) /* explicit password */
op = g_strdup (SUP->password);
if (super->url->password != NULL) /* explicit password */
op = g_strdup (super->url->password);
else if (netrcpass != NULL) /* password from netrc */
op = g_strdup (netrcpass);
else if (strcmp (SUP->user, "anonymous") == 0 || strcmp (SUP->user, "ftp") == 0)
else if (strcmp (super->url->user, "anonymous") == 0 || strcmp (super->url->user, "ftp") == 0)
{
if (!ftpfs_anonymous_passwd) /* default anonymous password */
if (ftpfs_anonymous_passwd == NULL) /* default anonymous password */
ftpfs_init_passwd ();
op = g_strdup (ftpfs_anonymous_passwd);
anon = 1;
@ -587,12 +586,12 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
{ /* ask user */
char *p;
p = g_strdup_printf (_("FTP: Password required for %s"), SUP->user);
p = g_strdup_printf (_("FTP: Password required for %s"), super->url->user);
op = vfs_get_password (p);
g_free (p);
if (op == NULL)
ERRNOR (EPERM, 0);
SUP->password = g_strdup (op);
super->url->password = g_strdup (op);
}
if (!anon || MEDATA->logfile)
@ -605,13 +604,12 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
/* Proxy server accepts: username@host-we-want-to-connect */
if (SUP->proxy)
{
name =
g_strconcat (SUP->user, "@",
SUP->host[0] == '!' ? SUP->host + 1 : SUP->host, (char *) NULL);
}
g_strconcat (super->url->user, "@",
super->url->host[0] == '!' ? super->url->host + 1 : super->url->host,
(char *) NULL);
else
name = g_strdup (SUP->user);
name = g_strdup (super->url->user);
if (ftpfs_get_reply (me, SUP->sock, reply_string, sizeof (reply_string) - 1) == COMPLETE)
{
@ -638,7 +636,7 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
{
char *p;
p = g_strdup_printf (_("FTP: Account required for user %s"), SUP->user);
p = g_strdup_printf (_("FTP: Account required for user %s"), super->url->user);
op = input_dialog (p, _("Account:"), MC_HISTORY_FTPFS_ACCOUNT, "");
g_free (p);
if (op == NULL)
@ -659,14 +657,15 @@ ftpfs_login_server (struct vfs_class *me, struct vfs_s_super *super, const char
default:
SUP->failed_on_login = 1;
if (SUP->password)
wipe_password (SUP->password);
SUP->password = 0;
wipe_password (super->url->password);
super->url->password = NULL;
goto login_fail;
}
}
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), SUP->user);
message (D_ERROR, MSG_ERROR, _("ftpfs: Login incorrect for user %s "), super->url->user);
login_fail:
wipe_password (pass);
g_free (name);
@ -764,11 +763,12 @@ ftpfs_check_proxy (const char *host)
static void
ftpfs_get_proxy_host_and_port (const char *proxy, char **host, int *port)
{
char *user, *dir;
vfs_url_t *url;
dir = vfs_split_url (proxy, host, &user, port, 0, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
g_free (user);
g_free (dir);
url = vfs_url_split (proxy, FTP_COMMAND_PORT, URL_USE_ANONYMOUS);
*host = g_strdup (url->host);
*port = url->port;
vfs_url_free (url);
}
/* --------------------------------------------------------------------------------------------- */
@ -779,16 +779,16 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
struct addrinfo hints, *res, *curr_res;
int my_socket = 0;
char *host = NULL;
char *port = NULL;
char port[8];
int tmp_port;
int e;
(void) me;
/* Use a proxy host? */
host = g_strdup (SUP->host);
host = g_strdup (super->url->host);
if (!host || !*host)
if (host == NULL || *host == '\0')
{
vfs_print_message (_("ftpfs: Invalid host name."));
ftpfs_errno = EINVAL;
@ -797,15 +797,13 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
}
/* Hosts to connect to that start with a ! should use proxy */
tmp_port = SUP->port;
tmp_port = super->url->port;
if (SUP->proxy)
{
if (SUP->proxy != NULL)
ftpfs_get_proxy_host_and_port (ftpfs_proxy_host, &host, &tmp_port);
}
port = g_strdup_printf ("%hu", (unsigned short) tmp_port);
if (port == NULL)
g_snprintf (port, sizeof (port), "%hu", (unsigned short) tmp_port);
if (port[0] == '\0')
{
g_free (host);
ftpfs_errno = errno;
@ -836,8 +834,7 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
}
#endif
g_free (port);
port = NULL;
*port = '\0';
if (e != 0)
{
@ -850,12 +847,10 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
for (curr_res = res; curr_res != NULL; curr_res = curr_res->ai_next)
{
my_socket = socket (curr_res->ai_family, curr_res->ai_socktype, curr_res->ai_protocol);
if (my_socket < 0)
{
if (curr_res->ai_next != NULL)
continue;
@ -878,18 +873,12 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
close (my_socket);
if (errno == EINTR && tty_got_interrupt ())
{
vfs_print_message (_("ftpfs: connection interrupted by user"));
}
else if (res->ai_next == NULL)
{
vfs_print_message (_("ftpfs: connection to server failed: %s"),
unix_error_string (errno));
}
else
{
continue;
}
freeaddrinfo (res);
tty_disable_interrupt_key ();
@ -906,13 +895,13 @@ ftpfs_open_socket (struct vfs_class *me, struct vfs_s_super *super)
static int
ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
{
int retry_seconds, count_down;
int retry_seconds = 0;
int count_down;
/* We do not want to use the passive if we are using proxies */
if (SUP->proxy)
SUP->use_passive_connection = ftpfs_use_passive_connections_over_proxy;
retry_seconds = 0;
do
{
SUP->failed_on_login = 0;
@ -921,29 +910,26 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
if (SUP->sock == -1)
return -1;
if (ftpfs_login_server (me, super, NULL))
if (ftpfs_login_server (me, super, NULL) != 0)
{
/* Logged in, no need to retry the connection */
break;
}
else
{
if (SUP->failed_on_login)
{
/* Close only the socket descriptor */
close (SUP->sock);
}
else
{
if (!SUP->failed_on_login)
return -1;
}
if (ftpfs_retry_seconds)
/* Close only the socket descriptor */
close (SUP->sock);
if (ftpfs_retry_seconds != 0)
{
retry_seconds = ftpfs_retry_seconds;
tty_enable_interrupt_key ();
for (count_down = retry_seconds; count_down; count_down--)
{
vfs_print_message (_("Waiting to retry... %d (Control-C to cancel)"),
vfs_print_message (_("Waiting to retry... %d (Control-G to cancel)"),
count_down);
sleep (1);
if (tty_got_interrupt ())
@ -957,11 +943,12 @@ ftpfs_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
}
}
}
while (retry_seconds);
while (retry_seconds != 0);
super->url->path = ftpfs_get_current_directory (me, super);
if (super->url->path == NULL)
super->url->path = g_strdup (PATH_SEP_STR);
SUP->cwdir = ftpfs_get_current_directory (me, super);
if (!SUP->cwdir)
SUP->cwdir = g_strdup (PATH_SEP_STR);
return 0;
}
@ -971,22 +958,14 @@ static int
ftpfs_open_archive (struct vfs_class *me, struct vfs_s_super *super,
const char *archive_name, char *op)
{
char *host, *user, *password;
int port;
(void) archive_name;
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, &password);
super->data = g_new0 (ftp_super_data_t, 1);
SUP->host = host;
SUP->user = user;
SUP->port = port;
SUP->cwdir = NULL;
SUP->proxy = 0;
if (ftpfs_check_proxy (host))
super->url = ftpfs_split_url (strchr (op, ':') + 1);
SUP->proxy = NULL;
if (ftpfs_check_proxy (super->url->host))
SUP->proxy = ftpfs_proxy_host;
SUP->password = password;
SUP->use_passive_connection = ftpfs_use_passive_connections;
SUP->strict = ftpfs_use_unix_list_options ? RFC_AUTODETECT : RFC_STRICT;
SUP->isbinary = TYPE_UNKNOWN;
@ -1003,22 +982,21 @@ static int
ftpfs_archive_same (struct vfs_class *me, struct vfs_s_super *super,
const char *archive_name, char *op, void *cookie)
{
char *host, *user;
int port;
vfs_url_t *url;
int result;
(void) me;
(void) archive_name;
(void) cookie;
ftpfs_split_url (strchr (op, ':') + 1, &host, &user, &port, 0);
url = ftpfs_split_url (strchr (op, ':') + 1);
port = ((strcmp (host, SUP->host) == 0) && (strcmp (user, SUP->user) == 0)
&& (port == SUP->port));
result = ((strcmp (url->host, super->url->host) == 0)
&& (strcmp (url->user, super->url->user) == 0)
&& (url->port == super->url->port)) ? 1 : 0;
g_free (host);
g_free (user);
return port;
vfs_url_free (url);
return result;
}
/* --------------------------------------------------------------------------------------------- */
@ -1149,10 +1127,7 @@ ftpfs_setup_passive_epsv (struct vfs_class *me, struct vfs_s_super *super,
break;
}
if (connect (my_socket, (struct sockaddr *) sa, *salen) < 0)
return 0;
return 1;
return (connect (my_socket, (struct sockaddr *) sa, *salen) < 0) ? 0 : 1;
}
/* --------------------------------------------------------------------------------------------- */
@ -1292,8 +1267,8 @@ ftpfs_init_data_socket (struct vfs_class *me, struct vfs_s_super *super,
vfs_print_message (_("ftpfs: could not create socket: %s"), unix_error_string (errno));
return -1;
}
else
return result;
return result;
}
/* --------------------------------------------------------------------------------------------- */
@ -1315,8 +1290,8 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
if (SUP->use_passive_connection)
{
int data_sock;
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
if (data_sock < 0)
return -1;
@ -1333,24 +1308,22 @@ ftpfs_initconn (struct vfs_class *me, struct vfs_s_super *super)
if (!SUP->use_passive_connection)
{
int data_sock;
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
data_sock = ftpfs_init_data_socket (me, super, &data_addr, &data_addrlen);
if (data_sock < 0)
return -1;
if ((bind (data_sock, (struct sockaddr *) &data_addr, data_addrlen) == 0) &&
(getsockname (data_sock, (struct sockaddr *) &data_addr, &data_addrlen) == 0) &&
(listen (data_sock, 1) == 0))
{
if (ftpfs_setup_active (me, super, data_addr, data_addrlen))
return data_sock;
}
(listen (data_sock, 1) == 0) &&
(ftpfs_setup_active (me, super, data_addr, data_addrlen) != 0))
return data_sock;
close (data_sock);
}
/* Restore the initial value of use_passive_connection (for subsequent retries) */
SUP->use_passive_connection = SUP->proxy ? ftpfs_use_passive_connections_over_proxy :
SUP->use_passive_connection = SUP->proxy != NULL ? ftpfs_use_passive_connections_over_proxy :
ftpfs_use_passive_connections;
ftpfs_errno = EIO;
@ -1413,7 +1386,7 @@ ftpfs_open_data_connection (struct vfs_class *me, struct vfs_s_super *super, con
/* --------------------------------------------------------------------------------------------- */
static void
ftpfs_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
ftpfs_linear_abort (struct vfs_class *me, vfs_file_handler_t * fh)
{
struct vfs_s_super *super = FH_SUPER;
static unsigned char const ipbuf[3] = { IAC, IP, IAC };
@ -1786,7 +1759,7 @@ ftpfs_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, char *remote_path
/* --------------------------------------------------------------------------------------------- */
static int
ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t * fh, char *name, char *localname)
{
int h, sock, n_read, n_written;
off_t n_stored;
@ -1877,7 +1850,7 @@ ftpfs_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char
/* --------------------------------------------------------------------------------------------- */
static int
ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t * fh, off_t offset)
{
char *name;
@ -1900,7 +1873,7 @@ ftpfs_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
/* --------------------------------------------------------------------------------------------- */
static int
ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t * fh, void *buf, size_t len)
{
ssize_t n;
struct vfs_s_super *super = FH_SUPER;
@ -1930,7 +1903,7 @@ ftpfs_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size
/* --------------------------------------------------------------------------------------------- */
static void
ftpfs_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
ftpfs_linear_close (struct vfs_class *me, vfs_file_handler_t * fh)
{
if (FH_SOCK != -1)
ftpfs_linear_abort (me, fh);
@ -2048,11 +2021,9 @@ ftpfs_is_same_dir (struct vfs_class *me, struct vfs_s_super *super, const char *
{
(void) me;
if (!SUP->cwdir)
return 0;
if (strcmp (path, SUP->cwdir) == 0)
return 1;
return 0;
if (super->url->path == NULL)
return FALSE;
return (strcmp (path, super->url->path) == 0);
}
/* --------------------------------------------------------------------------------------------- */
@ -2071,13 +2042,11 @@ ftpfs_chdir_internal (struct vfs_class *me, struct vfs_s_super *super, const cha
g_free (p);
if (r != COMPLETE)
{
ftpfs_errno = EIO;
}
else
{
g_free (SUP->cwdir);
SUP->cwdir = g_strdup (remote_path);
g_free (super->url->path);
super->url->path = g_strdup (remote_path);
SUP->cwd_deferred = 0;
}
return r;
@ -2113,7 +2082,7 @@ ftpfs_rmdir (struct vfs_class *me, const char *path)
/* --------------------------------------------------------------------------------------------- */
static int
ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
{
ftp_fh_data_t *ftp;
@ -2187,7 +2156,7 @@ ftpfs_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t m
/* --------------------------------------------------------------------------------------------- */
static int
ftpfs_fh_close (struct vfs_class *me, vfs_file_handler_t *fh)
ftpfs_fh_close (struct vfs_class *me, vfs_file_handler_t * fh)
{
if (fh->handle != -1 && !fh->ino->localname)
{
@ -2235,7 +2204,8 @@ ftpfs_fill_names (struct vfs_class *me, fill_names_f func)
const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
char *name;
name = g_strconcat ("/#ftp:", SUP->user, "@", SUP->host, "/", SUP->cwdir, (char *) NULL);
name = g_strconcat ("/#ftp:", super->url->user, "@", super->url->host, "/",
super->url->path, (char *) NULL);
func (name);
g_free (name);
}
@ -2252,7 +2222,6 @@ ftpfs_netrc_next (void)
"login", "password", "passwd", "account", "macdef", NULL
};
while (1)
{
netrcp = skip_separators (netrcp);
@ -2286,15 +2255,10 @@ ftpfs_netrc_next (void)
if (!*buffer)
return NETRC_NONE;
i = NETRC_DEFAULT;
while (keywords[i - 1])
{
if (!strcmp (keywords[i - 1], buffer))
for (i = NETRC_DEFAULT; keywords[i - 1] != NULL; i++)
if (strcmp (keywords[i - 1], buffer) == 0)
return i;
i++;
}
return NETRC_UNKNOWN;
}
@ -2407,11 +2371,10 @@ ftpfs_netrc_lookup (const char *host, char **login, char **pass)
} *rup_cache = NULL, *rupp;
/* Initialize *login and *pass */
if (!login)
return 0;
g_free (*login);
*login = NULL;
if (pass)
*pass = NULL;
g_free (*pass);
*pass = NULL;
/* Look up in the cache first */
for (rupp = rup_cache; rupp != NULL; rupp = rupp->next)
@ -2521,19 +2484,13 @@ ftpfs_netrc_lookup (const char *host, char **login, char **pass)
rupp = g_new (struct rupcache, 1);
rupp->host = g_strdup (host);
rupp->login = rupp->pass = 0;
rupp->login = g_strdup (*login);
rupp->pass = g_strdup (tmp_pass);
if (*login != NULL)
{
rupp->login = g_strdup (*login);
}
if (tmp_pass != NULL)
rupp->pass = g_strdup (tmp_pass);
rupp->next = rup_cache;
rup_cache = rupp;
if (pass)
*pass = tmp_pass;
*pass = tmp_pass;
return 0;
}

View File

@ -84,11 +84,6 @@ extern FILE *dbf;
#define CNV_LANG(s) dos_to_unix(s,False)
#define GNAL_VNC(s) unix_to_dos(s,False)
/* Extract the hostname and username from the path */
/* path is in the form: [user@]hostname/share/remote-dir */
#define smbfs_get_host_and_username(path, host, user, port, pass) \
vfs_split_url (*path, host, user, port, pass, SMB_PORT, 0)
#define smbfs_lstat smbfs_stat /* no symlinks on smb filesystem? */
/*** file scope type declarations ****************************************************************/
@ -1324,42 +1319,46 @@ smbfs_open_link (char *host, char *path, const char *user, int *port, char *this
static char *
smbfs_get_path (smbfs_connection ** sc, const char *path)
{
char *user, *host, *remote_path, *pass;
int port = SMB_PORT;
char *remote_path = NULL;
vfs_url_t *url;
DEBUG (3, ("smbfs_get_path(%s)\n", path));
if (strncmp (path, URL_HEADER, HEADER_LEN))
if (strncmp (path, URL_HEADER, HEADER_LEN) != 0)
return NULL;
path += HEADER_LEN;
if (*path == '/') /* '/' leading server name */
path++; /* probably came from server browsing */
if ((remote_path = smbfs_get_host_and_username (&path, &host, &user, &port, &pass)))
if ((*sc = smbfs_open_link (host, remote_path, user, &port, pass)) == NULL)
{
g_free (remote_path);
remote_path = NULL;
}
g_free (host);
g_free (user);
if (pass)
wipe_password (pass);
url = vfs_url_split (path, SMB_PORT, URL_FLAGS_NONE);
if (!remote_path)
if (url != NULL)
{
*sc = smbfs_open_link (url->host, url->path, url->user, &url->port, url->password);
wipe_password (url->password);
if (*sc != NULL)
remote_path = g_strdup (url->path);
vfs_url_free (url);
}
if (remote_path == NULL)
return NULL;
/* NOTE: tildes are deprecated. See ftpfs.c */
{
int f = !strcmp (remote_path, "/~");
if (f || !strncmp (remote_path, "/~/", 3))
int f = strcmp (remote_path, "/~") ? 0 : 1;
if (f != 0 || strncmp (remote_path, "/~/", 3) == 0)
{
char *s;
s = concat_dir_and_file ((*sc)->home, remote_path + 3 - f);
g_free (remote_path);
return s;
remote_path = s;
}
}
return remote_path;
}
@ -1942,10 +1941,9 @@ smbfs_free (vfsid id)
static void
smbfs_forget (const char *path)
{
char *host, *user, *p;
int port;
vfs_url_t *p;
if (strncmp (path, URL_HEADER, HEADER_LEN))
if (strncmp (path, URL_HEADER, HEADER_LEN) != 0)
return;
DEBUG (3, ("smbfs_forget(path:%s)\n", path));
@ -1954,30 +1952,29 @@ smbfs_forget (const char *path)
if (path[0] == '/' && path[1] == '/')
path += 2;
if ((p = smbfs_get_host_and_username (&path, &host, &user, &port, NULL)))
p = vfs_url_split (path, SMB_PORT, URL_FLAGS_NONE);
if (p != NULL)
{
size_t i;
g_free (p);
for (i = 0; i < SMBFS_MAX_CONNECTIONS; i++)
{
if (smbfs_connections[i].cli
&& (strcmp (host, smbfs_connections[i].host) == 0)
&& (strcmp (user, smbfs_connections[i].user) == 0)
&& (port == smbfs_connections[i].port))
&& (strcmp (p->host, smbfs_connections[i].host) == 0)
&& (strcmp (p->user, smbfs_connections[i].user) == 0)
&& (p->port == smbfs_connections[i].port))
{
/* close socket: the child owns it now */
cli_shutdown (smbfs_connections[i].cli);
/* reopen the connection */
smbfs_connections[i].cli = smbfs_do_connect (host, smbfs_connections[i].service);
smbfs_connections[i].cli = smbfs_do_connect (p->host, smbfs_connections[i].service);
}
}
vfs_url_free (p);
}
g_free (host);
g_free (user);
}
/* --------------------------------------------------------------------------------------------- */