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