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