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