1 /* File Transfer Protocol support.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
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.
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.
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/>.
20 Additional permission under GNU GPL version 3 section 7
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. */
51 #include "convert.h" /* for downloaded_file */
52 #include "recur.h" /* for INFINITE_RECURSION */
56 #endif /* def __VMS */
59 /* File where the "ls -al" listing will be saved. */
61 #define LIST_FILENAME "_listing"
63 #define LIST_FILENAME ".listing"
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 */
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
84 ftp_expected_bytes (const char *s)
90 while (*s && *s != '(')
94 ++s; /* skip the '(' */
95 res = str_to_wgint (s, (char **) &s, 10);
98 while (*s && c_isspace (*s))
102 if (c_tolower (*s) != 'b')
104 if (strncasecmp (s, "byte", 4))
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.
118 ftp_do_pasv (int csock, ip_address *addr, int *port)
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))
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)
134 if (!opt.server_response)
135 logputs (LOG_VERBOSE, "==> PASV ... ");
136 err = ftp_pasv (csock, addr, port);
139 if (!opt.server_response)
140 logputs (LOG_VERBOSE, "==> EPSV ... ");
141 err = ftp_epsv (csock, addr, port);
143 /* If EPSV is not supported try LPSV */
144 if (err == FTPNOPASV)
146 if (!opt.server_response)
147 logputs (LOG_VERBOSE, "==> LPSV ... ");
148 err = ftp_lpsv (csock, addr, port);
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.
163 ftp_do_port (int csock, int *local_sock)
168 if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
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. */
177 if (!opt.server_response)
178 logputs (LOG_VERBOSE, "==> PORT ... ");
179 err = ftp_port (csock, local_sock);
182 if (!opt.server_response)
183 logputs (LOG_VERBOSE, "==> EPRT ... ");
184 err = ftp_eprt (csock, local_sock);
186 /* If EPRT is not supported try LPRT */
187 if (err == FTPPORTERR)
189 if (!opt.server_response)
190 logputs (LOG_VERBOSE, "==> LPRT ... ");
191 err = ftp_lprt (csock, local_sock);
202 ftp_do_pasv (int csock, ip_address *addr, int *port)
204 if (!opt.server_response)
205 logputs (LOG_VERBOSE, "==> PASV ... ");
206 return ftp_pasv (csock, addr, port);
210 ftp_do_port (int csock, int *local_sock)
212 if (!opt.server_response)
213 logputs (LOG_VERBOSE, "==> PORT ... ");
214 return ftp_port (csock, local_sock);
219 print_length (wgint size, wgint start, bool authoritative)
221 logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
223 logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
226 if (size - start >= 1024)
227 logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
228 number_to_static_string (size - start),
229 human_readable (size - start));
231 logprintf (LOG_VERBOSE, _(", %s remaining"),
232 number_to_static_string (size - start));
234 logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
237 static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
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. */
243 getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
244 wgint restval, ccon *con)
246 int csock, dtsock, local_sock, res;
247 uerr_t err = RETROK; /* appease the compiler */
249 char *user, *passwd, *respline;
253 bool pasv_mode_open = false;
254 wgint expected_bytes = 0;
255 bool got_expected_bytes = false;
256 bool rest_failed = false;
261 assert (con != NULL);
262 assert (con->target != NULL);
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
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);
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@";
285 if (!(cmd & DO_LOGIN))
287 else /* cmd & DO_LOGIN */
289 char *host = con->proxy ? con->proxy->host : u->host;
290 int port = con->proxy ? con->proxy->port : u->port;
291 char *logname = user;
295 /* If proxy is in use, log in as username@target-site. */
296 logname = concat_strings (user, "@", u->host, (char *) 0);
299 /* Login to the server: */
301 /* First: Establish the control connection. */
303 csock = connect_to_host (host, port);
307 return (retryable_socket_connect_error (errno)
308 ? CONERROR : CONIMPOSSIBLE);
310 if (cmd & LEAVE_PENDING)
315 /* Second: Login with proper USER/PASS sequence. */
316 logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
317 quotearg_style (escape_quoting_style, user));
318 if (opt.server_response)
319 logputs (LOG_ALWAYS, "\n");
320 err = ftp_login (csock, logname, passwd);
325 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
329 logputs (LOG_VERBOSE, "\n");
330 logputs (LOG_NOTQUIET, _("\
331 Error in server response, closing control connection.\n"));
336 logputs (LOG_VERBOSE, "\n");
337 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
342 logputs (LOG_VERBOSE, "\n");
343 logputs (LOG_NOTQUIET,
344 _("Write failed, closing control connection.\n"));
349 logputs (LOG_VERBOSE, "\n");
350 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
353 return FTPLOGREFUSED;
355 logputs (LOG_VERBOSE, "\n");
356 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
361 if (!opt.server_response)
362 logputs (LOG_VERBOSE, _("Logged in!\n"));
367 /* Third: Get the system type */
368 if (!opt.server_response)
369 logprintf (LOG_VERBOSE, "==> SYST ... ");
370 err = ftp_syst (csock, &con->rs);
375 logputs (LOG_VERBOSE, "\n");
376 logputs (LOG_NOTQUIET, _("\
377 Error in server response, closing control connection.\n"));
382 logputs (LOG_VERBOSE, "\n");
383 logputs (LOG_NOTQUIET,
384 _("Server error, can't determine system type.\n"));
387 /* Everything is OK. */
392 if (!opt.server_response && err != FTPSRVERR)
393 logputs (LOG_VERBOSE, _("done. "));
395 /* Fourth: Find the initial ftp directory */
397 if (!opt.server_response)
398 logprintf (LOG_VERBOSE, "==> PWD ... ");
399 err = ftp_pwd (csock, &con->id);
404 logputs (LOG_VERBOSE, "\n");
405 logputs (LOG_NOTQUIET, _("\
406 Error in server response, closing control connection.\n"));
411 /* PWD unsupported -- assume "/". */
412 xfree_null (con->id);
413 con->id = xstrdup ("/");
416 /* Everything is OK. */
424 Don't help me out. Please.
425 A reasonably recent VMS FTP server will cope just fine with
426 UNIX file specifications. This code just spoils things.
427 Discarding the device name, for example, is not a wise move.
428 This code was disabled but left in as an example of what not
432 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
433 Convert it to "/INITIAL/FOLDER" */
434 if (con->rs == ST_VMS)
436 char *path = strchr (con->id, '[');
437 char *pathend = path ? strchr (path + 1, ']') : NULL;
438 if (!path || !pathend)
439 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
442 char *idir = con->id;
443 DEBUGP (("Preprocessing the initial VMS directory\n"));
444 DEBUGP ((" old = '%s'\n", con->id));
445 /* We do the conversion in-place by copying the stuff
446 between [ and ] to the beginning, and changing dots
447 to slashes at the same time. */
449 for (++path; path < pathend; path++, idir++)
450 *idir = *path == '.' ? '/' : *path;
452 DEBUGP ((" new = '%s'\n\n", con->id));
457 if (!opt.server_response)
458 logputs (LOG_VERBOSE, _("done.\n"));
460 /* Fifth: Set the FTP type. */
461 type_char = ftp_process_type (u->params);
462 if (!opt.server_response)
463 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
464 err = ftp_type (csock, type_char);
465 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
469 logputs (LOG_VERBOSE, "\n");
470 logputs (LOG_NOTQUIET, _("\
471 Error in server response, closing control connection.\n"));
476 logputs (LOG_VERBOSE, "\n");
477 logputs (LOG_NOTQUIET,
478 _("Write failed, closing control connection.\n"));
483 logputs (LOG_VERBOSE, "\n");
484 logprintf (LOG_NOTQUIET,
485 _("Unknown type `%c', closing control connection.\n"),
491 /* Everything is OK. */
496 if (!opt.server_response)
497 logputs (LOG_VERBOSE, _("done. "));
503 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
511 char *target = u->dir;
513 DEBUGP (("changing working directory\n"));
515 /* Change working directory. To change to a non-absolute
516 Unix directory, we need to prepend initial directory
517 (con->id) to it. Absolute directories "just work".
519 A relative directory is one that does not begin with '/'
520 and, on non-Unix OS'es, one that doesn't begin with
523 This is not done for OS400, which doesn't use
524 "/"-delimited directories, nor does it support directory
525 hierarchies. "CWD foo" followed by "CWD bar" leaves us
526 in "bar", not in "foo/bar", as would be customary
530 Why is this wise even on UNIX? It certainly fouls VMS.
531 See below for a more reliable, more universal method.
535 I'm not crazy about it either. I'm informed it's useful
536 for misconfigured servers that have some dirs in the path
537 with +x but -r, but this method is not RFC-conformant. I
538 understand the need to deal with crappy server
539 configurations, but it's far better to use the canonical
540 method first, and fall back to kludges second.
544 && !(con->rs != ST_UNIX
545 && c_isalpha (target[0])
547 && (con->rs != ST_OS400)
548 && (con->rs != ST_VMS))
550 int idlen = strlen (con->id);
553 /* Strip trailing slash(es) from con->id. */
554 while (idlen > 0 && con->id[idlen - 1] == '/')
556 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
557 memcpy (p, con->id, idlen);
562 DEBUGP (("Prepended initial PWD to relative path:\n"));
563 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
564 con->id, target, ntarget));
570 Don't help me out. Please.
571 A reasonably recent VMS FTP server will cope just fine with
572 UNIX file specifications. This code just spoils things.
573 Discarding the device name, for example, is not a wise
575 This code was disabled but left in as an example of what
579 /* If the FTP host runs VMS, we will have to convert the absolute
580 directory path in UNIX notation to absolute directory path in
581 VMS notation as VMS FTP servers do not like UNIX notation of
582 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
584 if (con->rs == ST_VMS)
587 char *ntarget = (char *)alloca (strlen (target) + 2);
588 /* We use a converted initial dir, so directories in
589 TARGET will be separated with slashes, something like
590 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
591 "[INITIAL.FOLDER.DIR.SUBDIR]". */
592 strcpy (ntarget, target);
593 assert (*ntarget == '/');
595 for (tmpp = ntarget + 1; *tmpp; tmpp++)
600 DEBUGP (("Changed file name to VMS syntax:\n"));
601 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
607 A relative directory is relative to the initial directory.
608 Thus, what _is_ useful on VMS (and probably elsewhere) is
609 to CWD to the initial directory (ideally, whatever the
610 server reports, _exactly_, NOT badly UNIX-ixed), and then
611 CWD to the (new) relative directory. This should probably
612 be restructured as a function, called once or twice, but
613 I'm lazy enough to take the badly indented loop short-cut
617 /* Decide on one pass (absolute) or two (relative).
618 The VMS restriction may be relaxed when the squirrely code
621 if ((con->rs == ST_VMS) && (target[0] != '/'))
624 DEBUGP (("Using two-step CWD for relative path.\n"));
628 /* Go straight to the target. */
632 /* At least one VMS FTP server (TCPware V5.6-2) can switch to
633 a UNIX emulation mode when given a UNIX-like directory
634 specification (like "a/b/c"). If allowed to continue this
635 way, LIST interpretation will be confused, because the
636 system type (SYST response) will not be re-checked, and
637 future UNIX-format directory listings (for multiple URLs or
638 "-r") will be horribly misinterpreted.
640 The cheap and nasty work-around is to do a "CWD []" after a
641 UNIX-like directory specification is used. (A single-level
642 directory is harmless.) This puts the TCPware server back
643 into VMS mode, and does no harm on other servers.
645 Unlike the rest of this block, this particular behavior
646 _is_ VMS-specific, so it gets its own VMS test.
648 if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
651 DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
658 /* 2004-09-20 SMS. */
659 /* Sorry about the deviant indenting. Laziness. */
661 for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
666 /* Step one (optional): Go to the initial directory,
667 exactly as reported by the server.
673 /* Step two: Go to the target directory. (Absolute or
674 relative will work now.)
680 /* Step three (optional): "CWD []" to restore server
691 if (!opt.server_response)
692 logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
693 quotearg_style (escape_quoting_style, target));
694 err = ftp_cwd (csock, targ);
695 /* FTPRERR, WRITEFAILED, FTPNSFOD */
699 logputs (LOG_VERBOSE, "\n");
700 logputs (LOG_NOTQUIET, _("\
701 Error in server response, closing control connection.\n"));
706 logputs (LOG_VERBOSE, "\n");
707 logputs (LOG_NOTQUIET,
708 _("Write failed, closing control connection.\n"));
713 logputs (LOG_VERBOSE, "\n");
714 logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
724 if (!opt.server_response)
725 logputs (LOG_VERBOSE, _("done.\n"));
729 /* 2004-09-20 SMS. */
730 /* End of deviant indenting. */
734 else /* do not CWD */
735 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
737 if ((cmd & DO_RETR) && passed_expected_bytes == 0)
741 if (!opt.server_response)
742 logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
743 quotearg_style (escape_quoting_style, u->file));
746 err = ftp_size (csock, u->file, &expected_bytes);
752 logputs (LOG_VERBOSE, "\n");
753 logputs (LOG_NOTQUIET, _("\
754 Error in server response, closing control connection.\n"));
759 got_expected_bytes = true;
760 /* Everything is OK. */
765 if (!opt.server_response)
766 logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
767 number_to_static_string (expected_bytes));
770 if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
772 /* Server confirms that file has length restval. We should stop now.
773 Some servers (f.e. NcFTPd) return error when receive REST 0 */
774 logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
780 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
781 if (cmd & (DO_LIST | DO_RETR))
785 ip_address passive_addr;
787 err = ftp_do_pasv (csock, &passive_addr, &passive_port);
788 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
792 logputs (LOG_VERBOSE, "\n");
793 logputs (LOG_NOTQUIET, _("\
794 Error in server response, closing control connection.\n"));
799 logputs (LOG_VERBOSE, "\n");
800 logputs (LOG_NOTQUIET,
801 _("Write failed, closing control connection.\n"));
806 logputs (LOG_VERBOSE, "\n");
807 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
810 logputs (LOG_VERBOSE, "\n");
811 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
820 DEBUGP (("trying to connect to %s port %d\n",
821 print_address (&passive_addr), passive_port));
822 dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
825 int save_errno = errno;
828 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
829 print_address (&passive_addr), passive_port,
830 strerror (save_errno));
831 return (retryable_socket_connect_error (save_errno)
832 ? CONERROR : CONIMPOSSIBLE);
835 pasv_mode_open = true; /* Flag to avoid accept port */
836 if (!opt.server_response)
837 logputs (LOG_VERBOSE, _("done. "));
841 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
843 err = ftp_do_port (csock, &local_sock);
844 /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
849 logputs (LOG_VERBOSE, "\n");
850 logputs (LOG_NOTQUIET, _("\
851 Error in server response, closing control connection.\n"));
855 fd_close (local_sock);
858 logputs (LOG_VERBOSE, "\n");
859 logputs (LOG_NOTQUIET,
860 _("Write failed, closing control connection.\n"));
864 fd_close (local_sock);
867 logputs (LOG_VERBOSE, "\n");
868 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
872 fd_close (local_sock);
875 logputs (LOG_VERBOSE, "\n");
876 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
881 logputs (LOG_VERBOSE, "\n");
882 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
886 fd_close (local_sock);
893 if (!opt.server_response)
894 logputs (LOG_VERBOSE, _("done. "));
896 } /* cmd & (DO_LIST | DO_RETR) */
898 /* Restart if needed. */
899 if (restval && (cmd & DO_RETR))
901 if (!opt.server_response)
902 logprintf (LOG_VERBOSE, "==> REST %s ... ",
903 number_to_static_string (restval));
904 err = ftp_rest (csock, restval);
906 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
910 logputs (LOG_VERBOSE, "\n");
911 logputs (LOG_NOTQUIET, _("\
912 Error in server response, closing control connection.\n"));
916 fd_close (local_sock);
919 logputs (LOG_VERBOSE, "\n");
920 logputs (LOG_NOTQUIET,
921 _("Write failed, closing control connection.\n"));
925 fd_close (local_sock);
928 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
936 if (err != FTPRESTFAIL && !opt.server_response)
937 logputs (LOG_VERBOSE, _("done. "));
938 } /* restval && cmd & DO_RETR */
942 /* If we're in spider mode, don't really retrieve anything except
943 the directory listing and verify whether the given "file" exists. */
949 res = ftp_get_listing (u, con, &f);
950 /* Set the DO_RETR command flag again, because it gets unset when
951 calling ftp_get_listing() and would otherwise cause an assertion
952 failure earlier on when this function gets repeatedly called
953 (e.g., when recursing). */
959 if (!strcmp (f->name, u->file))
968 logputs (LOG_VERBOSE, "\n");
969 logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
974 logputs (LOG_VERBOSE, "\n");
975 logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
982 fd_close (local_sock);
988 if (!opt.server_response)
991 logputs (LOG_VERBOSE, "\n");
992 logprintf (LOG_VERBOSE, "==> RETR %s ... ",
993 quotearg_style (escape_quoting_style, u->file));
997 err = ftp_retr (csock, u->file);
998 /* FTPRERR, WRITEFAILED, FTPNSFOD */
1002 logputs (LOG_VERBOSE, "\n");
1003 logputs (LOG_NOTQUIET, _("\
1004 Error in server response, closing control connection.\n"));
1008 fd_close (local_sock);
1011 logputs (LOG_VERBOSE, "\n");
1012 logputs (LOG_NOTQUIET,
1013 _("Write failed, closing control connection.\n"));
1017 fd_close (local_sock);
1020 logputs (LOG_VERBOSE, "\n");
1021 logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1024 fd_close (local_sock);
1032 if (!opt.server_response)
1033 logputs (LOG_VERBOSE, _("done.\n"));
1035 if (! got_expected_bytes)
1036 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1041 if (!opt.server_response)
1042 logputs (LOG_VERBOSE, "==> LIST ... ");
1043 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1044 without arguments is better than `LIST .'; confirmed by
1046 err = ftp_list (csock, NULL, con->rs);
1047 /* FTPRERR, WRITEFAILED */
1051 logputs (LOG_VERBOSE, "\n");
1052 logputs (LOG_NOTQUIET, _("\
1053 Error in server response, closing control connection.\n"));
1057 fd_close (local_sock);
1060 logputs (LOG_VERBOSE, "\n");
1061 logputs (LOG_NOTQUIET,
1062 _("Write failed, closing control connection.\n"));
1066 fd_close (local_sock);
1069 logputs (LOG_VERBOSE, "\n");
1070 logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1073 fd_close (local_sock);
1080 if (!opt.server_response)
1081 logputs (LOG_VERBOSE, _("done.\n"));
1083 if (! got_expected_bytes)
1084 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1085 } /* cmd & DO_LIST */
1087 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1088 return RETRFINISHED;
1090 /* Some FTP servers return the total length of file after REST
1091 command, others just return the remaining size. */
1092 if (passed_expected_bytes && restval && expected_bytes
1093 && (expected_bytes == passed_expected_bytes - restval))
1095 DEBUGP (("Lying FTP server found, adjusting.\n"));
1096 expected_bytes = passed_expected_bytes;
1099 /* If no transmission was required, then everything is OK. */
1100 if (!pasv_mode_open) /* we are not using pasive mode so we need
1103 /* Wait for the server to connect to the address we're waiting
1105 dtsock = accept_connection (local_sock);
1108 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1113 /* Open the file -- if output_stream is set, use it instead. */
1116 Note that having the output_stream ("-O") file opened in main()
1117 (main.c) rather limits the ability in VMS to open the file
1118 differently for ASCII versus binary FTP here. (Of course, doing it
1119 there allows a open failure to be detected immediately, without first
1120 connecting to the server.)
1122 if (!output_stream || con->cmd & DO_LIST)
1124 /* On VMS, alter the name as required. */
1128 targ = ods_conform (con->target);
1129 if (targ != con->target)
1131 xfree (con->target);
1134 #endif /* def __VMS */
1136 mkalldirs (con->target);
1138 rotate_backups (con->target);
1141 For VMS, define common fopen() optional arguments, and a handy macro
1142 for use as a variable "binary" flag.
1143 Elsewhere, define a constant "binary" flag.
1144 Isn't it nice to have distinct text and binary file types?
1146 # define BIN_TYPE_TRANSFER (type_char != 'A')
1148 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1149 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1150 # define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1151 #else /* def __VMS */
1152 # define BIN_TYPE_FILE 1
1153 #endif /* def __VMS [else] */
1155 if (restval && !(con->cmd & DO_LIST))
1163 fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1168 fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1170 #else /* def __VMS */
1171 fp = fopen (con->target, "ab");
1172 #endif /* def __VMS [else] */
1174 else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1175 || opt.output_document)
1177 if (opt.unlink && file_exists_p (con->target))
1179 int res = unlink (con->target);
1182 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1187 fd_close (local_sock);
1198 fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1203 fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1205 #else /* def __VMS */
1206 fp = fopen (con->target, "wb");
1207 #endif /* def __VMS [else] */
1211 fp = fopen_excl (con->target, true);
1212 if (!fp && errno == EEXIST)
1214 /* We cannot just invent a new name and use it (which is
1215 what functions like unique_create typically do)
1216 because we told the user we'd use this name.
1217 Instead, return and retry the download. */
1218 logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1223 fd_close (local_sock);
1224 return FOPEN_EXCL_ERR;
1229 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1233 fd_close (local_sock);
1240 if (passed_expected_bytes)
1242 print_length (passed_expected_bytes, restval, true);
1243 expected_bytes = passed_expected_bytes;
1244 /* for fd_read_body's progress bar */
1246 else if (expected_bytes)
1247 print_length (expected_bytes, restval, false);
1249 /* Get the contents of the document. */
1251 if (restval && rest_failed)
1252 flags |= rb_skip_startpos;
1254 res = fd_read_body (dtsock, fp,
1255 expected_bytes ? expected_bytes - restval : 0,
1256 restval, &rd_size, qtyread, &con->dltime, flags);
1258 tms = datetime_str (time (NULL));
1259 tmrate = retr_rate (rd_size, con->dltime);
1260 total_download_time += con->dltime;
1262 fd_close (local_sock);
1263 /* Close the local file. */
1264 if (!output_stream || con->cmd & DO_LIST)
1267 /* If fd_read_body couldn't write to fp, bail out. */
1270 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1271 con->target, strerror (errno));
1279 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1280 tms, tmrate, fd_errstr (dtsock));
1281 if (opt.server_response)
1282 logputs (LOG_ALWAYS, "\n");
1286 /* Get the server to tell us if everything is retrieved. */
1287 err = ftp_response (csock, &respline);
1290 /* The control connection is decidedly closed. Print the time
1291 only if it hasn't already been printed. */
1293 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1294 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1295 /* If there is an error on the control connection, close it, but
1296 return FTPRETRINT, since there is a possibility that the
1297 whole file was retrieved nevertheless (but that is for
1298 ftp_loop_internal to decide). */
1302 } /* err != FTPOK */
1303 /* If retrieval failed for any reason, return FTPRETRINT, but do not
1304 close socket, since the control connection is still alive. If
1305 there is something wrong with the control connection, it will
1306 become apparent later. */
1307 if (*respline != '2')
1311 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1312 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1319 /* What now? The data connection was erroneous, whereas the
1320 response says everything is OK. We shall play it safe. */
1324 if (!(cmd & LEAVE_PENDING))
1326 /* Closing the socket is faster than sending 'QUIT' and the
1327 effect is the same. */
1331 /* If it was a listing, and opt.server_response is true,
1333 if (opt.server_response && (con->cmd & DO_LIST))
1336 Much of this work may already have been done, but repeating it should
1337 do no damage beyond wasting time.
1339 /* On VMS, alter the name as required. */
1343 targ = ods_conform( con->target);
1344 if (targ != con->target)
1346 xfree( con->target);
1349 #endif /* def __VMS */
1351 mkalldirs (con->target);
1352 fp = fopen (con->target, "r");
1354 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1358 /* The lines are being read with read_whole_line because of
1359 no-buffering on opt.lfile. */
1360 while ((line = read_whole_line (fp)) != NULL)
1362 char *p = strchr (line, '\0');
1363 while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1365 logprintf (LOG_ALWAYS, "%s\n",
1366 quotearg_style (escape_quoting_style, line));
1371 } /* con->cmd & DO_LIST && server_response */
1373 return RETRFINISHED;
1376 /* A one-file FTP loop. This is the part where FTP retrieval is
1377 retried, and retried, and retried, and...
1379 This loop either gets commands from con, or (if ON_YOUR_OWN is
1380 set), makes them up to retrieve the file given by the URL. */
1382 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1385 wgint restval, len = 0, qtyread = 0;
1387 const char *tmrate = NULL;
1391 /* Get the target, and set the name for the message accordingly. */
1392 if ((f == NULL) && (con->target))
1394 /* Explicit file (like ".listing"). */
1399 /* URL-derived file. Consider "-O file" name. */
1400 con->target = url_file_name (u, NULL);
1401 if (!opt.output_document)
1404 locf = opt.output_document;
1407 /* If the output_document was given, then this check was already done and
1408 the file didn't exist. Hence the !opt.output_document */
1409 if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1411 logprintf (LOG_VERBOSE,
1412 _("File %s already there; not retrieving.\n"), quote (con->target));
1413 /* If the file is there, we suppose it's retrieved OK. */
1417 /* Remove it if it's a link. */
1418 remove_link (con->target);
1422 if (con->st & ON_YOUR_OWN)
1423 con->st = ON_YOUR_OWN;
1425 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1430 /* Increment the pass counter. */
1432 sleep_between_retrievals (count);
1433 if (con->st & ON_YOUR_OWN)
1436 con->cmd |= (DO_RETR | LEAVE_PENDING);
1437 if (con->csock != -1)
1438 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1440 con->cmd |= (DO_LOGIN | DO_CWD);
1442 else /* not on your own */
1444 if (con->csock != -1)
1445 con->cmd &= ~DO_LOGIN;
1447 con->cmd |= DO_LOGIN;
1448 if (con->st & DONE_CWD)
1449 con->cmd &= ~DO_CWD;
1454 /* Decide whether or not to restart. */
1455 if (con->cmd & DO_LIST)
1457 else if (opt.always_rest
1458 && stat (locf, &st) == 0
1459 && S_ISREG (st.st_mode))
1460 /* When -c is used, continue from on-disk size. (Can't use
1461 hstat.len even if count>1 because we don't want a failed
1462 first attempt to clobber existing data.) */
1463 restval = st.st_size;
1465 restval = qtyread; /* start where the previous run left off */
1469 /* Get the current time string. */
1470 tms = datetime_str (time (NULL));
1471 /* Print fetch message, if opt.verbose. */
1474 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1478 sprintf (tmp, _("(try:%2d)"), count);
1479 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => %s\n",
1480 tms, hurl, tmp, quote (locf));
1482 ws_changetitle (hurl);
1486 /* Send getftp the proper length, if fileinfo was provided. */
1487 if (f && f->type != FT_SYMLINK)
1491 err = getftp (u, len, &qtyread, restval, con);
1493 if (con->csock == -1)
1494 con->st &= ~DONE_CWD;
1496 con->st |= DONE_CWD;
1500 case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1501 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1503 /* Fatal errors, give up. */
1505 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1506 case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1507 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1508 case FOPEN_EXCL_ERR:
1509 printwhat (count, opt.ntry);
1510 /* non-fatal errors */
1511 if (err == FOPEN_EXCL_ERR)
1513 /* Re-determine the file name. */
1514 xfree_null (con->target);
1515 con->target = url_file_name (u, NULL);
1520 /* If the control connection was closed, the retrieval
1521 will be considered OK if f->size == len. */
1522 if (!f || qtyread != f->size)
1524 printwhat (count, opt.ntry);
1535 tms = datetime_str (time (NULL));
1537 tmrate = retr_rate (qtyread - restval, con->dltime);
1539 /* If we get out of the switch above without continue'ing, we've
1540 successfully downloaded a file. Remember this fact. */
1541 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1543 if (con->st & ON_YOUR_OWN)
1545 fd_close (con->csock);
1550 bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1552 logprintf (LOG_VERBOSE,
1554 ? _("%s (%s) - written to stdout %s[%s]\n\n")
1555 : _("%s (%s) - %s saved [%s]\n\n"),
1557 write_to_stdout ? "" : quote (locf),
1558 number_to_static_string (qtyread));
1560 if (!opt.verbose && !opt.quiet)
1562 /* Need to hide the password from the URL. The `if' is here
1563 so that we don't do the needless allocation every
1565 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1566 logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1567 tms, hurl, number_to_static_string (qtyread), locf, count);
1571 if ((con->cmd & DO_LIST))
1572 /* This is a directory listing file. */
1574 if (!opt.remove_listing)
1575 /* --dont-remove-listing was specified, so do count this towards the
1576 number of bytes and files downloaded. */
1578 total_downloaded_bytes += qtyread;
1582 /* Deletion of listing files is not controlled by --delete-after, but
1583 by the more specific option --dont-remove-listing, and the code
1584 to do this deletion is in another function. */
1586 else if (!opt.spider)
1587 /* This is not a directory listing file. */
1589 /* Unlike directory listing files, don't pretend normal files weren't
1590 downloaded if they're going to be deleted. People seeding proxies,
1591 for instance, may want to know how many bytes and files they've
1592 downloaded through it. */
1593 total_downloaded_bytes += qtyread;
1596 if (opt.delete_after && !input_file_url (opt.input_filename))
1599 Removing file due to --delete-after in ftp_loop_internal():\n"));
1600 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1602 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1606 /* Restore the original leave-pendingness. */
1608 con->cmd |= LEAVE_PENDING;
1610 con->cmd &= ~LEAVE_PENDING;
1613 *local_file = xstrdup (locf);
1616 } while (!opt.ntry || (count < opt.ntry));
1618 if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1620 fd_close (con->csock);
1626 /* Return the directory listing in a reusable format. The directory
1627 is specifed in u->dir. */
1629 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1632 char *uf; /* url file name */
1633 char *lf; /* list file name */
1634 char *old_target = con->target;
1636 con->st &= ~ON_YOUR_OWN;
1637 con->cmd |= (DO_LIST | LEAVE_PENDING);
1638 con->cmd &= ~DO_RETR;
1640 /* Find the listing file name. We do it by taking the file name of
1641 the URL and replacing the last component with the listing file
1643 uf = url_file_name (u, NULL);
1644 lf = file_merge (uf, LIST_FILENAME);
1646 DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1648 con->target = xstrdup (lf);
1650 err = ftp_loop_internal (u, NULL, con, NULL);
1651 lf = xstrdup (con->target);
1652 xfree (con->target);
1653 con->target = old_target;
1657 *f = ftp_parse_ls (lf, con->rs);
1658 if (opt.remove_listing)
1661 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1663 logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1669 con->cmd &= ~DO_LIST;
1673 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1674 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1675 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1676 static void freefileinfo (struct fileinfo *f);
1678 /* Retrieve a list of files given in struct fileinfo linked list. If
1679 a file is a symbolic link, do not retrieve it, but rather try to
1680 set up a similar link on the local disk, if the symlinks are
1683 If opt.recursive is set, after all files have been retrieved,
1684 ftp_retrieve_dirs will be called to retrieve the directories. */
1686 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1688 static int depth = 0;
1690 struct fileinfo *orig;
1693 bool dlthis; /* Download this (file). */
1694 const char *actual_target = NULL;
1696 /* Increase the depth. */
1698 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1700 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1701 depth, opt.reclevel));
1709 con->st &= ~ON_YOUR_OWN;
1710 if (!(con->st & DONE_CWD))
1713 con->cmd &= ~DO_CWD;
1714 con->cmd |= (DO_RETR | LEAVE_PENDING);
1717 con->cmd |= DO_LOGIN;
1719 con->cmd &= ~DO_LOGIN;
1721 err = RETROK; /* in case it's not used */
1725 char *old_target, *ofile;
1727 if (opt.quota && total_downloaded_bytes > opt.quota)
1732 old_target = con->target;
1734 ofile = xstrdup (u->file);
1735 url_set_file (u, f->name);
1737 con->target = url_file_name (u, NULL);
1741 if (opt.timestamping && f->type == FT_PLAINFILE)
1744 /* If conversion of HTML files retrieved via FTP is ever implemented,
1745 we'll need to stat() <file>.orig here when -K has been specified.
1746 I'm not implementing it now since files on an FTP server are much
1747 more likely than files on an HTTP server to legitimately have a
1749 if (!stat (con->target, &st))
1753 /* Else, get it from the file. */
1754 local_size = st.st_size;
1757 /* Modification time granularity is 2 seconds for Windows, so
1758 increase local time by 1 second for later comparison. */
1761 /* Compare file sizes only for servers that tell us correct
1762 values. Assume sizes being equal for servers that lie
1764 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1765 eq_size = cor_val ? (local_size == f->size) : true;
1766 if (f->tstamp <= tml && eq_size)
1768 /* Remote file is older, file sizes can be compared and
1770 logprintf (LOG_VERBOSE, _("\
1771 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1776 /* Remote file is newer or sizes cannot be matched */
1777 logprintf (LOG_VERBOSE, _("\
1778 Remote file is newer than local file %s -- retrieving.\n\n"),
1779 quote (con->target));
1783 /* Sizes do not match */
1784 logprintf (LOG_VERBOSE, _("\
1785 The sizes do not match (local %s) -- retrieving.\n\n"),
1786 number_to_static_string (local_size));
1789 } /* opt.timestamping && f->type == FT_PLAINFILE */
1793 /* If opt.retr_symlinks is defined, we treat symlinks as
1794 if they were normal files. There is currently no way
1795 to distinguish whether they might be directories, and
1797 if (!opt.retr_symlinks)
1801 logputs (LOG_NOTQUIET,
1802 _("Invalid name of the symlink, skipping.\n"));
1806 /* Check whether we already have the correct
1808 int rc = lstat (con->target, &st);
1811 size_t len = strlen (f->linkto) + 1;
1812 if (S_ISLNK (st.st_mode))
1814 char *link_target = (char *)alloca (len);
1815 size_t n = readlink (con->target, link_target, len);
1817 && (memcmp (link_target, f->linkto, n) == 0))
1819 logprintf (LOG_VERBOSE, _("\
1820 Already have correct symlink %s -> %s\n\n"),
1821 quote (con->target),
1828 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1829 quote (con->target), quote (f->linkto));
1830 /* Unlink before creating symlink! */
1831 unlink (con->target);
1832 if (symlink (f->linkto, con->target) == -1)
1833 logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1834 logputs (LOG_VERBOSE, "\n");
1835 } /* have f->linkto */
1836 #else /* not HAVE_SYMLINK */
1837 logprintf (LOG_NOTQUIET,
1838 _("Symlinks not supported, skipping symlink %s.\n"),
1839 quote (con->target));
1840 #endif /* not HAVE_SYMLINK */
1842 else /* opt.retr_symlinks */
1845 err = ftp_loop_internal (u, f, con, NULL);
1846 } /* opt.retr_symlinks */
1850 logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1854 /* Call the retrieve loop. */
1856 err = ftp_loop_internal (u, f, con, NULL);
1859 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1866 * Set permissions _before_ setting the times, as setting the
1867 * permissions changes the modified-time, at least on VMS.
1868 * Also, use the opt.output_document name here, too, as
1869 * appropriate. (Do the test once, and save the result.)
1872 set_local_file (&actual_target, con->target);
1874 /* If downloading a plain file, set valid (non-zero) permissions. */
1875 if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1878 chmod (actual_target, f->perms);
1880 DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1883 /* Set the time-stamp information to the local file. Symlinks
1884 are not to be stamped because it sets the stamp on the
1886 if (actual_target != NULL)
1888 if (opt.useservertimestamps
1889 && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1892 && file_exists_p (con->target))
1894 touch (actual_target, f->tstamp);
1896 else if (f->tstamp == -1)
1897 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1901 xfree (con->target);
1902 con->target = old_target;
1904 url_set_file (u, ofile);
1907 /* Break on fatals. */
1908 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1910 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1914 /* We do not want to call ftp_retrieve_dirs here */
1915 if (opt.recursive &&
1916 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1917 err = ftp_retrieve_dirs (u, orig, con);
1918 else if (opt.recursive)
1919 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1920 depth, opt.reclevel));
1925 /* Retrieve the directories given in a file list. This function works
1926 by simply going through the linked list and calling
1927 ftp_retrieve_glob on each directory entry. The function knows
1928 about excluded directories. */
1930 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1932 char *container = NULL;
1933 int container_size = 0;
1935 for (; f; f = f->next)
1938 char *odir, *newdir;
1940 if (opt.quota && total_downloaded_bytes > opt.quota)
1942 if (f->type != FT_DIRECTORY)
1945 /* Allocate u->dir off stack, but reallocate only if a larger
1946 string is needed. It's a pity there's no "realloca" for an
1947 item on the bottom of the stack. */
1948 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1949 if (size > container_size)
1950 container = (char *)alloca (size);
1955 || (*odir == '/' && *(odir + 1) == '\0'))
1956 /* If ODIR is empty or just "/", simply append f->name to
1957 ODIR. (In the former case, to preserve u->dir being
1958 relative; in the latter case, to avoid double slash.) */
1959 sprintf (newdir, "%s%s", odir, f->name);
1961 /* Else, use a separator. */
1962 sprintf (newdir, "%s/%s", odir, f->name);
1964 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1965 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1966 odir, f->name, newdir));
1967 if (!accdir (newdir))
1969 logprintf (LOG_VERBOSE, _("\
1970 Not descending to %s as it is excluded/not-included.\n"),
1975 con->st &= ~DONE_CWD;
1977 odir = xstrdup (u->dir); /* because url_set_dir will free
1979 url_set_dir (u, newdir);
1980 ftp_retrieve_glob (u, con, GLOB_GETALL);
1981 url_set_dir (u, odir);
1984 /* Set the time-stamp? */
1987 if (opt.quota && total_downloaded_bytes > opt.quota)
1993 /* Return true if S has a leading '/' or contains '../' */
1995 has_insecure_name_p (const char *s)
2000 if (strstr (s, "../") != 0)
2006 /* A near-top-level function to retrieve the files in a directory.
2007 The function calls ftp_get_listing, to get a linked list of files.
2008 Then it weeds out the file names that do not match the pattern.
2009 ftp_retrieve_list is called with this updated list as an argument.
2011 If the argument ACTION is GLOB_GETONE, just download the file (but
2012 first get the listing, so that the time-stamp is heeded); if it's
2013 GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
2016 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2018 struct fileinfo *f, *start;
2021 con->cmd |= LEAVE_PENDING;
2023 res = ftp_get_listing (u, con, &start);
2026 /* First: weed out that do not conform the global rules given in
2027 opt.accepts and opt.rejects. */
2028 if (opt.accepts || opt.rejects)
2033 if (f->type != FT_DIRECTORY && !acceptable (f->name))
2035 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2037 f = delelement (f, &start);
2043 /* Remove all files with possible harmful names */
2047 if (has_insecure_name_p (f->name))
2049 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2051 f = delelement (f, &start);
2056 /* Now weed out the files that do not match our globbing pattern.
2057 If we are dealing with a globbing pattern, that is. */
2060 if (action == GLOB_GLOBALL)
2062 int (*matcher) (const char *, const char *, int)
2063 = opt.ignore_case ? fnmatch_nocase : fnmatch;
2069 matchres = matcher (u->file, f->name, 0);
2072 logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2073 u->file, quotearg_style (escape_quoting_style, f->name),
2077 if (matchres == FNM_NOMATCH)
2078 f = delelement (f, &start); /* delete the element from the list */
2080 f = f->next; /* leave the element in the list */
2084 freefileinfo (start);
2085 return RETRBADPATTERN;
2088 else if (action == GLOB_GETONE)
2092 * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2093 * bug causes spurious %CC-E-BADCONDIT complaint with this
2094 * "?:" statement. (Different linkage attributes for strcmp()
2095 * and strcasecmp().) Converting to "if" changes the
2096 * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
2097 * the senseless type cast clears the complaint, and looks
2100 int (*cmp) (const char *, const char *)
2101 = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2102 #else /* def __VMS */
2103 int (*cmp) (const char *, const char *)
2104 = opt.ignore_case ? strcasecmp : strcmp;
2105 #endif /* def __VMS [else] */
2109 if (0 != cmp(u->file, f->name))
2110 f = delelement (f, &start);
2118 /* Just get everything. */
2119 ftp_retrieve_list (u, start, con);
2123 if (action == GLOB_GLOBALL)
2126 /* #### This message SUCKS. We should see what was the
2127 reason that nothing was retrieved. */
2128 logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2131 else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2133 /* Let's try retrieving it anyway. */
2134 con->st |= ON_YOUR_OWN;
2135 res = ftp_loop_internal (u, NULL, con, NULL);
2139 /* If action == GLOB_GETALL, and the file list is empty, there's
2140 no point in trying to download anything or in complaining about
2141 it. (An empty directory should not cause complaints.)
2144 freefileinfo (start);
2145 if (opt.quota && total_downloaded_bytes > opt.quota)
2148 /* #### Should we return `res' here? */
2152 /* The wrapper that calls an appropriate routine according to contents
2153 of URL. Inherently, its capabilities are limited on what can be
2154 encoded into a URL. */
2156 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2157 bool recursive, bool glob)
2159 ccon con; /* FTP connection */
2167 con.st = ON_YOUR_OWN;
2172 /* If the file name is empty, the user probably wants a directory
2173 index. We'll provide one, properly HTML-ized. Unless
2174 opt.htmlify is 0, of course. :-) */
2175 if (!*u->file && !recursive)
2178 res = ftp_get_listing (u, &con, &f);
2182 if (opt.htmlify && !opt.spider)
2184 char *filename = (opt.output_document
2185 ? xstrdup (opt.output_document)
2186 : (con.target ? xstrdup (con.target)
2187 : url_file_name (u, NULL)));
2188 res = ftp_index (filename, u, f);
2189 if (res == FTPOK && opt.verbose)
2191 if (!opt.output_document)
2195 if (stat (filename, &st) == 0)
2199 logprintf (LOG_NOTQUIET,
2200 _("Wrote HTML-ized index to %s [%s].\n"),
2201 quote (filename), number_to_static_string (sz));
2204 logprintf (LOG_NOTQUIET,
2205 _("Wrote HTML-ized index to %s.\n"),
2215 bool ispattern = false;
2218 /* Treat the URL as a pattern if the file name part of the
2219 URL path contains wildcards. (Don't check for u->file
2220 because it is unescaped and therefore doesn't leave users
2221 the option to escape literal '*' as %2A.) */
2222 char *file_part = strrchr (u->path, '/');
2224 file_part = u->path;
2225 ispattern = has_wildcards_p (file_part);
2227 if (ispattern || recursive || opt.timestamping)
2229 /* ftp_retrieve_glob is a catch-all function that gets called
2230 if we need globbing, time-stamping or recursion. Its
2231 third argument is just what we really need. */
2232 res = ftp_retrieve_glob (u, &con,
2233 ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2236 res = ftp_loop_internal (u, NULL, &con, local_file);
2242 /* If a connection was left, quench it. */
2243 if (con.csock != -1)
2244 fd_close (con.csock);
2245 xfree_null (con.id);
2247 xfree_null (con.target);
2252 /* Delete an element from the fileinfo linked list. Returns the
2253 address of the next element, or NULL if the list is exhausted. It
2254 can modify the start of the list. */
2255 static struct fileinfo *
2256 delelement (struct fileinfo *f, struct fileinfo **start)
2258 struct fileinfo *prev = f->prev;
2259 struct fileinfo *next = f->next;
2262 xfree_null (f->linkto);
2274 /* Free the fileinfo linked list of files. */
2276 freefileinfo (struct fileinfo *f)
2280 struct fileinfo *next = f->next;