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