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