]> sjero.net Git - wget/blob - src/ftp.c
Recieve ftp listing even when .listing file exist and --no-clobber option is given.
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3    2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
4    Inc.
5
6 This file is part of GNU Wget.
7
8 GNU Wget is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Wget is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21 Additional permission under GNU GPL version 3 section 7
22
23 If you modify this program, or any covered work, by linking or
24 combining it with the OpenSSL project's OpenSSL library (or a
25 modified version of that library), containing parts covered by the
26 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27 grants you additional permission to convey the resulting work.
28 Corresponding Source for a non-source form of such a combination
29 shall include the source code for the parts of OpenSSL used as well
30 as that of the covered work.  */
31
32 #include "wget.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <unistd.h>
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 #include "warc.h"
53
54 #ifdef __VMS
55 # include "vms.h"
56 #endif /* def __VMS */
57
58
59 /* File where the "ls -al" listing will be saved.  */
60 #ifdef MSDOS
61 #define LIST_FILENAME "_listing"
62 #else
63 #define LIST_FILENAME ".listing"
64 #endif
65
66 typedef struct
67 {
68   int st;                       /* connection status */
69   int cmd;                      /* command code */
70   int csock;                    /* control connection socket */
71   double dltime;                /* time of the download in msecs */
72   enum stype rs;                /* remote system reported by ftp server */
73   char *id;                     /* initial directory */
74   char *target;                 /* target file name */
75   struct url *proxy;            /* FTWK-style proxy */
76 } ccon;
77
78 extern int numurls;
79
80 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
81    the string S, and return the number converted to wgint, if found, 0
82    otherwise.  */
83 static wgint
84 ftp_expected_bytes (const char *s)
85 {
86   wgint res;
87
88   while (1)
89     {
90       while (*s && *s != '(')
91         ++s;
92       if (!*s)
93         return 0;
94       ++s;                      /* skip the '(' */
95       res = str_to_wgint (s, (char **) &s, 10);
96       if (!*s)
97         return 0;
98       while (*s && c_isspace (*s))
99         ++s;
100       if (!*s)
101         return 0;
102       if (c_tolower (*s) != 'b')
103         continue;
104       if (strncasecmp (s, "byte", 4))
105         continue;
106       else
107         break;
108     }
109   return res;
110 }
111
112 #ifdef ENABLE_IPV6
113 /*
114  * This function sets up a passive data connection with the FTP server.
115  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
116  */
117 static uerr_t
118 ftp_do_pasv (int csock, ip_address *addr, int *port)
119 {
120   uerr_t err;
121
122   /* We need to determine the address family and need to call
123      getpeername, so while we're at it, store the address to ADDR.
124      ftp_pasv and ftp_lpsv can simply override it.  */
125   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
126     abort ();
127
128   /* If our control connection is over IPv6, then we first try EPSV and then
129    * LPSV if the former is not supported. If the control connection is over
130    * IPv4, we simply issue the good old PASV request. */
131   switch (addr->family)
132     {
133     case AF_INET:
134       if (!opt.server_response)
135         logputs (LOG_VERBOSE, "==> PASV ... ");
136       err = ftp_pasv (csock, addr, port);
137       break;
138     case AF_INET6:
139       if (!opt.server_response)
140         logputs (LOG_VERBOSE, "==> EPSV ... ");
141       err = ftp_epsv (csock, addr, port);
142
143       /* If EPSV is not supported try LPSV */
144       if (err == FTPNOPASV)
145         {
146           if (!opt.server_response)
147             logputs (LOG_VERBOSE, "==> LPSV ... ");
148           err = ftp_lpsv (csock, addr, port);
149         }
150       break;
151     default:
152       abort ();
153     }
154
155   return err;
156 }
157
158 /*
159  * This function sets up an active data connection with the FTP server.
160  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
161  */
162 static uerr_t
163 ftp_do_port (int csock, int *local_sock)
164 {
165   uerr_t err;
166   ip_address cip;
167
168   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
169     abort ();
170
171   /* If our control connection is over IPv6, then we first try EPRT and then
172    * LPRT if the former is not supported. If the control connection is over
173    * IPv4, we simply issue the good old PORT request. */
174   switch (cip.family)
175     {
176     case AF_INET:
177       if (!opt.server_response)
178         logputs (LOG_VERBOSE, "==> PORT ... ");
179       err = ftp_port (csock, local_sock);
180       break;
181     case AF_INET6:
182       if (!opt.server_response)
183         logputs (LOG_VERBOSE, "==> EPRT ... ");
184       err = ftp_eprt (csock, local_sock);
185
186       /* If EPRT is not supported try LPRT */
187       if (err == FTPPORTERR)
188         {
189           if (!opt.server_response)
190             logputs (LOG_VERBOSE, "==> LPRT ... ");
191           err = ftp_lprt (csock, local_sock);
192         }
193       break;
194     default:
195       abort ();
196     }
197   return err;
198 }
199 #else
200
201 static uerr_t
202 ftp_do_pasv (int csock, ip_address *addr, int *port)
203 {
204   if (!opt.server_response)
205     logputs (LOG_VERBOSE, "==> PASV ... ");
206   return ftp_pasv (csock, addr, port);
207 }
208
209 static uerr_t
210 ftp_do_port (int csock, int *local_sock)
211 {
212   if (!opt.server_response)
213     logputs (LOG_VERBOSE, "==> PORT ... ");
214   return ftp_port (csock, local_sock);
215 }
216 #endif
217
218 static void
219 print_length (wgint size, wgint start, bool authoritative)
220 {
221   logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
222   if (size >= 1024)
223     logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
224   if (start > 0)
225     {
226       if (size - start >= 1024)
227         logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
228                    number_to_static_string (size - start),
229                    human_readable (size - start));
230       else
231         logprintf (LOG_VERBOSE, _(", %s remaining"),
232                    number_to_static_string (size - start));
233     }
234   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
235 }
236
237 static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
238
239 /* Retrieves a file with denoted parameters through opening an FTP
240    connection to the server.  It always closes the data connection,
241    and closes the control connection in case of error.  If warc_tmp
242    is non-NULL, the downloaded data will be written there as well.  */
243 static uerr_t
244 getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
245         wgint restval, ccon *con, int count, FILE *warc_tmp)
246 {
247   int csock, dtsock, local_sock, res;
248   uerr_t err = RETROK;          /* appease the compiler */
249   FILE *fp;
250   char *respline, *tms;
251   const char *user, *passwd, *tmrate;
252   int cmd = con->cmd;
253   bool pasv_mode_open = false;
254   wgint expected_bytes = 0;
255   bool got_expected_bytes = false;
256   bool rest_failed = false;
257   int flags;
258   wgint rd_size;
259   char type_char;
260
261   assert (con != NULL);
262   assert (con->target != NULL);
263
264   /* Debug-check of the sanity of the request by making sure that LIST
265      and RETR are never both requested (since we can handle only one
266      at a time.  */
267   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
268   /* Make sure that at least *something* is requested.  */
269   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
270
271   *qtyread = restval;
272
273   user = u->user;
274   passwd = u->passwd;
275   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
276   user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
277   if (!user) user = "anonymous";
278   passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
279   if (!passwd) passwd = "-wget@";
280
281   dtsock = -1;
282   local_sock = -1;
283   con->dltime = 0;
284
285   if (!(cmd & DO_LOGIN))
286     csock = con->csock;
287   else                          /* cmd & DO_LOGIN */
288     {
289       char    *host = con->proxy ? con->proxy->host : u->host;
290       int      port = con->proxy ? con->proxy->port : u->port;
291
292       /* Login to the server: */
293
294       /* First: Establish the control connection.  */
295
296       csock = connect_to_host (host, port);
297       if (csock == E_HOST)
298           return HOSTERR;
299       else if (csock < 0)
300           return (retryable_socket_connect_error (errno)
301                   ? CONERROR : CONIMPOSSIBLE);
302
303       if (cmd & LEAVE_PENDING)
304         con->csock = csock;
305       else
306         con->csock = -1;
307
308       /* Second: Login with proper USER/PASS sequence.  */
309       logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
310                  quotearg_style (escape_quoting_style, user));
311       if (opt.server_response)
312         logputs (LOG_ALWAYS, "\n");
313       if (con->proxy)
314         {
315           /* If proxy is in use, log in as username@target-site. */
316           char *logname = concat_strings (user, "@", u->host, (char *) 0);
317           err = ftp_login (csock, logname, passwd);
318           xfree (logname);
319         }
320       else
321         err = ftp_login (csock, user, passwd);
322
323       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
324       switch (err)
325         {
326         case FTPRERR:
327           logputs (LOG_VERBOSE, "\n");
328           logputs (LOG_NOTQUIET, _("\
329 Error in server response, closing control connection.\n"));
330           fd_close (csock);
331           con->csock = -1;
332           return err;
333         case FTPSRVERR:
334           logputs (LOG_VERBOSE, "\n");
335           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
336           fd_close (csock);
337           con->csock = -1;
338           return err;
339         case WRITEFAILED:
340           logputs (LOG_VERBOSE, "\n");
341           logputs (LOG_NOTQUIET,
342                    _("Write failed, closing control connection.\n"));
343           fd_close (csock);
344           con->csock = -1;
345           return err;
346         case FTPLOGREFUSED:
347           logputs (LOG_VERBOSE, "\n");
348           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
349           fd_close (csock);
350           con->csock = -1;
351           return FTPLOGREFUSED;
352         case FTPLOGINC:
353           logputs (LOG_VERBOSE, "\n");
354           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
355           fd_close (csock);
356           con->csock = -1;
357           return FTPLOGINC;
358         case FTPOK:
359           if (!opt.server_response)
360             logputs (LOG_VERBOSE, _("Logged in!\n"));
361           break;
362         default:
363           abort ();
364         }
365       /* Third: Get the system type */
366       if (!opt.server_response)
367         logprintf (LOG_VERBOSE, "==> SYST ... ");
368       err = ftp_syst (csock, &con->rs);
369       /* FTPRERR */
370       switch (err)
371         {
372         case FTPRERR:
373           logputs (LOG_VERBOSE, "\n");
374           logputs (LOG_NOTQUIET, _("\
375 Error in server response, closing control connection.\n"));
376           fd_close (csock);
377           con->csock = -1;
378           return err;
379         case FTPSRVERR:
380           logputs (LOG_VERBOSE, "\n");
381           logputs (LOG_NOTQUIET,
382                    _("Server error, can't determine system type.\n"));
383           break;
384         case FTPOK:
385           /* Everything is OK.  */
386           break;
387         default:
388           abort ();
389         }
390       if (!opt.server_response && err != FTPSRVERR)
391         logputs (LOG_VERBOSE, _("done.    "));
392
393       /* Fourth: Find the initial ftp directory */
394
395       if (!opt.server_response)
396         logprintf (LOG_VERBOSE, "==> PWD ... ");
397       err = ftp_pwd (csock, &con->id);
398       /* FTPRERR */
399       switch (err)
400         {
401         case FTPRERR:
402           logputs (LOG_VERBOSE, "\n");
403           logputs (LOG_NOTQUIET, _("\
404 Error in server response, closing control connection.\n"));
405           fd_close (csock);
406           con->csock = -1;
407           return err;
408         case FTPSRVERR :
409           /* PWD unsupported -- assume "/". */
410           xfree_null (con->id);
411           con->id = xstrdup ("/");
412           break;
413         case FTPOK:
414           /* Everything is OK.  */
415           break;
416         default:
417           abort ();
418         }
419
420 #if 0
421       /* 2004-09-17 SMS.
422          Don't help me out.  Please.
423          A reasonably recent VMS FTP server will cope just fine with
424          UNIX file specifications.  This code just spoils things.
425          Discarding the device name, for example, is not a wise move.
426          This code was disabled but left in as an example of what not
427          to do.
428       */
429
430       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
431          Convert it to "/INITIAL/FOLDER" */
432       if (con->rs == ST_VMS)
433         {
434           char *path = strchr (con->id, '[');
435           char *pathend = path ? strchr (path + 1, ']') : NULL;
436           if (!path || !pathend)
437             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
438           else
439             {
440               char *idir = con->id;
441               DEBUGP (("Preprocessing the initial VMS directory\n"));
442               DEBUGP (("  old = '%s'\n", con->id));
443               /* We do the conversion in-place by copying the stuff
444                  between [ and ] to the beginning, and changing dots
445                  to slashes at the same time.  */
446               *idir++ = '/';
447               for (++path; path < pathend; path++, idir++)
448                 *idir = *path == '.' ? '/' : *path;
449               *idir = '\0';
450               DEBUGP (("  new = '%s'\n\n", con->id));
451             }
452         }
453 #endif /* 0 */
454
455       if (!opt.server_response)
456         logputs (LOG_VERBOSE, _("done.\n"));
457
458       /* Fifth: Set the FTP type.  */
459       type_char = ftp_process_type (u->params);
460       if (!opt.server_response)
461         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
462       err = ftp_type (csock, type_char);
463       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
464       switch (err)
465         {
466         case FTPRERR:
467           logputs (LOG_VERBOSE, "\n");
468           logputs (LOG_NOTQUIET, _("\
469 Error in server response, closing control connection.\n"));
470           fd_close (csock);
471           con->csock = -1;
472           return err;
473         case WRITEFAILED:
474           logputs (LOG_VERBOSE, "\n");
475           logputs (LOG_NOTQUIET,
476                    _("Write failed, closing control connection.\n"));
477           fd_close (csock);
478           con->csock = -1;
479           return err;
480         case FTPUNKNOWNTYPE:
481           logputs (LOG_VERBOSE, "\n");
482           logprintf (LOG_NOTQUIET,
483                      _("Unknown type `%c', closing control connection.\n"),
484                      type_char);
485           fd_close (csock);
486           con->csock = -1;
487           return err;
488         case FTPOK:
489           /* Everything is OK.  */
490           break;
491         default:
492           abort ();
493         }
494       if (!opt.server_response)
495         logputs (LOG_VERBOSE, _("done.  "));
496     } /* do login */
497
498   if (cmd & DO_CWD)
499     {
500       if (!*u->dir)
501         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
502       else
503         {
504           const char *targ = NULL;
505           int cwd_count;
506           int cwd_end;
507           int cwd_start;
508
509           char *target = u->dir;
510
511           DEBUGP (("changing working directory\n"));
512
513           /* Change working directory.  To change to a non-absolute
514              Unix directory, we need to prepend initial directory
515              (con->id) to it.  Absolute directories "just work".
516
517              A relative directory is one that does not begin with '/'
518              and, on non-Unix OS'es, one that doesn't begin with
519              "[a-z]:".
520
521              This is not done for OS400, which doesn't use
522              "/"-delimited directories, nor does it support directory
523              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
524              in "bar", not in "foo/bar", as would be customary
525              elsewhere.  */
526
527             /* 2004-09-20 SMS.
528                Why is this wise even on UNIX?  It certainly fouls VMS.
529                See below for a more reliable, more universal method.
530             */
531
532             /* 2008-04-22 MJC.
533                I'm not crazy about it either. I'm informed it's useful
534                for misconfigured servers that have some dirs in the path
535                with +x but -r, but this method is not RFC-conformant. I
536                understand the need to deal with crappy server
537                configurations, but it's far better to use the canonical
538                method first, and fall back to kludges second.
539             */
540
541           if (target[0] != '/'
542               && !(con->rs != ST_UNIX
543                    && c_isalpha (target[0])
544                    && target[1] == ':')
545               && (con->rs != ST_OS400)
546               && (con->rs != ST_VMS))
547             {
548               int idlen = strlen (con->id);
549               char *ntarget, *p;
550
551               /* Strip trailing slash(es) from con->id. */
552               while (idlen > 0 && con->id[idlen - 1] == '/')
553                 --idlen;
554               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
555               memcpy (p, con->id, idlen);
556               p += idlen;
557               *p++ = '/';
558               strcpy (p, target);
559
560               DEBUGP (("Prepended initial PWD to relative path:\n"));
561               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
562                        con->id, target, ntarget));
563               target = ntarget;
564             }
565
566 #if 0
567           /* 2004-09-17 SMS.
568              Don't help me out.  Please.
569              A reasonably recent VMS FTP server will cope just fine with
570              UNIX file specifications.  This code just spoils things.
571              Discarding the device name, for example, is not a wise
572              move.
573              This code was disabled but left in as an example of what
574              not to do.
575           */
576
577           /* If the FTP host runs VMS, we will have to convert the absolute
578              directory path in UNIX notation to absolute directory path in
579              VMS notation as VMS FTP servers do not like UNIX notation of
580              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
581
582           if (con->rs == ST_VMS)
583             {
584               char *tmpp;
585               char *ntarget = (char *)alloca (strlen (target) + 2);
586               /* We use a converted initial dir, so directories in
587                  TARGET will be separated with slashes, something like
588                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
589                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
590               strcpy (ntarget, target);
591               assert (*ntarget == '/');
592               *ntarget = '[';
593               for (tmpp = ntarget + 1; *tmpp; tmpp++)
594                 if (*tmpp == '/')
595                   *tmpp = '.';
596               *tmpp++ = ']';
597               *tmpp = '\0';
598               DEBUGP (("Changed file name to VMS syntax:\n"));
599               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
600               target = ntarget;
601             }
602 #endif /* 0 */
603
604           /* 2004-09-20 SMS.
605              A relative directory is relative to the initial directory.
606              Thus, what _is_ useful on VMS (and probably elsewhere) is
607              to CWD to the initial directory (ideally, whatever the
608              server reports, _exactly_, NOT badly UNIX-ixed), and then
609              CWD to the (new) relative directory.  This should probably
610              be restructured as a function, called once or twice, but
611              I'm lazy enough to take the badly indented loop short-cut
612              for now.
613           */
614
615           /* Decide on one pass (absolute) or two (relative).
616              The VMS restriction may be relaxed when the squirrely code
617              above is reformed.
618           */
619           if ((con->rs == ST_VMS) && (target[0] != '/'))
620             {
621               cwd_start = 0;
622               DEBUGP (("Using two-step CWD for relative path.\n"));
623             }
624           else
625             {
626               /* Go straight to the target. */
627               cwd_start = 1;
628             }
629
630           /* At least one VMS FTP server (TCPware V5.6-2) can switch to
631              a UNIX emulation mode when given a UNIX-like directory
632              specification (like "a/b/c").  If allowed to continue this
633              way, LIST interpretation will be confused, because the
634              system type (SYST response) will not be re-checked, and
635              future UNIX-format directory listings (for multiple URLs or
636              "-r") will be horribly misinterpreted.
637
638              The cheap and nasty work-around is to do a "CWD []" after a
639              UNIX-like directory specification is used.  (A single-level
640              directory is harmless.)  This puts the TCPware server back
641              into VMS mode, and does no harm on other servers.
642
643              Unlike the rest of this block, this particular behavior
644              _is_ VMS-specific, so it gets its own VMS test.
645           */
646           if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
647             {
648               cwd_end = 3;
649               DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
650             }
651           else
652             {
653               cwd_end = 2;
654             }
655
656           /* 2004-09-20 SMS. */
657           /* Sorry about the deviant indenting.  Laziness. */
658
659           for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
660         {
661           switch (cwd_count)
662             {
663               case 0:
664                 /* Step one (optional): Go to the initial directory,
665                    exactly as reported by the server.
666                 */
667                 targ = con->id;
668                 break;
669
670               case 1:
671                 /* Step two: Go to the target directory.  (Absolute or
672                    relative will work now.)
673                 */
674                 targ = target;
675                 break;
676
677               case 2:
678                 /* Step three (optional): "CWD []" to restore server
679                    VMS-ness.
680                 */
681                 targ = "[]";
682                 break;
683
684               default:
685                 /* Can't happen. */
686                 assert (1);
687             }
688
689           if (!opt.server_response)
690             logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
691                        quotearg_style (escape_quoting_style, target));
692           err = ftp_cwd (csock, targ);
693           /* FTPRERR, WRITEFAILED, FTPNSFOD */
694           switch (err)
695             {
696             case FTPRERR:
697               logputs (LOG_VERBOSE, "\n");
698               logputs (LOG_NOTQUIET, _("\
699 Error in server response, closing control connection.\n"));
700               fd_close (csock);
701               con->csock = -1;
702               return err;
703             case WRITEFAILED:
704               logputs (LOG_VERBOSE, "\n");
705               logputs (LOG_NOTQUIET,
706                        _("Write failed, closing control connection.\n"));
707               fd_close (csock);
708               con->csock = -1;
709               return err;
710             case FTPNSFOD:
711               logputs (LOG_VERBOSE, "\n");
712               logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
713                          quote (u->dir));
714               fd_close (csock);
715               con->csock = -1;
716               return err;
717             case FTPOK:
718               break;
719             default:
720               abort ();
721             }
722           if (!opt.server_response)
723             logputs (LOG_VERBOSE, _("done.\n"));
724
725         } /* for */
726
727           /* 2004-09-20 SMS. */
728           /* End of deviant indenting. */
729
730         } /* else */
731     }
732   else /* do not CWD */
733     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
734
735   if ((cmd & DO_RETR) && passed_expected_bytes == 0)
736     {
737       if (opt.verbose)
738         {
739           if (!opt.server_response)
740             logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
741                        quotearg_style (escape_quoting_style, u->file));
742         }
743
744       err = ftp_size (csock, u->file, &expected_bytes);
745       /* FTPRERR */
746       switch (err)
747         {
748         case FTPRERR:
749         case FTPSRVERR:
750           logputs (LOG_VERBOSE, "\n");
751           logputs (LOG_NOTQUIET, _("\
752 Error in server response, closing control connection.\n"));
753           fd_close (csock);
754           con->csock = -1;
755           return err;
756         case FTPOK:
757           got_expected_bytes = true;
758           /* Everything is OK.  */
759           break;
760         default:
761           abort ();
762         }
763         if (!opt.server_response)
764           logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
765                      number_to_static_string (expected_bytes));
766     }
767
768   if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
769     {
770       /* Server confirms that file has length restval. We should stop now.
771          Some servers (f.e. NcFTPd) return error when receive REST 0 */
772       logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
773       fd_close (csock);
774       con->csock = -1;
775       return RETRFINISHED;
776     }
777
778   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
779   if (cmd & (DO_LIST | DO_RETR))
780     {
781       if (opt.ftp_pasv)
782         {
783           ip_address passive_addr;
784           int        passive_port;
785           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
786           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
787           switch (err)
788             {
789             case FTPRERR:
790               logputs (LOG_VERBOSE, "\n");
791               logputs (LOG_NOTQUIET, _("\
792 Error in server response, closing control connection.\n"));
793               fd_close (csock);
794               con->csock = -1;
795               return err;
796             case WRITEFAILED:
797               logputs (LOG_VERBOSE, "\n");
798               logputs (LOG_NOTQUIET,
799                        _("Write failed, closing control connection.\n"));
800               fd_close (csock);
801               con->csock = -1;
802               return err;
803             case FTPNOPASV:
804               logputs (LOG_VERBOSE, "\n");
805               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
806               break;
807             case FTPINVPASV:
808               logputs (LOG_VERBOSE, "\n");
809               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
810               break;
811             case FTPOK:
812               break;
813             default:
814               abort ();
815             }   /* switch (err) */
816           if (err==FTPOK)
817             {
818               DEBUGP (("trying to connect to %s port %d\n",
819                       print_address (&passive_addr), passive_port));
820               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
821               if (dtsock < 0)
822                 {
823                   int save_errno = errno;
824                   fd_close (csock);
825                   con->csock = -1;
826                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
827                              print_address (&passive_addr), passive_port,
828                              strerror (save_errno));
829                   return (retryable_socket_connect_error (save_errno)
830                           ? CONERROR : CONIMPOSSIBLE);
831                 }
832
833               pasv_mode_open = true;  /* Flag to avoid accept port */
834               if (!opt.server_response)
835                 logputs (LOG_VERBOSE, _("done.    "));
836             } /* err==FTP_OK */
837         }
838
839       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
840         {
841           err = ftp_do_port (csock, &local_sock);
842           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
843              FTPPORTERR */
844           switch (err)
845             {
846             case FTPRERR:
847               logputs (LOG_VERBOSE, "\n");
848               logputs (LOG_NOTQUIET, _("\
849 Error in server response, closing control connection.\n"));
850               fd_close (csock);
851               con->csock = -1;
852               fd_close (dtsock);
853               fd_close (local_sock);
854               return err;
855             case WRITEFAILED:
856               logputs (LOG_VERBOSE, "\n");
857               logputs (LOG_NOTQUIET,
858                        _("Write failed, closing control connection.\n"));
859               fd_close (csock);
860               con->csock = -1;
861               fd_close (dtsock);
862               fd_close (local_sock);
863               return err;
864             case CONSOCKERR:
865               logputs (LOG_VERBOSE, "\n");
866               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
867               fd_close (csock);
868               con->csock = -1;
869               fd_close (dtsock);
870               fd_close (local_sock);
871               return err;
872             case FTPSYSERR:
873               logputs (LOG_VERBOSE, "\n");
874               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
875                          strerror (errno));
876               fd_close (dtsock);
877               return err;
878             case FTPPORTERR:
879               logputs (LOG_VERBOSE, "\n");
880               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
881               fd_close (csock);
882               con->csock = -1;
883               fd_close (dtsock);
884               fd_close (local_sock);
885               return err;
886             case FTPOK:
887               break;
888             default:
889               abort ();
890             } /* port switch */
891           if (!opt.server_response)
892             logputs (LOG_VERBOSE, _("done.    "));
893         } /* dtsock == -1 */
894     } /* cmd & (DO_LIST | DO_RETR) */
895
896   /* Restart if needed.  */
897   if (restval && (cmd & DO_RETR))
898     {
899       if (!opt.server_response)
900         logprintf (LOG_VERBOSE, "==> REST %s ... ",
901                    number_to_static_string (restval));
902       err = ftp_rest (csock, restval);
903
904       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
905       switch (err)
906         {
907         case FTPRERR:
908           logputs (LOG_VERBOSE, "\n");
909           logputs (LOG_NOTQUIET, _("\
910 Error in server response, closing control connection.\n"));
911           fd_close (csock);
912           con->csock = -1;
913           fd_close (dtsock);
914           fd_close (local_sock);
915           return err;
916         case WRITEFAILED:
917           logputs (LOG_VERBOSE, "\n");
918           logputs (LOG_NOTQUIET,
919                    _("Write failed, closing control connection.\n"));
920           fd_close (csock);
921           con->csock = -1;
922           fd_close (dtsock);
923           fd_close (local_sock);
924           return err;
925         case FTPRESTFAIL:
926           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
927           rest_failed = true;
928           break;
929         case FTPOK:
930           break;
931         default:
932           abort ();
933         }
934       if (err != FTPRESTFAIL && !opt.server_response)
935         logputs (LOG_VERBOSE, _("done.    "));
936     } /* restval && cmd & DO_RETR */
937
938   if (cmd & DO_RETR)
939     {
940       /* If we're in spider mode, don't really retrieve anything except
941          the directory listing and verify whether the given "file" exists.  */
942       if (opt.spider)
943         {
944           bool exists = false;
945           uerr_t res;
946           struct fileinfo *f;
947           res = ftp_get_listing (u, con, &f);
948           /* Set the DO_RETR command flag again, because it gets unset when
949              calling ftp_get_listing() and would otherwise cause an assertion
950              failure earlier on when this function gets repeatedly called
951              (e.g., when recursing).  */
952           con->cmd |= DO_RETR;
953           if (res == RETROK)
954             {
955               while (f)
956                 {
957                   if (!strcmp (f->name, u->file))
958                     {
959                       exists = true;
960                       break;
961                     }
962                   f = f->next;
963                 }
964               if (exists)
965                 {
966                   logputs (LOG_VERBOSE, "\n");
967                   logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
968                              quote (u->file));
969                 }
970               else
971                 {
972                   logputs (LOG_VERBOSE, "\n");
973                   logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
974                              quote (u->file));
975                 }
976             }
977           fd_close (csock);
978           con->csock = -1;
979           fd_close (dtsock);
980           fd_close (local_sock);
981           return RETRFINISHED;
982         }
983
984       if (opt.verbose)
985         {
986           if (!opt.server_response)
987             {
988               if (restval)
989                 logputs (LOG_VERBOSE, "\n");
990               logprintf (LOG_VERBOSE, "==> RETR %s ... ",
991                          quotearg_style (escape_quoting_style, u->file));
992             }
993         }
994
995       err = ftp_retr (csock, u->file);
996       /* FTPRERR, WRITEFAILED, FTPNSFOD */
997       switch (err)
998         {
999         case FTPRERR:
1000           logputs (LOG_VERBOSE, "\n");
1001           logputs (LOG_NOTQUIET, _("\
1002 Error in server response, closing control connection.\n"));
1003           fd_close (csock);
1004           con->csock = -1;
1005           fd_close (dtsock);
1006           fd_close (local_sock);
1007           return err;
1008         case WRITEFAILED:
1009           logputs (LOG_VERBOSE, "\n");
1010           logputs (LOG_NOTQUIET,
1011                    _("Write failed, closing control connection.\n"));
1012           fd_close (csock);
1013           con->csock = -1;
1014           fd_close (dtsock);
1015           fd_close (local_sock);
1016           return err;
1017         case FTPNSFOD:
1018           logputs (LOG_VERBOSE, "\n");
1019           logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1020                      quote (u->file));
1021           fd_close (dtsock);
1022           fd_close (local_sock);
1023           return err;
1024         case FTPOK:
1025           break;
1026         default:
1027           abort ();
1028         }
1029
1030       if (!opt.server_response)
1031         logputs (LOG_VERBOSE, _("done.\n"));
1032
1033       if (! got_expected_bytes)
1034         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1035     } /* do retrieve */
1036
1037   if (cmd & DO_LIST)
1038     {
1039       if (!opt.server_response)
1040         logputs (LOG_VERBOSE, "==> LIST ... ");
1041       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1042          without arguments is better than `LIST .'; confirmed by
1043          RFC959.  */
1044       err = ftp_list (csock, NULL, con->rs);
1045       /* FTPRERR, WRITEFAILED */
1046       switch (err)
1047         {
1048         case FTPRERR:
1049           logputs (LOG_VERBOSE, "\n");
1050           logputs (LOG_NOTQUIET, _("\
1051 Error in server response, closing control connection.\n"));
1052           fd_close (csock);
1053           con->csock = -1;
1054           fd_close (dtsock);
1055           fd_close (local_sock);
1056           return err;
1057         case WRITEFAILED:
1058           logputs (LOG_VERBOSE, "\n");
1059           logputs (LOG_NOTQUIET,
1060                    _("Write failed, closing control connection.\n"));
1061           fd_close (csock);
1062           con->csock = -1;
1063           fd_close (dtsock);
1064           fd_close (local_sock);
1065           return err;
1066         case FTPNSFOD:
1067           logputs (LOG_VERBOSE, "\n");
1068           logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1069                      quote ("."));
1070           fd_close (dtsock);
1071           fd_close (local_sock);
1072           return err;
1073         case FTPOK:
1074           break;
1075         default:
1076           abort ();
1077         }
1078       if (!opt.server_response)
1079         logputs (LOG_VERBOSE, _("done.\n"));
1080
1081       if (! got_expected_bytes)
1082         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1083     } /* cmd & DO_LIST */
1084
1085   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1086     return RETRFINISHED;
1087
1088   /* Some FTP servers return the total length of file after REST
1089      command, others just return the remaining size. */
1090   if (passed_expected_bytes && restval && expected_bytes
1091       && (expected_bytes == passed_expected_bytes - restval))
1092     {
1093       DEBUGP (("Lying FTP server found, adjusting.\n"));
1094       expected_bytes = passed_expected_bytes;
1095     }
1096
1097   /* If no transmission was required, then everything is OK.  */
1098   if (!pasv_mode_open)  /* we are not using pasive mode so we need
1099                               to accept */
1100     {
1101       /* Wait for the server to connect to the address we're waiting
1102          at.  */
1103       dtsock = accept_connection (local_sock);
1104       if (dtsock < 0)
1105         {
1106           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1107           return CONERROR;
1108         }
1109     }
1110
1111   /* Open the file -- if output_stream is set, use it instead.  */
1112
1113   /* 2005-04-17 SMS.
1114      Note that having the output_stream ("-O") file opened in main()
1115      (main.c) rather limits the ability in VMS to open the file
1116      differently for ASCII versus binary FTP here.  (Of course, doing it
1117      there allows a open failure to be detected immediately, without first
1118      connecting to the server.)
1119   */
1120   if (!output_stream || con->cmd & DO_LIST)
1121     {
1122 /* On VMS, alter the name as required. */
1123 #ifdef __VMS
1124       char *targ;
1125
1126       targ = ods_conform (con->target);
1127       if (targ != con->target)
1128         {
1129           xfree (con->target);
1130           con->target = targ;
1131         }
1132 #endif /* def __VMS */
1133
1134       mkalldirs (con->target);
1135       if (opt.backups)
1136         rotate_backups (con->target);
1137
1138 /* 2005-04-15 SMS.
1139    For VMS, define common fopen() optional arguments, and a handy macro
1140    for use as a variable "binary" flag.
1141    Elsewhere, define a constant "binary" flag.
1142    Isn't it nice to have distinct text and binary file types?
1143 */
1144 /* 2011-09-30 SMS.
1145    Added listing files to the set of non-"binary" (text, Stream_LF)
1146    files.  (Wget works either way, but other programs, like, say, text
1147    editors, work better on listing files which have text attributes.)
1148    Now we use "binary" attributes for a binary ("IMAGE") transfer,
1149    unless "--ftp-stmlf" was specified, and we always use non-"binary"
1150    (text, Stream_LF) attributes for a listing file, or for an ASCII
1151    transfer.
1152    Tidied the VMS-specific BIN_TYPE_xxx macros, and changed the call to
1153    fopen_excl() (restored?) to use BIN_TYPE_FILE instead of "true".
1154 */
1155 #ifdef __VMS
1156 # define BIN_TYPE_TRANSFER (type_char != 'A')
1157 # define BIN_TYPE_FILE \
1158    ((!(cmd & DO_LIST)) && BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1159 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1160 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1161 #else /* def __VMS */
1162 # define BIN_TYPE_FILE true
1163 #endif /* def __VMS [else] */
1164
1165       if (restval && !(con->cmd & DO_LIST))
1166         {
1167 #ifdef __VMS
1168           int open_id;
1169
1170           if (BIN_TYPE_FILE)
1171             {
1172               open_id = 3;
1173               fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1174             }
1175           else
1176             {
1177               open_id = 4;
1178               fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1179             }
1180 #else /* def __VMS */
1181           fp = fopen (con->target, "ab");
1182 #endif /* def __VMS [else] */
1183         }
1184       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1185                || opt.output_document || count > 0)
1186         {
1187           if (opt.unlink && file_exists_p (con->target))
1188             {
1189               int res = unlink (con->target);
1190               if (res < 0)
1191                 {
1192                   logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1193                              strerror (errno));
1194                   fd_close (csock);
1195                   con->csock = -1;
1196                   fd_close (dtsock);
1197                   fd_close (local_sock);
1198                   return UNLINKERR;
1199                 }
1200             }
1201
1202 #ifdef __VMS
1203           int open_id;
1204
1205           if (BIN_TYPE_FILE)
1206             {
1207               open_id = 5;
1208               fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1209             }
1210           else
1211             {
1212               open_id = 6;
1213               fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1214             }
1215 #else /* def __VMS */
1216           fp = fopen (con->target, "wb");
1217 #endif /* def __VMS [else] */
1218         }
1219       else
1220         {
1221           fp = fopen_excl (con->target, BIN_TYPE_FILE);
1222           if (!fp && errno == EEXIST)
1223             {
1224               /* We cannot just invent a new name and use it (which is
1225                  what functions like unique_create typically do)
1226                  because we told the user we'd use this name.
1227                  Instead, return and retry the download.  */
1228               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1229                          con->target);
1230               fd_close (csock);
1231               con->csock = -1;
1232               fd_close (dtsock);
1233               fd_close (local_sock);
1234               return FOPEN_EXCL_ERR;
1235             }
1236         }
1237       if (!fp)
1238         {
1239           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1240           fd_close (csock);
1241           con->csock = -1;
1242           fd_close (dtsock);
1243           fd_close (local_sock);
1244           return FOPENERR;
1245         }
1246     }
1247   else
1248     fp = output_stream;
1249
1250   if (passed_expected_bytes)
1251     {
1252       print_length (passed_expected_bytes, restval, true);
1253       expected_bytes = passed_expected_bytes;
1254         /* for fd_read_body's progress bar */
1255     }
1256   else if (expected_bytes)
1257     print_length (expected_bytes, restval, false);
1258
1259   /* Get the contents of the document.  */
1260   flags = 0;
1261   if (restval && rest_failed)
1262     flags |= rb_skip_startpos;
1263   rd_size = 0;
1264   res = fd_read_body (dtsock, fp,
1265                       expected_bytes ? expected_bytes - restval : 0,
1266                       restval, &rd_size, qtyread, &con->dltime, flags, warc_tmp);
1267
1268   tms = datetime_str (time (NULL));
1269   tmrate = retr_rate (rd_size, con->dltime);
1270   total_download_time += con->dltime;
1271
1272   fd_close (local_sock);
1273   /* Close the local file.  */
1274   if (!output_stream || con->cmd & DO_LIST)
1275     fclose (fp);
1276
1277   /* If fd_read_body couldn't write to fp or warc_tmp, bail out.  */
1278   if (res == -2 || (warc_tmp != NULL && res == -3))
1279     {
1280       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1281                  con->target, strerror (errno));
1282       fd_close (csock);
1283       con->csock = -1;
1284       fd_close (dtsock);
1285       if (res == -2)
1286         return FWRITEERR;
1287       else if (res == -3)
1288         return WARC_TMP_FWRITEERR;
1289     }
1290   else if (res == -1)
1291     {
1292       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1293                  tms, tmrate, fd_errstr (dtsock));
1294       if (opt.server_response)
1295         logputs (LOG_ALWAYS, "\n");
1296     }
1297   fd_close (dtsock);
1298
1299   /* Get the server to tell us if everything is retrieved.  */
1300   err = ftp_response (csock, &respline);
1301   if (err != FTPOK)
1302     {
1303       /* The control connection is decidedly closed.  Print the time
1304          only if it hasn't already been printed.  */
1305       if (res != -1)
1306         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1307       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1308       /* If there is an error on the control connection, close it, but
1309          return FTPRETRINT, since there is a possibility that the
1310          whole file was retrieved nevertheless (but that is for
1311          ftp_loop_internal to decide).  */
1312       fd_close (csock);
1313       con->csock = -1;
1314       return FTPRETRINT;
1315     } /* err != FTPOK */
1316   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1317      close socket, since the control connection is still alive.  If
1318      there is something wrong with the control connection, it will
1319      become apparent later.  */
1320   if (*respline != '2')
1321     {
1322       xfree (respline);
1323       if (res != -1)
1324         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1325       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1326       return FTPRETRINT;
1327     }
1328   xfree (respline);
1329
1330   if (res == -1)
1331     {
1332       /* What now?  The data connection was erroneous, whereas the
1333          response says everything is OK.  We shall play it safe.  */
1334       return FTPRETRINT;
1335     }
1336
1337   if (!(cmd & LEAVE_PENDING))
1338     {
1339       /* Closing the socket is faster than sending 'QUIT' and the
1340          effect is the same.  */
1341       fd_close (csock);
1342       con->csock = -1;
1343     }
1344   /* If it was a listing, and opt.server_response is true,
1345      print it out.  */
1346   if (opt.server_response && (con->cmd & DO_LIST))
1347     {
1348 /* 2005-02-25 SMS.
1349    Much of this work may already have been done, but repeating it should
1350    do no damage beyond wasting time.
1351 */
1352 /* On VMS, alter the name as required. */
1353 #ifdef __VMS
1354       char *targ;
1355
1356       targ = ods_conform( con->target);
1357       if (targ != con->target)
1358         {
1359           xfree( con->target);
1360           con->target = targ;
1361         }
1362 #endif /* def __VMS */
1363
1364       mkalldirs (con->target);
1365       fp = fopen (con->target, "r");
1366       if (!fp)
1367         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1368       else
1369         {
1370           char *line;
1371           /* The lines are being read with read_whole_line because of
1372              no-buffering on opt.lfile.  */
1373           while ((line = read_whole_line (fp)) != NULL)
1374             {
1375               char *p = strchr (line, '\0');
1376               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1377                 *--p = '\0';
1378               logprintf (LOG_ALWAYS, "%s\n",
1379                          quotearg_style (escape_quoting_style, line));
1380               xfree (line);
1381             }
1382           fclose (fp);
1383         }
1384     } /* con->cmd & DO_LIST && server_response */
1385
1386   return RETRFINISHED;
1387 }
1388
1389 /* A one-file FTP loop.  This is the part where FTP retrieval is
1390    retried, and retried, and retried, and...
1391
1392    This loop either gets commands from con, or (if ON_YOUR_OWN is
1393    set), makes them up to retrieve the file given by the URL.  */
1394 static uerr_t
1395 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1396 {
1397   int count, orig_lp;
1398   wgint restval, len = 0, qtyread = 0;
1399   char *tms, *locf;
1400   const char *tmrate = NULL;
1401   uerr_t err;
1402   struct_stat st;
1403
1404   /* Declare WARC variables. */
1405   bool warc_enabled = (opt.warc_filename != NULL);
1406   FILE *warc_tmp = NULL;
1407   ip_address *warc_ip = NULL;
1408
1409   /* Get the target, and set the name for the message accordingly. */
1410   if ((f == NULL) && (con->target))
1411     {
1412       /* Explicit file (like ".listing"). */
1413       locf = con->target;
1414     }
1415   else
1416     {
1417       /* URL-derived file.  Consider "-O file" name. */
1418       con->target = url_file_name (u, NULL);
1419       if (!opt.output_document)
1420         locf = con->target;
1421       else
1422         locf = opt.output_document;
1423     }
1424
1425   /* If the output_document was given, then this check was already done and
1426      the file didn't exist. Hence the !opt.output_document */
1427
1428   /* If we receive .listing file it is necessary to determine system type of the ftp
1429      server even if opn.noclobber is given. Thus we must ignore opt.noclobber in
1430      order to establish connection with the server and get system type. */
1431   if (opt.noclobber && !opt.output_document && file_exists_p (con->target)
1432       && !((con->cmd & DO_LIST) && !(con->cmd & DO_RETR)))
1433     {
1434       logprintf (LOG_VERBOSE,
1435                  _("File %s already there; not retrieving.\n"), quote (con->target));
1436       /* If the file is there, we suppose it's retrieved OK.  */
1437       return RETROK;
1438     }
1439
1440   /* Remove it if it's a link.  */
1441   remove_link (con->target);
1442
1443   count = 0;
1444
1445   if (con->st & ON_YOUR_OWN)
1446     con->st = ON_YOUR_OWN;
1447
1448   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1449
1450   /* For file RETR requests, we can write a WARC record.
1451      We record the file contents to a temporary file. */
1452   if (warc_enabled && (con->cmd & DO_RETR))
1453     {
1454       warc_tmp = warc_tempfile ();
1455       if (warc_tmp == NULL)
1456         return WARC_TMP_FOPENERR;
1457
1458       if (!con->proxy && con->csock != -1)
1459         {
1460           warc_ip = (ip_address *) alloca (sizeof (ip_address));
1461           socket_ip_address (con->csock, warc_ip, ENDPOINT_PEER);
1462         }
1463     }
1464
1465   /* THE loop.  */
1466   do
1467     {
1468       /* Increment the pass counter.  */
1469       ++count;
1470       sleep_between_retrievals (count);
1471       if (con->st & ON_YOUR_OWN)
1472         {
1473           con->cmd = 0;
1474           con->cmd |= (DO_RETR | LEAVE_PENDING);
1475           if (con->csock != -1)
1476             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1477           else
1478             con->cmd |= (DO_LOGIN | DO_CWD);
1479         }
1480       else /* not on your own */
1481         {
1482           if (con->csock != -1)
1483             con->cmd &= ~DO_LOGIN;
1484           else
1485             con->cmd |= DO_LOGIN;
1486           if (con->st & DONE_CWD)
1487             con->cmd &= ~DO_CWD;
1488           else
1489             con->cmd |= DO_CWD;
1490         }
1491
1492       /* Decide whether or not to restart.  */
1493       if (con->cmd & DO_LIST)
1494         restval = 0;
1495       else if (opt.always_rest
1496           && stat (locf, &st) == 0
1497           && S_ISREG (st.st_mode))
1498         /* When -c is used, continue from on-disk size.  (Can't use
1499            hstat.len even if count>1 because we don't want a failed
1500            first attempt to clobber existing data.)  */
1501         restval = st.st_size;
1502       else if (count > 1)
1503         restval = qtyread;          /* start where the previous run left off */
1504       else
1505         restval = 0;
1506
1507       /* Get the current time string.  */
1508       tms = datetime_str (time (NULL));
1509       /* Print fetch message, if opt.verbose.  */
1510       if (opt.verbose)
1511         {
1512           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1513           char tmp[256];
1514           strcpy (tmp, "        ");
1515           if (count > 1)
1516             sprintf (tmp, _("(try:%2d)"), count);
1517           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => %s\n",
1518                      tms, hurl, tmp, quote (locf));
1519 #ifdef WINDOWS
1520           ws_changetitle (hurl);
1521 #endif
1522           xfree (hurl);
1523         }
1524       /* Send getftp the proper length, if fileinfo was provided.  */
1525       if (f && f->type != FT_SYMLINK)
1526         len = f->size;
1527       else
1528         len = 0;
1529
1530       /* If we are working on a WARC record, getftp should also write
1531          to the warc_tmp file. */
1532       err = getftp (u, len, &qtyread, restval, con, count, warc_tmp);
1533
1534       if (con->csock == -1)
1535         con->st &= ~DONE_CWD;
1536       else
1537         con->st |= DONE_CWD;
1538
1539       switch (err)
1540         {
1541         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1542         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1543         case UNLINKERR: case WARC_TMP_FWRITEERR:
1544           /* Fatal errors, give up.  */
1545           if (warc_tmp != NULL)
1546             fclose (warc_tmp);
1547           return err;
1548         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1549         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1550         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1551         case FOPEN_EXCL_ERR:
1552           printwhat (count, opt.ntry);
1553           /* non-fatal errors */
1554           if (err == FOPEN_EXCL_ERR)
1555             {
1556               /* Re-determine the file name. */
1557               xfree_null (con->target);
1558               con->target = url_file_name (u, NULL);
1559               locf = con->target;
1560             }
1561           continue;
1562         case FTPRETRINT:
1563           /* If the control connection was closed, the retrieval
1564              will be considered OK if f->size == len.  */
1565           if (!f || qtyread != f->size)
1566             {
1567               printwhat (count, opt.ntry);
1568               continue;
1569             }
1570           break;
1571         case RETRFINISHED:
1572           /* Great!  */
1573           break;
1574         default:
1575           /* Not as great.  */
1576           abort ();
1577         }
1578       tms = datetime_str (time (NULL));
1579       if (!opt.spider)
1580         tmrate = retr_rate (qtyread - restval, con->dltime);
1581
1582       /* If we get out of the switch above without continue'ing, we've
1583          successfully downloaded a file.  Remember this fact. */
1584       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1585
1586       if (con->st & ON_YOUR_OWN)
1587         {
1588           fd_close (con->csock);
1589           con->csock = -1;
1590         }
1591       if (!opt.spider)
1592         {
1593           bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1594
1595           logprintf (LOG_VERBOSE,
1596                      write_to_stdout
1597                      ? _("%s (%s) - written to stdout %s[%s]\n\n")
1598                      : _("%s (%s) - %s saved [%s]\n\n"),
1599                      tms, tmrate,
1600                      write_to_stdout ? "" : quote (locf),
1601                      number_to_static_string (qtyread));
1602         }
1603       if (!opt.verbose && !opt.quiet)
1604         {
1605           /* Need to hide the password from the URL.  The `if' is here
1606              so that we don't do the needless allocation every
1607              time. */
1608           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1609           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1610                      tms, hurl, number_to_static_string (qtyread), locf, count);
1611           xfree (hurl);
1612         }
1613
1614       if (warc_enabled && (con->cmd & DO_RETR))
1615         {
1616           /* Create and store a WARC resource record for the retrieved file. */
1617           bool warc_res;
1618
1619           warc_res = warc_write_resource_record (NULL, u->url, NULL, NULL,
1620                                                   warc_ip, NULL, warc_tmp, -1);
1621           if (! warc_res)
1622             return WARC_ERR;
1623
1624           /* warc_write_resource_record has also closed warc_tmp. */
1625         }
1626
1627       if ((con->cmd & DO_LIST))
1628         /* This is a directory listing file. */
1629         {
1630           if (!opt.remove_listing)
1631             /* --dont-remove-listing was specified, so do count this towards the
1632                number of bytes and files downloaded. */
1633             {
1634               total_downloaded_bytes += qtyread;
1635               numurls++;
1636             }
1637
1638           /* Deletion of listing files is not controlled by --delete-after, but
1639              by the more specific option --dont-remove-listing, and the code
1640              to do this deletion is in another function. */
1641         }
1642       else if (!opt.spider)
1643         /* This is not a directory listing file. */
1644         {
1645           /* Unlike directory listing files, don't pretend normal files weren't
1646              downloaded if they're going to be deleted.  People seeding proxies,
1647              for instance, may want to know how many bytes and files they've
1648              downloaded through it. */
1649           total_downloaded_bytes += qtyread;
1650           numurls++;
1651
1652           if (opt.delete_after && !input_file_url (opt.input_filename))
1653             {
1654               DEBUGP (("\
1655 Removing file due to --delete-after in ftp_loop_internal():\n"));
1656               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1657               if (unlink (locf))
1658                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1659             }
1660         }
1661
1662       /* Restore the original leave-pendingness.  */
1663       if (orig_lp)
1664         con->cmd |= LEAVE_PENDING;
1665       else
1666         con->cmd &= ~LEAVE_PENDING;
1667
1668       if (local_file)
1669         *local_file = xstrdup (locf);
1670
1671       return RETROK;
1672     } while (!opt.ntry || (count < opt.ntry));
1673
1674   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1675     {
1676       fd_close (con->csock);
1677       con->csock = -1;
1678     }
1679   return TRYLIMEXC;
1680 }
1681
1682 /* Return the directory listing in a reusable format.  The directory
1683    is specifed in u->dir.  */
1684 static uerr_t
1685 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1686 {
1687   uerr_t err;
1688   char *uf;                     /* url file name */
1689   char *lf;                     /* list file name */
1690   char *old_target = con->target;
1691
1692   con->st &= ~ON_YOUR_OWN;
1693   con->cmd |= (DO_LIST | LEAVE_PENDING);
1694   con->cmd &= ~DO_RETR;
1695
1696   /* Find the listing file name.  We do it by taking the file name of
1697      the URL and replacing the last component with the listing file
1698      name.  */
1699   uf = url_file_name (u, NULL);
1700   lf = file_merge (uf, LIST_FILENAME);
1701   xfree (uf);
1702   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1703
1704   con->target = xstrdup (lf);
1705   xfree (lf);
1706   err = ftp_loop_internal (u, NULL, con, NULL);
1707   lf = xstrdup (con->target);
1708   xfree (con->target);
1709   con->target = old_target;
1710
1711   if (err == RETROK)
1712     {
1713       *f = ftp_parse_ls (lf, con->rs);
1714       if (opt.remove_listing)
1715         {
1716           if (unlink (lf))
1717             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1718           else
1719             logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1720         }
1721     }
1722   else
1723     *f = NULL;
1724   xfree (lf);
1725   con->cmd &= ~DO_LIST;
1726   return err;
1727 }
1728
1729 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1730 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1731 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1732 static void freefileinfo (struct fileinfo *f);
1733
1734 /* Retrieve a list of files given in struct fileinfo linked list.  If
1735    a file is a symbolic link, do not retrieve it, but rather try to
1736    set up a similar link on the local disk, if the symlinks are
1737    supported.
1738
1739    If opt.recursive is set, after all files have been retrieved,
1740    ftp_retrieve_dirs will be called to retrieve the directories.  */
1741 static uerr_t
1742 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1743 {
1744   static int depth = 0;
1745   uerr_t err;
1746   struct fileinfo *orig;
1747   wgint local_size;
1748   time_t tml;
1749   bool dlthis; /* Download this (file). */
1750   const char *actual_target = NULL;
1751
1752   /* Increase the depth.  */
1753   ++depth;
1754   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1755     {
1756       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1757                depth, opt.reclevel));
1758       --depth;
1759       return RECLEVELEXC;
1760     }
1761
1762   assert (f != NULL);
1763   orig = f;
1764
1765   con->st &= ~ON_YOUR_OWN;
1766   if (!(con->st & DONE_CWD))
1767     con->cmd |= DO_CWD;
1768   else
1769     con->cmd &= ~DO_CWD;
1770   con->cmd |= (DO_RETR | LEAVE_PENDING);
1771
1772   if (con->csock < 0)
1773     con->cmd |= DO_LOGIN;
1774   else
1775     con->cmd &= ~DO_LOGIN;
1776
1777   err = RETROK;                 /* in case it's not used */
1778
1779   while (f)
1780     {
1781       char *old_target, *ofile;
1782
1783       if (opt.quota && total_downloaded_bytes > opt.quota)
1784         {
1785           --depth;
1786           return QUOTEXC;
1787         }
1788       old_target = con->target;
1789
1790       ofile = xstrdup (u->file);
1791       url_set_file (u, f->name);
1792
1793       con->target = url_file_name (u, NULL);
1794       err = RETROK;
1795
1796       dlthis = true;
1797       if (opt.timestamping && f->type == FT_PLAINFILE)
1798         {
1799           struct_stat st;
1800           /* If conversion of HTML files retrieved via FTP is ever implemented,
1801              we'll need to stat() <file>.orig here when -K has been specified.
1802              I'm not implementing it now since files on an FTP server are much
1803              more likely than files on an HTTP server to legitimately have a
1804              .orig suffix. */
1805           if (!stat (con->target, &st))
1806             {
1807               bool eq_size;
1808               bool cor_val;
1809               /* Else, get it from the file.  */
1810               local_size = st.st_size;
1811               tml = st.st_mtime;
1812 #ifdef WINDOWS
1813               /* Modification time granularity is 2 seconds for Windows, so
1814                  increase local time by 1 second for later comparison. */
1815               tml++;
1816 #endif
1817               /* Compare file sizes only for servers that tell us correct
1818                  values. Assume sizes being equal for servers that lie
1819                  about file size.  */
1820               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1821               eq_size = cor_val ? (local_size == f->size) : true;
1822               if (f->tstamp <= tml && eq_size)
1823                 {
1824                   /* Remote file is older, file sizes can be compared and
1825                      are both equal. */
1826                   logprintf (LOG_VERBOSE, _("\
1827 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1828                   dlthis = false;
1829                 }
1830               else if (eq_size)
1831                 {
1832                   /* Remote file is newer or sizes cannot be matched */
1833                   logprintf (LOG_VERBOSE, _("\
1834 Remote file is newer than local file %s -- retrieving.\n\n"),
1835                              quote (con->target));
1836                 }
1837               else
1838                 {
1839                   /* Sizes do not match */
1840                   logprintf (LOG_VERBOSE, _("\
1841 The sizes do not match (local %s) -- retrieving.\n\n"),
1842                              number_to_static_string (local_size));
1843                 }
1844             }
1845         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1846       switch (f->type)
1847         {
1848         case FT_SYMLINK:
1849           /* If opt.retr_symlinks is defined, we treat symlinks as
1850              if they were normal files.  There is currently no way
1851              to distinguish whether they might be directories, and
1852              follow them.  */
1853           if (!opt.retr_symlinks)
1854             {
1855 #ifdef HAVE_SYMLINK
1856               if (!f->linkto)
1857                 logputs (LOG_NOTQUIET,
1858                          _("Invalid name of the symlink, skipping.\n"));
1859               else
1860                 {
1861                   struct_stat st;
1862                   /* Check whether we already have the correct
1863                      symbolic link.  */
1864                   int rc = lstat (con->target, &st);
1865                   if (rc == 0)
1866                     {
1867                       size_t len = strlen (f->linkto) + 1;
1868                       if (S_ISLNK (st.st_mode))
1869                         {
1870                           char *link_target = (char *)alloca (len);
1871                           size_t n = readlink (con->target, link_target, len);
1872                           if ((n == len - 1)
1873                               && (memcmp (link_target, f->linkto, n) == 0))
1874                             {
1875                               logprintf (LOG_VERBOSE, _("\
1876 Already have correct symlink %s -> %s\n\n"),
1877                                          quote (con->target),
1878                                          quote (f->linkto));
1879                               dlthis = false;
1880                               break;
1881                             }
1882                         }
1883                     }
1884                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1885                              quote (con->target), quote (f->linkto));
1886                   /* Unlink before creating symlink!  */
1887                   unlink (con->target);
1888                   if (symlink (f->linkto, con->target) == -1)
1889                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1890                   logputs (LOG_VERBOSE, "\n");
1891                 } /* have f->linkto */
1892 #else  /* not HAVE_SYMLINK */
1893               logprintf (LOG_NOTQUIET,
1894                          _("Symlinks not supported, skipping symlink %s.\n"),
1895                          quote (con->target));
1896 #endif /* not HAVE_SYMLINK */
1897             }
1898           else                /* opt.retr_symlinks */
1899             {
1900               if (dlthis)
1901                 err = ftp_loop_internal (u, f, con, NULL);
1902             } /* opt.retr_symlinks */
1903           break;
1904         case FT_DIRECTORY:
1905           if (!opt.recursive)
1906             logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1907                        quote (f->name));
1908           break;
1909         case FT_PLAINFILE:
1910           /* Call the retrieve loop.  */
1911           if (dlthis)
1912             err = ftp_loop_internal (u, f, con, NULL);
1913           break;
1914         case FT_UNKNOWN:
1915           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1916                      quote (f->name));
1917           break;
1918         }       /* switch */
1919
1920
1921       /* 2004-12-15 SMS.
1922        * Set permissions _before_ setting the times, as setting the
1923        * permissions changes the modified-time, at least on VMS.
1924        * Also, use the opt.output_document name here, too, as
1925        * appropriate.  (Do the test once, and save the result.)
1926        */
1927
1928       set_local_file (&actual_target, con->target);
1929
1930       /* If downloading a plain file, and the user requested it, then
1931          set valid (non-zero) permissions. */
1932       if (dlthis && (actual_target != NULL) &&
1933        (f->type == FT_PLAINFILE) && opt.preserve_perm)
1934         {
1935           if (f->perms)
1936             chmod (actual_target, f->perms);
1937           else
1938             DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1939         }
1940
1941       /* Set the time-stamp information to the local file.  Symlinks
1942          are not to be stamped because it sets the stamp on the
1943          original.  :( */
1944       if (actual_target != NULL)
1945         {
1946           if (opt.useservertimestamps
1947               && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1948               && f->tstamp != -1
1949               && dlthis
1950               && file_exists_p (con->target))
1951             {
1952               touch (actual_target, f->tstamp);
1953             }
1954           else if (f->tstamp == -1)
1955             logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1956                        actual_target);
1957         }
1958
1959       xfree (con->target);
1960       con->target = old_target;
1961
1962       url_set_file (u, ofile);
1963       xfree (ofile);
1964
1965       /* Break on fatals.  */
1966       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR
1967           || err == WARC_ERR || err == WARC_TMP_FOPENERR
1968           || err == WARC_TMP_FWRITEERR)
1969         break;
1970       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1971       f = f->next;
1972     }
1973
1974   /* We do not want to call ftp_retrieve_dirs here */
1975   if (opt.recursive &&
1976       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1977     err = ftp_retrieve_dirs (u, orig, con);
1978   else if (opt.recursive)
1979     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1980              depth, opt.reclevel));
1981   --depth;
1982   return err;
1983 }
1984
1985 /* Retrieve the directories given in a file list.  This function works
1986    by simply going through the linked list and calling
1987    ftp_retrieve_glob on each directory entry.  The function knows
1988    about excluded directories.  */
1989 static uerr_t
1990 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1991 {
1992   char *container = NULL;
1993   int container_size = 0;
1994
1995   for (; f; f = f->next)
1996     {
1997       int size;
1998       char *odir, *newdir;
1999
2000       if (opt.quota && total_downloaded_bytes > opt.quota)
2001         break;
2002       if (f->type != FT_DIRECTORY)
2003         continue;
2004
2005       /* Allocate u->dir off stack, but reallocate only if a larger
2006          string is needed.  It's a pity there's no "realloca" for an
2007          item on the bottom of the stack.  */
2008       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
2009       if (size > container_size)
2010         container = (char *)alloca (size);
2011       newdir = container;
2012
2013       odir = u->dir;
2014       if (*odir == '\0'
2015           || (*odir == '/' && *(odir + 1) == '\0'))
2016         /* If ODIR is empty or just "/", simply append f->name to
2017            ODIR.  (In the former case, to preserve u->dir being
2018            relative; in the latter case, to avoid double slash.)  */
2019         sprintf (newdir, "%s%s", odir, f->name);
2020       else
2021         /* Else, use a separator. */
2022         sprintf (newdir, "%s/%s", odir, f->name);
2023
2024       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
2025       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
2026                odir, f->name, newdir));
2027       if (!accdir (newdir))
2028         {
2029           logprintf (LOG_VERBOSE, _("\
2030 Not descending to %s as it is excluded/not-included.\n"),
2031                      quote (newdir));
2032           continue;
2033         }
2034
2035       con->st &= ~DONE_CWD;
2036
2037       odir = xstrdup (u->dir);  /* because url_set_dir will free
2038                                    u->dir. */
2039       url_set_dir (u, newdir);
2040       ftp_retrieve_glob (u, con, GLOB_GETALL);
2041       url_set_dir (u, odir);
2042       xfree (odir);
2043
2044       /* Set the time-stamp?  */
2045     }
2046
2047   if (opt.quota && total_downloaded_bytes > opt.quota)
2048     return QUOTEXC;
2049   else
2050     return RETROK;
2051 }
2052
2053 /* Return true if S has a leading '/'  or contains '../' */
2054 static bool
2055 has_insecure_name_p (const char *s)
2056 {
2057   if (*s == '/')
2058     return true;
2059
2060   if (strstr (s, "../") != 0)
2061     return true;
2062
2063   return false;
2064 }
2065
2066 /* A near-top-level function to retrieve the files in a directory.
2067    The function calls ftp_get_listing, to get a linked list of files.
2068    Then it weeds out the file names that do not match the pattern.
2069    ftp_retrieve_list is called with this updated list as an argument.
2070
2071    If the argument ACTION is GLOB_GETONE, just download the file (but
2072    first get the listing, so that the time-stamp is heeded); if it's
2073    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
2074    directory.  */
2075 static uerr_t
2076 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2077 {
2078   struct fileinfo *f, *start;
2079   uerr_t res;
2080
2081   con->cmd |= LEAVE_PENDING;
2082
2083   res = ftp_get_listing (u, con, &start);
2084   if (res != RETROK)
2085     return res;
2086   /* First: weed out that do not conform the global rules given in
2087      opt.accepts and opt.rejects.  */
2088   if (opt.accepts || opt.rejects)
2089     {
2090       f = start;
2091       while (f)
2092         {
2093           if (f->type != FT_DIRECTORY && !acceptable (f->name))
2094             {
2095               logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2096                          quote (f->name));
2097               f = delelement (f, &start);
2098             }
2099           else
2100             f = f->next;
2101         }
2102     }
2103   /* Remove all files with possible harmful names */
2104   f = start;
2105   while (f)
2106     {
2107       if (has_insecure_name_p (f->name))
2108         {
2109           logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2110                      quote (f->name));
2111           f = delelement (f, &start);
2112         }
2113       else
2114         f = f->next;
2115     }
2116   /* Now weed out the files that do not match our globbing pattern.
2117      If we are dealing with a globbing pattern, that is.  */
2118   if (*u->file)
2119     {
2120       if (action == GLOB_GLOBALL)
2121         {
2122           int (*matcher) (const char *, const char *, int)
2123             = opt.ignore_case ? fnmatch_nocase : fnmatch;
2124           int matchres = 0;
2125
2126           f = start;
2127           while (f)
2128             {
2129               matchres = matcher (u->file, f->name, 0);
2130               if (matchres == -1)
2131                 {
2132                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2133                              u->file, quotearg_style (escape_quoting_style, f->name),
2134                              strerror (errno));
2135                   break;
2136                 }
2137               if (matchres == FNM_NOMATCH)
2138                 f = delelement (f, &start); /* delete the element from the list */
2139               else
2140                 f = f->next;        /* leave the element in the list */
2141             }
2142           if (matchres == -1)
2143             {
2144               freefileinfo (start);
2145               return RETRBADPATTERN;
2146             }
2147         }
2148       else if (action == GLOB_GETONE)
2149         {
2150 #ifdef __VMS
2151           /* 2009-09-09 SMS.
2152            * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2153            * bug causes spurious %CC-E-BADCONDIT complaint with this
2154            * "?:" statement.  (Different linkage attributes for strcmp()
2155            * and strcasecmp().)  Converting to "if" changes the
2156            * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;".  Adding
2157            * the senseless type cast clears the complaint, and looks
2158            * harmless.
2159            */
2160           int (*cmp) (const char *, const char *)
2161             = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2162 #else /* def __VMS */
2163           int (*cmp) (const char *, const char *)
2164             = opt.ignore_case ? strcasecmp : strcmp;
2165 #endif /* def __VMS [else] */
2166           f = start;
2167           while (f)
2168             {
2169               if (0 != cmp(u->file, f->name))
2170                 f = delelement (f, &start);
2171               else
2172                 f = f->next;
2173             }
2174         }
2175     }
2176   if (start)
2177     {
2178       /* Just get everything.  */
2179       res = ftp_retrieve_list (u, start, con);
2180     }
2181   else
2182     {
2183       if (action == GLOB_GLOBALL)
2184         {
2185           /* No luck.  */
2186           /* #### This message SUCKS.  We should see what was the
2187              reason that nothing was retrieved.  */
2188           logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2189                      quote (u->file));
2190         }
2191       else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2192         {
2193           /* Let's try retrieving it anyway.  */
2194           con->st |= ON_YOUR_OWN;
2195           res = ftp_loop_internal (u, NULL, con, NULL);
2196           return res;
2197         }
2198
2199       /* If action == GLOB_GETALL, and the file list is empty, there's
2200          no point in trying to download anything or in complaining about
2201          it.  (An empty directory should not cause complaints.)
2202       */
2203     }
2204   freefileinfo (start);
2205   if (opt.quota && total_downloaded_bytes > opt.quota)
2206     return QUOTEXC;
2207   else
2208     return res;
2209 }
2210
2211 /* The wrapper that calls an appropriate routine according to contents
2212    of URL.  Inherently, its capabilities are limited on what can be
2213    encoded into a URL.  */
2214 uerr_t
2215 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2216           bool recursive, bool glob)
2217 {
2218   ccon con;                     /* FTP connection */
2219   uerr_t res;
2220
2221   *dt = 0;
2222
2223   xzero (con);
2224
2225   con.csock = -1;
2226   con.st = ON_YOUR_OWN;
2227   con.rs = ST_UNIX;
2228   con.id = NULL;
2229   con.proxy = proxy;
2230
2231   /* If the file name is empty, the user probably wants a directory
2232      index.  We'll provide one, properly HTML-ized.  Unless
2233      opt.htmlify is 0, of course.  :-) */
2234   if (!*u->file && !recursive)
2235     {
2236       struct fileinfo *f;
2237       res = ftp_get_listing (u, &con, &f);
2238
2239       if (res == RETROK)
2240         {
2241           if (opt.htmlify && !opt.spider)
2242             {
2243               char *filename = (opt.output_document
2244                                 ? xstrdup (opt.output_document)
2245                                 : (con.target ? xstrdup (con.target)
2246                                    : url_file_name (u, NULL)));
2247               res = ftp_index (filename, u, f);
2248               if (res == FTPOK && opt.verbose)
2249                 {
2250                   if (!opt.output_document)
2251                     {
2252                       struct_stat st;
2253                       wgint sz;
2254                       if (stat (filename, &st) == 0)
2255                         sz = st.st_size;
2256                       else
2257                         sz = -1;
2258                       logprintf (LOG_NOTQUIET,
2259                                  _("Wrote HTML-ized index to %s [%s].\n"),
2260                                  quote (filename), number_to_static_string (sz));
2261                     }
2262                   else
2263                     logprintf (LOG_NOTQUIET,
2264                                _("Wrote HTML-ized index to %s.\n"),
2265                                quote (filename));
2266                 }
2267               xfree (filename);
2268             }
2269           freefileinfo (f);
2270         }
2271     }
2272   else
2273     {
2274       bool ispattern = false;
2275       if (glob)
2276         {
2277           /* Treat the URL as a pattern if the file name part of the
2278              URL path contains wildcards.  (Don't check for u->file
2279              because it is unescaped and therefore doesn't leave users
2280              the option to escape literal '*' as %2A.)  */
2281           char *file_part = strrchr (u->path, '/');
2282           if (!file_part)
2283             file_part = u->path;
2284           ispattern = has_wildcards_p (file_part);
2285         }
2286       if (ispattern || recursive || opt.timestamping)
2287         {
2288           /* ftp_retrieve_glob is a catch-all function that gets called
2289              if we need globbing, time-stamping or recursion.  Its
2290              third argument is just what we really need.  */
2291           res = ftp_retrieve_glob (u, &con,
2292                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2293         }
2294       else
2295         res = ftp_loop_internal (u, NULL, &con, local_file);
2296     }
2297   if (res == FTPOK)
2298     res = RETROK;
2299   if (res == RETROK)
2300     *dt |= RETROKF;
2301   /* If a connection was left, quench it.  */
2302   if (con.csock != -1)
2303     fd_close (con.csock);
2304   xfree_null (con.id);
2305   con.id = NULL;
2306   xfree_null (con.target);
2307   con.target = NULL;
2308   return res;
2309 }
2310
2311 /* Delete an element from the fileinfo linked list.  Returns the
2312    address of the next element, or NULL if the list is exhausted.  It
2313    can modify the start of the list.  */
2314 static struct fileinfo *
2315 delelement (struct fileinfo *f, struct fileinfo **start)
2316 {
2317   struct fileinfo *prev = f->prev;
2318   struct fileinfo *next = f->next;
2319
2320   xfree (f->name);
2321   xfree_null (f->linkto);
2322   xfree (f);
2323
2324   if (next)
2325     next->prev = prev;
2326   if (prev)
2327     prev->next = next;
2328   else
2329     *start = next;
2330   return next;
2331 }
2332
2333 /* Free the fileinfo linked list of files.  */
2334 static void
2335 freefileinfo (struct fileinfo *f)
2336 {
2337   while (f)
2338     {
2339       struct fileinfo *next = f->next;
2340       xfree (f->name);
2341       if (f->linkto)
2342         xfree (f->linkto);
2343       xfree (f);
2344       f = next;
2345     }
2346 }