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