From 02964335538e48aabdb1ab2ca89b9e619aec240c Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 20 Nov 2001 13:01:27 -0800 Subject: [PATCH] [svn] Support the SIZE command. Originally by Dave Turner. Modified by Ian Abbott and published in <3BFAA33C.6236.6D42F6@localhost>. --- src/ChangeLog | 8 +++++++ src/ftp-basic.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ftp.c | 32 +++++++++++++++++++++++++++ src/ftp.h | 1 + 4 files changed, 100 insertions(+) diff --git a/src/ChangeLog b/src/ChangeLog index 24b22777..9e766719 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2001-08-21 Dave Turner + + * ftp-basic.c (ftp_size): New function to send non-standard SIZE + command to server to request file size. + * ftp.h (ftp_size): Export it. + * ftp.c (getftp): Use new ftp_size function if restoring + transfer of a file with unknown size. + 2001-11-20 Hrvoje Niksic * url.c (parseurl): Don't depend on the now-obsolete TYPE. diff --git a/src/ftp-basic.c b/src/ftp-basic.c index cb2621ae..ee176690 100644 --- a/src/ftp-basic.c +++ b/src/ftp-basic.c @@ -21,6 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include +#include + #ifdef HAVE_STRING_H # include #else @@ -631,3 +633,60 @@ ftp_pwd (struct rbuf *rbuf, char **pwd) /* All OK. */ return FTPOK; } +/* Sends the SIZE command to the server, and returns the value in 'size'. + * If an error occurs, size is set to zero. */ +uerr_t +ftp_size (struct rbuf *rbuf, const char *file, long int *size) +{ + char *request, *respline; + int nwritten; + uerr_t err; + + /* Send PWD request. */ + request = ftp_request ("SIZE", file); + nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request)); + if (nwritten < 0) + { + xfree (request); + *size = 0; + return WRITEFAILED; + } + xfree (request); + /* Get appropriate response. */ + err = ftp_response (rbuf, &respline); + if (err != FTPOK) + { + xfree (respline); + *size = 0; + return err; + } + if (*respline == '5') + { + /* + * Probably means SIZE isn't supported on this server. + * Error is nonfatal since SIZE isn't in RFC 959 + */ + xfree (respline); + *size = 0; + return FTPOK; + } + + errno = 0; + *size = strtol (respline + 4, NULL, 0); + if (errno) + { + /* + * Couldn't parse the response for some reason. On the (few) + * tests I've done, the response is 213 with nothing else - + * maybe something a bit more resilient is necessary. It's not a + * fatal error, however. + */ + xfree (respline); + *size = 0; + return FTPOK; + } + + xfree (respline); + /* All OK. */ + return FTPOK; +} diff --git a/src/ftp.c b/src/ftp.c index 7bcca7ab..7427d9e8 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -462,6 +462,38 @@ Error in server response, closing control connection.\n")); else /* do not CWD */ logputs (LOG_VERBOSE, _("==> CWD not required.\n")); + if ((cmd & DO_RETR) && restval && *len == 0) + { + if (opt.verbose) + { + if (!opt.server_response) + logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file); + } + + err = ftp_size(&con->rbuf, u->file, len); + /* FTPRERR */ + switch (err) + { + case FTPRERR: + case FTPSRVERR : + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_NOTQUIET, _("\ +Error in server response, closing control connection.\n")); + CLOSE (csock); + rbuf_uninitialize (&con->rbuf); + return err; + break; + case FTPOK: + /* Everything is OK. */ + break; + default: + abort (); + break; + } + if (!opt.server_response) + logputs (LOG_VERBOSE, _("done.\n")); + } + /* If anything is to be retrieved, PORT (or PASV) must be sent. */ if (cmd & (DO_LIST | DO_RETR)) { diff --git a/src/ftp.h b/src/ftp.h index 718106ce..e0ad7ccb 100644 --- a/src/ftp.h +++ b/src/ftp.h @@ -44,6 +44,7 @@ uerr_t ftp_rest PARAMS ((struct rbuf *, long)); uerr_t ftp_list PARAMS ((struct rbuf *, const char *)); uerr_t ftp_syst PARAMS ((struct rbuf *, enum stype *)); uerr_t ftp_pwd PARAMS ((struct rbuf *, char **)); +uerr_t ftp_size PARAMS ((struct rbuf *, const char *, long int *)); struct urlinfo; -- 2.39.2