]> sjero.net Git - wget/blob - src/ftp.c
[svn] Make indentation consistent (all-spaces, no tabs).
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996-2006 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 3 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, see <http://www.gnu.org/licenses/>.
18
19 In addition, as a special exception, the Free Software Foundation
20 gives permission to link the code of its release of Wget with the
21 OpenSSL project's "OpenSSL" library (or with modified versions of it
22 that use the same license as the "OpenSSL" library), and distribute
23 the linked executables.  You must obey the GNU General Public License
24 in all respects for all of the code used other than "OpenSSL".  If you
25 modify this file, you may extend this exception to your version of the
26 file, but you are not obligated to do so.  If you do not wish to do
27 so, delete this exception statement from your version.  */
28
29 #include <config.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include <assert.h>
38 #include <errno.h>
39 #include <time.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->family)
120     {
121     case AF_INET:
122       if (!opt.server_response)
123         logputs (LOG_VERBOSE, "==> PASV ... ");
124       err = ftp_pasv (csock, addr, port);
125       break;
126     case AF_INET6:
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.family)
163     {
164     case AF_INET:
165       if (!opt.server_response)
166         logputs (LOG_VERBOSE, "==> PORT ... ");
167       err = ftp_port (csock, local_sock);
168       break;
169     case AF_INET6:
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 (time (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       /* The control connection is decidedly closed.  Print the time
1003          only if it hasn't already been printed.  */
1004       if (res != -1)
1005         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1006       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1007       /* If there is an error on the control connection, close it, but
1008          return FTPRETRINT, since there is a possibility that the
1009          whole file was retrieved nevertheless (but that is for
1010          ftp_loop_internal to decide).  */
1011       fd_close (csock);
1012       con->csock = -1;
1013       return FTPRETRINT;
1014     } /* err != FTPOK */
1015   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1016      close socket, since the control connection is still alive.  If
1017      there is something wrong with the control connection, it will
1018      become apparent later.  */
1019   if (*respline != '2')
1020     {
1021       xfree (respline);
1022       if (res != -1)
1023         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1024       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1025       return FTPRETRINT;
1026     }
1027   xfree (respline);
1028
1029   if (res == -1)
1030     {
1031       /* What now?  The data connection was erroneous, whereas the
1032          response says everything is OK.  We shall play it safe.  */
1033       return FTPRETRINT;
1034     }
1035
1036   if (!(cmd & LEAVE_PENDING))
1037     {
1038       /* Closing the socket is faster than sending 'QUIT' and the
1039          effect is the same.  */
1040       fd_close (csock);
1041       con->csock = -1;
1042     }
1043   /* If it was a listing, and opt.server_response is true,
1044      print it out.  */
1045   if (opt.server_response && (con->cmd & DO_LIST))
1046     {
1047       mkalldirs (con->target);
1048       fp = fopen (con->target, "r");
1049       if (!fp)
1050         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1051       else
1052         {
1053           char *line;
1054           /* The lines are being read with read_whole_line because of
1055              no-buffering on opt.lfile.  */
1056           while ((line = read_whole_line (fp)) != NULL)
1057             {
1058               char *p = strchr (line, '\0');
1059               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1060                 *--p = '\0';
1061               logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
1062               xfree (line);
1063             }
1064           fclose (fp);
1065         }
1066     } /* con->cmd & DO_LIST && server_response */
1067
1068   return RETRFINISHED;
1069 }
1070
1071 /* A one-file FTP loop.  This is the part where FTP retrieval is
1072    retried, and retried, and retried, and...
1073
1074    This loop either gets commands from con, or (if ON_YOUR_OWN is
1075    set), makes them up to retrieve the file given by the URL.  */
1076 static uerr_t
1077 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1078 {
1079   int count, orig_lp;
1080   wgint restval, len = 0;
1081   char *tms, *locf;
1082   const char *tmrate = NULL;
1083   uerr_t err;
1084   struct_stat st;
1085
1086   if (!con->target)
1087     con->target = url_file_name (u);
1088
1089   if (opt.noclobber && file_exists_p (con->target))
1090     {
1091       logprintf (LOG_VERBOSE,
1092                  _("File `%s' already there; not retrieving.\n"), con->target);
1093       /* If the file is there, we suppose it's retrieved OK.  */
1094       return RETROK;
1095     }
1096
1097   /* Remove it if it's a link.  */
1098   remove_link (con->target);
1099   if (!opt.output_document)
1100     locf = con->target;
1101   else
1102     locf = opt.output_document;
1103
1104   count = 0;
1105
1106   if (con->st & ON_YOUR_OWN)
1107     con->st = ON_YOUR_OWN;
1108
1109   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1110
1111   /* THE loop.  */
1112   do
1113     {
1114       /* Increment the pass counter.  */
1115       ++count;
1116       sleep_between_retrievals (count);
1117       if (con->st & ON_YOUR_OWN)
1118         {
1119           con->cmd = 0;
1120           con->cmd |= (DO_RETR | LEAVE_PENDING);
1121           if (con->csock != -1)
1122             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1123           else
1124             con->cmd |= (DO_LOGIN | DO_CWD);
1125         }
1126       else /* not on your own */
1127         {
1128           if (con->csock != -1)
1129             con->cmd &= ~DO_LOGIN;
1130           else
1131             con->cmd |= DO_LOGIN;
1132           if (con->st & DONE_CWD)
1133             con->cmd &= ~DO_CWD;
1134           else
1135             con->cmd |= DO_CWD;
1136         }
1137
1138       /* Decide whether or not to restart.  */
1139       if (opt.always_rest
1140           && stat (locf, &st) == 0
1141           && S_ISREG (st.st_mode))
1142         /* When -c is used, continue from on-disk size.  (Can't use
1143            hstat.len even if count>1 because we don't want a failed
1144            first attempt to clobber existing data.)  */
1145         restval = st.st_size;
1146       else if (count > 1)
1147         restval = len;          /* start where the previous run left off */
1148       else
1149         restval = 0;
1150
1151       /* Get the current time string.  */
1152       tms = time_str (time (NULL));
1153       /* Print fetch message, if opt.verbose.  */
1154       if (opt.verbose)
1155         {
1156           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1157           char tmp[256];
1158           strcpy (tmp, "        ");
1159           if (count > 1)
1160             sprintf (tmp, _("(try:%2d)"), count);
1161           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1162                      tms, hurl, tmp, locf);
1163 #ifdef WINDOWS
1164           ws_changetitle (hurl);
1165 #endif
1166           xfree (hurl);
1167         }
1168       /* Send getftp the proper length, if fileinfo was provided.  */
1169       if (f)
1170         len = f->size;
1171       else
1172         len = 0;
1173       err = getftp (u, &len, restval, con);
1174
1175       if (con->csock == -1)
1176         con->st &= ~DONE_CWD;
1177       else
1178         con->st |= DONE_CWD;
1179
1180       switch (err)
1181         {
1182         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1183         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1184           /* Fatal errors, give up.  */
1185           return err;
1186         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1187         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1188         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1189         case FOPEN_EXCL_ERR:
1190           printwhat (count, opt.ntry);
1191           /* non-fatal errors */
1192           if (err == FOPEN_EXCL_ERR)
1193             {
1194               /* Re-determine the file name. */
1195               xfree_null (con->target);
1196               con->target = url_file_name (u);
1197               locf = con->target;
1198             }
1199           continue;
1200         case FTPRETRINT:
1201           /* If the control connection was closed, the retrieval
1202              will be considered OK if f->size == len.  */
1203           if (!f || len != f->size)
1204             {
1205               printwhat (count, opt.ntry);
1206               continue;
1207             }
1208           break;
1209         case RETRFINISHED:
1210           /* Great!  */
1211           break;
1212         default:
1213           /* Not as great.  */
1214           abort ();
1215         }
1216       tms = time_str (time (NULL));
1217       if (!opt.spider)
1218         tmrate = retr_rate (len - restval, con->dltime);
1219
1220       /* If we get out of the switch above without continue'ing, we've
1221          successfully downloaded a file.  Remember this fact. */
1222       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1223
1224       if (con->st & ON_YOUR_OWN)
1225         {
1226           fd_close (con->csock);
1227           con->csock = -1;
1228         }
1229       if (!opt.spider)
1230         logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1231                    tms, tmrate, locf, number_to_static_string (len));
1232       if (!opt.verbose && !opt.quiet)
1233         {
1234           /* Need to hide the password from the URL.  The `if' is here
1235              so that we don't do the needless allocation every
1236              time. */
1237           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1238           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1239                      tms, hurl, number_to_static_string (len), locf, count);
1240           xfree (hurl);
1241         }
1242
1243       if ((con->cmd & DO_LIST))
1244         /* This is a directory listing file. */
1245         {
1246           if (!opt.remove_listing)
1247             /* --dont-remove-listing was specified, so do count this towards the
1248                number of bytes and files downloaded. */
1249             {
1250               total_downloaded_bytes += len;
1251               opt.numurls++;
1252             }
1253
1254           /* Deletion of listing files is not controlled by --delete-after, but
1255              by the more specific option --dont-remove-listing, and the code
1256              to do this deletion is in another function. */
1257         }
1258       else if (!opt.spider)
1259         /* This is not a directory listing file. */
1260         {
1261           /* Unlike directory listing files, don't pretend normal files weren't
1262              downloaded if they're going to be deleted.  People seeding proxies,
1263              for instance, may want to know how many bytes and files they've
1264              downloaded through it. */
1265           total_downloaded_bytes += len;
1266           opt.numurls++;
1267
1268           if (opt.delete_after)
1269             {
1270               DEBUGP (("\
1271 Removing file due to --delete-after in ftp_loop_internal():\n"));
1272               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1273               if (unlink (locf))
1274                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1275             }
1276         }
1277
1278       /* Restore the original leave-pendingness.  */
1279       if (orig_lp)
1280         con->cmd |= LEAVE_PENDING;
1281       else
1282         con->cmd &= ~LEAVE_PENDING;
1283       return RETROK;
1284     } while (!opt.ntry || (count < opt.ntry));
1285
1286   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1287     {
1288       fd_close (con->csock);
1289       con->csock = -1;
1290     }
1291   return TRYLIMEXC;
1292 }
1293
1294 /* Return the directory listing in a reusable format.  The directory
1295    is specifed in u->dir.  */
1296 static uerr_t
1297 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1298 {
1299   uerr_t err;
1300   char *uf;                     /* url file name */
1301   char *lf;                     /* list file name */
1302   char *old_target = con->target;
1303
1304   con->st &= ~ON_YOUR_OWN;
1305   con->cmd |= (DO_LIST | LEAVE_PENDING);
1306   con->cmd &= ~DO_RETR;
1307
1308   /* Find the listing file name.  We do it by taking the file name of
1309      the URL and replacing the last component with the listing file
1310      name.  */
1311   uf = url_file_name (u);
1312   lf = file_merge (uf, LIST_FILENAME);
1313   xfree (uf);
1314   DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1315
1316   con->target = lf;
1317   err = ftp_loop_internal (u, NULL, con);
1318   con->target = old_target;
1319
1320   if (err == RETROK)
1321     *f = ftp_parse_ls (lf, con->rs);
1322   else
1323     *f = NULL;
1324   if (opt.remove_listing)
1325     {
1326       if (unlink (lf))
1327         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1328       else
1329         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1330     }
1331   xfree (lf);
1332   con->cmd &= ~DO_LIST;
1333   return err;
1334 }
1335
1336 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1337 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1338 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1339 static void freefileinfo (struct fileinfo *f);
1340
1341 /* Retrieve a list of files given in struct fileinfo linked list.  If
1342    a file is a symbolic link, do not retrieve it, but rather try to
1343    set up a similar link on the local disk, if the symlinks are
1344    supported.
1345
1346    If opt.recursive is set, after all files have been retrieved,
1347    ftp_retrieve_dirs will be called to retrieve the directories.  */
1348 static uerr_t
1349 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1350 {
1351   static int depth = 0;
1352   uerr_t err;
1353   struct fileinfo *orig;
1354   wgint local_size;
1355   time_t tml;
1356   bool dlthis;
1357
1358   /* Increase the depth.  */
1359   ++depth;
1360   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1361     {
1362       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1363                depth, opt.reclevel));
1364       --depth;
1365       return RECLEVELEXC;
1366     }
1367
1368   assert (f != NULL);
1369   orig = f;
1370
1371   con->st &= ~ON_YOUR_OWN;
1372   if (!(con->st & DONE_CWD))
1373     con->cmd |= DO_CWD;
1374   else
1375     con->cmd &= ~DO_CWD;
1376   con->cmd |= (DO_RETR | LEAVE_PENDING);
1377
1378   if (con->csock < 0)
1379     con->cmd |= DO_LOGIN;
1380   else
1381     con->cmd &= ~DO_LOGIN;
1382
1383   err = RETROK;                 /* in case it's not used */
1384
1385   while (f)
1386     {
1387       char *old_target, *ofile;
1388
1389       if (opt.quota && total_downloaded_bytes > opt.quota)
1390         {
1391           --depth;
1392           return QUOTEXC;
1393         }
1394       old_target = con->target;
1395
1396       ofile = xstrdup (u->file);
1397       url_set_file (u, f->name);
1398
1399       con->target = url_file_name (u);
1400       err = RETROK;
1401
1402       dlthis = true;
1403       if (opt.timestamping && f->type == FT_PLAINFILE)
1404         {
1405           struct_stat st;
1406           /* If conversion of HTML files retrieved via FTP is ever implemented,
1407              we'll need to stat() <file>.orig here when -K has been specified.
1408              I'm not implementing it now since files on an FTP server are much
1409              more likely than files on an HTTP server to legitimately have a
1410              .orig suffix. */
1411           if (!stat (con->target, &st))
1412             {
1413               bool eq_size;
1414               bool cor_val;
1415               /* Else, get it from the file.  */
1416               local_size = st.st_size;
1417               tml = st.st_mtime;
1418 #ifdef WINDOWS
1419               /* Modification time granularity is 2 seconds for Windows, so
1420                  increase local time by 1 second for later comparison. */
1421               tml++;
1422 #endif
1423               /* Compare file sizes only for servers that tell us correct
1424                  values. Assume sizes being equal for servers that lie
1425                  about file size.  */
1426               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1427               eq_size = cor_val ? (local_size == f->size) : true;
1428               if (f->tstamp <= tml && eq_size)
1429                 {
1430                   /* Remote file is older, file sizes can be compared and
1431                      are both equal. */
1432                   logprintf (LOG_VERBOSE, _("\
1433 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1434                   dlthis = false;
1435                 }
1436               else if (eq_size)
1437                 {
1438                   /* Remote file is newer or sizes cannot be matched */
1439                   logprintf (LOG_VERBOSE, _("\
1440 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1441                              con->target);
1442                 }
1443               else
1444                 {
1445                   /* Sizes do not match */
1446                   logprintf (LOG_VERBOSE, _("\
1447 The sizes do not match (local %s) -- retrieving.\n\n"),
1448                              number_to_static_string (local_size));
1449                 }
1450             }
1451         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1452       switch (f->type)
1453         {
1454         case FT_SYMLINK:
1455           /* If opt.retr_symlinks is defined, we treat symlinks as
1456              if they were normal files.  There is currently no way
1457              to distinguish whether they might be directories, and
1458              follow them.  */
1459           if (!opt.retr_symlinks)
1460             {
1461 #ifdef HAVE_SYMLINK
1462               if (!f->linkto)
1463                 logputs (LOG_NOTQUIET,
1464                          _("Invalid name of the symlink, skipping.\n"));
1465               else
1466                 {
1467                   struct_stat st;
1468                   /* Check whether we already have the correct
1469                      symbolic link.  */
1470                   int rc = lstat (con->target, &st);
1471                   if (rc == 0)
1472                     {
1473                       size_t len = strlen (f->linkto) + 1;
1474                       if (S_ISLNK (st.st_mode))
1475                         {
1476                           char *link_target = (char *)alloca (len);
1477                           size_t n = readlink (con->target, link_target, len);
1478                           if ((n == len - 1)
1479                               && (memcmp (link_target, f->linkto, n) == 0))
1480                             {
1481                               logprintf (LOG_VERBOSE, _("\
1482 Already have correct symlink %s -> %s\n\n"),
1483                                          con->target, escnonprint (f->linkto));
1484                               dlthis = false;
1485                               break;
1486                             }
1487                         }
1488                     }
1489                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1490                              con->target, escnonprint (f->linkto));
1491                   /* Unlink before creating symlink!  */
1492                   unlink (con->target);
1493                   if (symlink (f->linkto, con->target) == -1)
1494                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1495                   logputs (LOG_VERBOSE, "\n");
1496                 } /* have f->linkto */
1497 #else  /* not HAVE_SYMLINK */
1498               logprintf (LOG_NOTQUIET,
1499                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1500                          con->target);
1501 #endif /* not HAVE_SYMLINK */
1502             }
1503           else                /* opt.retr_symlinks */
1504             {
1505               if (dlthis)
1506                 err = ftp_loop_internal (u, f, con);
1507             } /* opt.retr_symlinks */
1508           break;
1509         case FT_DIRECTORY:
1510           if (!opt.recursive)
1511             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1512                        escnonprint (f->name));
1513           break;
1514         case FT_PLAINFILE:
1515           /* Call the retrieve loop.  */
1516           if (dlthis)
1517             err = ftp_loop_internal (u, f, con);
1518           break;
1519         case FT_UNKNOWN:
1520           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1521                      escnonprint (f->name));
1522           break;
1523         }       /* switch */
1524
1525       /* Set the time-stamp information to the local file.  Symlinks
1526          are not to be stamped because it sets the stamp on the
1527          original.  :( */
1528       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1529           && f->tstamp != -1
1530           && dlthis
1531           && file_exists_p (con->target))
1532         {
1533           /* #### This code repeats in http.c and ftp.c.  Move it to a
1534              function!  */
1535           const char *fl = NULL;
1536           if (opt.output_document)
1537             {
1538               if (output_stream_regular)
1539                 fl = opt.output_document;
1540             }
1541           else
1542             fl = con->target;
1543           if (fl)
1544             touch (fl, f->tstamp);
1545         }
1546       else if (f->tstamp == -1)
1547         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1548
1549       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1550         {
1551           if (opt.preserve_perm)
1552             chmod (con->target, f->perms);
1553         }
1554       else
1555         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1556
1557       xfree (con->target);
1558       con->target = old_target;
1559
1560       url_set_file (u, ofile);
1561       xfree (ofile);
1562
1563       /* Break on fatals.  */
1564       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1565         break;
1566       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1567       f = f->next;
1568     }
1569
1570   /* We do not want to call ftp_retrieve_dirs here */
1571   if (opt.recursive &&
1572       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1573     err = ftp_retrieve_dirs (u, orig, con);
1574   else if (opt.recursive)
1575     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1576              depth, opt.reclevel));
1577   --depth;
1578   return err;
1579 }
1580
1581 /* Retrieve the directories given in a file list.  This function works
1582    by simply going through the linked list and calling
1583    ftp_retrieve_glob on each directory entry.  The function knows
1584    about excluded directories.  */
1585 static uerr_t
1586 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1587 {
1588   char *container = NULL;
1589   int container_size = 0;
1590
1591   for (; f; f = f->next)
1592     {
1593       int size;
1594       char *odir, *newdir;
1595
1596       if (opt.quota && total_downloaded_bytes > opt.quota)
1597         break;
1598       if (f->type != FT_DIRECTORY)
1599         continue;
1600
1601       /* Allocate u->dir off stack, but reallocate only if a larger
1602          string is needed.  It's a pity there's no "realloca" for an
1603          item on the bottom of the stack.  */
1604       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1605       if (size > container_size)
1606         container = (char *)alloca (size);
1607       newdir = container;
1608
1609       odir = u->dir;
1610       if (*odir == '\0'
1611           || (*odir == '/' && *(odir + 1) == '\0'))
1612         /* If ODIR is empty or just "/", simply append f->name to
1613            ODIR.  (In the former case, to preserve u->dir being
1614            relative; in the latter case, to avoid double slash.)  */
1615         sprintf (newdir, "%s%s", odir, f->name);
1616       else
1617         /* Else, use a separator. */
1618         sprintf (newdir, "%s/%s", odir, f->name);
1619
1620       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1621       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1622                odir, f->name, newdir));
1623       if (!accdir (newdir))
1624         {
1625           logprintf (LOG_VERBOSE, _("\
1626 Not descending to `%s' as it is excluded/not-included.\n"),
1627                      escnonprint (newdir));
1628           continue;
1629         }
1630
1631       con->st &= ~DONE_CWD;
1632
1633       odir = xstrdup (u->dir);  /* because url_set_dir will free
1634                                    u->dir. */
1635       url_set_dir (u, newdir);
1636       ftp_retrieve_glob (u, con, GLOB_GETALL);
1637       url_set_dir (u, odir);
1638       xfree (odir);
1639
1640       /* Set the time-stamp?  */
1641     }
1642
1643   if (opt.quota && total_downloaded_bytes > opt.quota)
1644     return QUOTEXC;
1645   else
1646     return RETROK;
1647 }
1648
1649 /* Return true if S has a leading '/'  or contains '../' */
1650 static bool
1651 has_insecure_name_p (const char *s)
1652 {
1653   if (*s == '/')
1654     return true;
1655
1656   if (strstr (s, "../") != 0)
1657     return true;
1658
1659   return false;
1660 }
1661
1662 /* A near-top-level function to retrieve the files in a directory.
1663    The function calls ftp_get_listing, to get a linked list of files.
1664    Then it weeds out the file names that do not match the pattern.
1665    ftp_retrieve_list is called with this updated list as an argument.
1666
1667    If the argument ACTION is GLOB_GETONE, just download the file (but
1668    first get the listing, so that the time-stamp is heeded); if it's
1669    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1670    directory.  */
1671 static uerr_t
1672 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1673 {
1674   struct fileinfo *f, *start;
1675   uerr_t res;
1676
1677   con->cmd |= LEAVE_PENDING;
1678
1679   res = ftp_get_listing (u, con, &start);
1680   if (res != RETROK)
1681     return res;
1682   /* First: weed out that do not conform the global rules given in
1683      opt.accepts and opt.rejects.  */
1684   if (opt.accepts || opt.rejects)
1685     {
1686       f = start;
1687       while (f)
1688         {
1689           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1690             {
1691               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1692                          escnonprint (f->name));
1693               f = delelement (f, &start);
1694             }
1695           else
1696             f = f->next;
1697         }
1698     }
1699   /* Remove all files with possible harmful names */
1700   f = start;
1701   while (f)
1702     {
1703       if (has_insecure_name_p (f->name))
1704         {
1705           logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"),
1706                      escnonprint (f->name));
1707           f = delelement (f, &start);
1708         }
1709       else
1710         f = f->next;
1711     }
1712   /* Now weed out the files that do not match our globbing pattern.
1713      If we are dealing with a globbing pattern, that is.  */
1714   if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE))
1715     {
1716       int (*matcher) (const char *, const char *, int)
1717         = opt.ignore_case ? fnmatch_nocase : fnmatch;
1718       int matchres = 0;
1719
1720       f = start;
1721       while (f)
1722         {
1723           matchres = matcher (u->file, f->name, 0);
1724           if (matchres == -1)
1725             {
1726               logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1727                          strerror (errno));
1728               break;
1729             }
1730           if (matchres == FNM_NOMATCH)
1731             f = delelement (f, &start); /* delete the element from the list */
1732           else
1733             f = f->next;        /* leave the element in the list */
1734         }
1735       if (matchres == -1)
1736         {
1737           freefileinfo (start);
1738           return RETRBADPATTERN;
1739         }
1740     }
1741   if (start)
1742     {
1743       /* Just get everything.  */
1744       ftp_retrieve_list (u, start, con);
1745     }
1746   else if (!start)
1747     {
1748       if (action == GLOB_GLOBALL)
1749         {
1750           /* No luck.  */
1751           /* #### This message SUCKS.  We should see what was the
1752              reason that nothing was retrieved.  */
1753           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
1754                      escnonprint (u->file));
1755         }
1756       else /* GLOB_GETONE or GLOB_GETALL */
1757         {
1758           /* Let's try retrieving it anyway.  */
1759           con->st |= ON_YOUR_OWN;
1760           res = ftp_loop_internal (u, NULL, con);
1761           return res;
1762         }
1763     }
1764   freefileinfo (start);
1765   if (opt.quota && total_downloaded_bytes > opt.quota)
1766     return QUOTEXC;
1767   else
1768     /* #### Should we return `res' here?  */
1769     return RETROK;
1770 }
1771
1772 /* The wrapper that calls an appropriate routine according to contents
1773    of URL.  Inherently, its capabilities are limited on what can be
1774    encoded into a URL.  */
1775 uerr_t
1776 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
1777 {
1778   ccon con;                     /* FTP connection */
1779   uerr_t res;
1780
1781   *dt = 0;
1782
1783   xzero (con);
1784
1785   con.csock = -1;
1786   con.st = ON_YOUR_OWN;
1787   con.rs = ST_UNIX;
1788   con.id = NULL;
1789   con.proxy = proxy;
1790
1791   /* If the file name is empty, the user probably wants a directory
1792      index.  We'll provide one, properly HTML-ized.  Unless
1793      opt.htmlify is 0, of course.  :-) */
1794   if (!*u->file && !recursive)
1795     {
1796       struct fileinfo *f;
1797       res = ftp_get_listing (u, &con, &f);
1798
1799       if (res == RETROK)
1800         {
1801           if (opt.htmlify && !opt.spider)
1802             {
1803               char *filename = (opt.output_document
1804                                 ? xstrdup (opt.output_document)
1805                                 : (con.target ? xstrdup (con.target)
1806                                    : url_file_name (u)));
1807               res = ftp_index (filename, u, f);
1808               if (res == FTPOK && opt.verbose)
1809                 {
1810                   if (!opt.output_document)
1811                     {
1812                       struct_stat st;
1813                       wgint sz;
1814                       if (stat (filename, &st) == 0)
1815                         sz = st.st_size;
1816                       else
1817                         sz = -1;
1818                       logprintf (LOG_NOTQUIET,
1819                                  _("Wrote HTML-ized index to `%s' [%s].\n"),
1820                                  filename, number_to_static_string (sz));
1821                     }
1822                   else
1823                     logprintf (LOG_NOTQUIET,
1824                                _("Wrote HTML-ized index to `%s'.\n"),
1825                                filename);
1826                 }
1827               xfree (filename);
1828             }
1829           freefileinfo (f);
1830         }
1831     }
1832   else
1833     {
1834       bool ispattern = false;
1835       if (glob)
1836         {
1837           /* Treat the URL as a pattern if the file name part of the
1838              URL path contains wildcards.  (Don't check for u->file
1839              because it is unescaped and therefore doesn't leave users
1840              the option to escape literal '*' as %2A.)  */
1841           char *file_part = strrchr (u->path, '/');
1842           if (!file_part)
1843             file_part = u->path;
1844           ispattern = has_wildcards_p (file_part);
1845         }
1846       if (ispattern || recursive || opt.timestamping)
1847         {
1848           /* ftp_retrieve_glob is a catch-all function that gets called
1849              if we need globbing, time-stamping or recursion.  Its
1850              third argument is just what we really need.  */
1851           res = ftp_retrieve_glob (u, &con,
1852                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
1853         }
1854       else
1855         res = ftp_loop_internal (u, NULL, &con);
1856     }
1857   if (res == FTPOK)
1858     res = RETROK;
1859   if (res == RETROK)
1860     *dt |= RETROKF;
1861   /* If a connection was left, quench it.  */
1862   if (con.csock != -1)
1863     fd_close (con.csock);
1864   xfree_null (con.id);
1865   con.id = NULL;
1866   xfree_null (con.target);
1867   con.target = NULL;
1868   return res;
1869 }
1870
1871 /* Delete an element from the fileinfo linked list.  Returns the
1872    address of the next element, or NULL if the list is exhausted.  It
1873    can modify the start of the list.  */
1874 static struct fileinfo *
1875 delelement (struct fileinfo *f, struct fileinfo **start)
1876 {
1877   struct fileinfo *prev = f->prev;
1878   struct fileinfo *next = f->next;
1879
1880   xfree (f->name);
1881   xfree_null (f->linkto);
1882   xfree (f);
1883
1884   if (next)
1885     next->prev = prev;
1886   if (prev)
1887     prev->next = next;
1888   else
1889     *start = next;
1890   return next;
1891 }
1892
1893 /* Free the fileinfo linked list of files.  */
1894 static void
1895 freefileinfo (struct fileinfo *f)
1896 {
1897   while (f)
1898     {
1899       struct fileinfo *next = f->next;
1900       xfree (f->name);
1901       if (f->linkto)
1902         xfree (f->linkto);
1903       xfree (f);
1904       f = next;
1905     }
1906 }