Thanks
I have attached a patch of where I'm at, it seems to work for all the
cases I can think of on my machine, except that a timeout or other
connection error while testing if I can cd to a symlink will
cause it to skip over that file rather than retry. I'm not really sure
about error handling, and what should be handled where, what is fatal, etc
Should I be calling a higher level function to CWD and PWD, in order to
handle this?
Alternatively, how should errors be handled from within
ftp_retrieve_list()
Thanks
Matt
diff --git a/src/ftp-basic.c b/src/ftp-basic.c
index b6e67e2..152e399 100644
--- a/src/ftp-basic.c
+++ b/src/ftp-basic.c
@@ -1213,3 +1213,26 @@ ftp_process_type (const char *params)
else
return 'I';
}
+
+/* Get current working diectory, CWD to dir, and CWD back */
+uerr_t
+try_cwd (int csock, char *dir)
+{
+ char *pwd = NULL;
+ uerr_t err;
+ err = ftp_pwd (csock, &pwd);
+ if (err != FTPOK)
+ return err;
+ err = ftp_cwd (csock, dir);
+ if (err != FTPOK)
+ return err;
+ err = ftp_cwd (csock, pwd);
+ if (err != FTPOK)
+ {
+ /* What if any cleanup is necessary here, or just return err rather than
+ * abort? */
+ fd_close (csock);
+ abort ();
+ }
+ return err;
+}
diff --git a/src/ftp.c b/src/ftp.c
index 2d54333..c369809 100644
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -2046,7 +2046,30 @@ Already have correct symlink %s -> %s\n\n"),
else /* opt.retr_symlinks */
{
if (dlthis)
- err = ftp_loop_internal (u, f, con, NULL);
+ {
+ err = ftp_loop_internal (u, f, con, NULL);
+ if (err == FTPNSFOD)
+ {
+ err = try_cwd (con->csock, f->name);
+ /* CWD to a non directory will return FTPNSFOD
+ * eg if the symlink points to a non readable file
+ * Should we do this on (err != FTPOK || err != FTPNSFOD?)
+ */
+ if (err == FTPRERR || err == FTPSRVERR)
+ {
+ logputs (LOG_VERBOSE, "\n");
+ logputs (LOG_NOTQUIET, _("\
+Error in server response, closing control connection.\n"));
+ fd_close (con->csock);
+ con->csock = -1;
+ }
+ if (err == FTPOK)
+ /* Does anything else afterwards depend on this being
+ * FT_SYMLINK? */
+ f->type = FT_DIRECTORY;
+ }
+ }
+
} /* opt.retr_symlinks */
break;
case FT_DIRECTORY:
diff --git a/src/ftp.h b/src/ftp.h
index 78b5270..50d4b65 100644
--- a/src/ftp.h
+++ b/src/ftp.h
@@ -73,6 +73,7 @@ uerr_t ftp_list (int, const char *, bool, bool, bool *);
uerr_t ftp_syst (int, enum stype *, enum ustype *);
uerr_t ftp_pwd (int, char **);
uerr_t ftp_size (int, const char *, wgint *);
+uerr_t try_cwd (int, char *);
#ifdef ENABLE_OPIE
const char *skey_response (int, const char *, const char *);