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