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