/* File Transfer Protocol support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Wget.
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
-#define USE_GNULIB_ALLOC
-
#include "wget.h"
#include <stdio.h>
struct url *proxy; /* FTWK-style proxy */
} ccon;
+extern int numurls;
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
the string S, and return the number converted to wgint, if found, 0
logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
if (start > 0)
{
- if (start >= 1024)
+ if (size - start >= 1024)
logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
number_to_static_string (size - start),
human_readable (size - start));
logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
}
+static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
+
/* Retrieves a file with denoted parameters through opening an FTP
connection to the server. It always closes the data connection,
and closes the control connection in case of error. */
con->csock = -1;
/* Second: Login with proper USER/PASS sequence. */
- logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
+ logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
+ quotearg_style (escape_quoting_style, user));
if (opt.server_response)
logputs (LOG_ALWAYS, "\n");
err = ftp_login (csock, logname, passwd);
}
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> CWD %s ... ", escnonprint (target));
+ logprintf (LOG_VERBOSE, "==> CWD %s ... ",
+ quotearg_style (escape_quoting_style, target));
err = ftp_cwd (csock, target);
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
- quote (escnonprint (u->dir)));
+ quote (u->dir));
fd_close (csock);
con->csock = -1;
return err;
if (opt.verbose)
{
if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
+ logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
+ quotearg_style (escape_quoting_style, u->file));
}
err = ftp_size (csock, u->file, len);
if (cmd & DO_RETR)
{
- /* If we're in spider mode, don't really retrieve anything. The
- fact that we got to this point should be proof enough that
- the file exists, vaguely akin to HTTP's concept of a "HEAD"
- request. */
+ /* If we're in spider mode, don't really retrieve anything except
+ the directory listing and verify whether the given "file" exists. */
if (opt.spider)
{
+ bool exists = false;
+ 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
+ (e.g., when recursing). */
+ con->cmd |= DO_RETR;
+ if (res == RETROK)
+ {
+ while (f)
+ {
+ if (!strcmp (f->name, u->file))
+ {
+ exists = true;
+ break;
+ }
+ f = f->next;
+ }
+ if (exists)
+ {
+ logputs (LOG_VERBOSE, "\n");
+ logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
+ quote (u->file));
+ }
+ else
+ {
+ logputs (LOG_VERBOSE, "\n");
+ logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
+ quote (u->file));
+ }
+ }
fd_close (csock);
con->csock = -1;
fd_close (dtsock);
{
if (restval)
logputs (LOG_VERBOSE, "\n");
- logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
+ logprintf (LOG_VERBOSE, "==> RETR %s ... ",
+ quotearg_style (escape_quoting_style, u->file));
}
}
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
- quote (escnonprint (u->file)));
+ quote (u->file));
fd_close (dtsock);
fd_close (local_sock);
return err;
char *p = strchr (line, '\0');
while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
*--p = '\0';
- logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
+ logprintf (LOG_ALWAYS, "%s\n",
+ quotearg_style (escape_quoting_style, line));
xfree (line);
}
fclose (fp);
if (!con->target)
con->target = url_file_name (u);
- if (opt.noclobber && file_exists_p (con->target))
+ /* If the output_document was given, then this check was already done and
+ the file didn't exist. Hence the !opt.output_document */
+ if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
{
logprintf (LOG_VERBOSE,
_("File %s already there; not retrieving.\n"), quote (con->target));
con->csock = -1;
}
if (!opt.spider)
- logprintf (LOG_VERBOSE, _("%s (%s) - %s saved [%s]\n\n"),
- tms, tmrate, quote (locf), number_to_static_string (len));
+ {
+ bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
+
+ logprintf (LOG_VERBOSE,
+ write_to_stdout
+ ? _("%s (%s) - written to stdout %s[%s]\n\n")
+ : _("%s (%s) - %s saved [%s]\n\n"),
+ tms, tmrate,
+ write_to_stdout ? "" : quote (locf),
+ number_to_static_string (len));
+ }
if (!opt.verbose && !opt.quiet)
{
/* Need to hide the password from the URL. The `if' is here
number of bytes and files downloaded. */
{
total_downloaded_bytes += len;
- opt.numurls++;
+ numurls++;
}
/* Deletion of listing files is not controlled by --delete-after, but
for instance, may want to know how many bytes and files they've
downloaded through it. */
total_downloaded_bytes += len;
- opt.numurls++;
+ numurls++;
if (opt.delete_after)
{
xfree (uf);
DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
- con->target = lf;
+ con->target = xstrdup (lf);
+ xfree (lf);
err = ftp_loop_internal (u, NULL, con);
+ lf = xstrdup (con->target);
+ xfree (con->target);
con->target = old_target;
if (err == RETROK)
- *f = ftp_parse_ls (lf, con->rs);
- else
- *f = NULL;
- if (opt.remove_listing)
{
- if (unlink (lf))
- logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
- else
- logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
+ *f = ftp_parse_ls (lf, con->rs);
+ if (opt.remove_listing)
+ {
+ if (unlink (lf))
+ logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
+ else
+ logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
+ }
}
+ else
+ *f = NULL;
xfree (lf);
con->cmd &= ~DO_LIST;
return err;
{
logprintf (LOG_VERBOSE, _("\
Already have correct symlink %s -> %s\n\n"),
- con->target, escnonprint (f->linkto));
+ quote (con->target),
+ quote (f->linkto));
dlthis = false;
break;
}
}
}
logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
- con->target, escnonprint (f->linkto));
+ quote (con->target), quote (f->linkto));
/* Unlink before creating symlink! */
unlink (con->target);
if (symlink (f->linkto, con->target) == -1)
case FT_DIRECTORY:
if (!opt.recursive)
logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
- quote (escnonprint (f->name)));
+ quote (f->name));
break;
case FT_PLAINFILE:
/* Call the retrieve loop. */
break;
case FT_UNKNOWN:
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
- escnonprint (f->name));
+ quote (f->name));
break;
} /* switch */
&& dlthis
&& file_exists_p (con->target))
{
- /* #### This code repeats in http.c and ftp.c. Move it to a
- function! */
const char *fl = NULL;
- if (opt.output_document)
- {
- if (output_stream_regular)
- fl = opt.output_document;
- }
- else
- fl = con->target;
+ set_local_file (&fl, con->target);
if (fl)
touch (fl, f->tstamp);
}
{
logprintf (LOG_VERBOSE, _("\
Not descending to %s as it is excluded/not-included.\n"),
- quote (escnonprint (newdir)));
+ quote (newdir));
continue;
}
if (f->type != FT_DIRECTORY && !acceptable (f->name))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
- quote (escnonprint (f->name)));
+ quote (f->name));
f = delelement (f, &start);
}
else
if (has_insecure_name_p (f->name))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
- quote (escnonprint (f->name)));
+ quote (f->name));
f = delelement (f, &start);
}
else
if (matchres == -1)
{
logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
- u->file, escnonprint (f->name), strerror (errno));
+ u->file, quotearg_style (escape_quoting_style, f->name),
+ strerror (errno));
break;
}
if (matchres == FNM_NOMATCH)
/* #### This message SUCKS. We should see what was the
reason that nothing was retrieved. */
logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
- quote (escnonprint (u->file)));
+ quote (u->file));
}
else /* GLOB_GETONE or GLOB_GETALL */
{