]> sjero.net Git - wget/blob - src/ftp.c
Fixed bug #23238: --no-clobber doesn't work with -O flag
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3    2004, 2005, 2006, 2007, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.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 #include <time.h>
42
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 #ifdef MSDOS
55 #define LIST_FILENAME "_listing"
56 #else
57 #define LIST_FILENAME ".listing"
58 #endif
59
60 typedef struct
61 {
62   int st;                       /* connection status */
63   int cmd;                      /* command code */
64   int csock;                    /* control connection socket */
65   double dltime;                /* time of the download in msecs */
66   enum stype rs;                /* remote system reported by ftp server */ 
67   char *id;                     /* initial directory */
68   char *target;                 /* target file name */
69   struct url *proxy;            /* FTWK-style proxy */
70 } ccon;
71
72
73 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
74    the string S, and return the number converted to wgint, if found, 0
75    otherwise.  */
76 static wgint
77 ftp_expected_bytes (const char *s)
78 {
79   wgint res;
80
81   while (1)
82     {
83       while (*s && *s != '(')
84         ++s;
85       if (!*s)
86         return 0;
87       ++s;                      /* skip the '(' */
88       res = str_to_wgint (s, (char **) &s, 10);
89       if (!*s)
90         return 0;
91       while (*s && c_isspace (*s))
92         ++s;
93       if (!*s)
94         return 0;
95       if (c_tolower (*s) != 'b')
96         continue;
97       if (strncasecmp (s, "byte", 4))
98         continue;
99       else
100         break;
101     }
102   return res;
103 }
104
105 #ifdef ENABLE_IPV6
106 /* 
107  * This function sets up a passive data connection with the FTP server.
108  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
109  */
110 static uerr_t
111 ftp_do_pasv (int csock, ip_address *addr, int *port)
112 {
113   uerr_t err;
114
115   /* We need to determine the address family and need to call
116      getpeername, so while we're at it, store the address to ADDR.
117      ftp_pasv and ftp_lpsv can simply override it.  */
118   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
119     abort ();
120
121   /* If our control connection is over IPv6, then we first try EPSV and then 
122    * LPSV if the former is not supported. If the control connection is over 
123    * IPv4, we simply issue the good old PASV request. */
124   switch (addr->family)
125     {
126     case AF_INET:
127       if (!opt.server_response)
128         logputs (LOG_VERBOSE, "==> PASV ... ");
129       err = ftp_pasv (csock, addr, port);
130       break;
131     case AF_INET6:
132       if (!opt.server_response)
133         logputs (LOG_VERBOSE, "==> EPSV ... ");
134       err = ftp_epsv (csock, addr, port);
135
136       /* If EPSV is not supported try LPSV */
137       if (err == FTPNOPASV)
138         {
139           if (!opt.server_response)
140             logputs (LOG_VERBOSE, "==> LPSV ... ");
141           err = ftp_lpsv (csock, addr, port);
142         }
143       break;
144     default:
145       abort ();
146     }
147
148   return err;
149 }
150
151 /* 
152  * This function sets up an active data connection with the FTP server.
153  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
154  */
155 static uerr_t
156 ftp_do_port (int csock, int *local_sock)
157 {
158   uerr_t err;
159   ip_address cip;
160
161   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
162     abort ();
163
164   /* If our control connection is over IPv6, then we first try EPRT and then 
165    * LPRT if the former is not supported. If the control connection is over 
166    * IPv4, we simply issue the good old PORT request. */
167   switch (cip.family)
168     {
169     case AF_INET:
170       if (!opt.server_response)
171         logputs (LOG_VERBOSE, "==> PORT ... ");
172       err = ftp_port (csock, local_sock);
173       break;
174     case AF_INET6:
175       if (!opt.server_response)
176         logputs (LOG_VERBOSE, "==> EPRT ... ");
177       err = ftp_eprt (csock, local_sock);
178
179       /* If EPRT is not supported try LPRT */
180       if (err == FTPPORTERR)
181         {
182           if (!opt.server_response)
183             logputs (LOG_VERBOSE, "==> LPRT ... ");
184           err = ftp_lprt (csock, local_sock);
185         }
186       break;
187     default:
188       abort ();
189     }
190   return err;
191 }
192 #else
193
194 static uerr_t
195 ftp_do_pasv (int csock, ip_address *addr, int *port)
196 {
197   if (!opt.server_response)
198     logputs (LOG_VERBOSE, "==> PASV ... ");
199   return ftp_pasv (csock, addr, port);
200 }
201
202 static uerr_t
203 ftp_do_port (int csock, int *local_sock)
204 {
205   if (!opt.server_response)
206     logputs (LOG_VERBOSE, "==> PORT ... ");
207   return ftp_port (csock, local_sock);
208 }
209 #endif
210
211 static void
212 print_length (wgint size, wgint start, bool authoritative)
213 {
214   logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
215   if (size >= 1024)
216     logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
217   if (start > 0)
218     {
219       if (start >= 1024)
220         logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
221                    number_to_static_string (size - start),
222                    human_readable (size - start));
223       else
224         logprintf (LOG_VERBOSE, _(", %s remaining"),
225                    number_to_static_string (size - start));
226     }
227   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
228 }
229
230 /* Retrieves a file with denoted parameters through opening an FTP
231    connection to the server.  It always closes the data connection,
232    and closes the control connection in case of error.  */
233 static uerr_t
234 getftp (struct url *u, wgint *len, wgint restval, ccon *con)
235 {
236   int csock, dtsock, local_sock, res;
237   uerr_t err = RETROK;          /* appease the compiler */
238   FILE *fp;
239   char *user, *passwd, *respline;
240   char *tms;
241   const char *tmrate;
242   int cmd = con->cmd;
243   bool pasv_mode_open = false;
244   wgint expected_bytes = 0;
245   bool rest_failed = false;
246   int flags;
247   wgint rd_size;
248
249   assert (con != NULL);
250   assert (con->target != NULL);
251
252   /* Debug-check of the sanity of the request by making sure that LIST
253      and RETR are never both requested (since we can handle only one
254      at a time.  */
255   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
256   /* Make sure that at least *something* is requested.  */
257   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
258
259   user = u->user;
260   passwd = u->passwd;
261   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
262   user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
263   if (!user) user = "anonymous";
264   passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
265   if (!passwd) passwd = "-wget@";
266
267   dtsock = -1;
268   local_sock = -1;
269   con->dltime = 0;
270
271   if (!(cmd & DO_LOGIN))
272     csock = con->csock;
273   else                          /* cmd & DO_LOGIN */
274     {
275       char type_char;
276       char    *host = con->proxy ? con->proxy->host : u->host;
277       int      port = con->proxy ? con->proxy->port : u->port;
278       char *logname = user;
279
280       if (con->proxy)
281         {
282           /* If proxy is in use, log in as username@target-site. */
283           logname = concat_strings (user, "@", u->host, (char *) 0);
284         }
285
286       /* Login to the server: */
287
288       /* First: Establish the control connection.  */
289
290       csock = connect_to_host (host, port);
291       if (csock == E_HOST)
292         return HOSTERR;
293       else if (csock < 0)
294         return (retryable_socket_connect_error (errno)
295                 ? CONERROR : CONIMPOSSIBLE);
296
297       if (cmd & LEAVE_PENDING)
298         con->csock = csock;
299       else
300         con->csock = -1;
301
302       /* Second: Login with proper USER/PASS sequence.  */
303       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), escnonprint (user));
304       if (opt.server_response)
305         logputs (LOG_ALWAYS, "\n");
306       err = ftp_login (csock, logname, passwd);
307
308       if (con->proxy)
309         xfree (logname);
310
311       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
312       switch (err)
313         {
314         case FTPRERR:
315           logputs (LOG_VERBOSE, "\n");
316           logputs (LOG_NOTQUIET, _("\
317 Error in server response, closing control connection.\n"));
318           fd_close (csock);
319           con->csock = -1;
320           return err;
321         case FTPSRVERR:
322           logputs (LOG_VERBOSE, "\n");
323           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
324           fd_close (csock);
325           con->csock = -1;
326           return err;
327         case WRITEFAILED:
328           logputs (LOG_VERBOSE, "\n");
329           logputs (LOG_NOTQUIET,
330                    _("Write failed, closing control connection.\n"));
331           fd_close (csock);
332           con->csock = -1;
333           return err;
334         case FTPLOGREFUSED:
335           logputs (LOG_VERBOSE, "\n");
336           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
337           fd_close (csock);
338           con->csock = -1;
339           return FTPLOGREFUSED;
340         case FTPLOGINC:
341           logputs (LOG_VERBOSE, "\n");
342           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
343           fd_close (csock);
344           con->csock = -1;
345           return FTPLOGINC;
346         case FTPOK:
347           if (!opt.server_response)
348             logputs (LOG_VERBOSE, _("Logged in!\n"));
349           break;
350         default:
351           abort ();
352         }
353       /* Third: Get the system type */
354       if (!opt.server_response)
355         logprintf (LOG_VERBOSE, "==> SYST ... ");
356       err = ftp_syst (csock, &con->rs);
357       /* FTPRERR */
358       switch (err)
359         {
360         case FTPRERR:
361           logputs (LOG_VERBOSE, "\n");
362           logputs (LOG_NOTQUIET, _("\
363 Error in server response, closing control connection.\n"));
364           fd_close (csock);
365           con->csock = -1;
366           return err;
367         case FTPSRVERR:
368           logputs (LOG_VERBOSE, "\n");
369           logputs (LOG_NOTQUIET,
370                    _("Server error, can't determine system type.\n"));
371           break;
372         case FTPOK:
373           /* Everything is OK.  */
374           break;
375         default:
376           abort ();
377         }
378       if (!opt.server_response && err != FTPSRVERR)
379         logputs (LOG_VERBOSE, _("done.    "));
380
381       /* Fourth: Find the initial ftp directory */
382
383       if (!opt.server_response)
384         logprintf (LOG_VERBOSE, "==> PWD ... ");
385       err = ftp_pwd (csock, &con->id);
386       /* FTPRERR */
387       switch (err)
388         {
389         case FTPRERR:
390           logputs (LOG_VERBOSE, "\n");
391           logputs (LOG_NOTQUIET, _("\
392 Error in server response, closing control connection.\n"));
393           fd_close (csock);
394           con->csock = -1;
395           return err;
396         case FTPSRVERR :
397           /* PWD unsupported -- assume "/". */
398           xfree_null (con->id);
399           con->id = xstrdup ("/");
400           break;
401         case FTPOK:
402           /* Everything is OK.  */
403           break;
404         default:
405           abort ();
406         }
407       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
408          Convert it to "/INITIAL/FOLDER" */ 
409       if (con->rs == ST_VMS)
410         {
411           char *path = strchr (con->id, '[');
412           char *pathend = path ? strchr (path + 1, ']') : NULL;
413           if (!path || !pathend)
414             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
415           else
416             {
417               char *idir = con->id;
418               DEBUGP (("Preprocessing the initial VMS directory\n"));
419               DEBUGP (("  old = '%s'\n", con->id));
420               /* We do the conversion in-place by copying the stuff
421                  between [ and ] to the beginning, and changing dots
422                  to slashes at the same time.  */
423               *idir++ = '/';
424               for (++path; path < pathend; path++, idir++)
425                 *idir = *path == '.' ? '/' : *path;
426               *idir = '\0';
427               DEBUGP (("  new = '%s'\n\n", con->id));
428             }
429         }
430       if (!opt.server_response)
431         logputs (LOG_VERBOSE, _("done.\n"));
432
433       /* Fifth: Set the FTP type.  */
434       type_char = ftp_process_type (u->params);
435       if (!opt.server_response)
436         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
437       err = ftp_type (csock, type_char);
438       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
439       switch (err)
440         {
441         case FTPRERR:
442           logputs (LOG_VERBOSE, "\n");
443           logputs (LOG_NOTQUIET, _("\
444 Error in server response, closing control connection.\n"));
445           fd_close (csock);
446           con->csock = -1;
447           return err;
448         case WRITEFAILED:
449           logputs (LOG_VERBOSE, "\n");
450           logputs (LOG_NOTQUIET,
451                    _("Write failed, closing control connection.\n"));
452           fd_close (csock);
453           con->csock = -1;
454           return err;
455         case FTPUNKNOWNTYPE:
456           logputs (LOG_VERBOSE, "\n");
457           logprintf (LOG_NOTQUIET,
458                      _("Unknown type `%c', closing control connection.\n"),
459                      type_char);
460           fd_close (csock);
461           con->csock = -1;
462           return err;
463         case FTPOK:
464           /* Everything is OK.  */
465           break;
466         default:
467           abort ();
468         }
469       if (!opt.server_response)
470         logputs (LOG_VERBOSE, _("done.  "));
471     } /* do login */
472
473   if (cmd & DO_CWD)
474     {
475       if (!*u->dir)
476         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
477       else
478         {
479           char *target = u->dir;
480
481           DEBUGP (("changing working directory\n"));
482
483           /* Change working directory.  To change to a non-absolute
484              Unix directory, we need to prepend initial directory
485              (con->id) to it.  Absolute directories "just work".
486
487              A relative directory is one that does not begin with '/'
488              and, on non-Unix OS'es, one that doesn't begin with
489              "[a-z]:".
490
491              This is not done for OS400, which doesn't use
492              "/"-delimited directories, nor does it support directory
493              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
494              in "bar", not in "foo/bar", as would be customary
495              elsewhere.  */
496
497           if (target[0] != '/'
498               && !(con->rs != ST_UNIX
499                    && c_isalpha (target[0])
500                    && target[1] == ':')
501               && con->rs != ST_OS400)
502             {
503               int idlen = strlen (con->id);
504               char *ntarget, *p;
505
506               /* Strip trailing slash(es) from con->id. */
507               while (idlen > 0 && con->id[idlen - 1] == '/')
508                 --idlen;
509               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
510               memcpy (p, con->id, idlen);
511               p += idlen;
512               *p++ = '/';
513               strcpy (p, target);
514
515               DEBUGP (("Prepended initial PWD to relative path:\n"));
516               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
517                        con->id, target, ntarget));
518               target = ntarget;
519             }
520
521           /* If the FTP host runs VMS, we will have to convert the absolute
522              directory path in UNIX notation to absolute directory path in
523              VMS notation as VMS FTP servers do not like UNIX notation of
524              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
525
526           if (con->rs == ST_VMS)
527             {
528               char *tmpp;
529               char *ntarget = (char *)alloca (strlen (target) + 2);
530               /* We use a converted initial dir, so directories in
531                  TARGET will be separated with slashes, something like
532                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
533                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
534               strcpy (ntarget, target);
535               assert (*ntarget == '/');
536               *ntarget = '[';
537               for (tmpp = ntarget + 1; *tmpp; tmpp++)
538                 if (*tmpp == '/')
539                   *tmpp = '.';
540               *tmpp++ = ']';
541               *tmpp = '\0';
542               DEBUGP (("Changed file name to VMS syntax:\n"));
543               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
544               target = ntarget;
545             }
546
547           if (!opt.server_response)
548             logprintf (LOG_VERBOSE, "==> CWD %s ... ", escnonprint (target));
549           err = ftp_cwd (csock, target);
550           /* FTPRERR, WRITEFAILED, FTPNSFOD */
551           switch (err)
552             {
553             case FTPRERR:
554               logputs (LOG_VERBOSE, "\n");
555               logputs (LOG_NOTQUIET, _("\
556 Error in server response, closing control connection.\n"));
557               fd_close (csock);
558               con->csock = -1;
559               return err;
560             case WRITEFAILED:
561               logputs (LOG_VERBOSE, "\n");
562               logputs (LOG_NOTQUIET,
563                        _("Write failed, closing control connection.\n"));
564               fd_close (csock);
565               con->csock = -1;
566               return err;
567             case FTPNSFOD:
568               logputs (LOG_VERBOSE, "\n");
569               logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
570                          escnonprint (u->dir));
571               fd_close (csock);
572               con->csock = -1;
573               return err;
574             case FTPOK:
575               break;
576             default:
577               abort ();
578             }
579           if (!opt.server_response)
580             logputs (LOG_VERBOSE, _("done.\n"));
581         }
582     }
583   else /* do not CWD */
584     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
585
586   if ((cmd & DO_RETR) && *len == 0)
587     {
588       if (opt.verbose)
589         {
590           if (!opt.server_response)
591             logprintf (LOG_VERBOSE, "==> SIZE %s ... ", escnonprint (u->file));
592         }
593
594       err = ftp_size (csock, u->file, len);
595       /* FTPRERR */
596       switch (err)
597         {
598         case FTPRERR:
599         case FTPSRVERR:
600           logputs (LOG_VERBOSE, "\n");
601           logputs (LOG_NOTQUIET, _("\
602 Error in server response, closing control connection.\n"));
603           fd_close (csock);
604           con->csock = -1;
605           return err;
606         case FTPOK:
607           /* Everything is OK.  */
608           break;
609         default:
610           abort ();
611         }
612         if (!opt.server_response)
613           logprintf (LOG_VERBOSE, *len ? "%s\n" : _("done.\n"),
614                      number_to_static_string (*len));
615     }
616
617   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
618   if (cmd & (DO_LIST | DO_RETR))
619     {
620       if (opt.ftp_pasv)
621         {
622           ip_address passive_addr;
623           int        passive_port;
624           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
625           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
626           switch (err)
627             {
628             case FTPRERR:
629               logputs (LOG_VERBOSE, "\n");
630               logputs (LOG_NOTQUIET, _("\
631 Error in server response, closing control connection.\n"));
632               fd_close (csock);
633               con->csock = -1;
634               return err;
635             case WRITEFAILED:
636               logputs (LOG_VERBOSE, "\n");
637               logputs (LOG_NOTQUIET,
638                        _("Write failed, closing control connection.\n"));
639               fd_close (csock);
640               con->csock = -1;
641               return err;
642             case FTPNOPASV:
643               logputs (LOG_VERBOSE, "\n");
644               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
645               break;
646             case FTPINVPASV:
647               logputs (LOG_VERBOSE, "\n");
648               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
649               break;
650             case FTPOK:
651               break;
652             default:
653               abort ();
654             }   /* switch (err) */
655           if (err==FTPOK)
656             {
657               DEBUGP (("trying to connect to %s port %d\n", 
658                       print_address (&passive_addr), passive_port));
659               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
660               if (dtsock < 0)
661                 {
662                   int save_errno = errno;
663                   fd_close (csock);
664                   con->csock = -1;
665                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
666                              print_address (&passive_addr), passive_port,
667                              strerror (save_errno));
668                   return (retryable_socket_connect_error (save_errno)
669                           ? CONERROR : CONIMPOSSIBLE);
670                 }
671
672               pasv_mode_open = true;  /* Flag to avoid accept port */
673               if (!opt.server_response)
674                 logputs (LOG_VERBOSE, _("done.    "));
675             } /* err==FTP_OK */
676         }
677
678       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
679         {
680           err = ftp_do_port (csock, &local_sock);
681           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
682              FTPPORTERR */
683           switch (err)
684             {
685             case FTPRERR:
686               logputs (LOG_VERBOSE, "\n");
687               logputs (LOG_NOTQUIET, _("\
688 Error in server response, closing control connection.\n"));
689               fd_close (csock);
690               con->csock = -1;
691               fd_close (dtsock);
692               fd_close (local_sock);
693               return err;
694             case WRITEFAILED:
695               logputs (LOG_VERBOSE, "\n");
696               logputs (LOG_NOTQUIET,
697                        _("Write failed, closing control connection.\n"));
698               fd_close (csock);
699               con->csock = -1;
700               fd_close (dtsock);
701               fd_close (local_sock);
702               return err;
703             case CONSOCKERR:
704               logputs (LOG_VERBOSE, "\n");
705               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
706               fd_close (csock);
707               con->csock = -1;
708               fd_close (dtsock);
709               fd_close (local_sock);
710               return err;
711             case FTPSYSERR:
712               logputs (LOG_VERBOSE, "\n");
713               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
714                          strerror (errno));
715               fd_close (dtsock);
716               return err;
717             case FTPPORTERR:
718               logputs (LOG_VERBOSE, "\n");
719               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
720               fd_close (csock);
721               con->csock = -1;
722               fd_close (dtsock);
723               fd_close (local_sock);
724               return err;
725             case FTPOK:
726               break;
727             default:
728               abort ();
729             } /* port switch */
730           if (!opt.server_response)
731             logputs (LOG_VERBOSE, _("done.    "));
732         } /* dtsock == -1 */
733     } /* cmd & (DO_LIST | DO_RETR) */
734
735   /* Restart if needed.  */
736   if (restval && (cmd & DO_RETR))
737     {
738       if (!opt.server_response)
739         logprintf (LOG_VERBOSE, "==> REST %s ... ",
740                    number_to_static_string (restval));
741       err = ftp_rest (csock, restval);
742
743       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
744       switch (err)
745         {
746         case FTPRERR:
747           logputs (LOG_VERBOSE, "\n");
748           logputs (LOG_NOTQUIET, _("\
749 Error in server response, closing control connection.\n"));
750           fd_close (csock);
751           con->csock = -1;
752           fd_close (dtsock);
753           fd_close (local_sock);
754           return err;
755         case WRITEFAILED:
756           logputs (LOG_VERBOSE, "\n");
757           logputs (LOG_NOTQUIET,
758                    _("Write failed, closing control connection.\n"));
759           fd_close (csock);
760           con->csock = -1;
761           fd_close (dtsock);
762           fd_close (local_sock);
763           return err;
764         case FTPRESTFAIL:
765           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
766           rest_failed = true;
767           break;
768         case FTPOK:
769           break;
770         default:
771           abort ();
772         }
773       if (err != FTPRESTFAIL && !opt.server_response)
774         logputs (LOG_VERBOSE, _("done.    "));
775     } /* restval && cmd & DO_RETR */
776
777   if (cmd & DO_RETR)
778     {
779       /* If we're in spider mode, don't really retrieve anything.  The
780          fact that we got to this point should be proof enough that
781          the file exists, vaguely akin to HTTP's concept of a "HEAD"
782          request.  */
783       if (opt.spider)
784         {
785           fd_close (csock);
786           con->csock = -1;
787           fd_close (dtsock);
788           fd_close (local_sock);
789           return RETRFINISHED;
790         }
791
792       if (opt.verbose)
793         {
794           if (!opt.server_response)
795             {
796               if (restval)
797                 logputs (LOG_VERBOSE, "\n");
798               logprintf (LOG_VERBOSE, "==> RETR %s ... ", escnonprint (u->file));
799             }
800         }
801
802       err = ftp_retr (csock, u->file);
803       /* FTPRERR, WRITEFAILED, FTPNSFOD */
804       switch (err)
805         {
806         case FTPRERR:
807           logputs (LOG_VERBOSE, "\n");
808           logputs (LOG_NOTQUIET, _("\
809 Error in server response, closing control connection.\n"));
810           fd_close (csock);
811           con->csock = -1;
812           fd_close (dtsock);
813           fd_close (local_sock);
814           return err;
815         case WRITEFAILED:
816           logputs (LOG_VERBOSE, "\n");
817           logputs (LOG_NOTQUIET,
818                    _("Write failed, closing control connection.\n"));
819           fd_close (csock);
820           con->csock = -1;
821           fd_close (dtsock);
822           fd_close (local_sock);
823           return err;
824         case FTPNSFOD:
825           logputs (LOG_VERBOSE, "\n");
826           logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"),
827                      escnonprint (u->file));
828           fd_close (dtsock);
829           fd_close (local_sock);
830           return err;
831         case FTPOK:
832           break;
833         default:
834           abort ();
835         }
836
837       if (!opt.server_response)
838         logputs (LOG_VERBOSE, _("done.\n"));
839       expected_bytes = ftp_expected_bytes (ftp_last_respline);
840     } /* do retrieve */
841
842   if (cmd & DO_LIST)
843     {
844       if (!opt.server_response)
845         logputs (LOG_VERBOSE, "==> LIST ... ");
846       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
847          without arguments is better than `LIST .'; confirmed by
848          RFC959.  */
849       err = ftp_list (csock, NULL);
850       /* FTPRERR, WRITEFAILED */
851       switch (err)
852         {
853         case FTPRERR:
854           logputs (LOG_VERBOSE, "\n");
855           logputs (LOG_NOTQUIET, _("\
856 Error in server response, closing control connection.\n"));
857           fd_close (csock);
858           con->csock = -1;
859           fd_close (dtsock);
860           fd_close (local_sock);
861           return err;
862         case WRITEFAILED:
863           logputs (LOG_VERBOSE, "\n");
864           logputs (LOG_NOTQUIET,
865                    _("Write failed, closing control connection.\n"));
866           fd_close (csock);
867           con->csock = -1;
868           fd_close (dtsock);
869           fd_close (local_sock);
870           return err;
871         case FTPNSFOD:
872           logputs (LOG_VERBOSE, "\n");
873           logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
874                      ".");
875           fd_close (dtsock);
876           fd_close (local_sock);
877           return err;
878         case FTPOK:
879           break;
880         default:
881           abort ();
882         }
883       if (!opt.server_response)
884         logputs (LOG_VERBOSE, _("done.\n"));
885       expected_bytes = ftp_expected_bytes (ftp_last_respline);
886     } /* cmd & DO_LIST */
887
888   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
889     return RETRFINISHED;
890
891   /* Some FTP servers return the total length of file after REST
892      command, others just return the remaining size. */
893   if (*len && restval && expected_bytes
894       && (expected_bytes == *len - restval))
895     {
896       DEBUGP (("Lying FTP server found, adjusting.\n"));
897       expected_bytes = *len;
898     }
899
900   /* If no transmission was required, then everything is OK.  */
901   if (!pasv_mode_open)  /* we are not using pasive mode so we need
902                               to accept */
903     {
904       /* Wait for the server to connect to the address we're waiting
905          at.  */
906       dtsock = accept_connection (local_sock);
907       if (dtsock < 0)
908         {
909           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
910           return err;
911         }
912     }
913
914   /* Open the file -- if output_stream is set, use it instead.  */
915   if (!output_stream || con->cmd & DO_LIST)
916     {
917       mkalldirs (con->target);
918       if (opt.backups)
919         rotate_backups (con->target);
920
921       if (restval && !(con->cmd & DO_LIST))
922         fp = fopen (con->target, "ab");
923       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
924                || opt.output_document)
925         fp = fopen (con->target, "wb");
926       else
927         {
928           fp = fopen_excl (con->target, true);
929           if (!fp && errno == EEXIST)
930             {
931               /* We cannot just invent a new name and use it (which is
932                  what functions like unique_create typically do)
933                  because we told the user we'd use this name.
934                  Instead, return and retry the download.  */
935               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
936                          con->target);
937               fd_close (csock);
938               con->csock = -1;
939               fd_close (dtsock);
940               fd_close (local_sock);
941               return FOPEN_EXCL_ERR;
942             }
943         }
944       if (!fp)
945         {
946           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
947           fd_close (csock);
948           con->csock = -1;
949           fd_close (dtsock);
950           fd_close (local_sock);
951           return FOPENERR;
952         }
953     }
954   else
955     fp = output_stream;
956
957   if (*len)
958     {
959       print_length (*len, restval, true);
960       expected_bytes = *len;    /* for fd_read_body's progress bar */
961     }
962   else if (expected_bytes)
963     print_length (expected_bytes, restval, false);
964
965   /* Get the contents of the document.  */
966   flags = 0;
967   if (restval && rest_failed)
968     flags |= rb_skip_startpos;
969   *len = restval;
970   rd_size = 0;
971   res = fd_read_body (dtsock, fp,
972                       expected_bytes ? expected_bytes - restval : 0,
973                       restval, &rd_size, len, &con->dltime, flags);
974
975   tms = datetime_str (time (NULL));
976   tmrate = retr_rate (rd_size, con->dltime);
977   total_download_time += con->dltime;
978
979   fd_close (local_sock);
980   /* Close the local file.  */
981   if (!output_stream || con->cmd & DO_LIST)
982     fclose (fp);
983
984   /* If fd_read_body couldn't write to fp, bail out.  */
985   if (res == -2)
986     {
987       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
988                  con->target, strerror (errno));
989       fd_close (csock);
990       con->csock = -1;
991       fd_close (dtsock);
992       return FWRITEERR;
993     }
994   else if (res == -1)
995     {
996       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
997                  tms, tmrate, fd_errstr (dtsock));
998       if (opt.server_response)
999         logputs (LOG_ALWAYS, "\n");
1000     }
1001   fd_close (dtsock);
1002
1003   /* Get the server to tell us if everything is retrieved.  */
1004   err = ftp_response (csock, &respline);
1005   if (err != FTPOK)
1006     {
1007       /* The control connection is decidedly closed.  Print the time
1008          only if it hasn't already been printed.  */
1009       if (res != -1)
1010         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1011       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1012       /* If there is an error on the control connection, close it, but
1013          return FTPRETRINT, since there is a possibility that the
1014          whole file was retrieved nevertheless (but that is for
1015          ftp_loop_internal to decide).  */
1016       fd_close (csock);
1017       con->csock = -1;
1018       return FTPRETRINT;
1019     } /* err != FTPOK */
1020   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1021      close socket, since the control connection is still alive.  If
1022      there is something wrong with the control connection, it will
1023      become apparent later.  */
1024   if (*respline != '2')
1025     {
1026       xfree (respline);
1027       if (res != -1)
1028         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1029       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1030       return FTPRETRINT;
1031     }
1032   xfree (respline);
1033
1034   if (res == -1)
1035     {
1036       /* What now?  The data connection was erroneous, whereas the
1037          response says everything is OK.  We shall play it safe.  */
1038       return FTPRETRINT;
1039     }
1040
1041   if (!(cmd & LEAVE_PENDING))
1042     {
1043       /* Closing the socket is faster than sending 'QUIT' and the
1044          effect is the same.  */
1045       fd_close (csock);
1046       con->csock = -1;
1047     }
1048   /* If it was a listing, and opt.server_response is true,
1049      print it out.  */
1050   if (opt.server_response && (con->cmd & DO_LIST))
1051     {
1052       mkalldirs (con->target);
1053       fp = fopen (con->target, "r");
1054       if (!fp)
1055         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1056       else
1057         {
1058           char *line;
1059           /* The lines are being read with read_whole_line because of
1060              no-buffering on opt.lfile.  */
1061           while ((line = read_whole_line (fp)) != NULL)
1062             {
1063               char *p = strchr (line, '\0');
1064               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1065                 *--p = '\0';
1066               logprintf (LOG_ALWAYS, "%s\n", escnonprint (line));
1067               xfree (line);
1068             }
1069           fclose (fp);
1070         }
1071     } /* con->cmd & DO_LIST && server_response */
1072
1073   return RETRFINISHED;
1074 }
1075
1076 /* A one-file FTP loop.  This is the part where FTP retrieval is
1077    retried, and retried, and retried, and...
1078
1079    This loop either gets commands from con, or (if ON_YOUR_OWN is
1080    set), makes them up to retrieve the file given by the URL.  */
1081 static uerr_t
1082 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1083 {
1084   int count, orig_lp;
1085   wgint restval, len = 0;
1086   char *tms, *locf;
1087   const char *tmrate = NULL;
1088   uerr_t err;
1089   struct_stat st;
1090
1091   if (!con->target)
1092     con->target = url_file_name (u);
1093
1094   /* If the output_document was given, then this check was already done and
1095      the file doesn't exist. Hence the !opt.output_document */
1096   if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1097     {
1098       logprintf (LOG_VERBOSE,
1099                  _("File `%s' already there; not retrieving.\n"), con->target);
1100       /* If the file is there, we suppose it's retrieved OK.  */
1101       return RETROK;
1102     }
1103
1104   /* Remove it if it's a link.  */
1105   remove_link (con->target);
1106   if (!opt.output_document)
1107     locf = con->target;
1108   else
1109     locf = opt.output_document;
1110
1111   count = 0;
1112
1113   if (con->st & ON_YOUR_OWN)
1114     con->st = ON_YOUR_OWN;
1115
1116   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1117
1118   /* THE loop.  */
1119   do
1120     {
1121       /* Increment the pass counter.  */
1122       ++count;
1123       sleep_between_retrievals (count);
1124       if (con->st & ON_YOUR_OWN)
1125         {
1126           con->cmd = 0;
1127           con->cmd |= (DO_RETR | LEAVE_PENDING);
1128           if (con->csock != -1)
1129             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1130           else
1131             con->cmd |= (DO_LOGIN | DO_CWD);
1132         }
1133       else /* not on your own */
1134         {
1135           if (con->csock != -1)
1136             con->cmd &= ~DO_LOGIN;
1137           else
1138             con->cmd |= DO_LOGIN;
1139           if (con->st & DONE_CWD)
1140             con->cmd &= ~DO_CWD;
1141           else
1142             con->cmd |= DO_CWD;
1143         }
1144
1145       /* Decide whether or not to restart.  */
1146       if (con->cmd & DO_LIST)
1147         restval = 0;
1148       else if (opt.always_rest
1149           && stat (locf, &st) == 0
1150           && S_ISREG (st.st_mode))
1151         /* When -c is used, continue from on-disk size.  (Can't use
1152            hstat.len even if count>1 because we don't want a failed
1153            first attempt to clobber existing data.)  */
1154         restval = st.st_size;
1155       else if (count > 1)
1156         restval = len;          /* start where the previous run left off */
1157       else
1158         restval = 0;
1159
1160       /* Get the current time string.  */
1161       tms = datetime_str (time (NULL));
1162       /* Print fetch message, if opt.verbose.  */
1163       if (opt.verbose)
1164         {
1165           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1166           char tmp[256];
1167           strcpy (tmp, "        ");
1168           if (count > 1)
1169             sprintf (tmp, _("(try:%2d)"), count);
1170           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1171                      tms, hurl, tmp, locf);
1172 #ifdef WINDOWS
1173           ws_changetitle (hurl);
1174 #endif
1175           xfree (hurl);
1176         }
1177       /* Send getftp the proper length, if fileinfo was provided.  */
1178       if (f)
1179         len = f->size;
1180       else
1181         len = 0;
1182       err = getftp (u, &len, restval, con);
1183
1184       if (con->csock == -1)
1185         con->st &= ~DONE_CWD;
1186       else
1187         con->st |= DONE_CWD;
1188
1189       switch (err)
1190         {
1191         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1192         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1193           /* Fatal errors, give up.  */
1194           return err;
1195         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1196         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1197         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1198         case FOPEN_EXCL_ERR:
1199           printwhat (count, opt.ntry);
1200           /* non-fatal errors */
1201           if (err == FOPEN_EXCL_ERR)
1202             {
1203               /* Re-determine the file name. */
1204               xfree_null (con->target);
1205               con->target = url_file_name (u);
1206               locf = con->target;
1207             }
1208           continue;
1209         case FTPRETRINT:
1210           /* If the control connection was closed, the retrieval
1211              will be considered OK if f->size == len.  */
1212           if (!f || len != f->size)
1213             {
1214               printwhat (count, opt.ntry);
1215               continue;
1216             }
1217           break;
1218         case RETRFINISHED:
1219           /* Great!  */
1220           break;
1221         default:
1222           /* Not as great.  */
1223           abort ();
1224         }
1225       tms = datetime_str (time (NULL));
1226       if (!opt.spider)
1227         tmrate = retr_rate (len - restval, con->dltime);
1228
1229       /* If we get out of the switch above without continue'ing, we've
1230          successfully downloaded a file.  Remember this fact. */
1231       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1232
1233       if (con->st & ON_YOUR_OWN)
1234         {
1235           fd_close (con->csock);
1236           con->csock = -1;
1237         }
1238       if (!opt.spider)
1239         logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%s]\n\n"),
1240                    tms, tmrate, locf, number_to_static_string (len));
1241       if (!opt.verbose && !opt.quiet)
1242         {
1243           /* Need to hide the password from the URL.  The `if' is here
1244              so that we don't do the needless allocation every
1245              time. */
1246           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1247           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1248                      tms, hurl, number_to_static_string (len), locf, count);
1249           xfree (hurl);
1250         }
1251
1252       if ((con->cmd & DO_LIST))
1253         /* This is a directory listing file. */
1254         {
1255           if (!opt.remove_listing)
1256             /* --dont-remove-listing was specified, so do count this towards the
1257                number of bytes and files downloaded. */
1258             {
1259               total_downloaded_bytes += len;
1260               opt.numurls++;
1261             }
1262
1263           /* Deletion of listing files is not controlled by --delete-after, but
1264              by the more specific option --dont-remove-listing, and the code
1265              to do this deletion is in another function. */
1266         }
1267       else if (!opt.spider)
1268         /* This is not a directory listing file. */
1269         {
1270           /* Unlike directory listing files, don't pretend normal files weren't
1271              downloaded if they're going to be deleted.  People seeding proxies,
1272              for instance, may want to know how many bytes and files they've
1273              downloaded through it. */
1274           total_downloaded_bytes += len;
1275           opt.numurls++;
1276
1277           if (opt.delete_after)
1278             {
1279               DEBUGP (("\
1280 Removing file due to --delete-after in ftp_loop_internal():\n"));
1281               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1282               if (unlink (locf))
1283                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1284             }
1285         }
1286
1287       /* Restore the original leave-pendingness.  */
1288       if (orig_lp)
1289         con->cmd |= LEAVE_PENDING;
1290       else
1291         con->cmd &= ~LEAVE_PENDING;
1292       return RETROK;
1293     } while (!opt.ntry || (count < opt.ntry));
1294
1295   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1296     {
1297       fd_close (con->csock);
1298       con->csock = -1;
1299     }
1300   return TRYLIMEXC;
1301 }
1302
1303 /* Return the directory listing in a reusable format.  The directory
1304    is specifed in u->dir.  */
1305 static uerr_t
1306 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1307 {
1308   uerr_t err;
1309   char *uf;                     /* url file name */
1310   char *lf;                     /* list file name */
1311   char *old_target = con->target;
1312
1313   con->st &= ~ON_YOUR_OWN;
1314   con->cmd |= (DO_LIST | LEAVE_PENDING);
1315   con->cmd &= ~DO_RETR;
1316
1317   /* Find the listing file name.  We do it by taking the file name of
1318      the URL and replacing the last component with the listing file
1319      name.  */
1320   uf = url_file_name (u);
1321   lf = file_merge (uf, LIST_FILENAME);
1322   xfree (uf);
1323   DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1324
1325   con->target = lf;
1326   err = ftp_loop_internal (u, NULL, con);
1327   con->target = old_target;
1328
1329   if (err == RETROK)
1330     {
1331       *f = ftp_parse_ls (lf, con->rs);
1332       if (opt.remove_listing)
1333         {
1334           if (unlink (lf))
1335             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1336           else
1337             logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1338         }
1339     }
1340   else
1341     *f = NULL;
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. Assume 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))
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)
1726     {
1727       if (action == GLOB_GLOBALL)
1728         {
1729           int (*matcher) (const char *, const char *, int)
1730             = opt.ignore_case ? fnmatch_nocase : fnmatch;
1731           int matchres = 0;
1732
1733           f = start;
1734           while (f)
1735             {
1736               matchres = matcher (u->file, f->name, 0);
1737               if (matchres == -1)
1738                 {
1739                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
1740                              u->file, escnonprint (f->name), strerror (errno));
1741                   break;
1742                 }
1743               if (matchres == FNM_NOMATCH)
1744                 f = delelement (f, &start); /* delete the element from the list */
1745               else
1746                 f = f->next;        /* leave the element in the list */
1747             }
1748           if (matchres == -1)
1749             {
1750               freefileinfo (start);
1751               return RETRBADPATTERN;
1752             }
1753         }
1754       else if (action == GLOB_GETONE)
1755         {
1756           int (*cmp) (const char *, const char *)
1757             = opt.ignore_case ? strcasecmp : strcmp;
1758           f = start;
1759           while (f)
1760             {
1761               if (0 != cmp(u->file, f->name))
1762                 f = delelement (f, &start);
1763               else
1764                 f = f->next;
1765             }
1766         }
1767     }
1768   if (start)
1769     {
1770       /* Just get everything.  */
1771       ftp_retrieve_list (u, start, con);
1772     }
1773   else
1774     {
1775       if (action == GLOB_GLOBALL)
1776         {
1777           /* No luck.  */
1778           /* #### This message SUCKS.  We should see what was the
1779              reason that nothing was retrieved.  */
1780           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"),
1781                      escnonprint (u->file));
1782         }
1783       else /* GLOB_GETONE or GLOB_GETALL */
1784         {
1785           /* Let's try retrieving it anyway.  */
1786           con->st |= ON_YOUR_OWN;
1787           res = ftp_loop_internal (u, NULL, con);
1788           return res;
1789         }
1790     }
1791   freefileinfo (start);
1792   if (opt.quota && total_downloaded_bytes > opt.quota)
1793     return QUOTEXC;
1794   else
1795     /* #### Should we return `res' here?  */
1796     return RETROK;
1797 }
1798
1799 /* The wrapper that calls an appropriate routine according to contents
1800    of URL.  Inherently, its capabilities are limited on what can be
1801    encoded into a URL.  */
1802 uerr_t
1803 ftp_loop (struct url *u, int *dt, struct url *proxy, bool recursive, bool glob)
1804 {
1805   ccon con;                     /* FTP connection */
1806   uerr_t res;
1807
1808   *dt = 0;
1809
1810   xzero (con);
1811
1812   con.csock = -1;
1813   con.st = ON_YOUR_OWN;
1814   con.rs = ST_UNIX;
1815   con.id = NULL;
1816   con.proxy = proxy;
1817
1818   /* If the file name is empty, the user probably wants a directory
1819      index.  We'll provide one, properly HTML-ized.  Unless
1820      opt.htmlify is 0, of course.  :-) */
1821   if (!*u->file && !recursive)
1822     {
1823       struct fileinfo *f;
1824       res = ftp_get_listing (u, &con, &f);
1825
1826       if (res == RETROK)
1827         {
1828           if (opt.htmlify && !opt.spider)
1829             {
1830               char *filename = (opt.output_document
1831                                 ? xstrdup (opt.output_document)
1832                                 : (con.target ? xstrdup (con.target)
1833                                    : url_file_name (u)));
1834               res = ftp_index (filename, u, f);
1835               if (res == FTPOK && opt.verbose)
1836                 {
1837                   if (!opt.output_document)
1838                     {
1839                       struct_stat st;
1840                       wgint sz;
1841                       if (stat (filename, &st) == 0)
1842                         sz = st.st_size;
1843                       else
1844                         sz = -1;
1845                       logprintf (LOG_NOTQUIET,
1846                                  _("Wrote HTML-ized index to `%s' [%s].\n"),
1847                                  filename, number_to_static_string (sz));
1848                     }
1849                   else
1850                     logprintf (LOG_NOTQUIET,
1851                                _("Wrote HTML-ized index to `%s'.\n"),
1852                                filename);
1853                 }
1854               xfree (filename);
1855             }
1856           freefileinfo (f);
1857         }
1858     }
1859   else
1860     {
1861       bool ispattern = false;
1862       if (glob)
1863         {
1864           /* Treat the URL as a pattern if the file name part of the
1865              URL path contains wildcards.  (Don't check for u->file
1866              because it is unescaped and therefore doesn't leave users
1867              the option to escape literal '*' as %2A.)  */
1868           char *file_part = strrchr (u->path, '/');
1869           if (!file_part)
1870             file_part = u->path;
1871           ispattern = has_wildcards_p (file_part);
1872         }
1873       if (ispattern || recursive || opt.timestamping)
1874         {
1875           /* ftp_retrieve_glob is a catch-all function that gets called
1876              if we need globbing, time-stamping or recursion.  Its
1877              third argument is just what we really need.  */
1878           res = ftp_retrieve_glob (u, &con,
1879                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
1880         }
1881       else
1882         res = ftp_loop_internal (u, NULL, &con);
1883     }
1884   if (res == FTPOK)
1885     res = RETROK;
1886   if (res == RETROK)
1887     *dt |= RETROKF;
1888   /* If a connection was left, quench it.  */
1889   if (con.csock != -1)
1890     fd_close (con.csock);
1891   xfree_null (con.id);
1892   con.id = NULL;
1893   xfree_null (con.target);
1894   con.target = NULL;
1895   return res;
1896 }
1897
1898 /* Delete an element from the fileinfo linked list.  Returns the
1899    address of the next element, or NULL if the list is exhausted.  It
1900    can modify the start of the list.  */
1901 static struct fileinfo *
1902 delelement (struct fileinfo *f, struct fileinfo **start)
1903 {
1904   struct fileinfo *prev = f->prev;
1905   struct fileinfo *next = f->next;
1906
1907   xfree (f->name);
1908   xfree_null (f->linkto);
1909   xfree (f);
1910
1911   if (next)
1912     next->prev = prev;
1913   if (prev)
1914     prev->next = next;
1915   else
1916     *start = next;
1917   return next;
1918 }
1919
1920 /* Free the fileinfo linked list of files.  */
1921 static void
1922 freefileinfo (struct fileinfo *f)
1923 {
1924   while (f)
1925     {
1926       struct fileinfo *next = f->next;
1927       xfree (f->name);
1928       if (f->linkto)
1929         xfree (f->linkto);
1930       xfree (f);
1931       f = next;
1932     }
1933 }