]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] A bunch of new features:
[wget] / src / ftp.c
index 9077c674c4b243477754e304553698711a20e3dd..aa283cf8fbbc554799f39185b164a54c38b6d327 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,5 +1,5 @@
 /* File Transfer Protocol support.
-   Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
 
 This file is part of Wget.
 
@@ -40,7 +40,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "rbuf.h"
 #include "retr.h"
 #include "ftp.h"
-#include "html.h"
 #include "connect.h"
 #include "host.h"
 #include "fnmatch.h"
@@ -90,7 +89,7 @@ ftp_expected_bytes (const char *s)
        ++s;
       if (!*s)
        return 0;
-      if (tolower (*s) != 'b')
+      if (TOLOWER (*s) != 'b')
        continue;
       if (strncasecmp (s, "byte", 4))
        continue;
@@ -243,8 +242,8 @@ Error in server response, closing control connection.\n"));
        }
       /* Third: Set type to Image (binary).  */
       if (!opt.server_response)
-       logprintf (LOG_VERBOSE, "==> TYPE %c ... ", toupper (u->ftp_type));
-      err = ftp_type (&con->rbuf, toupper (u->ftp_type));
+       logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
+      err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
       switch (err)
        {
@@ -268,7 +267,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logprintf (LOG_NOTQUIET,
                     _("Unknown type `%c', closing control connection.\n"),
-                    toupper (u->ftp_type));
+                    TOUPPER (u->ftp_type));
          CLOSE (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
@@ -337,7 +336,7 @@ Error in server response, closing control connection.\n"));
   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
   if (cmd & (DO_LIST | DO_RETR))
     {
-      if (opt.ftp_pasv)
+      if (opt.ftp_pasv > 0)
        {
          char thost[256];
          unsigned short tport;
@@ -648,6 +647,15 @@ Error in server response, closing control connection.\n"));
       expected_bytes = ftp_expected_bytes (ftp_last_respline);
     } /* cmd & DO_LIST */
 
+  /* Some FTP servers return the total length of file after REST
+     command, others just return the remaining size. */
+  if (*len && restval && expected_bytes
+      && (expected_bytes == *len - restval))
+    {
+      DEBUGP (("Lying FTP server found, adjusting.\n"));
+      expected_bytes = *len;
+    }
+
   /* If no transmission was required, then everything is OK.  */
   if (!(cmd & (DO_LIST | DO_RETR)))
     return RETRFINISHED;
@@ -685,7 +693,16 @@ Error in server response, closing control connection.\n"));
        }
     }
   else
-    fp = opt.dfp;
+    {
+      fp = opt.dfp;
+      if (!restval)
+       {
+         /* This will silently fail for streams that don't correspond
+            to regular files, but that's OK.  */
+         rewind (fp);
+         clearerr (fp);
+       }
+    }
 
   if (*len)
     {
@@ -704,17 +721,25 @@ Error in server response, closing control connection.\n"));
     }
   reset_timer ();
   /* Get the contents of the document.  */
-  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf);
+  res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
   con->dltime = elapsed_time ();
   tms = time_str (NULL);
   tmrate = rate (*len - restval, con->dltime);
   /* Close data connection socket.  */
   closeport (dtsock);
   /* Close the local file.  */
-  if (!opt.dfp || con->cmd & DO_LIST)
-    fclose (fp);
-  else
-    fflush (fp);
+  {
+    /* Close or flush the file.  We have to be careful to check for
+       error here.  Checking the result of fwrite() is not enough --
+       errors could go unnoticed!  */
+    int flush_res;
+    if (!opt.dfp || con->cmd & DO_LIST)
+      flush_res = fclose (fp);
+    else
+      flush_res = fflush (fp);
+    if (flush_res == EOF)
+      res = -2;
+  }
   /* If get_contents couldn't write to fp, bail out.  */
   if (res == -2)
     {
@@ -852,9 +877,20 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
       /* Increment the pass counter.  */
       ++count;
       /* Wait before the retrieval (unless this is the very first
-        retrieval).  */
-      if (!first_retrieval && opt.wait)
-       sleep (opt.wait);
+        retrieval).
+        Check if we are retrying or not, wait accordingly - HEH */
+      if (!first_retrieval && (opt.wait || (count && opt.waitretry)))
+       {
+         if (count)
+           {
+             if (count<opt.waitretry)
+               sleep(count);
+             else
+               sleep(opt.waitretry);
+           }
+         else
+           sleep (opt.wait);
+       }
       if (first_retrieval)
        first_retrieval = 0;
       if (con->st & ON_YOUR_OWN)
