]> sjero.net Git - wget/blobdiff - src/ftp-basic.c
[svn] Support Windows-2000 ftp servers. By Gisle Vanem.
[wget] / src / ftp-basic.c
index 39d98fd19fe4c32f6cc0d98a6b811630b75fb7cc..350d31035d8a06b4a49c0872e3085806b4d9ccc7 100644 (file)
@@ -134,10 +134,6 @@ ftp_request (const char *command, const char *value)
   return res;
 }
 
-#ifdef USE_OPIE
-const char *calculate_skey_response PARAMS ((int, const char *, const char *));
-#endif
-
 /* Sends the USER and PASS commands to the server, to control
    connection socket csock.  */
 uerr_t
@@ -162,7 +158,7 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
   xfree (respline);
   /* Send USER username.  */
   request = ftp_request ("USER", acc);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -195,41 +191,41 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
       "331 opiekey "
     };
     int i;
+    const char *seed = NULL;
 
     for (i = 0; i < countof (skey_head); i++)
       {
-        if (strncasecmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
-          break;
+       int l = strlen (skey_head[i]);
+        if (0 == strncasecmp (skey_head[i], respline, l))
+         {
+           seed = respline + l;
+           break;
+         }
       }
-    if (i < countof (skey_head))
+    if (seed)
       {
-        const char *cp;
         int skey_sequence = 0;
 
-        for (cp = respline + strlen (skey_head[i]);
-             '0' <= *cp && *cp <= '9';
-             cp++)
-          {
-            skey_sequence = skey_sequence * 10 + *cp - '0';
-          }
-        if (*cp == ' ')
-          cp++;
+       /* Extract the sequence from SEED.  */
+       for (; ISDIGIT (*seed); seed++)
+         skey_sequence = 10 * skey_sequence + *seed - '0';
+       if (*seed == ' ')
+         ++seed;
         else
           {
-          bad:
             xfree (respline);
             return FTPLOGREFUSED;
           }
-        if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
-          goto bad;
-        pass = cp;
+       /* Replace the password with the SKEY response to the
+          challenge.  */
+        pass = skey_response (skey_sequence, seed, pass);
       }
   }
 #endif /* USE_OPIE */
   xfree (respline);
   /* Send PASS password.  */
   request = ftp_request ("PASS", pass);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -254,20 +250,20 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
 }
 
 static void
-ip_address_to_port_repr (const ip_address *addr, unsigned short port, char *buf, 
+ip_address_to_port_repr (const ip_address *addr, int port, char *buf, 
                          size_t buflen)
 {
   unsigned char *ptr;
 
   assert (addr != NULL);
-  assert (addr->type == IPv4_ADDRESS);
+  assert (addr->type == IPV4_ADDRESS);
   assert (buf != NULL);
   /* buf must contain the argument of PORT (of the form a,b,c,d,e,f). */
   assert (buflen >= 6 * 4);
 
-  ptr = (unsigned char *)(&addr->addr.ipv4.addr.s_addr);
+  ptr = ADDRESS_IPV4_DATA (addr);
   snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d", ptr[0], ptr[1],
-            ptr[2], ptr[3], (unsigned) (port & 0xff00) >> 8, port & 0xff);
+            ptr[2], ptr[3], (port & 0xff00) >> 8, port & 0xff);
   buf[buflen - 1] = '\0';
 }
 
@@ -275,13 +271,13 @@ ip_address_to_port_repr (const ip_address *addr, unsigned short port, char *buf,
    server.  Use acceptport after RETR, to get the socket of data
    connection.  */
 uerr_t
-ftp_port (struct rbuf *rbuf)
+ftp_port (struct rbuf *rbuf, int *local_sock)
 {
   uerr_t err;
   char *request, *respline;
   ip_address addr;
   int nwritten;
-  unsigned short port;
+  int port;
   /* Must contain the argument of PORT (of the form a,b,c,d,e,f). */
   char bytes[6 * 4 + 1];
 
@@ -289,16 +285,16 @@ ftp_port (struct rbuf *rbuf)
   assert (rbuf_initialized_p (rbuf));
 
   /* Get the address of this side of the connection. */
-  if (!conaddr (RBUF_FD (rbuf), &addr))
+  if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL))
     return BINDERR;
 
-  assert (addr.type == IPv4_ADDRESS);
+  assert (addr.type == IPV4_ADDRESS);
 
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
 
   /* Bind the port.  */
-  err = bindport (&addr, &port);
+  err = bindport (&addr, &port, local_sock);
   if (err != BINDOK)
     return err;
 
@@ -307,11 +303,11 @@ ftp_port (struct rbuf *rbuf)
 
   /* Send PORT request.  */
   request = ftp_request ("PORT", bytes);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
-      closeport (-1);
+      xclose (*local_sock);
       return WRITEFAILED;
     }
   xfree (request);
