From a52aaeb451cfd1af2b37e5b534856fe4b44f59ad Mon Sep 17 00:00:00 2001 From: hniksic Date: Sun, 1 Apr 2001 13:04:21 -0700 Subject: [PATCH] [svn] Make sure -c doesn't truncate the file. Published in . --- src/ChangeLog | 10 +++++++ src/ftp.c | 33 +++++++++++++++++++---- src/ftp.h | 4 ++- src/http.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++----- src/wget.h | 7 ++--- 5 files changed, 113 insertions(+), 15 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 5eaa0ac2..e981baf3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2001-04-01 Hrvoje Niksic + + * ftp.c (getftp): Don't start the download from scratch if `-c' + was specified, but the file is already fully downloaded. + + * http.c (gethttp): Don't truncate a pre-existing file if `-c' was + specified and the server doesn't support continued download. + (gethttp): Don't start the download from scratch if `-c' was + specified, but the file is already fully downloaded. + 2001-03-31 Hrvoje Niksic (recursive_retrieve): Don't clear the hash tables at this point at diff --git a/src/ftp.c b/src/ftp.c index 7b33efd4..306dae83 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -281,8 +281,9 @@ Error in server response, closing control connection.\n")); 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")); @@ -296,7 +297,7 @@ Error in server response, closing control connection.\n")); default: abort (); break; - } + } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); @@ -639,6 +640,19 @@ Error in server response, closing control connection.\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; @@ -944,7 +958,7 @@ Error in server response, closing control connection.\n")); 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; @@ -975,6 +989,13 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) 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 { @@ -1001,6 +1022,8 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) else con->cmd |= DO_CWD; } + if (no_truncate) + con->cmd |= NO_TRUNCATE; /* Assume no restarting. */ restval = 0L; if ((count > 1 || opt.always_rest) @@ -1043,7 +1066,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) 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; diff --git a/src/ftp.h b/src/ftp.h index b7c4d254..9a516d4b 100644 --- a/src/ftp.h +++ b/src/ftp.h @@ -81,7 +81,9 @@ enum wget_ftp_command DO_CWD = 0x0002, /* Change current directory. */ DO_RETR = 0x0004, /* Retrieve the file. */ DO_LIST = 0x0008, /* Retrieve the directory list. */ - LEAVE_PENDING = 0x0010 /* Do not close the socket. */ + LEAVE_PENDING = 0x0010, /* Do not close the socket. */ + NO_TRUNCATE = 0x0020 /* Don't truncate the file if REST + malfunctions. */ }; enum wget_ftp_fstatus diff --git a/src/http.c b/src/http.c index 624e411f..589657f3 100644 --- a/src/http.c +++ b/src/http.c @@ -462,6 +462,8 @@ struct http_stat char *error; /* textual HTTP error */ int statcode; /* status code */ long dltime; /* time of the download */ + int no_truncate; /* whether truncating the file is + forbidden. */ }; /* Free the elements of hstat X. */ @@ -1128,7 +1130,58 @@ Accept: %s\r\n\ } if (contrange == -1) - hs->restval = 0; + { + /* We did not get a content-range header. This means that the + server did not honor our `Range' request. Normally, this + means we should reset hs->restval and continue normally. */ + + /* However, if `-c' is used, we need to be a bit more careful: + + 1. 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. I + believe this cannot happen unless `-c' was specified. + + 2. If `-c' is used on a file that is already fully + downloaded, we're requesting bytes after the end of file, + which can result in server not honoring `Range'. If this is + the case, `Content-Length' will be equal to the length of the + file. */ + if (opt.always_rest) + { + /* Check for condition #2. */ + if (hs->restval == contlen) + { + logputs (LOG_VERBOSE, _("\ +\n The file is already fully retrieved; nothing to do.\n\n")); + /* In case the caller inspects. */ + hs->len = contlen; + hs->res = 0; + FREE_MAYBE (type); + FREE_MAYBE (hs->newloc); + FREE_MAYBE (all_headers); + CLOSE_INVALIDATE (sock); /* would be CLOSE_FINISH, but there + might be more bytes in the body. */ + return RETRFINISHED; + } + + /* Check for condition #1. */ + if (hs->no_truncate) + { + logprintf (LOG_NOTQUIET, + _("\ + + The server does not support continued download; + refusing to truncate `%s'.\n\n"), u->local); + return CONTNOTSUPPORTED; + } + + /* Fallthrough */ + } + + hs->restval = 0; + } + else if (contrange != hs->restval || (H_PARTIAL (statcode) && contrange == -1)) { @@ -1204,7 +1257,7 @@ Accept: %s\r\n\ /* Return if we have no intention of further downloading. */ if (!(*dt & RETROKF) || (*dt & HEAD_ONLY)) { - /* In case someone cares to look... */ + /* In case the caller cares to look... */ hs->len = 0L; hs->res = 0; FREE_MAYBE (type); @@ -1347,8 +1400,10 @@ File `%s' already there, will not retrieve.\n"), u->local); { /* Would a single s[n]printf() call be faster? --dan - It wouldn't. sprintf() is horribly slow. At one point I - profiled Wget, and found that a measurable and + Definitely not. sprintf() is horribly slow. It's a + different question whether the difference between the two + affects a program. Usually I'd say "no", but at one + point I profiled Wget, and found that a measurable and non-negligible amount of time was lost calling sprintf() in url.c. Replacing sprintf with inline calls to strcpy() and long_to_string() made a difference. @@ -1439,6 +1494,13 @@ File `%s' already there, will not retrieve.\n"), u->local); else locf = opt.output_document; + /* 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. */ + if (opt.always_rest) + hstat.no_truncate = file_exists_p (locf); + /* Time? */ tms = time_str (NULL); /* Get the new location (with or without the redirection). */ @@ -1457,7 +1519,7 @@ File `%s' already there, will not retrieve.\n"), u->local); continue; break; case HOSTERR: case CONREFUSED: case PROXERR: case AUTHFAILED: - case SSLERRCTXCREATE: + case SSLERRCTXCREATE: case CONTNOTSUPPORTED: /* Fatal errors just return from the function. */ FREEHSTAT (hstat); xfree (filename_plus_orig_suffix); /* must precede every return! */ @@ -1471,7 +1533,7 @@ File `%s' already there, will not retrieve.\n"), u->local); FREEHSTAT (hstat); return err; break; - case CONSSLERR: + case CONSSLERR: /* Another fatal error. */ logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("Unable to establish SSL connection.\n")); diff --git a/src/wget.h b/src/wget.h index 42b138db..17733cb0 100644 --- a/src/wget.h +++ b/src/wget.h @@ -257,9 +257,10 @@ typedef enum URLBADHOST, FOPENERR, FWRITEERR, HOK, HLEXC, HEOF, HERR, RETROK, RECLEVELEXC, FTPACCDENIED, WRONGCODE, FTPINVPASV, FTPNOPASV, - RETRFINISHED, READERR, TRYLIMEXC, URLBADPATTERN, - FILEBADFILE, RANGEERR, RETRBADPATTERN, RETNOTSUP, - ROBOTSOK, NOROBOTS, PROXERR, AUTHFAILED, QUOTEXC, WRITEFAILED, + CONTNOTSUPPORTED, RETRFINISHED, READERR, TRYLIMEXC, + URLBADPATTERN, FILEBADFILE, RANGEERR, RETRBADPATTERN, + RETNOTSUP, ROBOTSOK, NOROBOTS, PROXERR, AUTHFAILED, + QUOTEXC, WRITEFAILED, SSLERRCERTFILE,SSLERRCERTKEY,SSLERRCTXCREATE } uerr_t; -- 2.39.2