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