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