]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] Rewrote bindport and acceptport to use a more standard calling convention.
[wget] / src / ftp.c
index 87bd8668a707b40f199e13ff1119c737c8c1841d..21b023c2e8e66c6f979517845630aa62de799063 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -123,22 +123,6 @@ ftp_expected_bytes (const char *s)
 }
 
 #ifdef ENABLE_IPV6
-static int
-getfamily (int fd)
-{
-  struct sockaddr_storage ss;
-  struct sockaddr *sa = (struct sockaddr *)&ss;
-  socklen_t len = sizeof (ss);
-
-  assert (fd >= 0);
-
-  if (getpeername (fd, sa, &len) < 0)
-    /* Mauro Tortonesi: HOW DO WE HANDLE THIS ERROR? */
-    abort ();
-
-  return sa->sa_family;
-}
-
 /* 
  * This function sets up a passive data connection with the FTP server.
  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
@@ -147,16 +131,24 @@ static uerr_t
 ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
 {
   uerr_t err;
-  int family;
 
-  family = getfamily (rbuf->fd);
-  assert (family == AF_INET || family == AF_INET6);
+  /* We need to determine the address family and need to call
+     getpeername, so while we're at it, store the address to ADDR.
+     ftp_pasv and ftp_lpsv can simply override it.  */
+  if (!socket_ip_address (RBUF_FD (rbuf), addr, ENDPOINT_PEER))
+    abort ();
 
   /* If our control connection is over IPv6, then we first try EPSV and then 
    * LPSV if the former is not supported. If the control connection is over 
    * IPv4, we simply issue the good old PASV request. */
-  if (family == AF_INET6)
+  switch (addr->type)
     {
+    case IPV4_ADDRESS:
+      if (!opt.server_response)
+        logputs (LOG_VERBOSE, "==> PASV ... ");
+      err = ftp_pasv (rbuf, addr, port);
+      break;
+    case IPV6_ADDRESS:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> EPSV ... ");
       err = ftp_epsv (rbuf, addr, port);
@@ -168,12 +160,9 @@ ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
             logputs (LOG_VERBOSE, "==> LPSV ... ");
           err = ftp_lpsv (rbuf, addr, port);
         }
-    }
-  else 
-    {
-      if (!opt.server_response)
-        logputs (LOG_VERBOSE, "==> PASV ... ");
-      err = ftp_pasv (rbuf, addr, port);
+      break;
+    default:
+      abort ();
     }
 
   return err;
@@ -187,19 +176,25 @@ static uerr_t
 ftp_do_port (struct rbuf *rbuf, int *local_sock)
 {
   uerr_t err;
-  int family;
+  ip_address cip;
 
   assert (rbuf != NULL);
   assert (rbuf_initialized_p (rbuf));
 
-  family = getfamily (rbuf->fd);
-  assert (family == AF_INET || family == AF_INET6);
+  if (!socket_ip_address (RBUF_FD (rbuf), &cip, ENDPOINT_PEER))
+    abort ();
 
   /* If our control connection is over IPv6, then we first try EPRT and then 
    * LPRT if the former is not supported. If the control connection is over 
    * IPv4, we simply issue the good old PORT request. */
-  if (family == AF_INET6)
+  switch (cip.type)
     {
+    case IPV4_ADDRESS:
+      if (!opt.server_response)
+        logputs (LOG_VERBOSE, "==> PORT ... ");
+      err = ftp_port (rbuf, local_sock);
+      break;
+    case IPV6_ADDRESS:
       if (!opt.server_response)
         logputs (LOG_VERBOSE, "==> EPRT ... ");
       err = ftp_eprt (rbuf, local_sock);
@@ -211,14 +206,10 @@ ftp_do_port (struct rbuf *rbuf, int *local_sock)
             logputs (LOG_VERBOSE, "==> LPRT ... ");
           err = ftp_lprt (rbuf, local_sock);
         }
+      break;
+    default:
+      abort ();
     }
-  else 
-    {
-      if (!opt.server_response)
-        logputs (LOG_VERBOSE, "==> PORT ... ");
-      err = ftp_port (rbuf, local_sock);
-    }
-
   return err;
 }
 #else
@@ -714,8 +705,8 @@ Error in server response, closing control connection.\n"));
       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
        {
          err = ftp_do_port (&con->rbuf, &local_sock);
-         /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
-            LISTENERR), HOSTERR, FTPPORTERR */
+         /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
+            FTPPORTERR */
          switch (err)
            {
            case FTPRERR:
@@ -747,13 +738,11 @@ Error in server response, closing control connection.\n"));
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
-           case CONPORTERR: case BINDERR: case LISTENERR:
-             /* What now?  These problems are local...  */
+           case FTPSYSERR:
              logputs (LOG_VERBOSE, "\n");
              logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
                         strerror (errno));
              xclose (dtsock);
-             xclose (local_sock);
              return err;
              break;
            case FTPPORTERR:
@@ -972,10 +961,10 @@ Error in server response, closing control connection.\n"));
   if (!pasv_mode_open)  /* we are not using pasive mode so we need
                              to accept */
     {
-      /* Open the data transmission socket by calling acceptport().  */
-      err = acceptport (local_sock, &dtsock);
-      /* Possible errors: ACCEPTERR.  */
-      if (err == ACCEPTERR)
+      /* Wait for the server to connect to the address we're waiting
+        at.  */
+      dtsock = accept_connection (local_sock);
+      if (dtsock < 0)
        {
          logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
          return err;
@@ -1270,8 +1259,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
          return err;
          break;
        case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
-       case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
-       case BINDERR: case LISTENERR: case ACCEPTERR:
+       case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
        case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
          printwhat (count, opt.ntry);
          /* non-fatal errors */
@@ -1630,7 +1618,10 @@ Already have correct symlink %s -> %s\n\n"),
        logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
 
       if (f->perms && f->type == FT_PLAINFILE && dlthis)
-       chmod (con->target, f->perms);
+        {
+         if (opt.preserve_perm)
+           chmod (con->target, f->perms);
+        }
       else
        DEBUGP (("Unrecognized permissions for %s.\n", con->target));