]> sjero.net Git - wget/blob - src/ftp.c
Automated merge.
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3    2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #ifdef HAVE_UNISTD_H
37 # include <unistd.h>
38 #endif
39 #include <assert.h>
40 #include <errno.h>
41 #include <time.h>
42
43 #include "utils.h"
44 #include "url.h"
45 #include "retr.h"
46 #include "ftp.h"
47 #include "connect.h"
48 #include "host.h"
49 #include "netrc.h"
50 #include "convert.h"            /* for downloaded_file */
51 #include "recur.h"              /* for INFINITE_RECURSION */
52
53 /* File where the "ls -al" listing will be saved.  */
54 #ifdef MSDOS
55 #define LIST_FILENAME "_listing"
56 #else
57 #define LIST_FILENAME ".listing"
58 #endif
59
60 typedef struct
61 {
62   int st;                       /* connection status */
63   int cmd;                      /* command code */
64   int csock;                    /* control connection socket */
65   double dltime;                /* time of the download in msecs */
66   enum stype rs;                /* remote system reported by ftp server */ 
67   char *id;                     /* initial directory */
68   char *target;                 /* target file name */
69   struct url *proxy;            /* FTWK-style proxy */
70 } ccon;
71
72 extern int numurls;
73
74 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
75    the string S, and return the number converted to wgint, if found, 0
76    otherwise.  */
77 static wgint
78 ftp_expected_bytes (const char *s)
79 {
80   wgint res;
81
82   while (1)
83     {
84       while (*s && *s != '(')
85         ++s;
86       if (!*s)
87         return 0;
88       ++s;                      /* skip the '(' */
89       res = str_to_wgint (s, (char **) &s, 10);
90       if (!*s)
91         return 0;
92       while (*s && c_isspace (*s))
93         ++s;
94       if (!*s)
95         return 0;
96       if (c_tolower (*s) != 'b')
97         continue;
98       if (strncasecmp (s, "byte", 4))
99         continue;
100       else
101         break;
102     }
103   return res;
104 }
105
106 #ifdef ENABLE_IPV6
107 /* 
108  * This function sets up a passive data connection with the FTP server.
109  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
110  */
111 static uerr_t
112 ftp_do_pasv (int csock, ip_address *addr, int *port)
113 {
114   uerr_t err;
115
116   /* We need to determine the address family and need to call
117      getpeername, so while we're at it, store the address to ADDR.
118      ftp_pasv and ftp_lpsv can simply override it.  */
119   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
120     abort ();
121
122   /* If our control connection is over IPv6, then we first try EPSV and then 
123    * LPSV if the former is not supported. If the control connection is over 
124    * IPv4, we simply issue the good old PASV request. */
125   switch (addr->family)
126     {
127     case AF_INET:
128       if (!opt.server_response)
129         logputs (LOG_VERBOSE, "==> PASV ... ");
130       err = ftp_pasv (csock, addr, port);
131       break;
132     case AF_INET6:
133       if (!opt.server_response)
134         logputs (LOG_VERBOSE, "==> EPSV ... ");
135       err = ftp_epsv (csock, addr, port);
136
137       /* If EPSV is not supported try LPSV */
138       if (err == FTPNOPASV)
139         {
140           if (!opt.server_response)
141             logputs (LOG_VERBOSE, "==> LPSV ... ");
142           err = ftp_lpsv (csock, addr, port);
143         }
144       break;
145     default:
146       abort ();
147     }
148
149   return err;
150 }
151
152 /* 
153  * This function sets up an active data connection with the FTP server.
154  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
155  */
156 static uerr_t
157 ftp_do_port (int csock, int *local_sock)
158 {
159   uerr_t err;
160   ip_address cip;
161
162   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
163     abort ();
164
165   /* If our control connection is over IPv6, then we first try EPRT and then 
166    * LPRT if the former is not supported. If the control connection is over 
167    * IPv4, we simply issue the good old PORT request. */
168   switch (cip.family)
169     {
170     case AF_INET:
171       if (!opt.server_response)
172         logputs (LOG_VERBOSE, "==> PORT ... ");
173       err = ftp_port (csock, local_sock);
174       break;
175     case AF_INET6:
176       if (!opt.server_response)
177         logputs (LOG_VERBOSE, "==> EPRT ... ");
178       err = ftp_eprt (csock, local_sock);
179
180       /* If EPRT is not supported try LPRT */
181       if (err == FTPPORTERR)
182         {
183           if (!opt.server_response)
184             logputs (LOG_VERBOSE, "==> LPRT ... ");
185           err = ftp_lprt (csock, local_sock);
186         }
187       break;
188     default:
189       abort ();
190     }
191   return err;
192 }
193 #else
194
195 static uerr_t
196 ftp_do_pasv (int csock, ip_address *addr, int *port)
197 {
198   if (!opt.server_response)
199     logputs (LOG_VERBOSE, "==> PASV ... ");
200   return ftp_pasv (csock, addr, port);
201 }
202
203 static uerr_t
204 ftp_do_port (int csock, int *local_sock)
205 {
206   if (!opt.server_response)
207     logputs (LOG_VERBOSE, "==> PORT ... ");
208   return ftp_port (csock, local_sock);
209 }
210 #endif
211
212 static void
213 print_length (wgint size, wgint start, bool authoritative)
214 {
215   logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
216   if (size >= 1024)
217     logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
218   if (start > 0)
219     {
220       if (size - start >= 1024)
221         logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
222                    number_to_static_string (size - start),
223                    human_readable (size - start));
224       else
225         logprintf (LOG_VERBOSE, _(", %s remaining"),
226                    number_to_static_string (size - start));
227     }
228   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
229 }
230
231 static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
232
233 /* Retrieves a file with denoted parameters through opening an FTP
234    connection to the server.  It always closes the data connection,
235    and closes the control connection in case of error.  */
236 static uerr_t
237 getftp (struct url *u, wgint *len, wgint restval, ccon *con)
238 {
239   int csock, dtsock, local_sock, res;
240   uerr_t err = RETROK;          /* appease the compiler */
241   FILE *fp;
242   char *user, *passwd, *respline;
243   char *tms;
244   const char *tmrate;
245   int cmd = con->cmd;
246   bool pasv_mode_open = false;
247   wgint expected_bytes = 0;
248   bool rest_failed = false;
249   int flags;
250   wgint rd_size;
251
252   assert (con != NULL);
253   assert (con->target != NULL);
254
255   /* Debug-check of the sanity of the request by making sure that LIST
256      and RETR are never both requested (since we can handle only one
257      at a time.  */
258   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
259   /* Make sure that at least *something* is requested.  */
260   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
261
262   user = u->user;
263   passwd = u->passwd;
264   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
265   user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
266   if (!user) user = "anonymous";
267   passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
268   if (!passwd) passwd = "-wget@";
269
270   dtsock = -1;
271   local_sock = -1;
272   con->dltime = 0;
273
274   if (!(cmd & DO_LOGIN))
275     csock = con->csock;
276   else                          /* cmd & DO_LOGIN */
277     {
278       char type_char;
279       char    *host = con->proxy ? con->proxy->host : u->host;
280       int      port = con->proxy ? con->proxy->port : u->port;
281       char *logname = user;
282
283       if (con->proxy)
284         {
285           /* If proxy is in use, log in as username@target-site. */
286           logname = concat_strings (user, "@", u->host, (char *) 0);
287         }
288
289       /* Login to the server: */
290
291       /* First: Establish the control connection.  */
292
293       csock = connect_to_host (host, port);
294       if (csock == E_HOST)
295         return HOSTERR;
296       else if (csock < 0)
297         return (retryable_socket_connect_error (errno)
298                 ? CONERROR : CONIMPOSSIBLE);
299
300       if (cmd & LEAVE_PENDING)
301         con->csock = csock;
302       else
303         con->csock = -1;
304
305       /* Second: Login with proper USER/PASS sequence.  */
306       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), 
307                  quotearg_style (escape_quoting_style, user));
308       if (opt.server_response)
309         logputs (LOG_ALWAYS, "\n");
310       err = ftp_login (csock, logname, passwd);
311
312       if (con->proxy)
313         xfree (logname);
314
315       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
316       switch (err)
317         {
318         case FTPRERR:
319           logputs (LOG_VERBOSE, "\n");
320           logputs (LOG_NOTQUIET, _("\
321 Error in server response, closing control connection.\n"));
322           fd_close (csock);
323           con->csock = -1;
324           return err;
325         case FTPSRVERR:
326           logputs (LOG_VERBOSE, "\n");
327           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
328           fd_close (csock);
329           con->csock = -1;
330           return err;
331         case WRITEFAILED:
332           logputs (LOG_VERBOSE, "\n");
333           logputs (LOG_NOTQUIET,
334                    _("Write failed, closing control connection.\n"));
335           fd_close (csock);
336           con->csock = -1;
337           return err;
338         case FTPLOGREFUSED:
339           logputs (LOG_VERBOSE, "\n");
340           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
341           fd_close (csock);
342           con->csock = -1;
343           return FTPLOGREFUSED;
344         case FTPLOGINC:
345           logputs (LOG_VERBOSE, "\n");
346           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
347           fd_close (csock);
348           con->csock = -1;
349           return FTPLOGINC;
350         case FTPOK:
351           if (!opt.server_response)
352             logputs (LOG_VERBOSE, _("Logged in!\n"));
353           break;
354         default:
355           abort ();
356         }
357       /* Third: Get the system type */
358       if (!opt.server_response)
359         logprintf (LOG_VERBOSE, "==> SYST ... ");
360       err = ftp_syst (csock, &con->rs);
361       /* FTPRERR */
362       switch (err)
363         {
364         case FTPRERR:
365           logputs (LOG_VERBOSE, "\n");
366           logputs (LOG_NOTQUIET, _("\
367 Error in server response, closing control connection.\n"));
368           fd_close (csock);
369           con->csock = -1;
370           return err;
371         case FTPSRVERR:
372           logputs (LOG_VERBOSE, "\n");
373           logputs (LOG_NOTQUIET,
374                    _("Server error, can't determine system type.\n"));
375           break;
376         case FTPOK:
377           /* Everything is OK.  */
378           break;
379         default:
380           abort ();
381         }
382       if (!opt.server_response && err != FTPSRVERR)
383         logputs (LOG_VERBOSE, _("done.    "));
384
385       /* Fourth: Find the initial ftp directory */
386
387       if (!opt.server_response)
388         logprintf (LOG_VERBOSE, "==> PWD ... ");
389       err = ftp_pwd (csock, &con->id);
390       /* FTPRERR */
391       switch (err)
392         {
393         case FTPRERR:
394           logputs (LOG_VERBOSE, "\n");
395           logputs (LOG_NOTQUIET, _("\
396 Error in server response, closing control connection.\n"));
397           fd_close (csock);
398           con->csock = -1;
399           return err;
400         case FTPSRVERR :
401           /* PWD unsupported -- assume "/". */
402           xfree_null (con->id);
403           con->id = xstrdup ("/");
404           break;
405         case FTPOK:
406           /* Everything is OK.  */
407           break;
408         default:
409           abort ();
410         }
411       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
412          Convert it to "/INITIAL/FOLDER" */ 
413       if (con->rs == ST_VMS)
414         {
415           char *path = strchr (con->id, '[');
416           char *pathend = path ? strchr (path + 1, ']') : NULL;
417           if (!path || !pathend)
418             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
419           else
420             {
421               char *idir = con->id;
422               DEBUGP (("Preprocessing the initial VMS directory\n"));
423               DEBUGP (("  old = '%s'\n", con->id));
424               /* We do the conversion in-place by copying the stuff
425                  between [ and ] to the beginning, and changing dots
426                  to slashes at the same time.  */
427               *idir++ = '/';
428               for (++path; path < pathend; path++, idir++)
429                 *idir = *path == '.' ? '/' : *path;
430               *idir = '\0';
431               DEBUGP (("  new = '%s'\n\n", con->id));
432             }
433         }
434       if (!opt.server_response)
435         logputs (LOG_VERBOSE, _("done.\n"));
436
437       /* Fifth: Set the FTP type.  */
438       type_char = ftp_process_type (u->params);
439       if (!opt.server_response)
440         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
441       err = ftp_type (csock, type_char);
442       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
443       switch (err)
444         {
445         case FTPRERR:
446           logputs (LOG_VERBOSE, "\n");
447           logputs (LOG_NOTQUIET, _("\
448 Error in server response, closing control connection.\n"));
449           fd_close (csock);
450           con->csock = -1;
451           return err;
452         case WRITEFAILED:
453           logputs (LOG_VERBOSE, "\n");
454           logputs (LOG_NOTQUIET,
455                    _("Write failed, closing control connection.\n"));
456           fd_close (csock);
457           con->csock = -1;
458           return err;
459         case FTPUNKNOWNTYPE:
460           logputs (LOG_VERBOSE, "\n");
461           logprintf (LOG_NOTQUIET,
462                      _("Unknown type `%c', closing control connection.\n"),
463                      type_char);
464           fd_close (csock);
465           con->csock = -1;
466           return err;
467         case FTPOK:
468           /* Everything is OK.  */
469           break;
470         default:
471           abort ();
472         }
473       if (!opt.server_response)
474         logputs (LOG_VERBOSE, _("done.  "));
475     } /* do login */
476
477   if (cmd & DO_CWD)
478     {
479       if (!*u->dir)
480         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
481       else
482         {
483           char *target = u->dir;
484
485           DEBUGP (("changing working directory\n"));
486
487           /* Change working directory.  To change to a non-absolute
488              Unix directory, we need to prepend initial directory
489              (con->id) to it.  Absolute directories "just work".
490
491              A relative directory is one that does not begin with '/'
492              and, on non-Unix OS'es, one that doesn't begin with
493              "[a-z]:".
494
495              This is not done for OS400, which doesn't use
496              "/"-delimited directories, nor does it support directory
497              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
498              in "bar", not in "foo/bar", as would be customary
499              elsewhere.  */
500
501           if (target[0] != '/'
502               && !(con->rs != ST_UNIX
503                    && c_isalpha (target[0])
504                    && target[1] == ':')
505               && con->rs != ST_OS400)
506             {
507               int idlen = strlen (con->id);
508               char *ntarget, *p;
509
510               /* Strip trailing slash(es) from con->id. */
511               while (idlen > 0 && con->id[idlen - 1] == '/')
512                 --idlen;
513               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
514               memcpy (p, con->id, idlen);
515               p += idlen;
516               *p++ = '/';
517               strcpy (p, target);
518
519               DEBUGP (("Prepended initial PWD to relative path:\n"));
520               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
521                        con->id, target, ntarget));
522               target = ntarget;
523             }
524
525           /* If the FTP host runs VMS, we will have to convert the absolute
526              directory path in UNIX notation to absolute directory path in
527              VMS notation as VMS FTP servers do not like UNIX notation of
528              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
529
530           if (con->rs == ST_VMS)
531             {
532               char *tmpp;
533               char *ntarget = (char *)alloca (strlen (target) + 2);
534               /* We use a converted initial dir, so directories in
535                  TARGET will be separated with slashes, something like
536                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
537                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
538               strcpy (ntarget, target);
539               assert (*ntarget == '/');
540               *ntarget = '[';
541               for (tmpp = ntarget + 1; *tmpp; tmpp++)
542                 if (*tmpp == '/')
543                   *tmpp = '.';
544               *tmpp++ = ']';
545               *tmpp = '\0';
546               DEBUGP (("Changed file name to VMS syntax:\n"));
547               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
548               target = ntarget;
549             }
550
551           if (!opt.server_response)
552             logprintf (LOG_VERBOSE, "==> CWD %s ... ", 
553                        quotearg_style (escape_quoting_style, target));
554           err = ftp_cwd (csock, target);
555           /* FTPRERR, WRITEFAILED, FTPNSFOD */
556           switch (err)
557             {
558             case FTPRERR:
559               logputs (LOG_VERBOSE, "\n");
560               logputs (LOG_NOTQUIET, _("\
561 Error in server response, closing control connection.\n"));
562               fd_close (csock);
563               con->csock = -1;
564               return err;
565             case WRITEFAILED:
566               logputs (LOG_VERBOSE, "\n");
567               logputs (LOG_NOTQUIET,
568                        _("Write failed, closing control connection.\n"));
569               fd_close (csock);
570               con->csock = -1;
571               return err;
572             case FTPNSFOD:
573               logputs (LOG_VERBOSE, "\n");
574               logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
575                          quote (u->dir));
576               fd_close (csock);
577               con->csock = -1;
578               return err;
579             case FTPOK:
580               break;
581             default:
582               abort ();
583             }
584           if (!opt.server_response)
585             logputs (LOG_VERBOSE, _("done.\n"));
586         }
587     }
588   else /* do not CWD */
589     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
590
591   if ((cmd & DO_RETR) && *len == 0)
592     {
593       if (opt.verbose)
594         {
595           if (!opt.server_response)
596             logprintf (LOG_VERBOSE, "==> SIZE %s ... ", 
597                        quotearg_style (escape_quoting_style, u->file));
598         }
599
600       err = ftp_size (csock, u->file, len);
601       /* FTPRERR */
602       switch (err)
603         {
604         case FTPRERR:
605         case FTPSRVERR:
606           logputs (LOG_VERBOSE, "\n");
607           logputs (LOG_NOTQUIET, _("\
608 Error in server response, closing control connection.\n"));
609           fd_close (csock);
610           con->csock = -1;
611           return err;
612         case FTPOK:
613           /* Everything is OK.  */
614           break;
615         default:
616           abort ();
617         }
618         if (!opt.server_response)
619           logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
620                      number_to_static_string (*len));
621     }
622
623   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
624   if (cmd & (DO_LIST | DO_RETR))
625     {
626       if (opt.ftp_pasv)
627         {
628           ip_address passive_addr;
629           int        passive_port;
630           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
631           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
632           switch (err)
633             {
634             case FTPRERR:
635               logputs (LOG_VERBOSE, "\n");
636               logputs (LOG_NOTQUIET, _("\
637 Error in server response, closing control connection.\n"));
638               fd_close (csock);
639               con->csock = -1;
640               return err;
641             case WRITEFAILED:
642               logputs (LOG_VERBOSE, "\n");
643               logputs (LOG_NOTQUIET,
644                        _("Write failed, closing control connection.\n"));
645               fd_close (csock);
646               con->csock = -1;
647               return err;
648             case FTPNOPASV:
649               logputs (LOG_VERBOSE, "\n");
650               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
651               break;
652             case FTPINVPASV:
653               logputs (LOG_VERBOSE, "\n");
654               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
655               break;
656             case FTPOK:
657               break;
658             default:
659               abort ();
660             }   /* switch (err) */
661           if (err==FTPOK)
662             {
663               DEBUGP (("trying to connect to %s port %d\n", 
664                       print_address (&passive_addr), passive_port));
665               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
666               if (dtsock < 0)
667                 {
668                   int save_errno = errno;
669                   fd_close (csock);
670                   con->csock = -1;
671                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
672                              print_address (&passive_addr), passive_port,
673                              strerror (save_errno));
674                   return (retryable_socket_connect_error (save_errno)
675                           ? CONERROR : CONIMPOSSIBLE);
676                 }
677
678               pasv_mode_open = true;  /* Flag to avoid accept port */
679               if (!opt.server_response)
680                 logputs (LOG_VERBOSE, _("done.    "));
681             } /* err==FTP_OK */
682         }
683
684       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
685         {
686           err = ftp_do_port (csock, &local_sock);
687           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
688              FTPPORTERR */
689           switch (err)
690             {
691             case FTPRERR:
692               logputs (LOG_VERBOSE, "\n");
693               logputs (LOG_NOTQUIET, _("\
694 Error in server response, closing control connection.\n"));
695               fd_close (csock);
696               con->csock = -1;
697               fd_close (dtsock);
698               fd_close (local_sock);
699               return err;
700             case WRITEFAILED:
701               logputs (LOG_VERBOSE, "\n");
702               logputs (LOG_NOTQUIET,
703                        _("Write failed, closing control connection.\n"));
704               fd_close (csock);
705               con->csock = -1;
706               fd_close (dtsock);
707               fd_close (local_sock);
708               return err;
709             case CONSOCKERR:
710               logputs (LOG_VERBOSE, "\n");
711               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
712               fd_close (csock);
713               con->csock = -1;
714               fd_close (dtsock);
715               fd_close (local_sock);
716               return err;
717             case FTPSYSERR:
718               logputs (LOG_VERBOSE, "\n");
719               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
720                          strerror (errno));
721               fd_close (dtsock);
722               return err;
723             case FTPPORTERR:
724               logputs (LOG_VERBOSE, "\n");
725               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
726               fd_close (csock);
727               con->csock = -1;
728               fd_close (dtsock);
729               fd_close (local_sock);
730               return err;
731             case FTPOK:
732               break;
733             default:
734               abort ();
735             } /* port switch */
736           if (!opt.server_response)
737             logputs (LOG_VERBOSE, _("done.    "));
738         } /* dtsock == -1 */
739     } /* cmd & (DO_LIST | DO_RETR) */
740
741   /* Restart if needed.  */
742   if (restval && (cmd & DO_RETR))
743     {
744       if (!opt.server_response)
745         logprintf (LOG_VERBOSE, "==> REST %s ... ",
746                    number_to_static_string (restval));
747       err = ftp_rest (csock, restval);
748
749       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
750       switch (err)
751         {
752         case FTPRERR:
753           logputs (LOG_VERBOSE, "\n");
754           logputs (LOG_NOTQUIET, _("\
755 Error in server response, closing control connection.\n"));
756           fd_close (csock);
757           con->csock = -1;
758           fd_close (dtsock);
759           fd_close (local_sock);
760           return err;
761         case WRITEFAILED:
762           logputs (LOG_VERBOSE, "\n");
763           logputs (LOG_NOTQUIET,
764                    _("Write failed, closing control connection.\n"));
765           fd_close (csock);
766           con->csock = -1;
767           fd_close (dtsock);
768           fd_close (local_sock);
769           return err;
770         case FTPRESTFAIL:
771           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
772           rest_failed = true;
773           break;
774         case FTPOK:
775           break;
776         default:
777           abort ();
778         }
779       if (err != FTPRESTFAIL && !opt.server_response)
780         logputs (LOG_VERBOSE, _("done.    "));
781     } /* restval && cmd & DO_RETR */
782
783   if (cmd & DO_RETR)
784     {
785       /* If we're in spider mode, don't really retrieve anything except
786          the directory listing and verify whether the given "file" exists.  */
787       if (opt.spider)
788         {
789           bool exists = false;
790           uerr_t res;
791           struct fileinfo *f;
792           res = ftp_get_listing (u, con, &f);
793           /* Set the DO_RETR command flag again, because it gets unset when 
794              calling ftp_get_listing() and would otherwise cause an assertion 
795              failure earlier on when this function gets repeatedly called 
796              (e.g., when recursing).  */
797           con->cmd |= DO_RETR;
798           if (res == RETROK)
799             {
800               while (f) 
801                 {
802                   if (!strcmp (f->name, u->file))
803                     {
804                       exists = true;
805                       break;
806                     }
807                   f = f->next;
808                 }
809               if (exists)
810                 {
811                   logputs (LOG_VERBOSE, "\n");
812                   logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
813                              quote (u->file));
814                 }
815               else
816                 {
817                   logputs (LOG_VERBOSE, "\n");
818                   logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
819                              quote (u->file));
820                 }
821             }
822           fd_close (csock);
823           con->csock = -1;
824           fd_close (dtsock);
825           fd_close (local_sock);
826           return RETRFINISHED;
827         }
828
829       if (opt.verbose)
830         {
831           if (!opt.server_response)
832             {
833               if (restval)
834                 logputs (LOG_VERBOSE, "\n");
835               logprintf (LOG_VERBOSE, "==> RETR %s ... ", 
836                          quotearg_style (escape_quoting_style, u->file));
837             }
838         }
839
840       err = ftp_retr (csock, u->file);
841       /* FTPRERR, WRITEFAILED, FTPNSFOD */
842       switch (err)
843         {
844         case FTPRERR:
845           logputs (LOG_VERBOSE, "\n");
846           logputs (LOG_NOTQUIET, _("\
847 Error in server response, closing control connection.\n"));
848           fd_close (csock);
849           con->csock = -1;
850           fd_close (dtsock);
851           fd_close (local_sock);
852           return err;
853         case WRITEFAILED:
854           logputs (LOG_VERBOSE, "\n");
855           logputs (LOG_NOTQUIET,
856                    _("Write failed, closing control connection.\n"));
857           fd_close (csock);
858           con->csock = -1;
859           fd_close (dtsock);
860           fd_close (local_sock);
861           return err;
862         case FTPNSFOD:
863           logputs (LOG_VERBOSE, "\n");
864           logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
865                      quote (u->file));
866           fd_close (dtsock);
867           fd_close (local_sock);
868           return err;
869         case FTPOK:
870           break;
871         default:
872           abort ();
873         }
874
875       if (!opt.server_response)
876         logputs (LOG_VERBOSE, _("done.\n"));
877       expected_bytes = ftp_expected_bytes (ftp_last_respline);
878     } /* do retrieve */
879
880   if (cmd & DO_LIST)
881     {
882       if (!opt.server_response)
883         logputs (LOG_VERBOSE, "==> LIST ... ");
884       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
885          without arguments is better than `LIST .'; confirmed by
886          RFC959.  */
887       err = ftp_list (csock, NULL);
888       /* FTPRERR, WRITEFAILED */
889       switch (err)
890         {
891         case FTPRERR:
892           logputs (LOG_VERBOSE, "\n");
893           logputs (LOG_NOTQUIET, _("\
894 Error in server response, closing control connection.\n"));
895           fd_close (csock);
896           con->csock = -1;
897           fd_close (dtsock);
898           fd_close (local_sock);
899           return err;
900         case WRITEFAILED:
901           logputs (LOG_VERBOSE, "\n");
902           logputs (LOG_NOTQUIET,
903                    _("Write failed, closing control connection.\n"));
904           fd_close (csock);
905           con->csock = -1;
906           fd_close (dtsock);
907           fd_close (local_sock);
908           return err;
909         case FTPNSFOD:
910           logputs (LOG_VERBOSE, "\n");
911           logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
912                      quote ("."));
913           fd_close (dtsock);
914           fd_close (local_sock);
915           return err;
916         case FTPOK:
917           break;
918         default:
919           abort ();
920         }
921       if (!opt.server_response)
922         logputs (LOG_VERBOSE, _("done.\n"));
923       expected_bytes = ftp_expected_bytes (ftp_last_respline);
924     } /* cmd & DO_LIST */
925
926   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
927     return RETRFINISHED;
928
929   /* Some FTP servers return the total length of file after REST
930      command, others just return the remaining size. */
931   if (*len && restval && expected_bytes
932       && (expected_bytes == *len - restval))
933     {
934       DEBUGP (("Lying FTP server found, adjusting.\n"));
935       expected_bytes = *len;
936     }
937
938   /* If no transmission was required, then everything is OK.  */
939   if (!pasv_mode_open)  /* we are not using pasive mode so we need
940                               to accept */
941     {
942       /* Wait for the server to connect to the address we're waiting
943          at.  */
944       dtsock = accept_connection (local_sock);
945       if (dtsock < 0)
946         {
947           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
948           return err;
949         }
950     }
951
952   /* Open the file -- if output_stream is set, use it instead.  */
953   if (!output_stream || con->cmd & DO_LIST)
954     {
955       mkalldirs (con->target);
956       if (opt.backups)
957         rotate_backups (con->target);
958
959       if (restval && !(con->cmd & DO_LIST))
960         fp = fopen (con->target, "ab");
961       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
962                || opt.output_document)
963         fp = fopen (con->target, "wb");
964       else
965         {
966           fp = fopen_excl (con->target, true);
967           if (!fp && errno == EEXIST)
968             {
969               /* We cannot just invent a new name and use it (which is
970                  what functions like unique_create typically do)
971                  because we told the user we'd use this name.
972                  Instead, return and retry the download.  */
973               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
974                          con->target);
975               fd_close (csock);
976               con->csock = -1;
977               fd_close (dtsock);
978               fd_close (local_sock);
979               return FOPEN_EXCL_ERR;
980             }
981         }
982       if (!fp)
983         {
984           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
985           fd_close (csock);
986           con->csock = -1;
987           fd_close (dtsock);
988           fd_close (local_sock);
989           return FOPENERR;
990         }
991     }
992   else
993     fp = output_stream;
994
995   if (*len)
996     {
997       print_length (*len, restval, true);
998       expected_bytes = *len;    /* for fd_read_body's progress bar */
999     }
1000   else if (expected_bytes)
1001     print_length (expected_bytes, restval, false);
1002
1003   /* Get the contents of the document.  */
1004   flags = 0;
1005   if (restval && rest_failed)
1006     flags |= rb_skip_startpos;
1007   *len = restval;
1008   rd_size = 0;
1009   res = fd_read_body (dtsock, fp,
1010                       expected_bytes ? expected_bytes - restval : 0,
1011                       restval, &rd_size, len, &con->dltime, flags);
1012
1013   tms = datetime_str (time (NULL));
1014   tmrate = retr_rate (rd_size, con->dltime);
1015   total_download_time += con->dltime;
1016
1017   fd_close (local_sock);
1018   /* Close the local file.  */
1019   if (!output_stream || con->cmd & DO_LIST)
1020     fclose (fp);
1021
1022   /* If fd_read_body couldn't write to fp, bail out.  */
1023   if (res == -2)
1024     {
1025       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1026                  con->target, strerror (errno));
1027       fd_close (csock);
1028       con->csock = -1;
1029       fd_close (dtsock);
1030       return FWRITEERR;
1031     }
1032   else if (res == -1)
1033     {
1034       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1035                  tms, tmrate, fd_errstr (dtsock));
1036       if (opt.server_response)
1037         logputs (LOG_ALWAYS, "\n");
1038     }
1039   fd_close (dtsock);
1040
1041   /* Get the server to tell us if everything is retrieved.  */
1042   err = ftp_response (csock, &respline);
1043   if (err != FTPOK)
1044     {
1045       /* The control connection is decidedly closed.  Print the time
1046          only if it hasn't already been printed.  */
1047       if (res != -1)
1048         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1049       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1050       /* If there is an error on the control connection, close it, but
1051          return FTPRETRINT, since there is a possibility that the
1052          whole file was retrieved nevertheless (but that is for
1053          ftp_loop_internal to decide).  */
1054       fd_close (csock);
1055       con->csock = -1;
1056       return FTPRETRINT;
1057     } /* err != FTPOK */
1058   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1059      close socket, since the control connection is still alive.  If
1060      there is something wrong with the control connection, it will
1061      become apparent later.  */
1062   if (*respline != '2')
1063     {
1064       xfree (respline);
1065       if (res != -1)
1066         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1067       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1068       return FTPRETRINT;
1069     }
1070   xfree (respline);
1071
1072   if (res == -1)
1073     {
1074       /* What now?  The data connection was erroneous, whereas the
1075          response says everything is OK.  We shall play it safe.  */
1076       return FTPRETRINT;
1077     }
1078
1079   if (!(cmd & LEAVE_PENDING))
1080     {
1081       /* Closing the socket is faster than sending 'QUIT' and the
1082          effect is the same.  */
1083       fd_close (csock);
1084       con->csock = -1;
1085     }
1086   /* If it was a listing, and opt.server_response is true,
1087      print it out.  */
1088   if (opt.server_response && (con->cmd & DO_LIST))
1089     {
1090       mkalldirs (con->target);
1091       fp = fopen (con->target, "r");
1092       if (!fp)
1093         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1094       else
1095         {
1096           char *line;
1097           /* The lines are being read with read_whole_line because of
1098              no-buffering on opt.lfile.  */
1099           while ((line = read_whole_line (fp)) != NULL)
1100             {
1101               char *p = strchr (line, '\0');
1102               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1103                 *--p = '\0';
1104               logprintf (LOG_ALWAYS, "%s\n", 
1105                          quotearg_style (escape_quoting_style, line));
1106               xfree (line);
1107             }
1108           fclose (fp);
1109         }
1110     } /* con->cmd & DO_LIST && server_response */
1111
1112   return RETRFINISHED;
1113 }
1114
1115 /* A one-file FTP loop.  This is the part where FTP retrieval is
1116    retried, and retried, and retried, and...
1117
1118    This loop either gets commands from con, or (if ON_YOUR_OWN is
1119    set), makes them up to retrieve the file given by the URL.  */
1120 static uerr_t
1121 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1122 {
1123   int count, orig_lp;
1124   wgint restval, len = 0;
1125   char *tms, *locf;
1126   const char *tmrate = NULL;
1127   uerr_t err;
1128   struct_stat st;
1129
1130   if (!con->target)
1131     con->target = url_file_name (u);
1132
1133   /* If the output_document was given, then this check was already done and
1134      the file didn't exist. Hence the !opt.output_document */
1135   if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1136     {
1137       logprintf (LOG_VERBOSE,
1138                  _("File %s already there; not retrieving.\n"), quote (con->target));
1139       /* If the file is there, we suppose it's retrieved OK.  */
1140       return RETROK;
1141     }
1142
1143   /* Remove it if it's a link.  */
1144   remove_link (con->target);
1145   if (!opt.output_document)
1146     locf = con->target;
1147   else
1148     locf = opt.output_document;
1149
1150   count = 0;
1151
1152   if (con->st & ON_YOUR_OWN)
1153     con->st = ON_YOUR_OWN;
1154
1155   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1156
1157   /* THE loop.  */
1158   do
1159     {
1160       /* Increment the pass counter.  */
1161       ++count;
1162       sleep_between_retrievals (count);
1163       if (con->st & ON_YOUR_OWN)
1164         {
1165           con->cmd = 0;
1166           con->cmd |= (DO_RETR | LEAVE_PENDING);
1167           if (con->csock != -1)
1168             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1169           else
1170             con->cmd |= (DO_LOGIN | DO_CWD);
1171         }
1172       else /* not on your own */
1173         {
1174           if (con->csock != -1)
1175             con->cmd &= ~DO_LOGIN;
1176           else
1177             con->cmd |= DO_LOGIN;
1178           if (con->st & DONE_CWD)
1179             con->cmd &= ~DO_CWD;
1180           else
1181             con->cmd |= DO_CWD;
1182         }
1183
1184       /* Decide whether or not to restart.  */
1185       if (con->cmd & DO_LIST)
1186         restval = 0;
1187       else if (opt.always_rest
1188           && stat (locf, &st) == 0
1189           && S_ISREG (st.st_mode))
1190         /* When -c is used, continue from on-disk size.  (Can't use
1191            hstat.len even if count>1 because we don't want a failed
1192            first attempt to clobber existing data.)  */
1193         restval = st.st_size;
1194       else if (count > 1)
1195         restval = len;          /* start where the previous run left off */
1196       else
1197         restval = 0;
1198
1199       /* Get the current time string.  */
1200       tms = datetime_str (time (NULL));
1201       /* Print fetch message, if opt.verbose.  */
1202       if (opt.verbose)
1203         {
1204           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1205           char tmp[256];
1206           strcpy (tmp, "        ");
1207           if (count > 1)
1208             sprintf (tmp, _("(try:%2d)"), count);
1209           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => %s\n",
1210                      tms, hurl, tmp, quote (locf));
1211 #ifdef WINDOWS
1212           ws_changetitle (hurl);
1213 #endif
1214           xfree (hurl);
1215         }
1216       /* Send getftp the proper length, if fileinfo was provided.  */
1217       if (f)
1218         len = f->size;
1219       else
1220         len = 0;
1221       err = getftp (u, &len, restval, con);
1222
1223       if (con->csock == -1)
1224         con->st &= ~DONE_CWD;
1225       else
1226         con->st |= DONE_CWD;
1227
1228       switch (err)
1229         {
1230         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1231         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1232           /* Fatal errors, give up.  */
1233           return err;
1234         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1235         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1236         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1237         case FOPEN_EXCL_ERR:
1238           printwhat (count, opt.ntry);
1239           /* non-fatal errors */
1240           if (err == FOPEN_EXCL_ERR)
1241             {
1242               /* Re-determine the file name. */
1243               xfree_null (con->target);
1244               con->target = url_file_name (u);
1245               locf = con->target;
1246             }
1247           continue;
1248         case FTPRETRINT:
1249           /* If the control connection was closed, the retrieval
1250              will be considered OK if f->size == len.  */
1251           if (!f || len != f->size)
1252             {
1253               printwhat (count, opt.ntry);
1254               continue;
1255             }
1256           break;
1257         case RETRFINISHED:
1258           /* Great!  */
1259           break;
1260         default:
1261           /* Not as great.  */
1262           abort ();
1263         }
1264       tms = datetime_str (time (NULL));
1265       if (!opt.spider)
1266         tmrate = retr_rate (len - restval, con->dltime);
1267
1268       /* If we get out of the switch above without continue'ing, we've
1269          successfully downloaded a file.  Remember this fact. */
1270       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1271
1272       if (con->st & ON_YOUR_OWN)
1273         {
1274           fd_close (con->csock);
1275           con->csock = -1;
1276         }
1277       if (!opt.spider)
1278         logprintf (LOG_VERBOSE, _("%s (%s) - %s saved [%s]\n\n"),
1279                    tms, tmrate, quote (locf), number_to_static_string (len));
1280       if (!opt.verbose && !opt.quiet)
1281         {
1282           /* Need to hide the password from the URL.  The `if' is here
1283              so that we don't do the needless allocation every
1284              time. */
1285           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1286           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1287                      tms, hurl, number_to_static_string (len), locf, count);
1288           xfree (hurl);
1289         }
1290
1291       if ((con->cmd & DO_LIST))
1292         /* This is a directory listing file. */
1293         {
1294           if (!opt.remove_listing)
1295             /* --dont-remove-listing was specified, so do count this towards the
1296                number of bytes and files downloaded. */
1297             {
1298               total_downloaded_bytes += len;
1299               numurls++;
1300             }
1301
1302           /* Deletion of listing files is not controlled by --delete-after, but
1303              by the more specific option --dont-remove-listing, and the code
1304              to do this deletion is in another function. */
1305         }
1306       else if (!opt.spider)
1307         /* This is not a directory listing file. */
1308         {
1309           /* Unlike directory listing files, don't pretend normal files weren't
1310              downloaded if they're going to be deleted.  People seeding proxies,
1311              for instance, may want to know how many bytes and files they've
1312              downloaded through it. */
1313           total_downloaded_bytes += len;
1314           numurls++;
1315
1316           if (opt.delete_after)
1317             {
1318               DEBUGP (("\
1319 Removing file due to --delete-after in ftp_loop_internal():\n"));
1320               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1321               if (unlink (locf))
1322                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1323             }
1324         }
1325
1326       /* Restore the original leave-pendingness.  */
1327       if (orig_lp)
1328         con->cmd |= LEAVE_PENDING;
1329       else
1330         con->cmd &= ~LEAVE_PENDING;
1331       return RETROK;
1332     } while (!opt.ntry || (count < opt.ntry));
1333
1334   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1335     {
1336       fd_close (con->csock);
1337       con->csock = -1;
1338     }
1339   return TRYLIMEXC;
1340 }
1341
1342 /* Return the directory listing in a reusable format.  The directory
1343    is specifed in u->dir.  */
1344 static uerr_t
1345 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1346 {
1347   uerr_t err;
1348   char *uf;                     /* url file name */
1349   char *lf;                     /* list file name */
1350   char *old_target = con->target;
1351
1352   con->st &= ~ON_YOUR_OWN;
1353   con->cmd |= (DO_LIST | LEAVE_PENDING);
1354   con->cmd &= ~DO_RETR;
1355
1356   /* Find the listing file name.  We do it by taking the file name of
1357      the URL and replacing the last component with the listing file
1358      name.  */
1359   uf = url_file_name (u);
1360   lf = file_merge (uf, LIST_FILENAME);
1361   xfree (uf);
1362   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1363
1364   con->target = lf;
1365   err = ftp_loop_internal (u, NULL, con);
1366   con->target = old_target;
1367
1368   if (err == RETROK)
1369     {
1370       *f = ftp_parse_ls (lf, con->rs);
1371       if (opt.remove_listing)
1372         {
1373           if (unlink (lf))
1374             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1375           else
1376             logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1377         }
1378     }
1379   else
1380     *f = NULL;
1381   xfree (lf);
1382   con->cmd &= ~DO_LIST;
1383   return err;
1384 }
1385
1386 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1387 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1388 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1389 static void freefileinfo (struct fileinfo *f);
1390
1391 /* Retrieve a list of files given in struct fileinfo linked list.  If
1392    a file is a symbolic link, do not retrieve it, but rather try to
1393    set up a similar link on the local disk, if the symlinks are
1394    supported.
1395
1396    If opt.recursive is set, after all files have been retrieved,
1397    ftp_retrieve_dirs will be called to retrieve the directories.  */
1398 static uerr_t
1399 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1400 {
1401   static int depth = 0;
1402   uerr_t err;
1403   struct fileinfo *orig;
1404   wgint local_size;
1405   time_t tml;
1406   bool dlthis;
1407
1408   /* Increase the depth.  */
1409   ++depth;
1410   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1411     {
1412       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1413                depth, opt.reclevel));
1414       --depth;
1415       return RECLEVELEXC;
1416     }
1417
1418   assert (f != NULL);
1419   orig = f;
1420
1421   con->st &= ~ON_YOUR_OWN;
1422   if (!(con->st & DONE_CWD))
1423     con->cmd |= DO_CWD;
1424   else
1425     con->cmd &= ~DO_CWD;
1426   con->cmd |= (DO_RETR | LEAVE_PENDING);
1427
1428   if (con->csock < 0)
1429     con->cmd |= DO_LOGIN;
1430   else
1431     con->cmd &= ~DO_LOGIN;
1432
1433   err = RETROK;                 /* in case it's not used */
1434
1435   while (f)
1436     {
1437       char *old_target, *ofile;
1438
1439       if (opt.quota && total_downloaded_bytes > opt.quota)
1440         {
1441           --depth;
1442           return QUOTEXC;
1443         }
1444       old_target = con->target;
1445
1446       ofile = xstrdup (u->file);
1447       url_set_file (u, f->name);
1448
1449       con->target = url_file_name (u);
1450       err = RETROK;
1451
1452       dlthis = true;
1453       if (opt.timestamping && f->type == FT_PLAINFILE)
1454         {
1455           struct_stat st;
1456           /* If conversion of HTML files retrieved via FTP is ever implemented,
1457              we'll need to stat() <file>.orig here when -K has been specified.
1458              I'm not implementing it now since files on an FTP server are much
1459              more likely than files on an HTTP server to legitimately have a
1460              .orig suffix. */
1461           if (!stat (con->target, &st))
1462             {
1463               bool eq_size;
1464               bool cor_val;
1465               /* Else, get it from the file.  */
1466               local_size = st.st_size;
1467               tml = st.st_mtime;
1468 #ifdef WINDOWS
1469               /* Modification time granularity is 2 seconds for Windows, so
1470                  increase local time by 1 second for later comparison. */
1471               tml++;
1472 #endif
1473               /* Compare file sizes only for servers that tell us correct
1474                  values. Assume sizes being equal for servers that lie
1475                  about file size.  */
1476               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1477               eq_size = cor_val ? (local_size == f->size) : true;
1478               if (f->tstamp <= tml && eq_size)
1479                 {
1480                   /* Remote file is older, file sizes can be compared and
1481                      are both equal. */
1482                   logprintf (LOG_VERBOSE, _("\
1483 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1484                   dlthis = false;
1485                 }
1486               else if (eq_size)
1487                 {
1488                   /* Remote file is newer or sizes cannot be matched */
1489                   logprintf (LOG_VERBOSE, _("\
1490 Remote file is newer than local file %s -- retrieving.\n\n"),
1491                              quote (con->target));
1492                 }
1493               else
1494                 {
1495                   /* Sizes do not match */
1496                   logprintf (LOG_VERBOSE, _("\
1497 The sizes do not match (local %s) -- retrieving.\n\n"),
1498                              number_to_static_string (local_size));
1499                 }
1500             }
1501         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1502       switch (f->type)
1503         {
1504         case FT_SYMLINK:
1505           /* If opt.retr_symlinks is defined, we treat symlinks as
1506              if they were normal files.  There is currently no way
1507              to distinguish whether they might be directories, and
1508              follow them.  */
1509           if (!opt.retr_symlinks)
1510             {
1511 #ifdef HAVE_SYMLINK
1512               if (!f->linkto)
1513                 logputs (LOG_NOTQUIET,
1514                          _("Invalid name of the symlink, skipping.\n"));
1515               else
1516                 {
1517                   struct_stat st;
1518                   /* Check whether we already have the correct
1519                      symbolic link.  */
1520                   int rc = lstat (con->target, &st);
1521                   if (rc == 0)
1522                     {
1523                       size_t len = strlen (f->linkto) + 1;
1524                       if (S_ISLNK (st.st_mode))
1525                         {
1526                           char *link_target = (char *)alloca (len);
1527                           size_t n = readlink (con->target, link_target, len);
1528                           if ((n == len - 1)
1529                               && (memcmp (link_target, f->linkto, n) == 0))
1530                             {
1531                               logprintf (LOG_VERBOSE, _("\
1532 Already have correct symlink %s -> %s\n\n"),
1533                                          quote (con->target),
1534                                          quote (f->linkto));
1535                               dlthis = false;
1536                               break;
1537                             }
1538                         }
1539                     }
1540                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1541                              quote (con->target), quote (f->linkto));
1542                   /* Unlink before creating symlink!  */
1543                   unlink (con->target);
1544                   if (symlink (f->linkto, con->target) == -1)
1545                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1546                   logputs (LOG_VERBOSE, "\n");
1547                 } /* have f->linkto */
1548 #else  /* not HAVE_SYMLINK */
1549               logprintf (LOG_NOTQUIET,
1550                          _("Symlinks not supported, skipping symlink %s.\n"),
1551                          quote (con->target));
1552 #endif /* not HAVE_SYMLINK */
1553             }
1554           else                /* opt.retr_symlinks */
1555             {
1556               if (dlthis)
1557                 err = ftp_loop_internal (u, f, con);
1558             } /* opt.retr_symlinks */
1559           break;
1560         case FT_DIRECTORY:
1561           if (!opt.recursive)
1562             logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1563                        quote (f->name));
1564           break;
1565         case FT_PLAINFILE:
1566           /* Call the retrieve loop.  */
1567           if (dlthis)
1568             err = ftp_loop_internal (u, f, con);
1569           break;
1570         case FT_UNKNOWN:
1571           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1572                      quote (f->name));
1573           break;
1574         }       /* switch */
1575
1576       /* Set the time-stamp information to the local file.  Symlinks
1577          are not to be stamped because it sets the stamp on the
1578          original.  :( */
1579       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1580           && f->tstamp != -1
1581           && dlthis
1582           && file_exists_p (con->target))
1583         {
1584           /* #### This code repeats in http.c and ftp.c.  Move it to a
1585              function!  */
1586           const char *fl = NULL;
1587           if (opt.output_document)
1588             {
1589               if (output_stream_regular)
1590                 fl = opt.output_document;
1591             }
1592           else
1593             fl = con->target;
1594           if (fl)
1595             touch (fl, f->tstamp);
1596         }
1597       else if (f->tstamp == -1)
1598         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1599
1600       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1601         {
1602           if (opt.preserve_perm)
1603             chmod (con->target, f->perms);
1604         }
1605       else
1606         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1607
1608       xfree (con->target);
1609       con->target = old_target;
1610
1611       url_set_file (u, ofile);
1612       xfree (ofile);
1613
1614       /* Break on fatals.  */
1615       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1616         break;
1617       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1618       f = f->next;
1619     }
1620
1621   /* We do not want to call ftp_retrieve_dirs here */
1622   if (opt.recursive &&
1623       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1624     err = ftp_retrieve_dirs (u, orig, con);
1625   else if (opt.recursive)
1626     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1627              depth, opt.reclevel));
1628   --depth;
1629   return err;
1630 }
1631
1632 /* Retrieve the directories given in a file list.  This function works
1633    by simply going through the linked list and calling
1634    ftp_retrieve_glob on each directory entry.  The function knows
1635    about excluded directories.  */
1636 static uerr_t
1637 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1638 {
1639   char *container = NULL;
1640   int container_size = 0;
1641
1642   for (; f; f = f->next)
1643     {
1644       int size;
1645       char *odir, *newdir;
1646
1647       if (opt.quota && total_downloaded_bytes > opt.quota)
1648         break;
1649       if (f->type != FT_DIRECTORY)
1650         continue;
1651
1652       /* Allocate u->dir off stack, but reallocate only if a larger
1653          string is needed.  It's a pity there's no "realloca" for an
1654          item on the bottom of the stack.  */
1655       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1656       if (size > container_size)
1657         container = (char *)alloca (size);
1658       newdir = container;
1659
1660       odir = u->dir;
1661       if (*odir == '\0'
1662           || (*odir == '/' && *(odir + 1) == '\0'))
1663         /* If ODIR is empty or just "/", simply append f->name to
1664            ODIR.  (In the former case, to preserve u->dir being
1665            relative; in the latter case, to avoid double slash.)  */
1666         sprintf (newdir, "%s%s", odir, f->name);
1667       else
1668         /* Else, use a separator. */
1669         sprintf (newdir, "%s/%s", odir, f->name);
1670
1671       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1672       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1673                odir, f->name, newdir));
1674       if (!accdir (newdir))
1675         {
1676           logprintf (LOG_VERBOSE, _("\
1677 Not descending to %s as it is excluded/not-included.\n"),
1678                      quote (newdir));
1679           continue;
1680         }
1681
1682       con->st &= ~DONE_CWD;
1683
1684       odir = xstrdup (u->dir);  /* because url_set_dir will free
1685                                    u->dir. */
1686       url_set_dir (u, newdir);
1687       ftp_retrieve_glob (u, con, GLOB_GETALL);
1688       url_set_dir (u, odir);
1689       xfree (odir);
1690
1691       /* Set the time-stamp?  */
1692     }
1693
1694   if (opt.quota && total_downloaded_bytes > opt.quota)
1695     return QUOTEXC;
1696   else
1697     return RETROK;
1698 }
1699
1700 /* Return true if S has a leading '/'  or contains '../' */
1701 static bool
1702 has_insecure_name_p (const char *s)
1703 {
1704   if (*s == '/')
1705     return true;
1706
1707   if (strstr (s, "../") != 0)
1708     return true;
1709
1710   return false;
1711 }
1712
1713 /* A near-top-level function to retrieve the files in a directory.
1714    The function calls ftp_get_listing, to get a linked list of files.
1715    Then it weeds out the file names that do not match the pattern.
1716    ftp_retrieve_list is called with this updated list as an argument.
1717
1718    If the argument ACTION is GLOB_GETONE, just download the file (but
1719    first get the listing, so that the time-stamp is heeded); if it's
1720    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1721    directory.  */
1722 static uerr_t
1723 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1724 {
1725   struct fileinfo *f, *start;
1726   uerr_t res;
1727
1728   con->cmd |= LEAVE_PENDING;
1729
1730   res = ftp_get_listing (u, con, &start);
1731   if (res != RETROK)
1732     return res;
1733   /* First: weed out that do not conform the global rules given in
1734      opt.accepts and opt.rejects.  */
1735   if (opt.accepts || opt.rejects)
1736     {
1737       f = start;
1738       while (f)
1739         {
1740           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1741             {
1742               logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
1743                          quote (f->name));
1744               f = delelement (f, &start);
1745             }
1746           else
1747             f = f->next;
1748         }
1749     }
1750   /* Remove all files with possible harmful names */
1751   f = start;
1752   while (f)
1753     {
1754       if (has_insecure_name_p (f->name))
1755         {
1756           logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
1757                      quote (f->name));
1758           f = delelement (f, &start);
1759         }
1760       else
1761         f = f->next;
1762     }
1763   /* Now weed out the files that do not match our globbing pattern.
1764      If we are dealing with a globbing pattern, that is.  */
1765   if (*u->file)
1766     {
1767       if (action == GLOB_GLOBALL)
1768         {
1769           int (*matcher) (const char *, const char *, int)
1770             = opt.ignore_case ? fnmatch_nocase : fnmatch;
1771           int matchres = 0;
1772
1773           f = start;
1774           while (f)
1775             {
1776               matchres = matcher (u->file, f->name, 0);
1777               if (matchres == -1)
1778                 {
1779                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
1780                              u->file, quotearg_style (escape_quoting_style, f->name), 
1781                              strerror (errno));
1782                   break;
1783                 }
1784               if (matchres == FNM_NOMATCH)
1785                 f = delelement (f, &start); /* delete the element from the list */
1786               else
1787                 f = f->next;        /* leave the element in the list */
1788             }
1789           if (matchres == -1)
1790             {
1791               freefileinfo (start);
1792               return RETRBADPATTERN;
1793             }
1794         }
1795       else if (action == GLOB_GETONE)
1796         {
1797           int (*cmp) (const char *, const char *)
1798             = opt.ignore_case ? strcasecmp : strcmp;
1799           f = start;
1800           while (f)
1801             {
1802               if (0 != cmp(u->file, f->name))
1803                 f = delelement (f, &start);
1804               else
1805                 f = f->next;
1806             }
1807         }
1808     }
1809   if (start)
1810     {
1811       /* Just get everything.  */
1812       ftp_retrieve_list (u, start, con);
1813     }
1814   else
1815     {
1816       if (action == GLOB_GLOBALL)
1817         {
1818           /* No luck.  */
1819           /* #### This message SUCKS.  We should see what was the
1820              reason that nothing was retrieved.  */
1821           logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
1822                      quote (u->file));
1823         }
1824       else /* GLOB_GETONE or GLOB_GETALL */
1825         {
1826           /* Let's try retrieving it anyway.  */
1827           con->st |= ON_YOUR_OWN;
1828           res = ftp_loop_internal (u, NULL, con);
1829           return res;
1830         }
1831     }
1832   freefileinfo (start);
1833   if (opt.quota && total_downloaded_bytes > opt.quota)
1834     return QUOTEXC;
1835   else
1836     /* #### Should we return `res' here?  */
1837     return RETROK;
1838 }
1839
1840 /* The wrapper that calls an appropriate routine according to contents
1841    of URL.  Inherently, its capabilities are limited on what can be
1842    encoded into a URL.  */
1843 uerr_t
1844 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
1845 {
1846   ccon con;                     /* FTP connection */
1847   uerr_t res;
1848
1849   *dt = 0;
1850
1851   xzero (con);
1852
1853   con.csock = -1;
1854   con.st = ON_YOUR_OWN;
1855   con.rs = ST_UNIX;
1856   con.id = NULL;
1857   con.proxy = proxy;
1858
1859   /* If the file name is empty, the user probably wants a directory
1860      index.  We'll provide one, properly HTML-ized.  Unless
1861      opt.htmlify is 0, of course.  :-) */
1862   if (!*u->file && !recursive)
1863     {
1864       struct fileinfo *f;
1865       res = ftp_get_listing (u, &con, &f);
1866
1867       if (res == RETROK)
1868         {
1869           if (opt.htmlify && !opt.spider)
1870             {
1871               char *filename = (opt.output_document
1872                                 ? xstrdup (opt.output_document)
1873                                 : (con.target ? xstrdup (con.target)
1874                                    : url_file_name (u)));
1875               res = ftp_index (filename, u, f);
1876               if (res == FTPOK && opt.verbose)
1877                 {
1878                   if (!opt.output_document)
1879                     {
1880                       struct_stat st;
1881                       wgint sz;
1882                       if (stat (filename, &st) == 0)
1883                         sz = st.st_size;
1884                       else
1885                         sz = -1;
1886                       logprintf (LOG_NOTQUIET,
1887                                  _("Wrote HTML-ized index to %s [%s].\n"),
1888                                  quote (filename), number_to_static_string (sz));
1889                     }
1890                   else
1891                     logprintf (LOG_NOTQUIET,
1892                                _("Wrote HTML-ized index to %s.\n"),
1893                                quote (filename));
1894                 }
1895               xfree (filename);
1896             }
1897           freefileinfo (f);
1898         }
1899     }
1900   else
1901     {
1902       bool ispattern = false;
1903       if (glob)
1904         {
1905           /* Treat the URL as a pattern if the file name part of the
1906              URL path contains wildcards.  (Don't check for u->file
1907              because it is unescaped and therefore doesn't leave users
1908              the option to escape literal '*' as %2A.)  */
1909           char *file_part = strrchr (u->path, '/');
1910           if (!file_part)
1911             file_part = u->path;
1912           ispattern = has_wildcards_p (file_part);
1913         }
1914       if (ispattern || recursive || opt.timestamping)
1915         {
1916           /* ftp_retrieve_glob is a catch-all function that gets called
1917              if we need globbing, time-stamping or recursion.  Its
1918              third argument is just what we really need.  */
1919           res = ftp_retrieve_glob (u, &con,
1920                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
1921         }
1922       else
1923         res = ftp_loop_internal (u, NULL, &con);
1924     }
1925   if (res == FTPOK)
1926     res = RETROK;
1927   if (res == RETROK)
1928     *dt |= RETROKF;
1929   /* If a connection was left, quench it.  */
1930   if (con.csock != -1)
1931     fd_close (con.csock);
1932   xfree_null (con.id);
1933   con.id = NULL;
1934   xfree_null (con.target);
1935   con.target = NULL;
1936   return res;
1937 }
1938
1939 /* Delete an element from the fileinfo linked list.  Returns the
1940    address of the next element, or NULL if the list is exhausted.  It
1941    can modify the start of the list.  */
1942 static struct fileinfo *
1943 delelement (struct fileinfo *f, struct fileinfo **start)
1944 {
1945   struct fileinfo *prev = f->prev;
1946   struct fileinfo *next = f->next;
1947
1948   xfree (f->name);
1949   xfree_null (f->linkto);
1950   xfree (f);
1951
1952   if (next)
1953     next->prev = prev;
1954   if (prev)
1955     prev->next = next;
1956   else
1957     *start = next;
1958   return next;
1959 }
1960
1961 /* Free the fileinfo linked list of files.  */
1962 static void
1963 freefileinfo (struct fileinfo *f)
1964 {
1965   while (f)
1966     {
1967       struct fileinfo *next = f->next;
1968       xfree (f->name);
1969       if (f->linkto)
1970         xfree (f->linkto);
1971       xfree (f);
1972       f = next;
1973     }
1974 }