]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] Fixes by Christian Biere:
[wget] / src / ftp.c
index fdac6d49846d6d308f04eb6e109fca311db45786..e4c3b621be6c7fae1dbe22281554edccaaca946a 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -66,6 +66,9 @@ extern LARGE_INT total_downloaded_bytes;
 
 extern char ftp_last_respline[];
 
+extern FILE *output_stream;
+extern int output_stream_regular;
+
 typedef struct
 {
   int st;                      /* connection status */
@@ -241,6 +244,9 @@ getftp (struct url *u, long *len, long restval, ccon *con)
   int cmd = con->cmd;
   int pasv_mode_open = 0;
   long expected_bytes = 0L;
+  int rest_failed = 0;
+  int flags;
+  long rd_size;
 
   assert (con != NULL);
   assert (con->target != NULL);
@@ -290,6 +296,11 @@ getftp (struct url *u, long *len, long restval, ccon *con)
        return (retryable_socket_connect_error (errno)
                ? CONERROR : CONIMPOSSIBLE);
 
+      if (cmd & LEAVE_PENDING)
+       con->csock = csock;
+      else
+       con->csock = -1;
+
       /* Second: Login with proper USER/PASS sequence.  */
       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
       if (opt.server_response)
@@ -307,12 +318,14 @@ getftp (struct url *u, long *len, long restval, ccon *con)
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPSRVERR:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case WRITEFAILED:
@@ -320,18 +333,21 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPLOGREFUSED:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
          fd_close (csock);
+         con->csock = -1;
          return FTPLOGREFUSED;
          break;
        case FTPLOGINC:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
          fd_close (csock);
+         con->csock = -1;
          return FTPLOGINC;
          break;
        case FTPOK:
@@ -355,6 +371,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPSRVERR:
@@ -376,7 +393,7 @@ Error in server response, closing control connection.\n"));
 
       if (!opt.server_response)
        logprintf (LOG_VERBOSE, "==> PWD ... ");
-      err = ftp_pwd(csock, &con->id);
+      err = ftp_pwd (csock, &con->id);
       /* FTPRERR */
       switch (err)
        {
@@ -385,6 +402,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPSRVERR :
@@ -438,6 +456,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case WRITEFAILED:
@@ -445,6 +464,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPUNKNOWNTYPE:
@@ -453,6 +473,7 @@ Error in server response, closing control connection.\n"));
                     _("Unknown type `%c', closing control connection.\n"),
                     type_char);
          fd_close (csock);
+         con->csock = -1;
          return err;
        case FTPOK:
          /* Everything is OK.  */
@@ -550,6 +571,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              return err;
              break;
            case WRITEFAILED:
@@ -557,6 +579,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              return err;
              break;
            case FTPNSFOD:
@@ -564,6 +587,7 @@ Error in server response, closing control connection.\n"));
              logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
                         u->dir);
              fd_close (csock);
+             con->csock = -1;
              return err;
              break;
            case FTPOK:
@@ -588,7 +612,7 @@ Error in server response, closing control connection.\n"));
            logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
        }
 
-      err = ftp_size(csock, u->file, len);
+      err = ftp_size (csock, u->file, len);
       /* FTPRERR */
       switch (err)
        {
@@ -598,6 +622,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          return err;
          break;
        case FTPOK:
@@ -627,6 +652,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              return err;
              break;
            case WRITEFAILED:
@@ -634,6 +660,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              return err;
              break;
            case FTPNOPASV:
@@ -650,7 +677,7 @@ Error in server response, closing control connection.\n"));
            default:
              abort ();
              break;
-           }   /* switch(err) */
+           }   /* switch (err) */
          if (err==FTPOK)
            {
              DEBUGP (("trying to connect to %s port %d\n", 
@@ -661,7 +688,8 @@ Error in server response, closing control connection.\n"));
                {
                  int save_errno = errno;
                  fd_close (csock);
-                 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %hu: %s\n"),
+                 con->csock = -1;
+                 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
                             pretty_print_address (&passive_addr), passive_port,
                             strerror (save_errno));
                  return (retryable_socket_connect_error (save_errno)
@@ -686,6 +714,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              fd_close (dtsock);
              fd_close (local_sock);
              return err;
@@ -695,6 +724,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
              fd_close (csock);
+             con->csock = -1;
              fd_close (dtsock);
              fd_close (local_sock);
              return err;
@@ -703,6 +733,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
              fd_close (csock);
+             con->csock = -1;
              fd_close (dtsock);
              fd_close (local_sock);
              return err;
@@ -718,6 +749,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
              fd_close (csock);
+             con->csock = -1;
              fd_close (dtsock);
              fd_close (local_sock);
              return err;
@@ -749,6 +781,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return err;
@@ -758,26 +791,14 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          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"),
-                        con->target);
-             fd_close (csock);
-             fd_close (dtsock);
-             fd_close (local_sock);
-             return CONTNOTSUPPORTED;
-           }
          logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
-         restval = 0L;
+         rest_failed = 1;
          break;
        case FTPOK:
          /* fine and dandy */
@@ -799,6 +820,7 @@ Error in server response, closing control connection.\n"));
       if (opt.spider)
        {
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return RETRFINISHED;
@@ -823,6 +845,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return err;
@@ -832,6 +855,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return err;
@@ -872,6 +896,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return err;
@@ -881,6 +906,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return err;
@@ -931,8 +957,8 @@ Error in server response, closing control connection.\n"));
        }
     }
 
-  /* Open the file -- if opt.dfp is set, use it instead.  */
-  if (!opt.dfp || con->cmd & DO_LIST)
+  /* Open the file -- if output_stream is set, use it instead.  */
+  if (!output_stream || con->cmd & DO_LIST)
     {
       mkalldirs (con->target);
       if (opt.backups)
@@ -945,30 +971,14 @@ Error in server response, closing control connection.\n"));
        {
          logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
          fd_close (csock);
+         con->csock = -1;
          fd_close (dtsock);
          fd_close (local_sock);
          return FOPENERR;
        }
     }
   else
-    {
-      extern int global_download_count;
-      fp = opt.dfp;
-
-      /* 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 && opt.dfp != stdout)
-       {
-         /* 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);
-       }
-    }
+    fp = output_stream;
 
   if (*len)
     {
@@ -988,10 +998,17 @@ Error in server response, closing control connection.\n"));
     }
 
   /* Get the contents of the document.  */
-  res = fd_read_body (dtsock, fp, len, restval, expected_bytes, 0,
-                     &con->dltime);
+  flags = 0;
+  if (restval && rest_failed)
+    flags |= rb_skip_startpos;
+  *len = restval;
+  rd_size = 0;
+  res = fd_read_body (dtsock, fp,
+                     expected_bytes ? expected_bytes - restval : 0,
+                     restval, &rd_size, len, &con->dltime, flags);
+
   tms = time_str (NULL);
-  tmrate = retr_rate (*len - restval, con->dltime, 0);
+  tmrate = retr_rate (rd_size, con->dltime, 0);
   /* Close data connection socket.  */
   fd_close (dtsock);
   fd_close (local_sock);
@@ -1001,7 +1018,7 @@ Error in server response, closing control connection.\n"));
        error here.  Checking the result of fwrite() is not enough --
        errors could go unnoticed!  */
     int flush_res;
-    if (!opt.dfp || con->cmd & DO_LIST)
+    if (!output_stream || con->cmd & DO_LIST)
       flush_res = fclose (fp);
     else
       flush_res = fflush (fp);
@@ -1015,6 +1032,7 @@ Error in server response, closing control connection.\n"));
       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
                 con->target, strerror (errno));
       fd_close (csock);
+      con->csock = -1;
       return FWRITEERR;
     }
   else if (res == -1)
