#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
int cmd; /* command code */
int csock; /* control connection socket */
double dltime; /* time of the download in msecs */
- enum stype rs; /* remote system reported by ftp server */
+ enum stype rs; /* remote system reported by ftp server */
char *id; /* initial directory */
char *target; /* target file name */
struct url *proxy; /* FTWK-style proxy */
}
#ifdef ENABLE_IPV6
-/*
+/*
* This function sets up a passive data connection with the FTP server.
* It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
*/
if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
abort ();
- /* If our control connection is over IPv6, then we first try EPSV and then
- * LPSV if the former is not supported. If the control connection is over
+ /* If our control connection is over IPv6, then we first try EPSV and then
+ * LPSV if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PASV request. */
switch (addr->family)
{
return err;
}
-/*
+/*
* This function sets up an active data connection with the FTP server.
* It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
*/
if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
abort ();
- /* If our control connection is over IPv6, then we first try EPRT and then
- * LPRT if the former is not supported. If the control connection is over
+ /* If our control connection is over IPv6, then we first try EPRT and then
+ * LPRT if the former is not supported. If the control connection is over
* IPv4, we simply issue the good old PORT request. */
switch (cip.family)
{
connection to the server. It always closes the data connection,
and closes the control connection in case of error. */
static uerr_t
-getftp (struct url *u, wgint *len, wgint restval, ccon *con)
+getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
+ wgint restval, ccon *con)
{
int csock, dtsock, local_sock, res;
uerr_t err = RETROK; /* appease the compiler */
/* Make sure that at least *something* is requested. */
assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
+ *qtyread = restval;
+
user = u->user;
passwd = u->passwd;
search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
con->csock = -1;
/* Second: Login with proper USER/PASS sequence. */
- logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
+ logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
quotearg_style (escape_quoting_style, user));
if (opt.server_response)
logputs (LOG_ALWAYS, "\n");
*/
/* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
- Convert it to "/INITIAL/FOLDER" */
+ Convert it to "/INITIAL/FOLDER" */
if (con->rs == ST_VMS)
{
char *path = strchr (con->id, '[');
Why is this wise even on UNIX? It certainly fouls VMS.
See below for a more reliable, more universal method.
*/
-
+
/* 2008-04-22 MJC.
I'm not crazy about it either. I'm informed it's useful
for misconfigured servers that have some dirs in the path
#endif /* 0 */
/* 2004-09-20 SMS.
- A relative directory is relative to the initial directory.
+ A relative directory is relative to the initial directory.
Thus, what _is_ useful on VMS (and probably elsewhere) is
to CWD to the initial directory (ideally, whatever the
server reports, _exactly_, NOT badly UNIX-ixed), and then
if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
quotearg_style (escape_quoting_style, target));
- err = ftp_cwd (csock, target);
+ err = ftp_cwd (csock, targ);
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
{
else /* do not CWD */
logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
- if ((cmd & DO_RETR) && *len == 0)
+ if ((cmd & DO_RETR) && passed_expected_bytes == 0)
{
if (opt.verbose)
{
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
+ logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
quotearg_style (escape_quoting_style, u->file));
}
- err = ftp_size (csock, u->file, len);
+ err = ftp_size (csock, u->file, &expected_bytes);
/* FTPRERR */
switch (err)
{
abort ();
}
if (!opt.server_response)
- logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
- number_to_static_string (*len));
+ logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
+ number_to_static_string (expected_bytes));
}
/* If anything is to be retrieved, PORT (or PASV) must be sent. */
} /* switch (err) */
if (err==FTPOK)
{
- DEBUGP (("trying to connect to %s port %d\n",
+ DEBUGP (("trying to connect to %s port %d\n",
print_address (&passive_addr), passive_port));
dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
if (dtsock < 0)
uerr_t res;
struct fileinfo *f;
res = ftp_get_listing (u, con, &f);
- /* Set the DO_RETR command flag again, because it gets unset when
- calling ftp_get_listing() and would otherwise cause an assertion
- failure earlier on when this function gets repeatedly called
+ /* Set the DO_RETR command flag again, because it gets unset when
+ calling ftp_get_listing() and would otherwise cause an assertion
+ failure earlier on when this function gets repeatedly called
(e.g., when recursing). */
con->cmd |= DO_RETR;
if (res == RETROK)
{
- while (f)
+ while (f)
{
if (!strcmp (f->name, u->file))
{
{
if (restval)
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_VERBOSE, "==> RETR %s ... ",
+ logprintf (LOG_VERBOSE, "==> RETR %s ... ",
quotearg_style (escape_quoting_style, u->file));
}
}
/* Some FTP servers return the total length of file after REST
command, others just return the remaining size. */
- if (*len && restval && expected_bytes
- && (expected_bytes == *len - restval))
+ if (passed_expected_bytes && restval && expected_bytes
+ && (expected_bytes == passed_expected_bytes - restval))
{
DEBUGP (("Lying FTP server found, adjusting.\n"));
- expected_bytes = *len;
+ expected_bytes = passed_expected_bytes;
}
/* If no transmission was required, then everything is OK. */
}
/* Open the file -- if output_stream is set, use it instead. */
-
+
/* 2005-04-17 SMS.
Note that having the output_stream ("-O") file opened in main()
(main.c) rather limits the ability in VMS to open the file
con->target = targ;
}
#endif /* def __VMS */
-
+
mkalldirs (con->target);
if (opt.backups)
rotate_backups (con->target);
#else /* def __VMS */
# define BIN_TYPE_FILE 1
#endif /* def __VMS [else] */
-
+
if (restval && !(con->cmd & DO_LIST))
{
#ifdef __VMS
else
fp = output_stream;
- if (*len)
+ if (passed_expected_bytes)
{
- print_length (*len, restval, true);
- expected_bytes = *len; /* for fd_read_body's progress bar */
+ print_length (passed_expected_bytes, restval, true);
+ expected_bytes = passed_expected_bytes;
+ /* for fd_read_body's progress bar */
}
else if (expected_bytes)
print_length (expected_bytes, restval, false);
flags = 0;
if (restval && rest_failed)
flags |= rb_skip_startpos;
- *len = restval;
rd_size = 0;
res = fd_read_body (dtsock, fp,
expected_bytes ? expected_bytes - restval : 0,
- restval, &rd_size, len, &con->dltime, flags);
+ restval, &rd_size, qtyread, &con->dltime, flags);
tms = datetime_str (time (NULL));
tmrate = retr_rate (rd_size, con->dltime);
char *p = strchr (line, '\0');
while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
*--p = '\0';
- logprintf (LOG_ALWAYS, "%s\n",
+ logprintf (LOG_ALWAYS, "%s\n",
quotearg_style (escape_quoting_style, line));
xfree (line);
}
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
{
int count, orig_lp;
- wgint restval, len = 0;
+ wgint restval, len = 0, qtyread = 0;
char *tms, *locf;
const char *tmrate = NULL;
uerr_t err;
first attempt to clobber existing data.) */
restval = st.st_size;
else if (count > 1)
- restval = len; /* start where the previous run left off */
+ restval = qtyread; /* start where the previous run left off */
else
restval = 0;
len = f->size;
else
len = 0;
- err = getftp (u, &len, restval, con);
+ err = getftp (u, len, &qtyread, restval, con);
if (con->csock == -1)
con->st &= ~DONE_CWD;
case FTPRETRINT:
/* If the control connection was closed, the retrieval
will be considered OK if f->size == len. */
- if (!f || len != f->size)
+ if (!f || qtyread != f->size)
{
printwhat (count, opt.ntry);
continue;
}
tms = datetime_str (time (NULL));
if (!opt.spider)
- tmrate = retr_rate (len - restval, con->dltime);
+ tmrate = retr_rate (qtyread - restval, con->dltime);
/* If we get out of the switch above without continue'ing, we've
successfully downloaded a file. Remember this fact. */
: _("%s (%s) - %s saved [%s]\n\n"),
tms, tmrate,
write_to_stdout ? "" : quote (locf),
- number_to_static_string (len));
+ number_to_static_string (qtyread));
}
if (!opt.verbose && !opt.quiet)
{
time. */
char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
- tms, hurl, number_to_static_string (len), locf, count);
+ tms, hurl, number_to_static_string (qtyread), locf, count);
xfree (hurl);
}
/* --dont-remove-listing was specified, so do count this towards the
number of bytes and files downloaded. */
{
- total_downloaded_bytes += len;
+ total_downloaded_bytes += qtyread;
numurls++;
}
downloaded if they're going to be deleted. People seeding proxies,
for instance, may want to know how many bytes and files they've
downloaded through it. */
- total_downloaded_bytes += len;
+ total_downloaded_bytes += qtyread;
numurls++;
if (opt.delete_after)
original. :( */
if (actual_target != NULL)
{
- if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
+ if (opt.useservertimestamps
+ && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
&& f->tstamp != -1
&& dlthis
&& file_exists_p (con->target))
if (matchres == -1)
{
logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
- u->file, quotearg_style (escape_quoting_style, f->name),
+ u->file, quotearg_style (escape_quoting_style, f->name),
strerror (errno));
break;
}
}
else if (action == GLOB_GETONE)
{
+#ifdef __VMS
+ /* 2009-09-09 SMS.
+ * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
+ * bug causes spurious %CC-E-BADCONDIT complaint with this
+ * "?:" statement. (Different linkage attributes for strcmp()
+ * and strcasecmp().) Converting to "if" changes the
+ * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
+ * the senseless type cast clears the complaint, and looks
+ * harmless.
+ */
+ int (*cmp) (const char *, const char *)
+ = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
+#else /* def __VMS */
int (*cmp) (const char *, const char *)
= opt.ignore_case ? strcasecmp : strcmp;
+#endif /* def __VMS [else] */
f = start;
while (f)
{