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