/* File Transfer Protocol support.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GNU Wget.
#define LIST_FILENAME ".listing"
#endif
+#define max(a, b) ((a > b) ? (a) : (b))
+
typedef struct
{
int st; /* connection status */
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)
{
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)
{
if (opt.verbose)
{
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
+ logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
quotearg_style (escape_quoting_style, u->file));
}
} /* 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));
}
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
- expected_bytes = ftp_expected_bytes (ftp_last_respline);
+
+ expected_bytes = max (ftp_expected_bytes (ftp_last_respline),
+ expected_bytes);
} /* do retrieve */
if (cmd & DO_LIST)
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
- expected_bytes = ftp_expected_bytes (ftp_last_respline);
+ expected_bytes = max (ftp_expected_bytes (ftp_last_respline),
+ expected_bytes);
} /* cmd & DO_LIST */
if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
}
/* 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
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);
}
This loop either gets commands from con, or (if ON_YOUR_OWN is
set), makes them up to retrieve the file given by the URL. */
static uerr_t
-ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
+ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
{
int count, orig_lp;
wgint restval, len = 0, qtyread = 0;
total_downloaded_bytes += qtyread;
numurls++;
- if (opt.delete_after)
+ if (opt.delete_after && !input_file_url (opt.input_filename))
{
DEBUGP (("\
Removing file due to --delete-after in ftp_loop_internal():\n"));
con->cmd |= LEAVE_PENDING;
else
con->cmd &= ~LEAVE_PENDING;
+
+ if (local_file)
+ *local_file = xstrdup (locf);
+
return RETROK;
} while (!opt.ntry || (count < opt.ntry));
con->target = xstrdup (lf);
xfree (lf);
- err = ftp_loop_internal (u, NULL, con);
+ err = ftp_loop_internal (u, NULL, con, NULL);
lf = xstrdup (con->target);
xfree (con->target);
con->target = old_target;
else /* opt.retr_symlinks */
{
if (dlthis)
- err = ftp_loop_internal (u, f, con);
+ err = ftp_loop_internal (u, f, con, NULL);
} /* opt.retr_symlinks */
break;
case FT_DIRECTORY:
case FT_PLAINFILE:
/* Call the retrieve loop. */
if (dlthis)
- err = ftp_loop_internal (u, f, con);
+ err = ftp_loop_internal (u, f, con, NULL);
break;
case FT_UNKNOWN:
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
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;
}
{
/* Let's try retrieving it anyway. */
con->st |= ON_YOUR_OWN;
- res = ftp_loop_internal (u, NULL, con);
+ res = ftp_loop_internal (u, NULL, con, NULL);
return res;
}
of URL. Inherently, its capabilities are limited on what can be
encoded into a URL. */
uerr_t
-ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
+ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
+ bool recursive, bool glob)
{
ccon con; /* FTP connection */
uerr_t res;
ispattern ? GLOB_GLOBALL : GLOB_GETONE);
}
else
- res = ftp_loop_internal (u, NULL, &con);
+ res = ftp_loop_internal (u, NULL, &con, local_file);
}
if (res == FTPOK)
res = RETROK;