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