+2001-08-21 Dave Turner <dct25@hermes.cam.ac.uk>
+
+ * 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 <hniksic@arsdigita.com>
* url.c (parseurl): Don't depend on the now-obsolete TYPE.
#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
+
#ifdef HAVE_STRING_H
# include <string.h>
#else
/* 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 <SIZE> 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;
+}
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))
{
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;