]> sjero.net Git - wget/blob - src/ftp.c
Return CONERROR when accept_connection fails (#25015).
[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, 2009 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 CONERROR;
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         {
1279           bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1280
1281           logprintf (LOG_VERBOSE,
1282                      write_to_stdout
1283                      ? _("%s (%s) - written to stdout %s[%s]\n\n")
1284                      : _("%s (%s) - %s saved [%s]\n\n"),
1285                      tms, tmrate,
1286                      write_to_stdout ? "" : quote (locf),
1287                      number_to_static_string (len));
1288         }
1289       if (!opt.verbose && !opt.quiet)
1290         {
1291           /* Need to hide the password from the URL.  The `if' is here
1292              so that we don't do the needless allocation every
1293              time. */
1294           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1295           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1296                      tms, hurl, number_to_static_string (len), locf, count);
1297           xfree (hurl);
1298         }
1299
1300       if ((con->cmd & DO_LIST))
1301         /* This is a directory listing file. */
1302         {
1303           if (!opt.remove_listing)
1304             /* --dont-remove-listing was specified, so do count this towards the
1305                number of bytes and files downloaded. */
1306             {
1307               total_downloaded_bytes += len;
1308               numurls++;
1309             }
1310
1311           /* Deletion of listing files is not controlled by --delete-after, but
1312              by the more specific option --dont-remove-listing, and the code
1313              to do this deletion is in another function. */
1314         }
1315       else if (!opt.spider)
1316         /* This is not a directory listing file. */
1317         {
1318           /* Unlike directory listing files, don't pretend normal files weren't
1319              downloaded if they're going to be deleted.  People seeding proxies,
1320              for instance, may want to know how many bytes and files they've
1321              downloaded through it. */
1322           total_downloaded_bytes += len;
1323           numurls++;
1324
1325           if (opt.delete_after)
1326             {
1327               DEBUGP (("\
1328 Removing file due to --delete-after in ftp_loop_internal():\n"));
1329               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1330               if (unlink (locf))
1331                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1332             }
1333         }
1334
1335       /* Restore the original leave-pendingness.  */
1336       if (orig_lp)
1337         con->cmd |= LEAVE_PENDING;
1338       else
1339         con->cmd &= ~LEAVE_PENDING;
1340       return RETROK;
1341     } while (!opt.ntry || (count < opt.ntry));
1342
1343   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1344     {
1345       fd_close (con->csock);
1346       con->csock = -1;
1347     }
1348   return TRYLIMEXC;
1349 }
1350
1351 /* Return the directory listing in a reusable format.  The directory
1352    is specifed in u->dir.  */
1353 static uerr_t
1354 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1355 {
1356   uerr_t err;
1357   char *uf;                     /* url file name */
1358   char *lf;                     /* list file name */
1359   char *old_target = con->target;
1360
1361   con->st &= ~ON_YOUR_OWN;
1362   con->cmd |= (DO_LIST | LEAVE_PENDING);
1363   con->cmd &= ~DO_RETR;
1364
1365   /* Find the listing file name.  We do it by taking the file name of
1366      the URL and replacing the last component with the listing file
1367      name.  */
1368   uf = url_file_name (u);
1369   lf = file_merge (uf, LIST_FILENAME);
1370   xfree (uf);
1371   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1372
1373   con->target = xstrdup (lf);
1374   xfree (lf);
1375   err = ftp_loop_internal (u, NULL, con);
1376   lf = xstrdup (con->target);
1377   xfree (con->target);
1378   con->target = old_target;
1379
1380   if (err == RETROK)
1381     {
1382       *f = ftp_parse_ls (lf, con->rs);
1383       if (opt.remove_listing)
1384         {
1385           if (unlink (lf))
1386             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1387           else
1388             logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1389         }
1390     }
1391   else
1392     *f = NULL;
1393   xfree (lf);
1394   con->cmd &= ~DO_LIST;
1395   return err;
1396 }
1397
1398 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1399 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1400 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1401 static void freefileinfo (struct fileinfo *f);
1402
1403 /* Retrieve a list of files given in struct fileinfo linked list.  If
1404    a file is a symbolic link, do not retrieve it, but rather try to
1405    set up a similar link on the local disk, if the symlinks are
1406    supported.
1407
1408    If opt.recursive is set, after all files have been retrieved,
1409    ftp_retrieve_dirs will be called to retrieve the directories.  */
1410 static uerr_t
1411 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1412 {
1413   static int depth = 0;
1414   uerr_t err;
1415   struct fileinfo *orig;
1416   wgint local_size;
1417   time_t tml;
1418   bool dlthis;
1419
1420   /* Increase the depth.  */
1421   ++depth;
1422   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1423     {
1424       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1425                depth, opt.reclevel));
1426       --depth;
1427       return RECLEVELEXC;
1428     }
1429
1430   assert (f != NULL);
1431   orig = f;
1432
1433   con->st &= ~ON_YOUR_OWN;
1434   if (!(con->st & DONE_CWD))
1435     con->cmd |= DO_CWD;
1436   else
1437     con->cmd &= ~DO_CWD;
1438   con->cmd |= (DO_RETR | LEAVE_PENDING);
1439
1440   if (con->csock < 0)
1441     con->cmd |= DO_LOGIN;
1442   else
1443     con->cmd &= ~DO_LOGIN;
1444
1445   err = RETROK;                 /* in case it's not used */
1446
1447   while (f)
1448     {
1449       char *old_target, *ofile;
1450
1451       if (opt.quota && total_downloaded_bytes > opt.quota)
1452         {
1453           --depth;
1454           return QUOTEXC;
1455         }
1456       old_target = con->target;
1457
1458       ofile = xstrdup (u->file);
1459       url_set_file (u, f->name);
1460
1461       con->target = url_file_name (u);
1462       err = RETROK;
1463
1464       dlthis = true;
1465       if (opt.timestamping && f->type == FT_PLAINFILE)
1466         {
1467           struct_stat st;
1468           /* If conversion of HTML files retrieved via FTP is ever implemented,
1469              we'll need to stat() <file>.orig here when -K has been specified.
1470              I'm not implementing it now since files on an FTP server are much
1471              more likely than files on an HTTP server to legitimately have a
1472              .orig suffix. */
1473           if (!stat (con->target, &st))
1474             {
1475               bool eq_size;
1476               bool cor_val;
1477               /* Else, get it from the file.  */
1478               local_size = st.st_size;
1479               tml = st.st_mtime;
1480 #ifdef WINDOWS
1481               /* Modification time granularity is 2 seconds for Windows, so
1482                  increase local time by 1 second for later comparison. */
1483               tml++;
1484 #endif
1485               /* Compare file sizes only for servers that tell us correct
1486                  values. Assume sizes being equal for servers that lie
1487                  about file size.  */
1488               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1489               eq_size = cor_val ? (local_size == f->size) : true;
1490               if (f->tstamp <= tml && eq_size)
1491                 {
1492                   /* Remote file is older, file sizes can be compared and
1493                      are both equal. */
1494                   logprintf (LOG_VERBOSE, _("\
1495 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1496                   dlthis = false;
1497                 }
1498               else if (eq_size)
1499                 {
1500                   /* Remote file is newer or sizes cannot be matched */
1501                   logprintf (LOG_VERBOSE, _("\
1502 Remote file is newer than local file %s -- retrieving.\n\n"),
1503                              quote (con->target));
1504                 }
1505               else
1506                 {
1507                   /* Sizes do not match */
1508                   logprintf (LOG_VERBOSE, _("\
1509 The sizes do not match (local %s) -- retrieving.\n\n"),
1510                              number_to_static_string (local_size));
1511                 }
1512             }
1513         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1514       switch (f->type)
1515         {
1516         case FT_SYMLINK:
1517           /* If opt.retr_symlinks is defined, we treat symlinks as
1518              if they were normal files.  There is currently no way
1519              to distinguish whether they might be directories, and
1520              follow them.  */
1521           if (!opt.retr_symlinks)
1522             {
1523 #ifdef HAVE_SYMLINK
1524               if (!f->linkto)
1525                 logputs (LOG_NOTQUIET,
1526                          _("Invalid name of the symlink, skipping.\n"));
1527               else
1528                 {
1529                   struct_stat st;
1530                   /* Check whether we already have the correct
1531                      symbolic link.  */
1532                   int rc = lstat (con->target, &st);
1533                   if (rc == 0)
1534                     {
1535                       size_t len = strlen (f->linkto) + 1;
1536                       if (S_ISLNK (st.st_mode))
1537                         {
1538                           char *link_target = (char *)alloca (len);
1539                           size_t n = readlink (con->target, link_target, len);
1540                           if ((n == len - 1)
1541                               && (memcmp (link_target, f->linkto, n) == 0))
1542                             {
1543                               logprintf (LOG_VERBOSE, _("\
1544 Already have correct symlink %s -> %s\n\n"),
1545                                          quote (con->target),
1546                                          quote (f->linkto));
1547                               dlthis = false;
1548                               break;
1549                             }
1550                         }
1551                     }
1552                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1553                              quote (con->target), quote (f->linkto));
1554                   /* Unlink before creating symlink!  */
1555                   unlink (con->target);
1556                   if (symlink (f->linkto, con->target) == -1)
1557                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1558                   logputs (LOG_VERBOSE, "\n");
1559                 } /* have f->linkto */
1560 #else  /* not HAVE_SYMLINK */
1561               logprintf (LOG_NOTQUIET,
1562                          _("Symlinks not supported, skipping symlink %s.\n"),
1563                          quote (con->target));
1564 #endif /* not HAVE_SYMLINK */
1565             }
1566           else                /* opt.retr_symlinks */
1567             {
1568               if (dlthis)
1569                 err = ftp_loop_internal (u, f, con);
1570             } /* opt.retr_symlinks */
1571           break;
1572         case FT_DIRECTORY:
1573           if (!opt.recursive)
1574             logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1575                        quote (f->name));
1576           break;
1577         case FT_PLAINFILE:
1578           /* Call the retrieve loop.  */
1579           if (dlthis)
1580             err = ftp_loop_internal (u, f, con);
1581           break;
1582         case FT_UNKNOWN:
1583           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1584                      quote (f->name));
1585           break;
1586         }       /* switch */
1587
1588       /* Set the time-stamp information to the local file.  Symlinks
1589          are not to be stamped because it sets the stamp on the
1590          original.  :( */
1591       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1592           && f->tstamp != -1
1593           && dlthis
1594           && file_exists_p (con->target))
1595         {
1596           const char *fl = NULL;
1597           set_local_file (&fl, con->target);
1598           if (fl)
1599             touch (fl, f->tstamp);
1600         }
1601       else if (f->tstamp == -1)
1602         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1603
1604       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1605         {
1606           if (opt.preserve_perm)
1607             chmod (con->target, f->perms);
1608         }
1609       else
1610         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1611
1612       xfree (con->target);
1613       con->target = old_target;
1614
1615       url_set_file (u, ofile);
1616       xfree (ofile);
1617
1618       /* Break on fatals.  */
1619       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1620         break;
1621       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1622       f = f->next;
1623     }
1624
1625   /* We do not want to call ftp_retrieve_dirs here */
1626   if (opt.recursive &&
1627       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1628     err = ftp_retrieve_dirs (u, orig, con);
1629   else if (opt.recursive)
1630     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1631              depth, opt.reclevel));
1632   --depth;
1633   return err;
1634 }
1635
1636 /* Retrieve the directories given in a file list.  This function works
1637    by simply going through the linked list and calling
1638    ftp_retrieve_glob on each directory entry.  The function knows
1639    about excluded directories.  */
1640 static uerr_t
1641 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1642 {
1643   char *container = NULL;
1644   int container_size = 0;
1645
1646   for (; f; f = f->next)
1647     {
1648       int size;
1649       char *odir, *newdir;
1650
1651       if (opt.quota && total_downloaded_bytes > opt.quota)
1652         break;
1653       if (f->type != FT_DIRECTORY)
1654         continue;
1655
1656       /* Allocate u->dir off stack, but reallocate only if a larger
1657          string is needed.  It's a pity there's no "realloca" for an
1658          item on the bottom of the stack.  */
1659       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1660       if (size > container_size)
1661         container = (char *)alloca (size);
1662       newdir = container;
1663
1664       odir = u->dir;
1665       if (*odir == '\0'
1666           || (*odir == '/' && *(odir + 1) == '\0'))
1667         /* If ODIR is empty or just "/", simply append f->name to
1668            ODIR.  (In the former case, to preserve u->dir being
1669            relative; in the latter case, to avoid double slash.)  */
1670         sprintf (newdir, "%s%s", odir, f->name);
1671       else
1672         /* Else, use a separator. */
1673         sprintf (newdir, "%s/%s", odir, f->name);
1674
1675       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1676       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1677                odir, f->name, newdir));
1678       if (!accdir (newdir))
1679         {
1680           logprintf (LOG_VERBOSE, _("\
1681 Not descending to %s as it is excluded/not-included.\n"),
1682                      quote (newdir));
1683           continue;
1684         }
1685
1686       con->st &= ~DONE_CWD;
1687
1688       odir = xstrdup (u->dir);  /* because url_set_dir will free
1689                                    u->dir. */
1690       url_set_dir (u, newdir);
1691       ftp_retrieve_glob (u, con, GLOB_GETALL);
1692       url_set_dir (u, odir);
1693       xfree (odir);
1694
1695       /* Set the time-stamp?  */
1696     }
1697
1698   if (opt.quota && total_downloaded_bytes > opt.quota)
1699     return QUOTEXC;
1700   else
1701     return RETROK;
1702 }
1703
1704 /* Return true if S has a leading '/'  or contains '../' */
1705 static bool
1706 has_insecure_name_p (const char *s)
1707 {
1708   if (*s == '/')
1709     return true;
1710
1711   if (strstr (s, "../") != 0)
1712     return true;
1713
1714   return false;
1715 }
1716
1717 /* A near-top-level function to retrieve the files in a directory.
1718    The function calls ftp_get_listing, to get a linked list of files.
1719    Then it weeds out the file names that do not match the pattern.
1720    ftp_retrieve_list is called with this updated list as an argument.
1721
1722    If the argument ACTION is GLOB_GETONE, just download the file (but
1723    first get the listing, so that the time-stamp is heeded); if it's
1724    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1725    directory.  */
1726 static uerr_t
1727 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1728 {
1729   struct fileinfo *f, *start;
1730   uerr_t res;
1731
1732   con->cmd |= LEAVE_PENDING;
1733
1734   res = ftp_get_listing (u, con, &start);
1735   if (res != RETROK)
1736     return res;
1737   /* First: weed out that do not conform the global rules given in
1738      opt.accepts and opt.rejects.  */
1739   if (opt.accepts || opt.rejects)
1740     {
1741       f = start;
1742       while (f)
1743         {
1744           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1745             {
1746               logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
1747                          quote (f->name));
1748               f = delelement (f, &start);
1749             }
1750           else
1751             f = f->next;
1752         }
1753     }
1754   /* Remove all files with possible harmful names */
1755   f = start;
1756   while (f)
1757     {
1758       if (has_insecure_name_p (f->name))
1759         {
1760           logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
1761                      quote (f->name));
1762           f = delelement (f, &start);
1763         }
1764       else
1765         f = f->next;
1766     }
1767   /* Now weed out the files that do not match our globbing pattern.
1768      If we are dealing with a globbing pattern, that is.  */
1769   if (*u->file)
1770     {
1771       if (action == GLOB_GLOBALL)
1772         {
1773           int (*matcher) (const char *, const char *, int)
1774             = opt.ignore_case ? fnmatch_nocase : fnmatch;
1775           int matchres = 0;
1776
1777           f = start;
1778           while (f)
1779             {
1780               matchres = matcher (u->file, f->name, 0);
1781               if (matchres == -1)
1782                 {
1783                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
1784                              u->file, quotearg_style (escape_quoting_style, f->name), 
1785                              strerror (errno));
1786                   break;
1787                 }
1788               if (matchres == FNM_NOMATCH)
1789                 f = delelement (f, &start); /* delete the element from the list */
1790               else
1791                 f = f->next;        /* leave the element in the list */
1792             }
1793           if (matchres == -1)
1794             {
1795               freefileinfo (start);
1796               return RETRBADPATTERN;
1797             }
1798         }
1799       else if (action == GLOB_GETONE)
1800         {
1801           int (*cmp) (const char *, const char *)
1802             = opt.ignore_case ? strcasecmp : strcmp;
1803           f = start;
1804           while (f)
1805             {
1806               if (0 != cmp(u->file, f->name))
1807                 f = delelement (f, &start);
1808               else
1809                 f = f->next;
1810             }
1811         }
1812     }
1813   if (start)
1814     {
1815       /* Just get everything.  */
1816       ftp_retrieve_list (u, start, con);
1817     }
1818   else
1819     {
1820       if (action == GLOB_GLOBALL)
1821         {
1822           /* No luck.  */
1823           /* #### This message SUCKS.  We should see what was the
1824              reason that nothing was retrieved.  */
1825           logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
1826                      quote (u->file));
1827         }
1828       else /* GLOB_GETONE or GLOB_GETALL */
1829         {
1830           /* Let's try retrieving it anyway.  */
1831           con->st |= ON_YOUR_OWN;
1832           res = ftp_loop_internal (u, NULL, con);
1833           return res;
1834         }
1835     }
1836   freefileinfo (start);
1837   if (opt.quota && total_downloaded_bytes > opt.quota)
1838     return QUOTEXC;
1839   else
1840     /* #### Should we return `res' here?  */
1841     return RETROK;
1842 }
1843
1844 /* The wrapper that calls an appropriate routine according to contents
1845    of URL.  Inherently, its capabilities are limited on what can be
1846    encoded into a URL.  */
1847 uerr_t
1848 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
1849 {
1850   ccon con;                     /* FTP connection */
1851   uerr_t res;
1852
1853   *dt = 0;
1854
1855   xzero (con);
1856
1857   con.csock = -1;
1858   con.st = ON_YOUR_OWN;
1859   con.rs = ST_UNIX;
1860   con.id = NULL;
1861   con.proxy = proxy;
1862
1863   /* If the file name is empty, the user probably wants a directory
1864      index.  We'll provide one, properly HTML-ized.  Unless
1865      opt.htmlify is 0, of course.  :-) */
1866   if (!*u->file && !recursive)
1867     {
1868       struct fileinfo *f;
1869       res = ftp_get_listing (u, &con, &f);
1870
1871       if (res == RETROK)
1872         {
1873           if (opt.htmlify && !opt.spider)
1874             {
1875               char *filename = (opt.output_document
1876                                 ? xstrdup (opt.output_document)
1877                                 : (con.target ? xstrdup (con.target)
1878                                    : url_file_name (u)));
1879               res = ftp_index (filename, u, f);
1880               if (res == FTPOK && opt.verbose)
1881                 {
1882                   if (!opt.output_document)
1883                     {
1884                       struct_stat st;
1885                       wgint sz;
1886                       if (stat (filename, &st) == 0)
1887                         sz = st.st_size;
1888                       else
1889                         sz = -1;
1890                       logprintf (LOG_NOTQUIET,
1891                                  _("Wrote HTML-ized index to %s [%s].\n"),
1892                                  quote (filename), number_to_static_string (sz));
1893                     }
1894                   else
1895                     logprintf (LOG_NOTQUIET,
1896                                _("Wrote HTML-ized index to %s.\n"),
1897                                quote (filename));
1898                 }
1899               xfree (filename);
1900             }
1901           freefileinfo (f);
1902         }
1903     }
1904   else
1905     {
1906       bool ispattern = false;
1907       if (glob)
1908         {
1909           /* Treat the URL as a pattern if the file name part of the
1910              URL path contains wildcards.  (Don't check for u->file
1911              because it is unescaped and therefore doesn't leave users
1912              the option to escape literal '*' as %2A.)  */
1913           char *file_part = strrchr (u->path, '/');
1914           if (!file_part)
1915             file_part = u->path;
1916           ispattern = has_wildcards_p (file_part);
1917         }
1918       if (ispattern || recursive || opt.timestamping)
1919         {
1920           /* ftp_retrieve_glob is a catch-all function that gets called
1921              if we need globbing, time-stamping or recursion.  Its
1922              third argument is just what we really need.  */
1923           res = ftp_retrieve_glob (u, &con,
1924                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
1925         }
1926       else
1927         res = ftp_loop_internal (u, NULL, &con);
1928     }
1929   if (res == FTPOK)
1930     res = RETROK;
1931   if (res == RETROK)
1932     *dt |= RETROKF;
1933   /* If a connection was left, quench it.  */
1934   if (con.csock != -1)
1935     fd_close (con.csock);
1936   xfree_null (con.id);
1937   con.id = NULL;
1938   xfree_null (con.target);
1939   con.target = NULL;
1940   return res;
1941 }
1942
1943 /* Delete an element from the fileinfo linked list.  Returns the
1944    address of the next element, or NULL if the list is exhausted.  It
1945    can modify the start of the list.  */
1946 static struct fileinfo *
1947 delelement (struct fileinfo *f, struct fileinfo **start)
1948 {
1949   struct fileinfo *prev = f->prev;
1950   struct fileinfo *next = f->next;
1951
1952   xfree (f->name);
1953   xfree_null (f->linkto);
1954   xfree (f);
1955
1956   if (next)
1957     next->prev = prev;
1958   if (prev)
1959     prev->next = next;
1960   else
1961     *start = next;
1962   return next;
1963 }
1964
1965 /* Free the fileinfo linked list of files.  */
1966 static void
1967 freefileinfo (struct fileinfo *f)
1968 {
1969   while (f)
1970     {
1971       struct fileinfo *next = f->next;
1972       xfree (f->name);
1973       if (f->linkto)
1974         xfree (f->linkto);
1975       xfree (f);
1976       f = next;
1977     }
1978 }