]> sjero.net Git - wget/commitdiff
[svn] Make sure -c doesn't truncate the file.
authorhniksic <devnull@localhost>
Sun, 1 Apr 2001 20:04:21 +0000 (13:04 -0700)
committerhniksic <devnull@localhost>
Sun, 1 Apr 2001 20:04:21 +0000 (13:04 -0700)
Published in <sxsofuhi4kc.fsf@florida.arsdigita.de>.

src/ChangeLog
src/ftp.c
src/ftp.h
src/http.c
src/wget.h

index 5eaa0ac21df0dc291039d4f494ce7552f238d35f..e981baf3d0769016f014f4fd63dbb93319be6721 100644 (file)
@@ -1,3 +1,13 @@
+2001-04-01  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * 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  <hniksic@arsdigita.com>
 
        (recursive_retrieve): Don't clear the hash tables at this point at
index 7b33efd4ef36a3ebeedf68c6e1aa7b824b9188ba..306dae83e6116555fd5721956b2db4f407315b6c 100644 (file)
--- 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;
index b7c4d254c6af379ae4060d1cefbcfb89b7ded143..9a516d4b2b2600bf2143804028aff31316ced2d5 100644 (file)
--- 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
index 624e411fce7f82ea438587979898897da811d6db..589657f37ee4bb171b69314758a98b6d3b41b56e 100644 (file)
@@ -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"));
index 42b138db1f3eb1a7deec32c95a04a057754300f9..17733cb04bb8bc492a0debc40efcab03a2781918 100644 (file)
@@ -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;