@@ -950,7 +986,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
 
       /* If we get out of the switch above without continue'ing, we've
         successfully downloaded a file.  Remember this fact. */
-      downloaded_file(ADD_FILE, locf);
+      downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
 
       if (con->st & ON_YOUR_OWN)
        {
@@ -959,15 +995,52 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
        }
       logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
                 tms, tmrate, locf, len);
-      logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
-                tms, u->url, len, locf, count);
-      /* Do not count listings among the downloaded stuff, since they
-        will get deleted anyway.  */
-      if (!(con->cmd & DO_LIST))
+      if (!opt.verbose && !opt.quiet)
        {
-         ++opt.numurls;
-         opt.downloaded += len;
+         /* Need to hide the password from the URL.  The `if' is here
+             so that we don't do the needless allocation every
+             time. */
+         char *hurl = str_url (u->proxy ? u->proxy : u, 1);
+         logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
+                    tms, hurl, len, locf, count);
+         free (hurl);
+       }
+
+      if ((con->cmd & DO_LIST))
+       /* This is a directory listing file. */
+       {
+         if (!opt.remove_listing)
+           /* --dont-remove-listing was specified, so do count this towards the
+              number of bytes and files downloaded. */
+           {
+             downloaded_increase (len);
+             opt.numurls++;
+           }
+
+         /* Deletion of listing files is not controlled by --delete-after, but
+            by the more specific option --dont-remove-listing, and the code
+            to do this deletion is in another function. */
        }
+      else
+       /* This is not a directory listing file. */
+       {
+         /* Unlike directory listing files, don't pretend normal files weren't
+            downloaded if they're going to be deleted.  People seeding proxies,
+            for instance, may want to know how many bytes and files they've
+            downloaded through it. */
+         downloaded_increase (len);
+         opt.numurls++;
+
+         if (opt.delete_after)
+           {
+             DEBUGP (("Removing file due to --delete-after in"
+                      " ftp_loop_internal():\n"));
+             logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
+             if (unlink (locf))
+               logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
+           }
+       }
+      
       /* Restore the original leave-pendingness.  */
       if (orig_lp)
        con->cmd |= LEAVE_PENDING;
@@ -1049,7 +1122,7 @@ ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
 
   /* Increase the depth.  */
   ++depth;
-  if (opt.reclevel && depth > opt.reclevel)
+  if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
     {
       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
               depth, opt.reclevel));
@@ -1076,7 +1149,7 @@ ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
 
   while (f)
     {
-      if (opt.quota && opt.downloaded > opt.quota)
+      if (downloaded_exceeds_quota ())
        {
          --depth;
          return QUOTEXC;
@@ -1202,7 +1275,7 @@ Already have correct symlink %s -> %s\n\n"),
       else if (f->tstamp == -1)
        logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
 
-      if (f->perms && dlthis)
+      if (f->perms && f->type == FT_PLAINFILE && dlthis)
        chmod (u->local, f->perms);
       else
        DEBUGP (("Unrecognized permissions for %s.\n", u->local));
@@ -1217,7 +1290,8 @@ Already have correct symlink %s -> %s\n\n"),
       f = f->next;
     } /* while */
   /* We do not want to call ftp_retrieve_dirs here */
-  if (opt.recursive && !(opt.reclevel && depth >= opt.reclevel))
+  if (opt.recursive &&
+      !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
     err = ftp_retrieve_dirs (u, orig, con);
   else if (opt.recursive)
     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
@@ -1241,7 +1315,7 @@ ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
     {
       int len;
 
-      if (opt.quota && opt.downloaded > opt.quota)
+      if (downloaded_exceeds_quota ())
        break;
       if (f->type != FT_DIRECTORY)
        continue;
@@ -1362,7 +1436,7 @@ ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
        }
     }
   freefileinfo (start);
-  if (opt.quota && opt.downloaded > opt.quota)
+  if (downloaded_exceeds_quota ())
     return QUOTEXC;
   else
     /* #### Should we return `res' here?  */