]> sjero.net Git - wget/blobdiff - src/ftp.c
mass change: update copyright years.
[wget] / src / ftp.c
index c5ac83032aa596ad659bd9fa3b384db5669618a7..2cc341bd2a09f70f561f6d5b26f0364ffabdc9dc 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1,6 +1,7 @@
 /* File Transfer Protocol support.
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+   Inc.
 
 This file is part of GNU Wget.
 
@@ -34,9 +35,7 @@ as that of the covered work.  */
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <unistd.h>
 #include <assert.h>
 #include <errno.h>
 #include <time.h>
@@ -63,8 +62,6 @@ as that of the covered work.  */
 #define LIST_FILENAME ".listing"
 #endif
 
-#define max(a, b) ((a > b) ? (a) : (b))
-
 typedef struct
 {
   int st;                       /* connection status */
@@ -243,7 +240,7 @@ static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
    and closes the control connection in case of error.  */
 static uerr_t
 getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
-        wgint restval, ccon *con)
+        wgint restval, ccon *con, int count)
 {
   int csock, dtsock, local_sock, res;
   uerr_t err = RETROK;          /* appease the compiler */
@@ -254,6 +251,7 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
   int cmd = con->cmd;
   bool pasv_mode_open = false;
   wgint expected_bytes = 0;
+  bool got_expected_bytes = false;
   bool rest_failed = false;
   int flags;
   wgint rd_size;
@@ -504,10 +502,10 @@ Error in server response, closing control connection.\n"));
         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
       else
         {
-          char *targ;
-         int cwd_count;
-         int cwd_end;
-         int cwd_start;
+          char *targ = NULL;
+          int cwd_count;
+          int cwd_end;
+          int cwd_start;
 
           char *target = u->dir;
 
@@ -757,6 +755,7 @@ Error in server response, closing control connection.\n"));
           con->csock = -1;
           return err;
         case FTPOK:
+          got_expected_bytes = true;
           /* Everything is OK.  */
           break;
         default:
@@ -767,6 +766,16 @@ Error in server response, closing control connection.\n"));
                      number_to_static_string (expected_bytes));
     }
 
+  if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
+    {
+      /* Server confirms that file has length restval. We should stop now.
+         Some servers (f.e. NcFTPd) return error when receive REST 0 */
+      logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
+      fd_close (csock);
+      con->csock = -1;
+      return RETRFINISHED;
+    }
+
   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
   if (cmd & (DO_LIST | DO_RETR))
     {
@@ -1022,8 +1031,8 @@ Error in server response, closing control connection.\n"));
       if (!opt.server_response)
         logputs (LOG_VERBOSE, _("done.\n"));
 
-      expected_bytes = max (ftp_expected_bytes (ftp_last_respline),
-                            expected_bytes);
+      if (! got_expected_bytes)
+        expected_bytes = ftp_expected_bytes (ftp_last_respline);
     } /* do retrieve */
 
   if (cmd & DO_LIST)
@@ -1069,8 +1078,9 @@ Error in server response, closing control connection.\n"));
         }
       if (!opt.server_response)
         logputs (LOG_VERBOSE, _("done.\n"));
-      expected_bytes = max (ftp_expected_bytes (ftp_last_respline),
-                            expected_bytes);
+
+      if (! got_expected_bytes)
+        expected_bytes = ftp_expected_bytes (ftp_last_respline);
     } /* cmd & DO_LIST */
 
   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
@@ -1161,8 +1171,23 @@ Error in server response, closing control connection.\n"));
 #endif /* def __VMS [else] */
         }
       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
-               || opt.output_document)
-        {
+               || opt.output_document || count > 0)
+        {        
+         if (opt.unlink && file_exists_p (con->target))
+           {
+             int res = unlink (con->target);
+             if (res < 0)
+               {
+                 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
+                            strerror (errno));
+                 fd_close (csock);
+                 con->csock = -1;
+                 fd_close (dtsock);
+                 fd_close (local_sock);
+                 return UNLINKERR;
+               }
+           }
+
 #ifdef __VMS
           int open_id;
 
@@ -1371,7 +1396,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
   else
     {
       /* URL-derived file.  Consider "-O file" name. */
-      con->target = url_file_name (u);
+      con->target = url_file_name (u, NULL);
       if (!opt.output_document)
         locf = con->target;
       else
@@ -1458,11 +1483,11 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
           xfree (hurl);
         }
       /* Send getftp the proper length, if fileinfo was provided.  */
-      if (f)
+      if (f && f->type != FT_SYMLINK)
         len = f->size;
       else
         len = 0;
-      err = getftp (u, len, &qtyread, restval, con);
+      err = getftp (u, len, &qtyread, restval, con, count);
 
       if (con->csock == -1)
         con->st &= ~DONE_CWD;
@@ -1473,6 +1498,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
         {
         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
+        case UNLINKERR:
           /* Fatal errors, give up.  */
           return err;
         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
@@ -1485,7 +1511,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
             {
               /* Re-determine the file name. */
               xfree_null (con->target);
-              con->target = url_file_name (u);
+              con->target = url_file_name (u, NULL);
               locf = con->target;
             }
           continue;
@@ -1613,7 +1639,7 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
   /* Find the listing file name.  We do it by taking the file name of
      the URL and replacing the last component with the listing file
      name.  */
-  uf = url_file_name (u);
+  uf = url_file_name (u, NULL);
   lf = file_merge (uf, LIST_FILENAME);
   xfree (uf);
   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
@@ -1707,7 +1733,7 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
       ofile = xstrdup (u->file);
       url_set_file (u, f->name);
 
-      con->target = url_file_name (u);
+      con->target = url_file_name (u, NULL);
       err = RETROK;
 
       dlthis = true;
@@ -2126,7 +2152,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
    of URL.  Inherently, its capabilities are limited on what can be
    encoded into a URL.  */
 uerr_t
-ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy, 
+ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
           bool recursive, bool glob)
 {
   ccon con;                     /* FTP connection */
@@ -2157,7 +2183,7 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
               char *filename = (opt.output_document
                                 ? xstrdup (opt.output_document)
                                 : (con.target ? xstrdup (con.target)
-                                   : url_file_name (u)));
+                                   : url_file_name (u, NULL)));
               res = ftp_index (filename, u, f);
               if (res == FTPOK && opt.verbose)
                 {