]> sjero.net Git - wget/blob - src/ftp.c
[svn] iInitialize err in getftp to suppress gcc warning.
[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       /* #### Is this correct? */
957       chmod (con->target, 0600);
958
959       fp = fopen (con->target, restval ? "ab" : "wb");
960       if (!fp)
961         {
962           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
963           fd_close (csock);
964           con->csock = -1;
965           fd_close (dtsock);
966           fd_close (local_sock);
967           return FOPENERR;
968         }
969     }
970   else
971     fp = output_stream;
972
973   if (*len)
974     {
975       logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
976       if (restval)
977         logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
978       logputs (LOG_VERBOSE, "\n");
979       expected_bytes = *len;    /* for get_contents/show_progress */
980     }
981   else if (expected_bytes)
982     {
983       logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
984       if (restval)
985         logprintf (LOG_VERBOSE, _(" [%s to go]"),
986                    legible (expected_bytes - restval));
987       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
988     }
989
990   /* Get the contents of the document.  */
991   flags = 0;
992   if (restval && rest_failed)
993     flags |= rb_skip_startpos;
994   *len = restval;
995   rd_size = 0;
996   res = fd_read_body (dtsock, fp,
997                       expected_bytes ? expected_bytes - restval : 0,
998                       restval, &rd_size, len, &con->dltime, flags);
999
1000   tms = time_str (NULL);
1001   tmrate = retr_rate (rd_size, con->dltime, 0);
1002   /* Close data connection socket.  */
1003   fd_close (dtsock);
1004   fd_close (local_sock);
1005   /* Close the local file.  */
1006   {
1007     /* Close or flush the file.  We have to be careful to check for
1008        error here.  Checking the result of fwrite() is not enough --
1009        errors could go unnoticed!  */
1010     int flush_res;
1011     if (!output_stream || con->cmd & DO_LIST)
1012       flush_res = fclose (fp);
1013     else
1014       flush_res = fflush (fp);
1015     if (flush_res == EOF)
1016       res = -2;
1017   }
1018
1019   /* If get_contents couldn't write to fp, bail out.  */
1020   if (res == -2)
1021     {
1022       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1023                  con->target, strerror (errno));
1024       fd_close (csock);
1025       con->csock = -1;
1026       return FWRITEERR;
1027     }
1028   else if (res == -1)
1029     {
1030       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1031                  tms, tmrate, strerror (errno));
1032       if (opt.server_response)
1033         logputs (LOG_ALWAYS, "\n");
1034     }
1035
1036   /* Get the server to tell us if everything is retrieved.  */
1037   err = ftp_response (csock, &respline);
1038   if (err != FTPOK)
1039     {
1040       xfree (respline);
1041       /* The control connection is decidedly closed.  Print the time
1042          only if it hasn't already been printed.  */
1043       if (res != -1)
1044         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1045       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1046       /* If there is an error on the control connection, close it, but
1047          return FTPRETRINT, since there is a possibility that the
1048          whole file was retrieved nevertheless (but that is for
1049          ftp_loop_internal to decide).  */
1050       fd_close (csock);
1051       con->csock = -1;
1052       return FTPRETRINT;
1053     } /* err != FTPOK */
1054   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1055      close socket, since the control connection is still alive.  If
1056      there is something wrong with the control connection, it will
1057      become apparent later.  */
1058   if (*respline != '2')
1059     {
1060       xfree (respline);
1061       if (res != -1)
1062         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1063       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1064       return FTPRETRINT;
1065     }
1066   xfree (respline);
1067
1068   if (res == -1)
1069     {
1070       /* What now?  The data connection was erroneous, whereas the
1071          response says everything is OK.  We shall play it safe.  */
1072       return FTPRETRINT;
1073     }
1074
1075   if (!(cmd & LEAVE_PENDING))
1076     {
1077       /* Closing the socket is faster than sending 'QUIT' and the
1078          effect is the same.  */
1079       fd_close (csock);
1080       con->csock = -1;
1081     }
1082   /* If it was a listing, and opt.server_response is true,
1083      print it out.  */
1084   if (opt.server_response && (con->cmd & DO_LIST))
1085     {
1086       mkalldirs (con->target);
1087       fp = fopen (con->target, "r");
1088       if (!fp)
1089         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1090       else
1091         {
1092           char *line;
1093           /* The lines are being read with read_whole_line because of
1094              no-buffering on opt.lfile.  */
1095           while ((line = read_whole_line (fp)))
1096             {
1097               logprintf (LOG_ALWAYS, "%s\n", line);
1098               xfree (line);
1099             }
1100           fclose (fp);
1101         }
1102     } /* con->cmd & DO_LIST && server_response */
1103
1104   return RETRFINISHED;
1105 }
1106
1107 /* A one-file FTP loop.  This is the part where FTP retrieval is
1108    retried, and retried, and retried, and...
1109
1110    This loop either gets commands from con, or (if ON_YOUR_OWN is
1111    set), makes them up to retrieve the file given by the URL.  */
1112 static uerr_t
1113 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1114 {
1115   int count, orig_lp;
1116   wgint restval, len = 0;
1117   char *tms, *locf;
1118   char *tmrate = NULL;
1119   uerr_t err;
1120   struct_stat st;
1121
1122   if (!con->target)
1123     con->target = url_file_name (u);
1124
1125   if (opt.noclobber && file_exists_p (con->target))
1126     {
1127       logprintf (LOG_VERBOSE,
1128                  _("File `%s' already there, not retrieving.\n"), con->target);
1129       /* If the file is there, we suppose it's retrieved OK.  */
1130       return RETROK;
1131     }
1132
1133   /* Remove it if it's a link.  */
1134   remove_link (con->target);
1135   if (!opt.output_document)
1136     locf = con->target;
1137   else
1138     locf = opt.output_document;
1139
1140   count = 0;
1141
1142   if (con->st & ON_YOUR_OWN)
1143     con->st = ON_YOUR_OWN;
1144
1145   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1146
1147   /* THE loop.  */
1148   do
1149     {
1150       /* Increment the pass counter.  */
1151       ++count;
1152       sleep_between_retrievals (count);
1153       if (con->st & ON_YOUR_OWN)
1154         {
1155           con->cmd = 0;
1156           con->cmd |= (DO_RETR | LEAVE_PENDING);
1157           if (con->csock != -1)
1158             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1159           else
1160             con->cmd |= (DO_LOGIN | DO_CWD);
1161         }
1162       else /* not on your own */
1163         {
1164           if (con->csock != -1)
1165             con->cmd &= ~DO_LOGIN;
1166           else
1167             con->cmd |= DO_LOGIN;
1168           if (con->st & DONE_CWD)
1169             con->cmd &= ~DO_CWD;
1170           else
1171             con->cmd |= DO_CWD;
1172         }
1173
1174       /* Decide whether or not to restart.  */
1175       restval = 0;
1176       if (count > 1)
1177         restval = len;          /* start where the previous run left off */
1178       else if (opt.always_rest
1179                && stat (locf, &st) == 0
1180                && S_ISREG (st.st_mode))
1181         restval = st.st_size;
1182
1183       /* Get the current time string.  */
1184       tms = time_str (NULL);
1185       /* Print fetch message, if opt.verbose.  */
1186       if (opt.verbose)
1187         {
1188           char *hurl = url_string (u, 1);
1189           char tmp[256];
1190           strcpy (tmp, "        ");
1191           if (count > 1)
1192             sprintf (tmp, _("(try:%2d)"), count);
1193           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1194                      tms, hurl, tmp, locf);
1195 #ifdef WINDOWS
1196           ws_changetitle (hurl);
1197 #endif
1198           xfree (hurl);
1199         }
1200       /* Send getftp the proper length, if fileinfo was provided.  */
1201       if (f)
1202         len = f->size;
1203       else
1204         len = 0;
1205       err = getftp (u, &len, restval, con);
1206
1207       if (con->csock != -1)
1208         con->st &= ~DONE_CWD;
1209       else
1210         con->st |= DONE_CWD;
1211
1212       switch (err)
1213         {
1214         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1215         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1216           /* Fatal errors, give up.  */
1217           return err;
1218           break;
1219         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1220         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1221         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1222           printwhat (count, opt.ntry);
1223           /* non-fatal errors */
1224           continue;
1225           break;
1226         case FTPRETRINT:
1227           /* If the control connection was closed, the retrieval
1228              will be considered OK if f->size == len.  */
1229           if (!f || len != f->size)
1230             {
1231               printwhat (count, opt.ntry);
1232               continue;
1233             }
1234           break;
1235         case RETRFINISHED:
1236           /* Great!  */
1237           break;
1238         default:
1239           /* Not as great.  */
1240           abort ();
1241         }
1242       tms = time_str (NULL);
1243       if (!opt.spider)
1244         tmrate = retr_rate (len - restval, con->dltime, 0);
1245
1246       /* If we get out of the switch above without continue'ing, we've
1247          successfully downloaded a file.  Remember this fact. */
1248       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1249
1250       if (con->st & ON_YOUR_OWN)
1251         {
1252           fd_close (con->csock);
1253           con->csock = -1;
1254         }
1255       if (!opt.spider)
1256         logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1257                    tms, tmrate, locf, number_to_static_string (len));
1258       if (!opt.verbose && !opt.quiet)
1259         {
1260           /* Need to hide the password from the URL.  The `if' is here
1261              so that we don't do the needless allocation every
1262              time. */
1263           char *hurl = url_string (u, 1);
1264           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1265                      tms, hurl, number_to_static_string (len), locf, count);
1266           xfree (hurl);
1267         }
1268
1269       if ((con->cmd & DO_LIST))
1270         /* This is a directory listing file. */
1271         {
1272           if (!opt.remove_listing)
1273             /* --dont-remove-listing was specified, so do count this towards the
1274                number of bytes and files downloaded. */
1275             {
1276               total_downloaded_bytes += len;
1277               opt.numurls++;
1278             }
1279
1280           /* Deletion of listing files is not controlled by --delete-after, but
1281              by the more specific option --dont-remove-listing, and the code
1282              to do this deletion is in another function. */
1283         }
1284       else if (!opt.spider)
1285         /* This is not a directory listing file. */
1286         {
1287           /* Unlike directory listing files, don't pretend normal files weren't
1288              downloaded if they're going to be deleted.  People seeding proxies,
1289              for instance, may want to know how many bytes and files they've
1290              downloaded through it. */
1291           total_downloaded_bytes += len;
1292           opt.numurls++;
1293
1294           if (opt.delete_after)
1295             {
1296               DEBUGP (("Removing file due to --delete-after in"
1297                        " ftp_loop_internal():\n"));
1298               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1299               if (unlink (locf))
1300                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1301             }
1302         }
1303
1304       /* Restore the original leave-pendingness.  */
1305       if (orig_lp)
1306         con->cmd |= LEAVE_PENDING;
1307       else
1308         con->cmd &= ~LEAVE_PENDING;
1309       return RETROK;
1310     } while (!opt.ntry || (count < opt.ntry));
1311
1312   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1313     {
1314       fd_close (con->csock);
1315       con->csock = -1;
1316     }
1317   return TRYLIMEXC;
1318 }
1319
1320 /* Return the directory listing in a reusable format.  The directory
1321    is specifed in u->dir.  */
1322 uerr_t
1323 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1324 {
1325   uerr_t err;
1326   char *uf;                     /* url file name */
1327   char *lf;                     /* list file name */
1328   char *old_target = con->target;
1329
1330   con->st &= ~ON_YOUR_OWN;
1331   con->cmd |= (DO_LIST | LEAVE_PENDING);
1332   con->cmd &= ~DO_RETR;
1333
1334   /* Find the listing file name.  We do it by taking the file name of
1335      the URL and replacing the last component with the listing file
1336      name.  */
1337   uf = url_file_name (u);
1338   lf = file_merge (uf, LIST_FILENAME);
1339   xfree (uf);
1340   DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1341
1342   con->target = lf;
1343   err = ftp_loop_internal (u, NULL, con);
1344   con->target = old_target;
1345
1346   if (err == RETROK)
1347     *f = ftp_parse_ls (lf, con->rs);
1348   else
1349     *f = NULL;
1350   if (opt.remove_listing)
1351     {
1352       if (unlink (lf))
1353         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1354       else
1355         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1356     }
1357   xfree (lf);
1358   con->cmd &= ~DO_LIST;
1359   return err;
1360 }
1361
1362 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1363                                          ccon *));
1364 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1365 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1366                                             struct fileinfo **));
1367 static void freefileinfo PARAMS ((struct fileinfo *f));
1368
1369 /* Retrieve a list of files given in struct fileinfo linked list.  If
1370    a file is a symbolic link, do not retrieve it, but rather try to
1371    set up a similar link on the local disk, if the symlinks are
1372    supported.
1373
1374    If opt.recursive is set, after all files have been retrieved,
1375    ftp_retrieve_dirs will be called to retrieve the directories.  */
1376 static uerr_t
1377 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1378 {
1379   static int depth = 0;
1380   uerr_t err;
1381   struct fileinfo *orig;
1382   wgint local_size;
1383   time_t tml;
1384   int dlthis;
1385
1386   /* Increase the depth.  */
1387   ++depth;
1388   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1389     {
1390       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1391                depth, opt.reclevel));
1392       --depth;
1393       return RECLEVELEXC;
1394     }
1395
1396   assert (f != NULL);
1397   orig = f;
1398
1399   con->st &= ~ON_YOUR_OWN;
1400   if (!(con->st & DONE_CWD))
1401     con->cmd |= DO_CWD;
1402   else
1403     con->cmd &= ~DO_CWD;
1404   con->cmd |= (DO_RETR | LEAVE_PENDING);
1405
1406   if (con->csock < 0)
1407     con->cmd |= DO_LOGIN;
1408   else
1409     con->cmd &= ~DO_LOGIN;
1410
1411   err = RETROK;                 /* in case it's not used */
1412
1413   while (f)
1414     {
1415       char *old_target, *ofile;
1416
1417       if (opt.quota && total_downloaded_bytes > opt.quota)
1418         {
1419           --depth;
1420           return QUOTEXC;
1421         }
1422       old_target = con->target;
1423
1424       ofile = xstrdup (u->file);
1425       url_set_file (u, f->name);
1426
1427       con->target = url_file_name (u);
1428       err = RETROK;
1429
1430       dlthis = 1;
1431       if (opt.timestamping && f->type == FT_PLAINFILE)
1432         {
1433           struct_stat st;
1434           /* If conversion of HTML files retrieved via FTP is ever implemented,
1435              we'll need to stat() <file>.orig here when -K has been specified.
1436              I'm not implementing it now since files on an FTP server are much
1437              more likely than files on an HTTP server to legitimately have a
1438              .orig suffix. */
1439           if (!stat (con->target, &st))
1440             {
1441               int eq_size;
1442               int cor_val;
1443               /* Else, get it from the file.  */
1444               local_size = st.st_size;
1445               tml = st.st_mtime;
1446 #ifdef WINDOWS
1447               /* Modification time granularity is 2 seconds for Windows, so
1448                  increase local time by 1 second for later comparison. */
1449               tml++;
1450 #endif
1451               /* Compare file sizes only for servers that tell us correct
1452                  values. Assumme sizes being equal for servers that lie
1453                  about file size.  */
1454               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1455               eq_size = cor_val ? (local_size == f->size) : 1 ;
1456               if (f->tstamp <= tml && eq_size)
1457                 {
1458                   /* Remote file is older, file sizes can be compared and
1459                      are both equal. */
1460                   logprintf (LOG_VERBOSE, _("\
1461 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1462                   dlthis = 0;
1463                 }
1464               else if (eq_size)
1465                 {
1466                   /* Remote file is newer or sizes cannot be matched */
1467                   logprintf (LOG_VERBOSE, _("\
1468 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1469                              con->target);
1470                 }
1471               else
1472                 {
1473                   /* Sizes do not match */
1474                   logprintf (LOG_VERBOSE, _("\
1475 The sizes do not match (local %s) -- retrieving.\n\n"),
1476                              number_to_static_string (local_size));
1477                 }
1478             }
1479         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1480       switch (f->type)
1481         {
1482         case FT_SYMLINK:
1483           /* If opt.retr_symlinks is defined, we treat symlinks as
1484              if they were normal files.  There is currently no way
1485              to distinguish whether they might be directories, and
1486              follow them.  */
1487           if (!opt.retr_symlinks)
1488             {
1489 #ifdef HAVE_SYMLINK
1490               if (!f->linkto)
1491                 logputs (LOG_NOTQUIET,
1492                          _("Invalid name of the symlink, skipping.\n"));
1493               else
1494                 {
1495                   struct_stat st;
1496                   /* Check whether we already have the correct
1497                      symbolic link.  */
1498                   int rc = lstat (con->target, &st);
1499                   if (rc == 0)
1500                     {
1501                       size_t len = strlen (f->linkto) + 1;
1502                       if (S_ISLNK (st.st_mode))
1503                         {
1504                           char *link_target = (char *)alloca (len);
1505                           size_t n = readlink (con->target, link_target, len);
1506                           if ((n == len - 1)
1507                               && (memcmp (link_target, f->linkto, n) == 0))
1508                             {
1509                               logprintf (LOG_VERBOSE, _("\
1510 Already have correct symlink %s -> %s\n\n"),
1511                                          con->target, f->linkto);
1512                               dlthis = 0;
1513                               break;
1514                             }
1515                         }
1516                     }
1517                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1518                              con->target, f->linkto);
1519                   /* Unlink before creating symlink!  */
1520                   unlink (con->target);
1521                   if (symlink (f->linkto, con->target) == -1)
1522                     logprintf (LOG_NOTQUIET, "symlink: %s\n",
1523                                strerror (errno));
1524                   logputs (LOG_VERBOSE, "\n");
1525                 } /* have f->linkto */
1526 #else  /* not HAVE_SYMLINK */
1527               logprintf (LOG_NOTQUIET,
1528                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1529                          con->target);
1530 #endif /* not HAVE_SYMLINK */
1531             }
1532           else                /* opt.retr_symlinks */
1533             {
1534               if (dlthis)
1535                 err = ftp_loop_internal (u, f, con);
1536             } /* opt.retr_symlinks */
1537           break;
1538         case FT_DIRECTORY:
1539           if (!opt.recursive)
1540             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1541                        f->name);
1542           break;
1543         case FT_PLAINFILE:
1544           /* Call the retrieve loop.  */
1545           if (dlthis)
1546             err = ftp_loop_internal (u, f, con);
1547           break;
1548         case FT_UNKNOWN:
1549           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1550                      f->name);
1551           break;
1552         }       /* switch */
1553
1554       /* Set the time-stamp information to the local file.  Symlinks
1555          are not to be stamped because it sets the stamp on the
1556          original.  :( */
1557       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1558           && f->tstamp != -1
1559           && dlthis
1560           && file_exists_p (con->target))
1561         {
1562           /* #### This code repeats in http.c and ftp.c.  Move it to a
1563              function!  */
1564           const char *fl = NULL;
1565           if (opt.output_document)
1566             {
1567               if (output_stream_regular)
1568                 fl = opt.output_document;
1569             }
1570           else
1571             fl = con->target;
1572           if (fl)
1573             touch (fl, f->tstamp);
1574         }
1575       else if (f->tstamp == -1)
1576         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1577
1578       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1579         {
1580           if (opt.preserve_perm)
1581             chmod (con->target, f->perms);
1582         }
1583       else
1584         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1585
1586       xfree (con->target);
1587       con->target = old_target;
1588
1589       url_set_file (u, ofile);
1590       xfree (ofile);
1591
1592       /* Break on fatals.  */
1593       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1594         break;
1595       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1596       f = f->next;
1597     }
1598
1599   /* We do not want to call ftp_retrieve_dirs here */
1600   if (opt.recursive &&
1601       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1602     err = ftp_retrieve_dirs (u, orig, con);
1603   else if (opt.recursive)
1604     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1605              depth, opt.reclevel));
1606   --depth;
1607   return err;
1608 }
1609
1610 /* Retrieve the directories given in a file list.  This function works
1611    by simply going through the linked list and calling
1612    ftp_retrieve_glob on each directory entry.  The function knows
1613    about excluded directories.  */
1614 static uerr_t
1615 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1616 {
1617   char *container = NULL;
1618   int container_size = 0;
1619
1620   for (; f; f = f->next)
1621     {
1622       int size;
1623       char *odir, *newdir;
1624
1625       if (opt.quota && total_downloaded_bytes > opt.quota)
1626         break;
1627       if (f->type != FT_DIRECTORY)
1628         continue;
1629
1630       /* Allocate u->dir off stack, but reallocate only if a larger
1631          string is needed.  It's a pity there's no "realloca" for an
1632          item on the bottom of the stack.  */
1633       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1634       if (size > container_size)
1635         container = (char *)alloca (size);
1636       newdir = container;
1637
1638       odir = u->dir;
1639       if (*odir == '\0'
1640           || (*odir == '/' && *(odir + 1) == '\0'))
1641         /* If ODIR is empty or just "/", simply append f->name to
1642            ODIR.  (In the former case, to preserve u->dir being
1643            relative; in the latter case, to avoid double slash.)  */
1644         sprintf (newdir, "%s%s", odir, f->name);
1645       else
1646         /* Else, use a separator. */
1647         sprintf (newdir, "%s/%s", odir, f->name);
1648
1649       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1650       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1651                odir, f->name, newdir));
1652       if (!accdir (newdir, ALLABS))
1653         {
1654           logprintf (LOG_VERBOSE, _("\
1655 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1656           continue;
1657         }
1658
1659       con->st &= ~DONE_CWD;
1660
1661       odir = xstrdup (u->dir);  /* because url_set_dir will free
1662                                    u->dir. */
1663       url_set_dir (u, newdir);
1664       ftp_retrieve_glob (u, con, GETALL);
1665       url_set_dir (u, odir);
1666       xfree (odir);
1667
1668       /* Set the time-stamp?  */
1669     }
1670
1671   if (opt.quota && total_downloaded_bytes > opt.quota)
1672     return QUOTEXC;
1673   else
1674     return RETROK;
1675 }
1676
1677 /* Return non-zero if S has a leading '/'  or contains '../' */
1678 static int
1679 has_insecure_name_p (const char *s)
1680 {
1681   if (*s == '/')
1682     return 1;
1683
1684   if (strstr (s, "../") != 0)
1685     return 1;
1686
1687   return 0;
1688 }
1689
1690 /* A near-top-level function to retrieve the files in a directory.
1691    The function calls ftp_get_listing, to get a linked list of files.
1692    Then it weeds out the file names that do not match the pattern.
1693    ftp_retrieve_list is called with this updated list as an argument.
1694
1695    If the argument ACTION is GETONE, just download the file (but first
1696    get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1697    use globbing; if it's GETALL, download the whole directory.  */
1698 static uerr_t
1699 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1700 {
1701   struct fileinfo *f, *start;
1702   uerr_t res;
1703
1704   con->cmd |= LEAVE_PENDING;
1705
1706   res = ftp_get_listing (u, con, &start);
1707   if (res != RETROK)
1708     return res;
1709   /* First: weed out that do not conform the global rules given in
1710      opt.accepts and opt.rejects.  */
1711   if (opt.accepts || opt.rejects)
1712     {
1713       f = start;
1714       while (f)
1715         {
1716           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1717             {
1718               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1719               f = delelement (f, &start);
1720             }
1721           else
1722             f = f->next;
1723         }
1724     }
1725   /* Remove all files with possible harmful names */
1726   f = start;
1727   while (f)
1728     {
1729       if (has_insecure_name_p (f->name))
1730         {
1731           logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1732           f = delelement (f, &start);
1733         }
1734       else
1735         f = f->next;
1736     }
1737   /* Now weed out the files that do not match our globbing pattern.
1738      If we are dealing with a globbing pattern, that is.  */
1739   if (*u->file && (action == GLOBALL || action == GETONE))
1740     {
1741       int matchres = 0;
1742
1743       f = start;
1744       while (f)
1745         {
1746           matchres = fnmatch (u->file, f->name, 0);
1747           if (matchres == -1)
1748             {
1749               logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1750                          strerror (errno));
1751               break;
1752             }
1753           if (matchres == FNM_NOMATCH)
1754             f = delelement (f, &start); /* delete the element from the list */
1755           else
1756             f = f->next;        /* leave the element in the list */
1757         }
1758       if (matchres == -1)
1759         {
1760           freefileinfo (start);
1761           return RETRBADPATTERN;
1762         }
1763     }
1764   res = RETROK;
1765   if (start)
1766     {
1767       /* Just get everything.  */
1768       ftp_retrieve_list (u, start, con);
1769     }
1770   else if (!start)
1771     {
1772       if (action == GLOBALL)
1773         {
1774           /* No luck.  */
1775           /* #### This message SUCKS.  We should see what was the
1776              reason that nothing was retrieved.  */
1777           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1778         }
1779       else /* GETONE or GETALL */
1780         {
1781           /* Let's try retrieving it anyway.  */
1782           con->st |= ON_YOUR_OWN;
1783           res = ftp_loop_internal (u, NULL, con);
1784           return res;
1785         }
1786     }
1787   freefileinfo (start);
1788   if (opt.quota && total_downloaded_bytes > opt.quota)
1789     return QUOTEXC;
1790   else
1791     /* #### Should we return `res' here?  */
1792     return RETROK;
1793 }
1794
1795 /* The wrapper that calls an appropriate routine according to contents
1796    of URL.  Inherently, its capabilities are limited on what can be
1797    encoded into a URL.  */
1798 uerr_t
1799 ftp_loop (struct url *u, int *dt, struct url *proxy)
1800 {
1801   ccon con;                     /* FTP connection */
1802   uerr_t res;
1803
1804   *dt = 0;
1805
1806   memset (&con, 0, sizeof (con));
1807
1808   con.csock = -1;
1809   con.st = ON_YOUR_OWN;
1810   con.rs = ST_UNIX;
1811   con.id = NULL;
1812   con.proxy = proxy;
1813   res = RETROK;                 /* in case it's not used */
1814
1815   /* If the file name is empty, the user probably wants a directory
1816      index.  We'll provide one, properly HTML-ized.  Unless
1817      opt.htmlify is 0, of course.  :-) */
1818   if (!*u->file && !opt.recursive)
1819     {
1820       struct fileinfo *f;
1821       res = ftp_get_listing (u, &con, &f);
1822
1823       if (res == RETROK)
1824         {
1825           if (opt.htmlify && !opt.spider)
1826             {
1827               char *filename = (opt.output_document
1828                                 ? xstrdup (opt.output_document)
1829                                 : (con.target ? xstrdup (con.target)
1830                                    : url_file_name (u)));
1831               res = ftp_index (filename, u, f);
1832               if (res == FTPOK && opt.verbose)
1833                 {
1834                   if (!opt.output_document)
1835                     {
1836                       struct_stat st;
1837                       wgint sz;
1838                       if (stat (filename, &st) == 0)
1839                         sz = st.st_size;
1840                       else
1841                         sz = -1;
1842                       logprintf (LOG_NOTQUIET,
1843                                  _("Wrote HTML-ized index to `%s' [%s].\n"),
1844                                  filename, number_to_static_string (sz));
1845                     }
1846                   else
1847                     logprintf (LOG_NOTQUIET,
1848                                _("Wrote HTML-ized index to `%s'.\n"),
1849                                filename);
1850                 }
1851               xfree (filename);
1852             }
1853           freefileinfo (f);
1854         }
1855     }
1856   else
1857     {
1858       int wild = has_wildcards_p (u->file);
1859       if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1860         {
1861           /* ftp_retrieve_glob is a catch-all function that gets called
1862              if we need globbing, time-stamping or recursion.  Its
1863              third argument is just what we really need.  */
1864           res = ftp_retrieve_glob (u, &con,
1865                                    (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1866         }
1867       else
1868         res = ftp_loop_internal (u, NULL, &con);
1869     }
1870   if (res == FTPOK)
1871     res = RETROK;
1872   if (res == RETROK)
1873     *dt |= RETROKF;
1874   /* If a connection was left, quench it.  */
1875   if (con.csock != -1)
1876     fd_close (con.csock);
1877   xfree_null (con.id);
1878   con.id = NULL;
1879   xfree_null (con.target);
1880   con.target = NULL;
1881   return res;
1882 }
1883
1884 /* Delete an element from the fileinfo linked list.  Returns the
1885    address of the next element, or NULL if the list is exhausted.  It
1886    can modify the start of the list.  */
1887 static struct fileinfo *
1888 delelement (struct fileinfo *f, struct fileinfo **start)
1889 {
1890   struct fileinfo *prev = f->prev;
1891   struct fileinfo *next = f->next;
1892
1893   xfree (f->name);
1894   xfree_null (f->linkto);
1895   xfree (f);
1896
1897   if (next)
1898     next->prev = prev;
1899   if (prev)
1900     prev->next = next;
1901   else
1902     *start = next;
1903   return next;
1904 }
1905
1906 /* Free the fileinfo linked list of files.  */
1907 static void
1908 freefileinfo (struct fileinfo *f)
1909 {
1910   while (f)
1911     {
1912       struct fileinfo *next = f->next;
1913       xfree (f->name);
1914       if (f->linkto)
1915         xfree (f->linkto);
1916       xfree (f);
1917       f = next;
1918     }
1919 }