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