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