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