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