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