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