From 42bc3171c326f1391a53ba300bd0b83a00bbbf9c Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Tue, 29 Mar 2011 10:20:34 +0300 Subject: [PATCH] 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 Signed-off-by: Slava Zanko --- lib/vfs/direntry.c | 3 + lib/vfs/utilvfs.c | 126 ++++++++++--------- lib/vfs/utilvfs.h | 22 +++- lib/vfs/xdirentry.h | 4 + src/vfs/fish/fish.c | 184 +++++++++++++-------------- src/vfs/ftpfs/ftpfs.c | 283 ++++++++++++++++++------------------------ src/vfs/smbfs/smbfs.c | 65 +++++----- 7 files changed, 325 insertions(+), 362 deletions(-) diff --git a/lib/vfs/direntry.c b/lib/vfs/direntry.c index 48690376d..b490de6d4 100644 --- a/lib/vfs/direntry.c +++ b/lib/vfs/direntry.c @@ -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); } diff --git a/lib/vfs/utilvfs.c b/lib/vfs/utilvfs.c index 703af429e..73e3c0c6f 100644 --- a/lib/vfs/utilvfs.c +++ b/lib/vfs/utilvfs.c @@ -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); + } } /* --------------------------------------------------------------------------------------------- */ diff --git a/lib/vfs/utilvfs.h b/lib/vfs/utilvfs.h index 0c1159d05..7439e400d 100644 --- a/lib/vfs/utilvfs.h +++ b/lib/vfs/utilvfs.h @@ -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); diff --git a/lib/vfs/xdirentry.h b/lib/vfs/xdirentry.h index 87252e061..33a3bb48c 100644 --- a/lib/vfs/xdirentry.h +++ b/lib/vfs/xdirentry.h @@ -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 */ }; diff --git a/src/vfs/fish/fish.c b/src/vfs/fish/fish.c index 17d4f5c59..e4cedece1 100644 --- a/src/vfs/fish/fish.c +++ b/src/vfs/fish/fish.c @@ -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); } diff --git a/src/vfs/ftpfs/ftpfs.c b/src/vfs/ftpfs/ftpfs.c index e2ba7dd29..ffc0e1b6b 100644 --- a/src/vfs/ftpfs/ftpfs.c +++ b/src/vfs/ftpfs/ftpfs.c @@ -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; } diff --git a/src/vfs/smbfs/smbfs.c b/src/vfs/smbfs/smbfs.c index 0ed238445..3b4a2dfe0 100644 --- a/src/vfs/smbfs/smbfs.c +++ b/src/vfs/smbfs/smbfs.c @@ -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); } /* --------------------------------------------------------------------------------------------- */