@@ -321,13 +317,13 @@ ftp_port (struct rbuf *rbuf)
   if (err != FTPOK)
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return err;
     }
   if (*respline != '2')
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return FTPPORTERR;
     }
   xfree (respline);
@@ -336,13 +332,13 @@ ftp_port (struct rbuf *rbuf)
 
 #ifdef ENABLE_IPV6
 static void
-ip_address_to_lprt_repr (const ip_address *addr, unsigned short port, char *buf, 
+ip_address_to_lprt_repr (const ip_address *addr, int port, char *buf, 
                          size_t buflen)
 {
   unsigned char *ptr;
 
   assert (addr != NULL);
-  assert (addr->type == IPv4_ADDRESS || addr->type == IPv6_ADDRESS);
+  assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
   assert (buf != NULL);
   /* buf must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
   assert (buflen >= 21 * 4);
@@ -350,19 +346,19 @@ ip_address_to_lprt_repr (const ip_address *addr, unsigned short port, char *buf,
   /* Construct the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
   switch (addr->type) 
     {
-      case IPv4_ADDRESS: 
-       ptr = (unsigned char *)(&addr->addr.ipv4.addr);
+      case IPV4_ADDRESS: 
+       ptr = ADDRESS_IPV4_DATA (addr);
         snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d", 4, 4, 
                   ptr[0], ptr[1], ptr[2], ptr[3], 2,
-                  (unsigned) (port & 0xff00) >> 8, port & 0xff);
+                  (port & 0xff00) >> 8, port & 0xff);
         buf[buflen - 1] = '\0';
         break;
-      case IPv6_ADDRESS: 
-       ptr = (unsigned char *)(&addr->addr.ipv6.addr);
+      case IPV6_ADDRESS: 
+       ptr = ADDRESS_IPV6_DATA (addr);
        snprintf (buf, buflen, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
                  6, 16, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], 
                  ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15], 2,
-                 (unsigned) (port & 0xff00) >> 8, port & 0xff);
+                 (port & 0xff00) >> 8, port & 0xff);
        buf[buflen - 1] = '\0';
        break;
     }
@@ -372,13 +368,13 @@ ip_address_to_lprt_repr (const ip_address *addr, unsigned short port, char *buf,
    server.  Use acceptport after RETR, to get the socket of data
    connection.  */
 uerr_t
-ftp_lprt (struct rbuf *rbuf)
+ftp_lprt (struct rbuf *rbuf, int *local_sock)
 {
   uerr_t err;
   char *request, *respline;
   ip_address addr;
   int nwritten;
-  unsigned short port;
+  int port;
   /* Must contain the argument of LPRT (of the form af,n,h1,h2,...,hn,p1,p2). */
   char bytes[21 * 4 + 1];
 
@@ -386,16 +382,16 @@ ftp_lprt (struct rbuf *rbuf)
   assert (rbuf_initialized_p (rbuf));
 
   /* Get the address of this side of the connection. */
-  if (!conaddr (RBUF_FD (rbuf), &addr))
+  if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL))
     return BINDERR;
 
-  assert (addr.type == IPv4_ADDRESS || addr.type == IPv6_ADDRESS);
+  assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
 
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
 
   /* Bind the port.  */
-  err = bindport (&addr, &port);
+  err = bindport (&addr, &port, local_sock);
   if (err != BINDOK)
     return err;
 
@@ -404,11 +400,11 @@ ftp_lprt (struct rbuf *rbuf)
 
   /* Send PORT request.  */
   request = ftp_request ("LPRT", bytes);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
-      closeport (-1);
+      xclose (*local_sock);
       return WRITEFAILED;
     }
   xfree (request);
@@ -417,13 +413,13 @@ ftp_lprt (struct rbuf *rbuf)
   if (err != FTPOK)
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return err;
     }
   if (*respline != '2')
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return FTPPORTERR;
     }
   xfree (respline);
@@ -431,13 +427,13 @@ ftp_lprt (struct rbuf *rbuf)
 }
 
 static void
