From 963863113f53c23446d50cf6224096718b9367bb Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 10 Apr 2001 17:24:59 -0700 Subject: [PATCH] [svn] Fix retrieval of directories when initial CWD is not `/'. Published in . * url.c (parseurl): Don't strip trailing slash when u->dir is "/" because that strips the *leading* slash, thus forcing relative FTP retrieval. * ftp.c (getftp): Convert initial FTP directory from VMS to UNIX notation for VMS servers. (ftp_retrieve_dirs): Do not prepend '/' to f->name when odir is an empty string. --- src/ChangeLog | 13 ++++++++++++ src/ftp.c | 57 ++++++++++++++++++++++++++++++++++++++++++++------- src/url.c | 2 +- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 29af7226..81cc52a7 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,16 @@ +2001-04-11 Hrvoje Niksic + + * url.c (parseurl): Don't strip trailing slash when u->dir is "/" + because that strips the *leading* slash, thus forcing relative + FTP retrieval. + +2001-04-10 Jan Prikryl + + * ftp.c (getftp): Convert initial FTP directory from VMS to UNIX + notation for VMS servers. + (ftp_retrieve_dirs): Do not prepend '/' to f->name when + odir is an empty string. + 2001-04-10 Jan Prikryl * ftp-ls.c (ftp_parse_winnt_ls): Made the fix for AM/PM more diff --git a/src/ftp.c b/src/ftp.c index c7f9274d..bf50ab32 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -298,6 +298,29 @@ Error in server response, closing control connection.\n")); abort (); break; } + /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]". + Convert it to "/INITIAL/FOLDER" */ + if (con->rs == ST_VMS) + { + char *path = strchr (con->id, '['); + char *pathend = path ? strchr (path + 1, ']') : NULL; + if (!path || !pathend) + DEBUGP (("Initial VMS directory not in the form [...]!\n")); + else + { + char *idir = con->id; + DEBUGP (("Preprocessing the initial VMS directory\n")); + DEBUGP ((" old = '%s'\n", con->id)); + /* We do the conversion in-place by copying the stuff + between [ and ] to the beginning, and changing dots + to slashes at the same time. */ + *idir++ = '/'; + for (++path; path < pathend; path++, idir++) + *idir = *path == '.' ? '/' : *path; + *idir = '\0'; + DEBUGP ((" new = '%s'\n\n", con->id)); + } + } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); @@ -361,19 +384,27 @@ Error in server response, closing control connection.\n")); { int idlen = strlen (con->id); char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1); - /* pwd_len == 1 means pwd = "/" */ + /* idlen == 1 means con->id = "/" */ sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/", target); + DEBUGP (("Prepended initial PWD to relative path:\n")); + DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget)); target = ntarget; } - /* If the FTP host runs VMS, we will have to convert it to - VMS style as VMS does not like leading slashes. "VMS - style" is [dir.subdir.subsubdir]. */ + /* If the FTP host runs VMS, we will have to convert the absolute + directory path in UNIX notation to absolute directory path in + VMS notation as VMS FTP servers do not like UNIX notation of + absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */ + if (con->rs == ST_VMS) { char *tmpp; - char *ntarget = (char *)alloca (strlen (target) + 1); + char *ntarget = (char *)alloca (strlen (target) + 2); + /* We use a converted initial dir, so directories in + TARGET will be separated with slashes, something like + "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to + "[INITIAL.FOLDER.DIR.SUBDIR]". */ strcpy (ntarget, target); assert (*ntarget == '/'); *ntarget = '['; @@ -382,6 +413,8 @@ Error in server response, closing control connection.\n")); *tmpp = '.'; *tmpp++ = ']'; *tmpp = '\0'; + DEBUGP (("Changed file name to VMS syntax:\n")); + DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget)); target = ntarget; } @@ -1460,8 +1493,18 @@ ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con) if (len > current_length) current_container = (char *)alloca (len); u->dir = current_container; - sprintf (u->dir, "%s%s%s", odir, - (*odir == '/' && !*(odir + 1)) ? "" : "/", f->name); + if (*odir == '\0' + || (*odir == '/' && *(odir + 1) == '\0')) + /* If ODIR is empty or just "/", simply append f->name to + ODIR. (In the former case, to preserve u->dir being + relative; in the latter case, to avoid double slash.) */ + sprintf (u->dir, "%s%s", odir, f->name); + else + /* Else, use a separator. */ + sprintf (u->dir, "%s/%s", odir, f->name); + DEBUGP (("Composing new CWD relative to the initial directory.\n")); + DEBUGP ((" odir = '%s'\n f->name = '%s'\n u->dir = '%s'\n\n", + odir, f->name, u->dir)); if (!accdir (u->dir, ALLABS)) { logprintf (LOG_VERBOSE, _("\ diff --git a/src/url.c b/src/url.c index 7e31e51e..cca3ac96 100644 --- a/src/url.c +++ b/src/url.c @@ -514,7 +514,7 @@ parseurl (const char *url, struct urlinfo *u, int strict) DEBUGP (("ndir %s\n", u->dir)); /* Strip trailing `/'. */ l = strlen (u->dir); - if (l && u->dir[l - 1] == '/') + if (l > 1 && u->dir[l - 1] == '/') u->dir[l - 1] = '\0'; /* Re-create the path: */ abs_ftp = (u->proto == URLFTP && *u->dir == '/'); -- 2.39.2