@@ -1040,6 +1058,7 @@ Error in server response, closing control connection.\n"));
         whole file was retrieved nevertheless (but that is for
         ftp_loop_internal to decide).  */
       fd_close (csock);
+      con->csock = -1;
       return FTPRETRINT;
     } /* err != FTPOK */
   /* If retrieval failed for any reason, return FTPRETRINT, but do not
@@ -1065,9 +1084,10 @@ Error in server response, closing control connection.\n"));
 
   if (!(cmd & LEAVE_PENDING))
     {
-      /* I should probably send 'QUIT' and check for a reply, but this
-        is faster.  #### Is it OK, though?  */
+      /* Closing the socket is faster than sending 'QUIT' and the
+        effect is the same.  */
       fd_close (csock);
+      con->csock = -1;
     }
   /* If it was a listing, and opt.server_response is true,
      print it out.  */
@@ -1103,7 +1123,7 @@ static uerr_t
 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
 {
   int count, orig_lp;
-  long restval, len;
+  long restval, len = 0;
   char *tms, *locf;
   char *tmrate = NULL;
   uerr_t err;
@@ -1161,20 +1181,14 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
            con->cmd |= DO_CWD;
        }
 
-      /* Assume no restarting.  */
-      restval = 0L;
-      if ((count > 1 || opt.always_rest)
-         && !(con->cmd & DO_LIST)
-         && file_exists_p (locf))
-       if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
-         restval = st.st_size;
-
-      /* In `-c' is used, check whether the file we're writing to
-        exists and is of non-zero length.  If so, we'll refuse to
-        truncate it if the server doesn't support continued
-        downloads.  */
-      if (opt.always_rest && restval > 0)
-       con->cmd |= NO_TRUNCATE;
+      /* Decide whether or not to restart.  */
+      restval = 0;
+      if (count > 1)
+       restval = len;          /* start where the previous run left off */
+      else if (opt.always_rest
+              && stat (locf, &st) == 0
+              && S_ISREG (st.st_mode))
+       restval = st.st_size;
 
       /* Get the current time string.  */
       tms = time_str (NULL);
@@ -1182,7 +1196,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
       if (opt.verbose)
        {
          char *hurl = url_string (u, 1);
-         char tmp[15];
+         char tmp[256];
          strcpy (tmp, "        ");
          if (count > 1)
            sprintf (tmp, _("(try:%2d)"), count);
@@ -1235,7 +1249,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
          /* Not as great.  */
          abort ();
        }
-      /* Time?  */
       tms = time_str (NULL);
       if (!opt.spider)
         tmrate = retr_rate (len - restval, con->dltime, 0);
@@ -1560,7 +1573,7 @@ Already have correct symlink %s -> %s\n\n"),
          const char *fl = NULL;
          if (opt.output_document)
            {
-             if (opt.od_known_regular)
+             if (output_stream_regular)
                fl = opt.output_document;
            }
          else
@@ -1677,7 +1690,7 @@ has_insecure_name_p (const char *s)
   if (*s == '/')
     return 1;
 
-  if (strstr(s, "../") != 0)
+  if (strstr (s, "../") != 0)
     return 1;
 
   return 0;