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