err = ftp_pwd(&con->rbuf, &con->id);
/* FTPRERR */
switch (err)
- {
- case FTPRERR || FTPSRVERR :
+ {
+ case FTPRERR:
+ case FTPSRVERR :
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n"));
default:
abort ();
break;
- }
+ }
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
return err;
break;
case FTPRESTFAIL:
+ /* If `-c' is specified and the file already existed when
+ Wget was started, it would be a bad idea for us to start
+ downloading it from scratch, effectively truncating it. */
+ if (opt.always_rest && (cmd & NO_TRUNCATE))
+ {
+ logprintf (LOG_NOTQUIET,
+ _("\nREST failed; will not truncate `%s'.\n"),
+ u->local);
+ CLOSE (csock);
+ closeport (dtsock);
+ rbuf_uninitialize (&con->rbuf);
+ return CONTNOTSUPPORTED;
+ }
logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
restval = 0L;
break;
}
else
{
+ extern int global_download_count;
fp = opt.dfp;
- if (!restval)
+
+ /* Rewind the output document if the download starts over and if
+ this is the first download. See gethttp() for a longer
+ explanation. */
+ if (!restval && global_download_count == 0)
{
/* This will silently fail for streams that don't correspond
to regular files, but that's OK. */
rewind (fp);
+ /* ftruncate is needed because opt.dfp is opened in append
+ mode if opt.always_rest is set. */
+ ftruncate (fileno (fp), 0);
clearerr (fp);
}
}
static uerr_t
ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
{
- int count, orig_lp;
+ int count, orig_lp, no_truncate;
long restval, len;
char *tms, *tmrate, *locf;
uerr_t err;
orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
+ /* In `-c' is used, check whether the file we're writing to exists
+ before we've done anything. If so, we'll refuse to truncate it
+ if the server doesn't support continued downloads. */
+ no_truncate = 0;
+ if (opt.always_rest)
+ no_truncate = file_exists_p (locf);
+
/* THE loop. */
do
{
else
con->cmd |= DO_CWD;
}
+ if (no_truncate)
+ con->cmd |= NO_TRUNCATE;
/* Assume no restarting. */
restval = 0L;
if ((count > 1 || opt.always_rest)
&& !(con->cmd & DO_LIST)
- && file_exists_p (u->local))
- if (stat (u->local, &st) == 0)
+ && file_exists_p (locf))
+ if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
restval = st.st_size;
/* Get the current time string. */
tms = time_str (NULL);
switch (err)
{
case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
- case FTPNSFOD: case FTPLOGINC: case FTPNOPASV:
+ case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
/* Fatal errors, give up. */
return err;
break;
/* Return the directory listing in a reusable format. The directory
is specifed in u->dir. */
-static struct fileinfo *
-ftp_get_listing (struct urlinfo *u, ccon *con)
+uerr_t
+ftp_get_listing (struct urlinfo *u, ccon *con, struct fileinfo **f)
{
- struct fileinfo *f;
uerr_t err;
char *olocal = u->local;
char *list_filename, *ofile;
err = ftp_loop_internal (u, NULL, con);
u->local = olocal;
if (err == RETROK)
- f = ftp_parse_ls (list_filename, con->rs);
+ *f = ftp_parse_ls (list_filename, con->rs);
else
- f = NULL;
+ *f = NULL;
if (opt.remove_listing)
{
if (unlink (list_filename))
}
xfree (list_filename);
con->cmd &= ~DO_LIST;
- return f;
+ return err;
}
static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
con->cmd |= LEAVE_PENDING;
- orig = ftp_get_listing (u, con);
+ res = ftp_get_listing (u, con, &orig);
+ if (res != RETROK)
+ return res;
start = orig;
/* First: weed out that do not conform the global rules given in
opt.accepts and opt.rejects. */
opt.htmlify is 0, of course. :-) */
if (!*u->file && !opt.recursive)
{
- struct fileinfo *f = ftp_get_listing (u, &con);
+ struct fileinfo *f;
+ res = ftp_get_listing (u, &con, &f);
- if (f)
+ if (res == RETROK)
{
if (opt.htmlify)
{