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