]> sjero.net Git - wget/blob - src/ftp.c
Fix problem when content-disposition is used with recursive downloading.
[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 (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
771     {
772       /* Server confirms that file has length restval. We should stop now.
773          Some servers (f.e. NcFTPd) return error when receive REST 0 */
774       logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
775       fd_close (csock);
776       con->csock = -1;
777       return RETRFINISHED;
778     }
779
780   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
781   if (cmd & (DO_LIST | DO_RETR))
782     {
783       if (opt.ftp_pasv)
784         {
785           ip_address passive_addr;
786           int        passive_port;
787           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
788           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
789           switch (err)
790             {
791             case FTPRERR:
792               logputs (LOG_VERBOSE, "\n");
793               logputs (LOG_NOTQUIET, _("\
794 Error in server response, closing control connection.\n"));
795               fd_close (csock);
796               con->csock = -1;
797               return err;
798             case WRITEFAILED:
799               logputs (LOG_VERBOSE, "\n");
800               logputs (LOG_NOTQUIET,
801                        _("Write failed, closing control connection.\n"));
802               fd_close (csock);
803               con->csock = -1;
804               return err;
805             case FTPNOPASV:
806               logputs (LOG_VERBOSE, "\n");
807               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
808               break;
809             case FTPINVPASV:
810               logputs (LOG_VERBOSE, "\n");
811               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
812               break;
813             case FTPOK:
814               break;
815             default:
816               abort ();
817             }   /* switch (err) */
818           if (err==FTPOK)
819             {
820               DEBUGP (("trying to connect to %s port %d\n",
821                       print_address (&passive_addr), passive_port));
822               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
823               if (dtsock < 0)
824                 {
825                   int save_errno = errno;
826                   fd_close (csock);
827                   con->csock = -1;
828                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
829                              print_address (&passive_addr), passive_port,
830                              strerror (save_errno));
831                   return (retryable_socket_connect_error (save_errno)
832                           ? CONERROR : CONIMPOSSIBLE);
833                 }
834
835               pasv_mode_open = true;  /* Flag to avoid accept port */
836               if (!opt.server_response)
837                 logputs (LOG_VERBOSE, _("done.    "));
838             } /* err==FTP_OK */
839         }
840
841       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
842         {
843           err = ftp_do_port (csock, &local_sock);
844           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
845              FTPPORTERR */
846           switch (err)
847             {
848             case FTPRERR:
849               logputs (LOG_VERBOSE, "\n");
850               logputs (LOG_NOTQUIET, _("\
851 Error in server response, closing control connection.\n"));
852               fd_close (csock);
853               con->csock = -1;
854               fd_close (dtsock);
855               fd_close (local_sock);
856               return err;
857             case WRITEFAILED:
858               logputs (LOG_VERBOSE, "\n");
859               logputs (LOG_NOTQUIET,
860                        _("Write failed, closing control connection.\n"));
861               fd_close (csock);
862               con->csock = -1;
863               fd_close (dtsock);
864               fd_close (local_sock);
865               return err;
866             case CONSOCKERR:
867               logputs (LOG_VERBOSE, "\n");
868               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
869               fd_close (csock);
870               con->csock = -1;
871               fd_close (dtsock);
872               fd_close (local_sock);
873               return err;
874             case FTPSYSERR:
875               logputs (LOG_VERBOSE, "\n");
876               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
877                          strerror (errno));
878               fd_close (dtsock);
879               return err;
880             case FTPPORTERR:
881               logputs (LOG_VERBOSE, "\n");
882               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
883               fd_close (csock);
884               con->csock = -1;
885               fd_close (dtsock);
886               fd_close (local_sock);
887               return err;
888             case FTPOK:
889               break;
890             default:
891               abort ();
892             } /* port switch */
893           if (!opt.server_response)
894             logputs (LOG_VERBOSE, _("done.    "));
895         } /* dtsock == -1 */
896     } /* cmd & (DO_LIST | DO_RETR) */
897
898   /* Restart if needed.  */
899   if (restval && (cmd & DO_RETR))
900     {
901       if (!opt.server_response)
902         logprintf (LOG_VERBOSE, "==> REST %s ... ",
903                    number_to_static_string (restval));
904       err = ftp_rest (csock, restval);
905
906       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
907       switch (err)
908         {
909         case FTPRERR:
910           logputs (LOG_VERBOSE, "\n");
911           logputs (LOG_NOTQUIET, _("\
912 Error in server response, closing control connection.\n"));
913           fd_close (csock);
914           con->csock = -1;
915           fd_close (dtsock);
916           fd_close (local_sock);
917           return err;
918         case WRITEFAILED:
919           logputs (LOG_VERBOSE, "\n");
920           logputs (LOG_NOTQUIET,
921                    _("Write failed, closing control connection.\n"));
922           fd_close (csock);
923           con->csock = -1;
924           fd_close (dtsock);
925           fd_close (local_sock);
926           return err;
927         case FTPRESTFAIL:
928           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
929           rest_failed = true;
930           break;
931         case FTPOK:
932           break;
933         default:
934           abort ();
935         }
936       if (err != FTPRESTFAIL && !opt.server_response)
937         logputs (LOG_VERBOSE, _("done.    "));
938     } /* restval && cmd & DO_RETR */
939
940   if (cmd & DO_RETR)
941     {
942       /* If we're in spider mode, don't really retrieve anything except
943          the directory listing and verify whether the given "file" exists.  */
944       if (opt.spider)
945         {
946           bool exists = false;
947           uerr_t res;
948           struct fileinfo *f;
949           res = ftp_get_listing (u, con, &f);
950           /* Set the DO_RETR command flag again, because it gets unset when
951              calling ftp_get_listing() and would otherwise cause an assertion
952              failure earlier on when this function gets repeatedly called
953              (e.g., when recursing).  */
954           con->cmd |= DO_RETR;
955           if (res == RETROK)
956             {
957               while (f)
958                 {
959                   if (!strcmp (f->name, u->file))
960                     {
961                       exists = true;
962                       break;
963                     }
964                   f = f->next;
965                 }
966               if (exists)
967                 {
968                   logputs (LOG_VERBOSE, "\n");
969                   logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
970                              quote (u->file));
971                 }
972               else
973                 {
974                   logputs (LOG_VERBOSE, "\n");
975                   logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
976                              quote (u->file));
977                 }
978             }
979           fd_close (csock);
980           con->csock = -1;
981           fd_close (dtsock);
982           fd_close (local_sock);
983           return RETRFINISHED;
984         }
985
986       if (opt.verbose)
987         {
988           if (!opt.server_response)
989             {
990               if (restval)
991                 logputs (LOG_VERBOSE, "\n");
992               logprintf (LOG_VERBOSE, "==> RETR %s ... ",
993                          quotearg_style (escape_quoting_style, u->file));
994             }
995         }
996
997       err = ftp_retr (csock, u->file);
998       /* FTPRERR, WRITEFAILED, FTPNSFOD */
999       switch (err)
1000         {
1001         case FTPRERR:
1002           logputs (LOG_VERBOSE, "\n");
1003           logputs (LOG_NOTQUIET, _("\
1004 Error in server response, closing control connection.\n"));
1005           fd_close (csock);
1006           con->csock = -1;
1007           fd_close (dtsock);
1008           fd_close (local_sock);
1009           return err;
1010         case WRITEFAILED:
1011           logputs (LOG_VERBOSE, "\n");
1012           logputs (LOG_NOTQUIET,
1013                    _("Write failed, closing control connection.\n"));
1014           fd_close (csock);
1015           con->csock = -1;
1016           fd_close (dtsock);
1017           fd_close (local_sock);
1018           return err;
1019         case FTPNSFOD:
1020           logputs (LOG_VERBOSE, "\n");
1021           logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1022                      quote (u->file));
1023           fd_close (dtsock);
1024           fd_close (local_sock);
1025           return err;
1026         case FTPOK:
1027           break;
1028         default:
1029           abort ();
1030         }
1031
1032       if (!opt.server_response)
1033         logputs (LOG_VERBOSE, _("done.\n"));
1034
1035       if (! got_expected_bytes)
1036         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1037     } /* do retrieve */
1038
1039   if (cmd & DO_LIST)
1040     {
1041       if (!opt.server_response)
1042         logputs (LOG_VERBOSE, "==> LIST ... ");
1043       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1044          without arguments is better than `LIST .'; confirmed by
1045          RFC959.  */
1046       err = ftp_list (csock, NULL, con->rs);
1047       /* FTPRERR, WRITEFAILED */
1048       switch (err)
1049         {
1050         case FTPRERR:
1051           logputs (LOG_VERBOSE, "\n");
1052           logputs (LOG_NOTQUIET, _("\
1053 Error in server response, closing control connection.\n"));
1054           fd_close (csock);
1055           con->csock = -1;
1056           fd_close (dtsock);
1057           fd_close (local_sock);
1058           return err;
1059         case WRITEFAILED:
1060           logputs (LOG_VERBOSE, "\n");
1061           logputs (LOG_NOTQUIET,
1062                    _("Write failed, closing control connection.\n"));
1063           fd_close (csock);
1064           con->csock = -1;
1065           fd_close (dtsock);
1066           fd_close (local_sock);
1067           return err;
1068         case FTPNSFOD:
1069           logputs (LOG_VERBOSE, "\n");
1070           logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1071                      quote ("."));
1072           fd_close (dtsock);
1073           fd_close (local_sock);
1074           return err;
1075         case FTPOK:
1076           break;
1077         default:
1078           abort ();
1079         }
1080       if (!opt.server_response)
1081         logputs (LOG_VERBOSE, _("done.\n"));
1082
1083       if (! got_expected_bytes)
1084         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1085     } /* cmd & DO_LIST */
1086
1087   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1088     return RETRFINISHED;
1089
1090   /* Some FTP servers return the total length of file after REST
1091      command, others just return the remaining size. */
1092   if (passed_expected_bytes && restval && expected_bytes
1093       && (expected_bytes == passed_expected_bytes - restval))
1094     {
1095       DEBUGP (("Lying FTP server found, adjusting.\n"));
1096       expected_bytes = passed_expected_bytes;
1097     }
1098
1099   /* If no transmission was required, then everything is OK.  */
1100   if (!pasv_mode_open)  /* we are not using pasive mode so we need
1101                               to accept */
1102     {
1103       /* Wait for the server to connect to the address we're waiting
1104          at.  */
1105       dtsock = accept_connection (local_sock);
1106       if (dtsock < 0)
1107         {
1108           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1109           return CONERROR;
1110         }
1111     }
1112
1113   /* Open the file -- if output_stream is set, use it instead.  */
1114
1115   /* 2005-04-17 SMS.
1116      Note that having the output_stream ("-O") file opened in main()
1117      (main.c) rather limits the ability in VMS to open the file
1118      differently for ASCII versus binary FTP here.  (Of course, doing it
1119      there allows a open failure to be detected immediately, without first
1120      connecting to the server.)
1121   */
1122   if (!output_stream || con->cmd & DO_LIST)
1123     {
1124 /* On VMS, alter the name as required. */
1125 #ifdef __VMS
1126       char *targ;
1127
1128       targ = ods_conform (con->target);
1129       if (targ != con->target)
1130         {
1131           xfree (con->target);
1132           con->target = targ;
1133         }
1134 #endif /* def __VMS */
1135
1136       mkalldirs (con->target);
1137       if (opt.backups)
1138         rotate_backups (con->target);
1139
1140 /* 2005-04-15 SMS.
1141    For VMS, define common fopen() optional arguments, and a handy macro
1142    for use as a variable "binary" flag.
1143    Elsewhere, define a constant "binary" flag.
1144    Isn't it nice to have distinct text and binary file types?
1145 */
1146 # define BIN_TYPE_TRANSFER (type_char != 'A')
1147 #ifdef __VMS
1148 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1149 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1150 # define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1151 #else /* def __VMS */
1152 # define BIN_TYPE_FILE 1
1153 #endif /* def __VMS [else] */
1154
1155       if (restval && !(con->cmd & DO_LIST))
1156         {
1157 #ifdef __VMS
1158           int open_id;
1159
1160           if (BIN_TYPE_FILE)
1161             {
1162               open_id = 3;
1163               fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1164             }
1165           else
1166             {
1167               open_id = 4;
1168               fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1169             }
1170 #else /* def __VMS */
1171           fp = fopen (con->target, "ab");
1172 #endif /* def __VMS [else] */
1173         }
1174       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1175                || opt.output_document)
1176         {
1177 #ifdef __VMS
1178           int open_id;
1179
1180           if (BIN_TYPE_FILE)
1181             {
1182               open_id = 5;
1183               fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1184             }
1185           else
1186             {
1187               open_id = 6;
1188               fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1189             }
1190 #else /* def __VMS */
1191           fp = fopen (con->target, "wb");
1192 #endif /* def __VMS [else] */
1193         }
1194       else
1195         {
1196           fp = fopen_excl (con->target, true);
1197           if (!fp && errno == EEXIST)
1198             {
1199               /* We cannot just invent a new name and use it (which is
1200                  what functions like unique_create typically do)
1201                  because we told the user we'd use this name.
1202                  Instead, return and retry the download.  */
1203               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1204                          con->target);
1205               fd_close (csock);
1206               con->csock = -1;
1207               fd_close (dtsock);
1208               fd_close (local_sock);
1209               return FOPEN_EXCL_ERR;
1210             }
1211         }
1212       if (!fp)
1213         {
1214           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1215           fd_close (csock);
1216           con->csock = -1;
1217           fd_close (dtsock);
1218           fd_close (local_sock);
1219           return FOPENERR;
1220         }
1221     }
1222   else
1223     fp = output_stream;
1224
1225   if (passed_expected_bytes)
1226     {
1227       print_length (passed_expected_bytes, restval, true);
1228       expected_bytes = passed_expected_bytes;
1229         /* for fd_read_body's progress bar */
1230     }
1231   else if (expected_bytes)
1232     print_length (expected_bytes, restval, false);
1233
1234   /* Get the contents of the document.  */
1235   flags = 0;
1236   if (restval && rest_failed)
1237     flags |= rb_skip_startpos;
1238   rd_size = 0;
1239   res = fd_read_body (dtsock, fp,
1240                       expected_bytes ? expected_bytes - restval : 0,
1241                       restval, &rd_size, qtyread, &con->dltime, flags);
1242
1243   tms = datetime_str (time (NULL));
1244   tmrate = retr_rate (rd_size, con->dltime);
1245   total_download_time += con->dltime;
1246
1247   fd_close (local_sock);
1248   /* Close the local file.  */
1249   if (!output_stream || con->cmd & DO_LIST)
1250     fclose (fp);
1251
1252   /* If fd_read_body couldn't write to fp, bail out.  */
1253   if (res == -2)
1254     {
1255       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1256                  con->target, strerror (errno));
1257       fd_close (csock);
1258       con->csock = -1;
1259       fd_close (dtsock);
1260       return FWRITEERR;
1261     }
1262   else if (res == -1)
1263     {
1264       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1265                  tms, tmrate, fd_errstr (dtsock));
1266       if (opt.server_response)
1267         logputs (LOG_ALWAYS, "\n");
1268     }
1269   fd_close (dtsock);
1270
1271   /* Get the server to tell us if everything is retrieved.  */
1272   err = ftp_response (csock, &respline);
1273   if (err != FTPOK)
1274     {
1275       /* The control connection is decidedly closed.  Print the time
1276          only if it hasn't already been printed.  */
1277       if (res != -1)
1278         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1279       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1280       /* If there is an error on the control connection, close it, but
1281          return FTPRETRINT, since there is a possibility that the
1282          whole file was retrieved nevertheless (but that is for
1283          ftp_loop_internal to decide).  */
1284       fd_close (csock);
1285       con->csock = -1;
1286       return FTPRETRINT;
1287     } /* err != FTPOK */
1288   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1289      close socket, since the control connection is still alive.  If
1290      there is something wrong with the control connection, it will
1291      become apparent later.  */
1292   if (*respline != '2')
1293     {
1294       xfree (respline);
1295       if (res != -1)
1296         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1297       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1298       return FTPRETRINT;
1299     }
1300   xfree (respline);
1301
1302   if (res == -1)
1303     {
1304       /* What now?  The data connection was erroneous, whereas the
1305          response says everything is OK.  We shall play it safe.  */
1306       return FTPRETRINT;
1307     }
1308
1309   if (!(cmd & LEAVE_PENDING))
1310     {
1311       /* Closing the socket is faster than sending 'QUIT' and the
1312          effect is the same.  */
1313       fd_close (csock);
1314       con->csock = -1;
1315     }
1316   /* If it was a listing, and opt.server_response is true,
1317      print it out.  */
1318   if (opt.server_response && (con->cmd & DO_LIST))
1319     {
1320 /* 2005-02-25 SMS.
1321    Much of this work may already have been done, but repeating it should
1322    do no damage beyond wasting time.
1323 */
1324 /* On VMS, alter the name as required. */
1325 #ifdef __VMS
1326       char *targ;
1327
1328       targ = ods_conform( con->target);
1329       if (targ != con->target)
1330         {
1331           xfree( con->target);
1332           con->target = targ;
1333         }
1334 #endif /* def __VMS */
1335
1336       mkalldirs (con->target);
1337       fp = fopen (con->target, "r");
1338       if (!fp)
1339         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1340       else
1341         {
1342           char *line;
1343           /* The lines are being read with read_whole_line because of
1344              no-buffering on opt.lfile.  */
1345           while ((line = read_whole_line (fp)) != NULL)
1346             {
1347               char *p = strchr (line, '\0');
1348               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1349                 *--p = '\0';
1350               logprintf (LOG_ALWAYS, "%s\n",
1351                          quotearg_style (escape_quoting_style, line));
1352               xfree (line);
1353             }
1354           fclose (fp);
1355         }
1356     } /* con->cmd & DO_LIST && server_response */
1357
1358   return RETRFINISHED;
1359 }
1360
1361 /* A one-file FTP loop.  This is the part where FTP retrieval is
1362    retried, and retried, and retried, and...
1363
1364    This loop either gets commands from con, or (if ON_YOUR_OWN is
1365    set), makes them up to retrieve the file given by the URL.  */
1366 static uerr_t
1367 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1368 {
1369   int count, orig_lp;
1370   wgint restval, len = 0, qtyread = 0;
1371   char *tms, *locf;
1372   const char *tmrate = NULL;
1373   uerr_t err;
1374   struct_stat st;
1375
1376   /* Get the target, and set the name for the message accordingly. */
1377   if ((f == NULL) && (con->target))
1378     {
1379       /* Explicit file (like ".listing"). */
1380       locf = con->target;
1381     }
1382   else
1383     {
1384       /* URL-derived file.  Consider "-O file" name. */
1385       con->target = url_file_name (u, NULL);
1386       if (!opt.output_document)
1387         locf = con->target;
1388       else
1389         locf = opt.output_document;
1390     }
1391
1392   /* If the output_document was given, then this check was already done and
1393      the file didn't exist. Hence the !opt.output_document */
1394   if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1395     {
1396       logprintf (LOG_VERBOSE,
1397                  _("File %s already there; not retrieving.\n"), quote (con->target));
1398       /* If the file is there, we suppose it's retrieved OK.  */
1399       return RETROK;
1400     }
1401
1402   /* Remove it if it's a link.  */
1403   remove_link (con->target);
1404
1405   count = 0;
1406
1407   if (con->st & ON_YOUR_OWN)
1408     con->st = ON_YOUR_OWN;
1409
1410   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1411
1412   /* THE loop.  */
1413   do
1414     {
1415       /* Increment the pass counter.  */
1416       ++count;
1417       sleep_between_retrievals (count);
1418       if (con->st & ON_YOUR_OWN)
1419         {
1420           con->cmd = 0;
1421           con->cmd |= (DO_RETR | LEAVE_PENDING);
1422           if (con->csock != -1)
1423             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1424           else
1425             con->cmd |= (DO_LOGIN | DO_CWD);
1426         }
1427       else /* not on your own */
1428         {
1429           if (con->csock != -1)
1430             con->cmd &= ~DO_LOGIN;
1431           else
1432             con->cmd |= DO_LOGIN;
1433           if (con->st & DONE_CWD)
1434             con->cmd &= ~DO_CWD;
1435           else
1436             con->cmd |= DO_CWD;
1437         }
1438
1439       /* Decide whether or not to restart.  */
1440       if (con->cmd & DO_LIST)
1441         restval = 0;
1442       else if (opt.always_rest
1443           && stat (locf, &st) == 0
1444           && S_ISREG (st.st_mode))
1445         /* When -c is used, continue from on-disk size.  (Can't use
1446            hstat.len even if count>1 because we don't want a failed
1447            first attempt to clobber existing data.)  */
1448         restval = st.st_size;
1449       else if (count > 1)
1450         restval = qtyread;          /* start where the previous run left off */
1451       else
1452         restval = 0;
1453
1454       /* Get the current time string.  */
1455       tms = datetime_str (time (NULL));
1456       /* Print fetch message, if opt.verbose.  */
1457       if (opt.verbose)
1458         {
1459           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1460           char tmp[256];
1461           strcpy (tmp, "        ");
1462           if (count > 1)
1463             sprintf (tmp, _("(try:%2d)"), count);
1464           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => %s\n",
1465                      tms, hurl, tmp, quote (locf));
1466 #ifdef WINDOWS
1467           ws_changetitle (hurl);
1468 #endif
1469           xfree (hurl);
1470         }
1471       /* Send getftp the proper length, if fileinfo was provided.  */
1472       if (f && f->type != FT_SYMLINK)
1473         len = f->size;
1474       else
1475         len = 0;
1476       err = getftp (u, len, &qtyread, restval, con);
1477
1478       if (con->csock == -1)
1479         con->st &= ~DONE_CWD;
1480       else
1481         con->st |= DONE_CWD;
1482
1483       switch (err)
1484         {
1485         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1486         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1487           /* Fatal errors, give up.  */
1488           return err;
1489         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1490         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1491         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1492         case FOPEN_EXCL_ERR:
1493           printwhat (count, opt.ntry);
1494           /* non-fatal errors */
1495           if (err == FOPEN_EXCL_ERR)
1496             {
1497               /* Re-determine the file name. */
1498               xfree_null (con->target);
1499               con->target = url_file_name (u, NULL);
1500               locf = con->target;
1501             }
1502           continue;
1503         case FTPRETRINT:
1504           /* If the control connection was closed, the retrieval
1505              will be considered OK if f->size == len.  */
1506           if (!f || qtyread != f->size)
1507             {
1508               printwhat (count, opt.ntry);
1509               continue;
1510             }
1511           break;
1512         case RETRFINISHED:
1513           /* Great!  */
1514           break;
1515         default:
1516           /* Not as great.  */
1517           abort ();
1518         }
1519       tms = datetime_str (time (NULL));
1520       if (!opt.spider)
1521         tmrate = retr_rate (qtyread - restval, con->dltime);
1522
1523       /* If we get out of the switch above without continue'ing, we've
1524          successfully downloaded a file.  Remember this fact. */
1525       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1526
1527       if (con->st & ON_YOUR_OWN)
1528         {
1529           fd_close (con->csock);
1530           con->csock = -1;
1531         }
1532       if (!opt.spider)
1533         {
1534           bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1535
1536           logprintf (LOG_VERBOSE,
1537                      write_to_stdout
1538                      ? _("%s (%s) - written to stdout %s[%s]\n\n")
1539                      : _("%s (%s) - %s saved [%s]\n\n"),
1540                      tms, tmrate,
1541                      write_to_stdout ? "" : quote (locf),
1542                      number_to_static_string (qtyread));
1543         }
1544       if (!opt.verbose && !opt.quiet)
1545         {
1546           /* Need to hide the password from the URL.  The `if' is here
1547              so that we don't do the needless allocation every
1548              time. */
1549           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1550           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1551                      tms, hurl, number_to_static_string (qtyread), locf, count);
1552           xfree (hurl);
1553         }
1554
1555       if ((con->cmd & DO_LIST))
1556         /* This is a directory listing file. */
1557         {
1558           if (!opt.remove_listing)
1559             /* --dont-remove-listing was specified, so do count this towards the
1560                number of bytes and files downloaded. */
1561             {
1562               total_downloaded_bytes += qtyread;
1563               numurls++;
1564             }
1565
1566           /* Deletion of listing files is not controlled by --delete-after, but
1567              by the more specific option --dont-remove-listing, and the code
1568              to do this deletion is in another function. */
1569         }
1570       else if (!opt.spider)
1571         /* This is not a directory listing file. */
1572         {
1573           /* Unlike directory listing files, don't pretend normal files weren't
1574              downloaded if they're going to be deleted.  People seeding proxies,
1575              for instance, may want to know how many bytes and files they've
1576              downloaded through it. */
1577           total_downloaded_bytes += qtyread;
1578           numurls++;
1579
1580           if (opt.delete_after && !input_file_url (opt.input_filename))
1581             {
1582               DEBUGP (("\
1583 Removing file due to --delete-after in ftp_loop_internal():\n"));
1584               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1585               if (unlink (locf))
1586                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1587             }
1588         }
1589
1590       /* Restore the original leave-pendingness.  */
1591       if (orig_lp)
1592         con->cmd |= LEAVE_PENDING;
1593       else
1594         con->cmd &= ~LEAVE_PENDING;
1595
1596       if (local_file)
1597         *local_file = xstrdup (locf);
1598
1599       return RETROK;
1600     } while (!opt.ntry || (count < opt.ntry));
1601
1602   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1603     {
1604       fd_close (con->csock);
1605       con->csock = -1;
1606     }
1607   return TRYLIMEXC;
1608 }
1609
1610 /* Return the directory listing in a reusable format.  The directory
1611    is specifed in u->dir.  */
1612 static uerr_t
1613 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1614 {
1615   uerr_t err;
1616   char *uf;                     /* url file name */
1617   char *lf;                     /* list file name */
1618   char *old_target = con->target;
1619
1620   con->st &= ~ON_YOUR_OWN;
1621   con->cmd |= (DO_LIST | LEAVE_PENDING);
1622   con->cmd &= ~DO_RETR;
1623
1624   /* Find the listing file name.  We do it by taking the file name of
1625      the URL and replacing the last component with the listing file
1626      name.  */
1627   uf = url_file_name (u, NULL);
1628   lf = file_merge (uf, LIST_FILENAME);
1629   xfree (uf);
1630   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1631
1632   con->target = xstrdup (lf);
1633   xfree (lf);
1634   err = ftp_loop_internal (u, NULL, con, NULL);
1635   lf = xstrdup (con->target);
1636   xfree (con->target);
1637   con->target = old_target;
1638
1639   if (err == RETROK)
1640     {
1641       *f = ftp_parse_ls (lf, con->rs);
1642       if (opt.remove_listing)
1643         {
1644           if (unlink (lf))
1645             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1646           else
1647             logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1648         }
1649     }
1650   else
1651     *f = NULL;
1652   xfree (lf);
1653   con->cmd &= ~DO_LIST;
1654   return err;
1655 }
1656
1657 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1658 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1659 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1660 static void freefileinfo (struct fileinfo *f);
1661
1662 /* Retrieve a list of files given in struct fileinfo linked list.  If
1663    a file is a symbolic link, do not retrieve it, but rather try to
1664    set up a similar link on the local disk, if the symlinks are
1665    supported.
1666
1667    If opt.recursive is set, after all files have been retrieved,
1668    ftp_retrieve_dirs will be called to retrieve the directories.  */
1669 static uerr_t
1670 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1671 {
1672   static int depth = 0;
1673   uerr_t err;
1674   struct fileinfo *orig;
1675   wgint local_size;
1676   time_t tml;
1677   bool dlthis; /* Download this (file). */
1678   const char *actual_target = NULL;
1679
1680   /* Increase the depth.  */
1681   ++depth;
1682   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1683     {
1684       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1685                depth, opt.reclevel));
1686       --depth;
1687       return RECLEVELEXC;
1688     }
1689
1690   assert (f != NULL);
1691   orig = f;
1692
1693   con->st &= ~ON_YOUR_OWN;
1694   if (!(con->st & DONE_CWD))
1695     con->cmd |= DO_CWD;
1696   else
1697     con->cmd &= ~DO_CWD;
1698   con->cmd |= (DO_RETR | LEAVE_PENDING);
1699
1700   if (con->csock < 0)
1701     con->cmd |= DO_LOGIN;
1702   else
1703     con->cmd &= ~DO_LOGIN;
1704
1705   err = RETROK;                 /* in case it's not used */
1706
1707   while (f)
1708     {
1709       char *old_target, *ofile;
1710
1711       if (opt.quota && total_downloaded_bytes > opt.quota)
1712         {
1713           --depth;
1714           return QUOTEXC;
1715         }
1716       old_target = con->target;
1717
1718       ofile = xstrdup (u->file);
1719       url_set_file (u, f->name);
1720
1721       con->target = url_file_name (u, NULL);
1722       err = RETROK;
1723
1724       dlthis = true;
1725       if (opt.timestamping && f->type == FT_PLAINFILE)
1726         {
1727           struct_stat st;
1728           /* If conversion of HTML files retrieved via FTP is ever implemented,
1729              we'll need to stat() <file>.orig here when -K has been specified.
1730              I'm not implementing it now since files on an FTP server are much
1731              more likely than files on an HTTP server to legitimately have a
1732              .orig suffix. */
1733           if (!stat (con->target, &st))
1734             {
1735               bool eq_size;
1736               bool cor_val;
1737               /* Else, get it from the file.  */
1738               local_size = st.st_size;
1739               tml = st.st_mtime;
1740 #ifdef WINDOWS
1741               /* Modification time granularity is 2 seconds for Windows, so
1742                  increase local time by 1 second for later comparison. */
1743               tml++;
1744 #endif
1745               /* Compare file sizes only for servers that tell us correct
1746                  values. Assume sizes being equal for servers that lie
1747                  about file size.  */
1748               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1749               eq_size = cor_val ? (local_size == f->size) : true;
1750               if (f->tstamp <= tml && eq_size)
1751                 {
1752                   /* Remote file is older, file sizes can be compared and
1753                      are both equal. */
1754                   logprintf (LOG_VERBOSE, _("\
1755 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1756                   dlthis = false;
1757                 }
1758               else if (eq_size)
1759                 {
1760                   /* Remote file is newer or sizes cannot be matched */
1761                   logprintf (LOG_VERBOSE, _("\
1762 Remote file is newer than local file %s -- retrieving.\n\n"),
1763                              quote (con->target));
1764                 }
1765               else
1766                 {
1767                   /* Sizes do not match */
1768                   logprintf (LOG_VERBOSE, _("\
1769 The sizes do not match (local %s) -- retrieving.\n\n"),
1770                              number_to_static_string (local_size));
1771                 }
1772             }
1773         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1774       switch (f->type)
1775         {
1776         case FT_SYMLINK:
1777           /* If opt.retr_symlinks is defined, we treat symlinks as
1778              if they were normal files.  There is currently no way
1779              to distinguish whether they might be directories, and
1780              follow them.  */
1781           if (!opt.retr_symlinks)
1782             {
1783 #ifdef HAVE_SYMLINK
1784               if (!f->linkto)
1785                 logputs (LOG_NOTQUIET,
1786                          _("Invalid name of the symlink, skipping.\n"));
1787               else
1788                 {
1789                   struct_stat st;
1790                   /* Check whether we already have the correct
1791                      symbolic link.  */
1792                   int rc = lstat (con->target, &st);
1793                   if (rc == 0)
1794                     {
1795                       size_t len = strlen (f->linkto) + 1;
1796                       if (S_ISLNK (st.st_mode))
1797                         {
1798                           char *link_target = (char *)alloca (len);
1799                           size_t n = readlink (con->target, link_target, len);
1800                           if ((n == len - 1)
1801                               && (memcmp (link_target, f->linkto, n) == 0))
1802                             {
1803                               logprintf (LOG_VERBOSE, _("\
1804 Already have correct symlink %s -> %s\n\n"),
1805                                          quote (con->target),
1806                                          quote (f->linkto));
1807                               dlthis = false;
1808                               break;
1809                             }
1810                         }
1811                     }
1812                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1813                              quote (con->target), quote (f->linkto));
1814                   /* Unlink before creating symlink!  */
1815                   unlink (con->target);
1816                   if (symlink (f->linkto, con->target) == -1)
1817                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1818                   logputs (LOG_VERBOSE, "\n");
1819                 } /* have f->linkto */
1820 #else  /* not HAVE_SYMLINK */
1821               logprintf (LOG_NOTQUIET,
1822                          _("Symlinks not supported, skipping symlink %s.\n"),
1823                          quote (con->target));
1824 #endif /* not HAVE_SYMLINK */
1825             }
1826           else                /* opt.retr_symlinks */
1827             {
1828               if (dlthis)
1829                 err = ftp_loop_internal (u, f, con, NULL);
1830             } /* opt.retr_symlinks */
1831           break;
1832         case FT_DIRECTORY:
1833           if (!opt.recursive)
1834             logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1835                        quote (f->name));
1836           break;
1837         case FT_PLAINFILE:
1838           /* Call the retrieve loop.  */
1839           if (dlthis)
1840             err = ftp_loop_internal (u, f, con, NULL);
1841           break;
1842         case FT_UNKNOWN:
1843           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1844                      quote (f->name));
1845           break;
1846         }       /* switch */
1847
1848
1849       /* 2004-12-15 SMS.
1850        * Set permissions _before_ setting the times, as setting the
1851        * permissions changes the modified-time, at least on VMS.
1852        * Also, use the opt.output_document name here, too, as
1853        * appropriate.  (Do the test once, and save the result.)
1854        */
1855
1856       set_local_file (&actual_target, con->target);
1857
1858       /* If downloading a plain file, set valid (non-zero) permissions. */
1859       if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1860         {
1861           if (f->perms)
1862             chmod (actual_target, f->perms);
1863           else
1864             DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1865         }
1866
1867       /* Set the time-stamp information to the local file.  Symlinks
1868          are not to be stamped because it sets the stamp on the
1869          original.  :( */
1870       if (actual_target != NULL)
1871         {
1872           if (opt.useservertimestamps
1873               && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1874               && f->tstamp != -1
1875               && dlthis
1876               && file_exists_p (con->target))
1877             {
1878               touch (actual_target, f->tstamp);
1879             }
1880           else if (f->tstamp == -1)
1881             logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1882                        actual_target);
1883         }
1884
1885       xfree (con->target);
1886       con->target = old_target;
1887
1888       url_set_file (u, ofile);
1889       xfree (ofile);
1890
1891       /* Break on fatals.  */
1892       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1893         break;
1894       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1895       f = f->next;
1896     }
1897
1898   /* We do not want to call ftp_retrieve_dirs here */
1899   if (opt.recursive &&
1900       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1901     err = ftp_retrieve_dirs (u, orig, con);
1902   else if (opt.recursive)
1903     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1904              depth, opt.reclevel));
1905   --depth;
1906   return err;
1907 }
1908
1909 /* Retrieve the directories given in a file list.  This function works
1910    by simply going through the linked list and calling
1911    ftp_retrieve_glob on each directory entry.  The function knows
1912    about excluded directories.  */
1913 static uerr_t
1914 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1915 {
1916   char *container = NULL;
1917   int container_size = 0;
1918
1919   for (; f; f = f->next)
1920     {
1921       int size;
1922       char *odir, *newdir;
1923
1924       if (opt.quota && total_downloaded_bytes > opt.quota)
1925         break;
1926       if (f->type != FT_DIRECTORY)
1927         continue;
1928
1929       /* Allocate u->dir off stack, but reallocate only if a larger
1930          string is needed.  It's a pity there's no "realloca" for an
1931          item on the bottom of the stack.  */
1932       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1933       if (size > container_size)
1934         container = (char *)alloca (size);
1935       newdir = container;
1936
1937       odir = u->dir;
1938       if (*odir == '\0'
1939           || (*odir == '/' && *(odir + 1) == '\0'))
1940         /* If ODIR is empty or just "/", simply append f->name to
1941            ODIR.  (In the former case, to preserve u->dir being
1942            relative; in the latter case, to avoid double slash.)  */
1943         sprintf (newdir, "%s%s", odir, f->name);
1944       else
1945         /* Else, use a separator. */
1946         sprintf (newdir, "%s/%s", odir, f->name);
1947
1948       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1949       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1950                odir, f->name, newdir));
1951       if (!accdir (newdir))
1952         {
1953           logprintf (LOG_VERBOSE, _("\
1954 Not descending to %s as it is excluded/not-included.\n"),
1955                      quote (newdir));
1956           continue;
1957         }
1958
1959       con->st &= ~DONE_CWD;
1960
1961       odir = xstrdup (u->dir);  /* because url_set_dir will free
1962                                    u->dir. */
1963       url_set_dir (u, newdir);
1964       ftp_retrieve_glob (u, con, GLOB_GETALL);
1965       url_set_dir (u, odir);
1966       xfree (odir);
1967
1968       /* Set the time-stamp?  */
1969     }
1970
1971   if (opt.quota && total_downloaded_bytes > opt.quota)
1972     return QUOTEXC;
1973   else
1974     return RETROK;
1975 }
1976
1977 /* Return true if S has a leading '/'  or contains '../' */
1978 static bool
1979 has_insecure_name_p (const char *s)
1980 {
1981   if (*s == '/')
1982     return true;
1983
1984   if (strstr (s, "../") != 0)
1985     return true;
1986
1987   return false;
1988 }
1989
1990 /* A near-top-level function to retrieve the files in a directory.
1991    The function calls ftp_get_listing, to get a linked list of files.
1992    Then it weeds out the file names that do not match the pattern.
1993    ftp_retrieve_list is called with this updated list as an argument.
1994
1995    If the argument ACTION is GLOB_GETONE, just download the file (but
1996    first get the listing, so that the time-stamp is heeded); if it's
1997    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
1998    directory.  */
1999 static uerr_t
2000 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2001 {
2002   struct fileinfo *f, *start;
2003   uerr_t res;
2004
2005   con->cmd |= LEAVE_PENDING;
2006
2007   res = ftp_get_listing (u, con, &start);
2008   if (res != RETROK)
2009     return res;
2010   /* First: weed out that do not conform the global rules given in
2011      opt.accepts and opt.rejects.  */
2012   if (opt.accepts || opt.rejects)
2013     {
2014       f = start;
2015       while (f)
2016         {
2017           if (f->type != FT_DIRECTORY && !acceptable (f->name))
2018             {
2019               logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2020                          quote (f->name));
2021               f = delelement (f, &start);
2022             }
2023           else
2024             f = f->next;
2025         }
2026     }
2027   /* Remove all files with possible harmful names */
2028   f = start;
2029   while (f)
2030     {
2031       if (has_insecure_name_p (f->name))
2032         {
2033           logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2034                      quote (f->name));
2035           f = delelement (f, &start);
2036         }
2037       else
2038         f = f->next;
2039     }
2040   /* Now weed out the files that do not match our globbing pattern.
2041      If we are dealing with a globbing pattern, that is.  */
2042   if (*u->file)
2043     {
2044       if (action == GLOB_GLOBALL)
2045         {
2046           int (*matcher) (const char *, const char *, int)
2047             = opt.ignore_case ? fnmatch_nocase : fnmatch;
2048           int matchres = 0;
2049
2050           f = start;
2051           while (f)
2052             {
2053               matchres = matcher (u->file, f->name, 0);
2054               if (matchres == -1)
2055                 {
2056                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2057                              u->file, quotearg_style (escape_quoting_style, f->name),
2058                              strerror (errno));
2059                   break;
2060                 }
2061               if (matchres == FNM_NOMATCH)
2062                 f = delelement (f, &start); /* delete the element from the list */
2063               else
2064                 f = f->next;        /* leave the element in the list */
2065             }
2066           if (matchres == -1)
2067             {
2068               freefileinfo (start);
2069               return RETRBADPATTERN;
2070             }
2071         }
2072       else if (action == GLOB_GETONE)
2073         {
2074 #ifdef __VMS
2075           /* 2009-09-09 SMS.
2076            * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2077            * bug causes spurious %CC-E-BADCONDIT complaint with this
2078            * "?:" statement.  (Different linkage attributes for strcmp()
2079            * and strcasecmp().)  Converting to "if" changes the
2080            * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;".  Adding
2081            * the senseless type cast clears the complaint, and looks
2082            * harmless.
2083            */
2084           int (*cmp) (const char *, const char *)
2085             = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2086 #else /* def __VMS */
2087           int (*cmp) (const char *, const char *)
2088             = opt.ignore_case ? strcasecmp : strcmp;
2089 #endif /* def __VMS [else] */
2090           f = start;
2091           while (f)
2092             {
2093               if (0 != cmp(u->file, f->name))
2094                 f = delelement (f, &start);
2095               else
2096                 f = f->next;
2097             }
2098         }
2099     }
2100   if (start)
2101     {
2102       /* Just get everything.  */
2103       ftp_retrieve_list (u, start, con);
2104     }
2105   else
2106     {
2107       if (action == GLOB_GLOBALL)
2108         {
2109           /* No luck.  */
2110           /* #### This message SUCKS.  We should see what was the
2111              reason that nothing was retrieved.  */
2112           logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2113                      quote (u->file));
2114         }
2115       else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2116         {
2117           /* Let's try retrieving it anyway.  */
2118           con->st |= ON_YOUR_OWN;
2119           res = ftp_loop_internal (u, NULL, con, NULL);
2120           return res;
2121         }
2122
2123       /* If action == GLOB_GETALL, and the file list is empty, there's
2124          no point in trying to download anything or in complaining about
2125          it.  (An empty directory should not cause complaints.)
2126       */
2127     }
2128   freefileinfo (start);
2129   if (opt.quota && total_downloaded_bytes > opt.quota)
2130     return QUOTEXC;
2131   else
2132     /* #### Should we return `res' here?  */
2133     return RETROK;
2134 }
2135
2136 /* The wrapper that calls an appropriate routine according to contents
2137    of URL.  Inherently, its capabilities are limited on what can be
2138    encoded into a URL.  */
2139 uerr_t
2140 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2141           bool recursive, bool glob)
2142 {
2143   ccon con;                     /* FTP connection */
2144   uerr_t res;
2145
2146   *dt = 0;
2147
2148   xzero (con);
2149
2150   con.csock = -1;
2151   con.st = ON_YOUR_OWN;
2152   con.rs = ST_UNIX;
2153   con.id = NULL;
2154   con.proxy = proxy;
2155
2156   /* If the file name is empty, the user probably wants a directory
2157      index.  We'll provide one, properly HTML-ized.  Unless
2158      opt.htmlify is 0, of course.  :-) */
2159   if (!*u->file && !recursive)
2160     {
2161       struct fileinfo *f;
2162       res = ftp_get_listing (u, &con, &f);
2163
2164       if (res == RETROK)
2165         {
2166           if (opt.htmlify && !opt.spider)
2167             {
2168               char *filename = (opt.output_document
2169                                 ? xstrdup (opt.output_document)
2170                                 : (con.target ? xstrdup (con.target)
2171                                    : url_file_name (u, NULL)));
2172               res = ftp_index (filename, u, f);
2173               if (res == FTPOK && opt.verbose)
2174                 {
2175                   if (!opt.output_document)
2176                     {
2177                       struct_stat st;
2178                       wgint sz;
2179                       if (stat (filename, &st) == 0)
2180                         sz = st.st_size;
2181                       else
2182                         sz = -1;
2183                       logprintf (LOG_NOTQUIET,
2184                                  _("Wrote HTML-ized index to %s [%s].\n"),
2185                                  quote (filename), number_to_static_string (sz));
2186                     }
2187                   else
2188                     logprintf (LOG_NOTQUIET,
2189                                _("Wrote HTML-ized index to %s.\n"),
2190                                quote (filename));
2191                 }
2192               xfree (filename);
2193             }
2194           freefileinfo (f);
2195         }
2196     }
2197   else
2198     {
2199       bool ispattern = false;
2200       if (glob)
2201         {
2202           /* Treat the URL as a pattern if the file name part of the
2203              URL path contains wildcards.  (Don't check for u->file
2204              because it is unescaped and therefore doesn't leave users
2205              the option to escape literal '*' as %2A.)  */
2206           char *file_part = strrchr (u->path, '/');
2207           if (!file_part)
2208             file_part = u->path;
2209           ispattern = has_wildcards_p (file_part);
2210         }
2211       if (ispattern || recursive || opt.timestamping)
2212         {
2213           /* ftp_retrieve_glob is a catch-all function that gets called
2214              if we need globbing, time-stamping or recursion.  Its
2215              third argument is just what we really need.  */
2216           res = ftp_retrieve_glob (u, &con,
2217                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2218         }
2219       else
2220         res = ftp_loop_internal (u, NULL, &con, local_file);
2221     }
2222   if (res == FTPOK)
2223     res = RETROK;
2224   if (res == RETROK)
2225     *dt |= RETROKF;
2226   /* If a connection was left, quench it.  */
2227   if (con.csock != -1)
2228     fd_close (con.csock);
2229   xfree_null (con.id);
2230   con.id = NULL;
2231   xfree_null (con.target);
2232   con.target = NULL;
2233   return res;
2234 }
2235
2236 /* Delete an element from the fileinfo linked list.  Returns the
2237    address of the next element, or NULL if the list is exhausted.  It
2238    can modify the start of the list.  */
2239 static struct fileinfo *
2240 delelement (struct fileinfo *f, struct fileinfo **start)
2241 {
2242   struct fileinfo *prev = f->prev;
2243   struct fileinfo *next = f->next;
2244
2245   xfree (f->name);
2246   xfree_null (f->linkto);
2247   xfree (f);
2248
2249   if (next)
2250     next->prev = prev;
2251   if (prev)
2252     prev->next = next;
2253   else
2254     *start = next;
2255   return next;
2256 }
2257
2258 /* Free the fileinfo linked list of files.  */
2259 static void
2260 freefileinfo (struct fileinfo *f)
2261 {
2262   while (f)
2263     {
2264       struct fileinfo *next = f->next;
2265       xfree (f->name);
2266       if (f->linkto)
2267         xfree (f->linkto);
2268       xfree (f);
2269       f = next;
2270     }
2271 }