]> sjero.net Git - wget/blobdiff - src/ftp.c
[svn] Applied Dennis Smit's --preserve-permissions patch.
[wget] / src / ftp.c
index 7e997393204a1df915b215b4a11331eae333fbcc..7e878e42c23ac88d76ef91bd94317489ca7dcb31 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -54,6 +54,7 @@ so, delete this exception statement from your version.  */
 #include "host.h"
 #include "netrc.h"
 #include "convert.h"           /* for downloaded_file */
+#include "recur.h"             /* for INFINITE_RECURSION */
 
 #ifndef errno
 extern int errno;
@@ -121,13 +122,131 @@ ftp_expected_bytes (const char *s)
   return res;
 }
 
+#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.
+ */
+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);
+
+  /* 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)
+    {
+      if (!opt.server_response)
+        logputs (LOG_VERBOSE, "==> EPSV ... ");
+      err = ftp_epsv (rbuf, addr, port);
+
+      /* If EPSV is not supported try LPSV */
+      if (err == FTPNOPASV)
+        {
+          if (!opt.server_response)
+            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);
+    }
+
+  return err;
+}
+
+/* 
+ * This function sets up an active data connection with the FTP server.
+ * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
+ */
+static uerr_t
+ftp_do_port (struct rbuf *rbuf, int *local_sock)
+{
+  uerr_t err;
+  int family;
+
+  assert (rbuf != NULL);
+  assert (rbuf_initialized_p (rbuf));
+
+  family = getfamily (rbuf->fd);
+  assert (family == AF_INET || family == AF_INET6);
+
+  /* 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)
+    {
+      if (!opt.server_response)
+        logputs (LOG_VERBOSE, "==> EPRT ... ");
+      err = ftp_eprt (rbuf, local_sock);
+
+      /* If EPRT is not supported try LPRT */
+      if (err == FTPPORTERR)
+        {
+          if (!opt.server_response)
+            logputs (LOG_VERBOSE, "==> LPRT ... ");
+          err = ftp_lprt (rbuf, local_sock);
+        }
+    }
+  else 
+    {
+      if (!opt.server_response)
+        logputs (LOG_VERBOSE, "==> PORT ... ");
+      err = ftp_port (rbuf, local_sock);
+    }
+
+  return err;
+}
+#else
+
+static uerr_t
+ftp_do_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
+{
+  if (!opt.server_response)
+    logputs (LOG_VERBOSE, "==> PASV ... ");
+  return ftp_pasv (rbuf, addr, port);
+}
+
+static uerr_t
+ftp_do_port (struct rbuf *rbuf, int *local_sock)
+{
+  if (!opt.server_response)
+    logputs (LOG_VERBOSE, "==> PORT ... ");
+  return ftp_port (rbuf, local_sock);
+}
+#endif
+
 /* Retrieves a file with denoted parameters through opening an FTP
    connection to the server.  It always closes the data connection,
    and closes the control connection in case of error.  */
 static uerr_t
 getftp (struct url *u, long *len, long restval, ccon *con)
 {
-  int csock, dtsock, res;
+  int csock, dtsock, local_sock, res;
   uerr_t err;
   FILE *fp;
   char *user, *passwd, *respline;
@@ -154,6 +273,7 @@ getftp (struct url *u, long *len, long restval, ccon *con)
   assert (user && passwd);
 
   dtsock = -1;
+  local_sock = -1;
   con->dltime = 0;
 
   if (!(cmd & DO_LOGIN))
@@ -161,8 +281,6 @@ getftp (struct url *u, long *len, long restval, ccon *con)
   else                         /* cmd & DO_LOGIN */
     {
       char type_char;
-      struct address_list *al;
-
       char    *host = con->proxy ? con->proxy->host : u->host;
       int      port = con->proxy ? con->proxy->port : u->port;
       char *logname = user;
@@ -178,15 +296,10 @@ getftp (struct url *u, long *len, long restval, ccon *con)
 
       /* First: Establish the control connection.  */
 
-      al = lookup_host (host, 0);
-      if (!al)
+      csock = connect_to_host (host, port);
+      if (csock == E_HOST)
        return HOSTERR;
-      set_connection_host_name (host);
-      csock = connect_to_many (al, port, 0);
-      set_connection_host_name (NULL);
-      address_list_release (al);
-
-      if (csock < 0)
+      else if (csock < 0)
        return CONNECT_ERROR (errno);
 
       if (cmd & LEAVE_PENDING)
@@ -214,14 +327,14 @@ getftp (struct url *u, long *len, long restval, ccon *con)
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
        case FTPSRVERR:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -229,21 +342,21 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
        case FTPLOGREFUSED:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return FTPLOGREFUSED;
          break;
        case FTPLOGINC:
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return FTPLOGINC;
          break;
@@ -267,7 +380,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -298,13 +411,13 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
        case FTPSRVERR :
          /* PWD unsupported -- assume "/". */
-         FREE_MAYBE (con->id);
+         xfree_null (con->id);
          con->id = xstrdup ("/");
          break;
        case FTPOK:
@@ -352,7 +465,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -360,7 +473,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -369,7 +482,7 @@ Error in server response, closing control connection.\n"));
          logprintf (LOG_NOTQUIET,
                     _("Unknown type `%c', closing control connection.\n"),
                     type_char);
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
        case FTPOK:
@@ -467,7 +580,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-             CLOSE (csock);
+             xclose (csock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -475,7 +588,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
-             CLOSE (csock);
+             xclose (csock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -483,7 +596,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
                         u->dir);
-             CLOSE (csock);
+             xclose (csock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -518,7 +631,7 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -538,11 +651,9 @@ Error in server response, closing control connection.\n"));
     {
       if (opt.ftp_pasv > 0)
        {
-         ip_address     passive_addr;
-         unsigned short passive_port;
-         if (!opt.server_response)
-           logputs (LOG_VERBOSE, "==> PASV ... ");
-         err = ftp_pasv (&con->rbuf, &passive_addr, &passive_port);
+         ip_address passive_addr;
+         int        passive_port;
+         err = ftp_do_pasv (&con->rbuf, &passive_addr, &passive_port);
          /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
          switch (err)
            {
@@ -550,7 +661,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-             CLOSE (csock);
+             xclose (csock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -558,7 +669,7 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
-             CLOSE (csock);
+             xclose (csock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -579,13 +690,16 @@ Error in server response, closing control connection.\n"));
            }   /* switch(err) */
          if (err==FTPOK)
            {
-             dtsock = connect_to_one (&passive_addr, passive_port, 1);
+             DEBUGP (("trying to connect to %s port %d\n", 
+                     pretty_print_address (&passive_addr),
+                     passive_port));
+             dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
              if (dtsock < 0)
                {
                  int save_errno = errno;
-                 CLOSE (csock);
+                 xclose (csock);
                  rbuf_uninitialize (&con->rbuf);
-                 logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
+                 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %hu: %s\n"),
                             pretty_print_address (&passive_addr), passive_port,
                             strerror (save_errno));
                  return CONNECT_ERROR (save_errno);
@@ -599,9 +713,7 @@ Error in server response, closing control connection.\n"));
 
       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
        {
-         if (!opt.server_response)
-           logputs (LOG_VERBOSE, "==> PORT ... ");
-         err = ftp_port (&con->rbuf);
+         err = ftp_do_port (&con->rbuf, &local_sock);
          /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
             LISTENERR), HOSTERR, FTPPORTERR */
          switch (err)
@@ -610,8 +722,9 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-             CLOSE (csock);
-             closeport (dtsock);
+             xclose (csock);
+             xclose (dtsock);
+             xclose (local_sock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -619,16 +732,18 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET,
                       _("Write failed, closing control connection.\n"));
-             CLOSE (csock);
-             closeport (dtsock);
+             xclose (csock);
+             xclose (dtsock);
+             xclose (local_sock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
            case CONSOCKERR:
              logputs (LOG_VERBOSE, "\n");
              logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
-             CLOSE (csock);
-             closeport (dtsock);
+             xclose (csock);
+             xclose (dtsock);
+             xclose (local_sock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -637,14 +752,16 @@ Error in server response, closing control connection.\n"));
              logputs (LOG_VERBOSE, "\n");
              logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
                         strerror (errno));
-             closeport (dtsock);
+             xclose (dtsock);
+             xclose (local_sock);
              return err;
              break;
            case FTPPORTERR:
              logputs (LOG_VERBOSE, "\n");
              logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
-             CLOSE (csock);
-             closeport (dtsock);
+             xclose (csock);
+             xclose (dtsock);
+             xclose (local_sock);
              rbuf_uninitialize (&con->rbuf);
              return err;
              break;
@@ -674,8 +791,9 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -683,8 +801,9 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -697,8 +816,9 @@ Error in server response, closing control connection.\n"));
              logprintf (LOG_NOTQUIET,
                         _("\nREST failed; will not truncate `%s'.\n"),
                         con->target);
-             CLOSE (csock);
-             closeport (dtsock);
+             xclose (csock);
+             xclose (dtsock);
+             xclose (local_sock);
              rbuf_uninitialize (&con->rbuf);
              return CONTNOTSUPPORTED;
            }
@@ -724,8 +844,9 @@ Error in server response, closing control connection.\n"));
         request.  */
       if (opt.spider)
        {
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return RETRFINISHED;
        }
@@ -739,6 +860,7 @@ Error in server response, closing control connection.\n"));
              logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
            }
        }
+
       err = ftp_retr (&con->rbuf, u->file);
       /* FTPRERR, WRITEFAILED, FTPNSFOD */
       switch (err)
@@ -747,8 +869,9 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -756,15 +879,17 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
        case FTPNSFOD:
          logputs (LOG_VERBOSE, "\n");
          logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
-         closeport (dtsock);
+         xclose (dtsock);
+         xclose (local_sock);
          return err;
          break;
        case FTPOK:
@@ -795,8 +920,9 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET, _("\
 Error in server response, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -804,8 +930,9 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logputs (LOG_NOTQUIET,
                   _("Write failed, closing control connection.\n"));
-         CLOSE (csock);
-         closeport (dtsock);
+         xclose (csock);
+         xclose (dtsock);
+         xclose (local_sock);
          rbuf_uninitialize (&con->rbuf);
          return err;
          break;
@@ -813,7 +940,8 @@ Error in server response, closing control connection.\n"));
          logputs (LOG_VERBOSE, "\n");
          logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
                     ".");
-         closeport (dtsock);
+         xclose (dtsock);
+         xclose (local_sock);
          return err;
          break;
        case FTPOK:
@@ -845,7 +973,7 @@ Error in server response, closing control connection.\n"));
                              to accept */
     {
       /* Open the data transmission socket by calling acceptport().  */
-      err = acceptport (&dtsock);
+      err = acceptport (local_sock, &dtsock);
       /* Possible errors: ACCEPTERR.  */
       if (err == ACCEPTERR)
        {
@@ -867,9 +995,10 @@ Error in server response, closing control connection.\n"));
       if (!fp)
        {
          logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
-         CLOSE (csock);
+         xclose (csock);
          rbuf_uninitialize (&con->rbuf);
-         closeport (dtsock);
+         xclose (dtsock);
+         xclose (local_sock);
          return FOPENERR;
        }
     }
@@ -916,7 +1045,8 @@ Error in server response, closing control connection.\n"));
   tms = time_str (NULL);
   tmrate = retr_rate (*len - restval, con->dltime, 0);
   /* Close data connection socket.  */
-  closeport (dtsock);
+  xclose (dtsock);
+  xclose (local_sock);
   /* Close the local file.  */
   {
     /* Close or flush the file.  We have to be careful to check for
@@ -930,12 +1060,13 @@ Error in server response, closing control connection.\n"));
     if (flush_res == EOF)
       res = -2;
   }
+
   /* If get_contents couldn't write to fp, bail out.  */
   if (res == -2)
     {
       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
                 con->target, strerror (errno));
-      CLOSE (csock);
+      xclose (csock);
       rbuf_uninitialize (&con->rbuf);
       return FWRITEERR;
     }
@@ -963,7 +1094,7 @@ Error in server response, closing control connection.\n"));
         return FTPRETRINT, since there is a possibility that the
         whole file was retrieved nevertheless (but that is for
         ftp_loop_internal to decide).  */
-      CLOSE (csock);
+      xclose (csock);
       rbuf_uninitialize (&con->rbuf);
       return FTPRETRINT;
     } /* err != FTPOK */
@@ -992,7 +1123,7 @@ Error in server response, closing control connection.\n"));
     {
       /* I should probably send 'QUIT' and check for a reply, but this
         is faster.  #### Is it OK, though?  */
-      CLOSE (csock);
+      xclose (csock);
       rbuf_uninitialize (&con->rbuf);
     }
   /* If it was a listing, and opt.server_response is true,
@@ -1133,7 +1264,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
 
       switch (err)
        {
-       case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
+       case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
        case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
          /* Fatal errors, give up.  */
          return err;
@@ -1173,7 +1304,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
 
       if (con->st & ON_YOUR_OWN)
        {
-         CLOSE (RBUF_FD (&con->rbuf));
+         xclose (RBUF_FD (&con->rbuf));
          rbuf_uninitialize (&con->rbuf);
        }
       if (!opt.spider)
@@ -1224,7 +1355,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
                logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
            }
        }
-      
+
       /* Restore the original leave-pendingness.  */
       if (orig_lp)
        con->cmd |= LEAVE_PENDING;
@@ -1235,7 +1366,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
 
   if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
     {
-      CLOSE (RBUF_FD (&con->rbuf));
+      xclose (RBUF_FD (&con->rbuf));
       rbuf_uninitialize (&con->rbuf);
     }
   return TRYLIMEXC;
@@ -1499,7 +1630,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));
 
@@ -1793,10 +1927,10 @@ ftp_loop (struct url *u, int *dt, struct url *proxy)
     *dt |= RETROKF;
   /* If a connection was left, quench it.  */
   if (rbuf_initialized_p (&con.rbuf))
-    CLOSE (RBUF_FD (&con.rbuf));
-  FREE_MAYBE (con.id);
+    xclose (RBUF_FD (&con.rbuf));
+  xfree_null (con.id);
   con.id = NULL;
-  FREE_MAYBE (con.target);
+  xfree_null (con.target);
   con.target = NULL;
   return res;
 }
@@ -1811,7 +1945,7 @@ delelement (struct fileinfo *f, struct fileinfo **start)
   struct fileinfo *next = f->next;
 
   xfree (f->name);
-  FREE_MAYBE (f->linkto);
+  xfree_null (f->linkto);
   xfree (f);
 
   if (next)