-ip_address_to_eprt_repr (const ip_address *addr, unsigned short port, char *buf, 
+ip_address_to_eprt_repr (const ip_address *addr, int port, char *buf, 
                          size_t buflen)
 {
   int afnum;
 
   assert (addr != NULL);
-  assert (addr->type == IPv4_ADDRESS || addr->type == IPv6_ADDRESS);
+  assert (addr->type == IPV4_ADDRESS || addr->type == IPV6_ADDRESS);
   assert (buf != NULL);
   /* buf must contain the argument of EPRT (of the form |af|addr|port|). 
    * 4 chars for the | separators, INET6_ADDRSTRLEN chars for addr  
@@ -445,7 +441,7 @@ ip_address_to_eprt_repr (const ip_address *addr, unsigned short port, char *buf,
   assert (buflen >= 4 + INET6_ADDRSTRLEN + 1 + 5); 
 
   /* Construct the argument of EPRT (of the form |af|addr|port|). */
-  afnum = (addr->type == IPv4_ADDRESS ? 1 : 2);
+  afnum = (addr->type == IPV4_ADDRESS ? 1 : 2);
   snprintf (buf, buflen, "|%d|%s|%d|", afnum, pretty_print_address (addr), port);
   buf[buflen - 1] = '\0';
 }
@@ -454,13 +450,13 @@ ip_address_to_eprt_repr (const ip_address *addr, unsigned short port, char *buf,
    server.  Use acceptport after RETR, to get the socket of data
    connection.  */
 uerr_t
-ftp_eprt (struct rbuf *rbuf)
+ftp_eprt (struct rbuf *rbuf, int *local_sock)
 {
   uerr_t err;
   char *request, *respline;
   ip_address addr;
   int nwritten;
-  unsigned short port;
+  int port;
   /* Must contain the argument of EPRT (of the form |af|addr|port|). 
    * 4 chars for the | separators, ENABLE_IPV6_ADDRSTRLEN chars for addr  
    * 1 char for af (1-2) and 5 chars for port (0-65535) */
@@ -470,16 +466,16 @@ ftp_eprt (struct rbuf *rbuf)
   assert (rbuf_initialized_p(rbuf));
 
   /* Get the address of this side of the connection. */
-  if (!conaddr (RBUF_FD (rbuf), &addr))
+  if (!socket_ip_address (RBUF_FD (rbuf), &addr, ENDPOINT_LOCAL))
     return BINDERR;
 
-  assert (addr.type == IPv4_ADDRESS || addr.type == IPv6_ADDRESS);
+  assert (addr.type == IPV4_ADDRESS || addr.type == IPV6_ADDRESS);
 
   /* Setting port to 0 lets the system choose a free port.  */
   port = 0;
 
   /* Bind the port.  */
-  err = bindport (&addr, &port);
+  err = bindport (&addr, &port, local_sock);
   if (err != BINDOK)
     return err;
 
@@ -488,11 +484,11 @@ ftp_eprt (struct rbuf *rbuf)
 
   /* Send PORT request.  */
   request = ftp_request ("EPRT", bytes);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
-      closeport (-1);
+      xclose (*local_sock);
       return WRITEFAILED;
     }
   xfree (request);
@@ -501,13 +497,13 @@ ftp_eprt (struct rbuf *rbuf)
   if (err != FTPOK)
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return err;
     }
   if (*respline != '2')
     {
       xfree (respline);
-      closeport (-1);
+      xclose (*local_sock);
       return FTPPORTERR;
     }
   xfree (respline);
@@ -519,7 +515,7 @@ ftp_eprt (struct rbuf *rbuf)
    transfer.  Reads the response from server and parses it.  Reads the
    host and port addresses and returns them.  */
 uerr_t
-ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
+ftp_pasv (struct rbuf *rbuf, ip_address *addr, int *port)
 {
   char *request, *respline, *s;
   int nwritten, i;
@@ -527,7 +523,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
   unsigned char tmp[6];
 
   assert (rbuf != NULL);
-  assert (rbuf_initialized_p(rbuf));
+  assert (rbuf_initialized_p (rbuf));
   assert (addr != NULL);
   assert (port != NULL);
 
@@ -536,7 +532,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
   /* Form the request.  */
   request = ftp_request ("PASV", NULL);
   /* And send it.  */
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -576,9 +572,8 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
     }
   xfree (respline);
 
-  addr->type = IPv4_ADDRESS;
-  /* Mauro Tortonesi: is this safe and/or elegant enough? */
-  memcpy (&addr->addr.ipv4.addr, tmp, 4);
+  addr->type = IPV4_ADDRESS;
+  memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
   *port = ((tmp[4] << 8) & 0xff00) + tmp[5];
 
   return FTPOK;
@@ -589,7 +584,7 @@ ftp_pasv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
    transfer.  Reads the response from server and parses it.  Reads the
    host and port addresses and returns them.  */
 uerr_t
-ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
+ftp_lpsv (struct rbuf *rbuf, ip_address *addr, int *port)
 {
   char *request, *respline, *s;
   int nwritten, i, af, addrlen, portlen;
@@ -608,7 +603,7 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
   request = ftp_request ("LPSV", NULL);
 
   /* And send it.  */
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -727,8 +722,8 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
 
   if (af == 4)
     {
-      addr->type = IPv4_ADDRESS;
-      memcpy (&addr->addr.ipv4.addr, tmp, 4);
+      addr->type = IPV4_ADDRESS;
+      memcpy (ADDRESS_IPV4_DATA (addr), tmp, 4);
       *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
       DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
       DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@@ -738,8 +733,8 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
   else
     {
       assert (af == 6);
-      addr->type = IPv6_ADDRESS;
-      memcpy (&addr->addr.ipv6.addr, tmp, 16);
+      addr->type = IPV6_ADDRESS;
+      memcpy (ADDRESS_IPV6_DATA (addr), tmp, 16);
       *port = ((tmpprt[0] << 8) & 0xff00) + tmpprt[1];
       DEBUGP (("lpsv addr is: %s\n", pretty_print_address(addr)));
       DEBUGP (("tmpprt[0] is: %d\n", tmpprt[0]));
@@ -755,36 +750,27 @@ ftp_lpsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
    transfer.  Reads the response from server and parses it.  Reads the
    host and port addresses and returns them.  */
 uerr_t
-ftp_epsv (struct rbuf *rbuf, ip_address *addr, unsigned short *port)
+ftp_epsv (struct rbuf *rbuf, ip_address *ip, int *port)
 {
   char *request, *respline, *start, delim, *s;
   int nwritten, i;
   uerr_t err;
-  unsigned short tport;
-  socklen_t addrlen;
-  struct sockaddr_storage ss;
-  struct sockaddr *sa = (struct sockaddr *)&ss;
+  int tport;
 
   assert (rbuf != NULL);
   assert (rbuf_initialized_p(rbuf));
-  assert (addr != NULL);
+  assert (ip != NULL);
   assert (port != NULL);
 
-  addrlen = sizeof (ss);
-  if (getpeername (rbuf->fd, sa, &addrlen) < 0)
-    /* Mauro Tortonesi: HOW DO WE HANDLE THIS ERROR? */
-    return CONPORTERR;
-
-  assert (sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
-
-  sockaddr_get_address (sa, NULL, addr);
+  /* IP already contains the IP address of the control connection's
+     peer, so we don't need to call socket_ip_address here.  */
 
   /* Form the request.  */
   /* EPSV 1 means that we ask for IPv4 and EPSV 2 means that we ask for IPv6. */
-  request = ftp_request ("EPSV", (sa->sa_family == AF_INET ? "1" : "2"));
+  request = ftp_request ("EPSV", (ip->type == IPV4_ADDRESS ? "1" : "2"));
 
   /* And send it.  */
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -884,7 +870,7 @@ ftp_type (struct rbuf *rbuf, int type)
   stype[1] = 0;
   /* Send TYPE request.  */
   request = ftp_request ("TYPE", stype);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -919,7 +905,7 @@ ftp_cwd (struct rbuf *rbuf, const char *dir)
 
   /* Send CWD request.  */
   request = ftp_request ("CWD", dir);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -959,7 +945,7 @@ ftp_rest (struct rbuf *rbuf, long offset)
 
   number_to_string (numbuf, offset);
   request = ftp_request ("REST", numbuf);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -993,7 +979,7 @@ ftp_retr (struct rbuf *rbuf, const char *file)
 
   /* Send RETR request.  */
   request = ftp_request ("RETR", file);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -1033,7 +1019,7 @@ ftp_list (struct rbuf *rbuf, const char *file)
 
   /* Send LIST request.  */
   request = ftp_request ("LIST", file);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -1072,7 +1058,7 @@ ftp_syst (struct rbuf *rbuf, enum stype *server_type)
 
   /* Send SYST request.  */
   request = ftp_request ("SYST", NULL);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -1104,7 +1090,8 @@ ftp_syst (struct rbuf *rbuf, enum stype *server_type)
     *server_type = ST_VMS;
   else if (!strcasecmp (request, "UNIX"))
     *server_type = ST_UNIX;
-  else if (!strcasecmp (request, "WINDOWS_NT"))
+  else if (!strcasecmp (request, "WINDOWS_NT")
+          || !strcasecmp (request, "WINDOWS2000"))
     *server_type = ST_WINNT;
   else if (!strcasecmp (request, "MACOS"))
     *server_type = ST_MACOS;
@@ -1128,7 +1115,7 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
 
   /* Send PWD request.  */
   request = ftp_request ("PWD", NULL);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);
@@ -1154,7 +1141,7 @@ ftp_pwd (struct rbuf *rbuf, char **pwd)
   request = strtok (NULL, "\"");
 
   /* Has the `pwd' been already allocated?  Free! */
-  FREE_MAYBE (*pwd);
+  xfree_null (*pwd);
 
   *pwd = xstrdup (request);
 
@@ -1174,7 +1161,7 @@ ftp_size (struct rbuf *rbuf, const char *file, long int *size)
 
   /* Send PWD request.  */
   request = ftp_request ("SIZE", file);
-  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  nwritten = xwrite (RBUF_FD (rbuf), request, strlen (request), -1);
   if (nwritten < 0)
     {
       xfree (request);