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