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