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