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,
6 This file is part of GNU Wget.
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.
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.
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/>.
21 Additional permission under GNU GPL version 3 section 7
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. */
50 #include "convert.h" /* for downloaded_file */
51 #include "recur.h" /* for INFINITE_RECURSION */
55 #endif /* def __VMS */
58 /* File where the "ls -al" listing will be saved. */
60 #define LIST_FILENAME "_listing"
62 #define LIST_FILENAME ".listing"
67 int st; /* connection status */
68 int cmd; /* command code */
69 int csock; /* control connection socket */
70 double dltime; /* time of the download in msecs */
71 enum stype rs; /* remote system reported by ftp server */
72 char *id; /* initial directory */
73 char *target; /* target file name */
74 struct url *proxy; /* FTWK-style proxy */
79 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
80 the string S, and return the number converted to wgint, if found, 0
83 ftp_expected_bytes (const char *s)
89 while (*s && *s != '(')
93 ++s; /* skip the '(' */
94 res = str_to_wgint (s, (char **) &s, 10);
97 while (*s && c_isspace (*s))
101 if (c_tolower (*s) != 'b')
103 if (strncasecmp (s, "byte", 4))
113 * This function sets up a passive data connection with the FTP server.
114 * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
117 ftp_do_pasv (int csock, ip_address *addr, int *port)
121 /* We need to determine the address family and need to call
122 getpeername, so while we're at it, store the address to ADDR.
123 ftp_pasv and ftp_lpsv can simply override it. */
124 if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
127 /* If our control connection is over IPv6, then we first try EPSV and then
128 * LPSV if the former is not supported. If the control connection is over
129 * IPv4, we simply issue the good old PASV request. */
130 switch (addr->family)
133 if (!opt.server_response)
134 logputs (LOG_VERBOSE, "==> PASV ... ");
135 err = ftp_pasv (csock, addr, port);
138 if (!opt.server_response)
139 logputs (LOG_VERBOSE, "==> EPSV ... ");
140 err = ftp_epsv (csock, addr, port);
142 /* If EPSV is not supported try LPSV */
143 if (err == FTPNOPASV)
145 if (!opt.server_response)
146 logputs (LOG_VERBOSE, "==> LPSV ... ");
147 err = ftp_lpsv (csock, addr, port);
158 * This function sets up an active data connection with the FTP server.
159 * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
162 ftp_do_port (int csock, int *local_sock)
167 if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
170 /* If our control connection is over IPv6, then we first try EPRT and then
171 * LPRT if the former is not supported. If the control connection is over
172 * IPv4, we simply issue the good old PORT request. */
176 if (!opt.server_response)
177 logputs (LOG_VERBOSE, "==> PORT ... ");
178 err = ftp_port (csock, local_sock);
181 if (!opt.server_response)
182 logputs (LOG_VERBOSE, "==> EPRT ... ");
183 err = ftp_eprt (csock, local_sock);
185 /* If EPRT is not supported try LPRT */
186 if (err == FTPPORTERR)
188 if (!opt.server_response)
189 logputs (LOG_VERBOSE, "==> LPRT ... ");
190 err = ftp_lprt (csock, local_sock);
201 ftp_do_pasv (int csock, ip_address *addr, int *port)
203 if (!opt.server_response)
204 logputs (LOG_VERBOSE, "==> PASV ... ");
205 return ftp_pasv (csock, addr, port);
209 ftp_do_port (int csock, int *local_sock)
211 if (!opt.server_response)
212 logputs (LOG_VERBOSE, "==> PORT ... ");
213 return ftp_port (csock, local_sock);
218 print_length (wgint size, wgint start, bool authoritative)
220 logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
222 logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
225 if (size - start >= 1024)
226 logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
227 number_to_static_string (size - start),
228 human_readable (size - start));
230 logprintf (LOG_VERBOSE, _(", %s remaining"),
231 number_to_static_string (size - start));
233 logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
236 static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
238 /* Retrieves a file with denoted parameters through opening an FTP
239 connection to the server. It always closes the data connection,
240 and closes the control connection in case of error. */
242 getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
243 wgint restval, ccon *con, int count)
245 int csock, dtsock, local_sock, res;
246 uerr_t err = RETROK; /* appease the compiler */
248 char *user, *passwd, *respline;
252 bool pasv_mode_open = false;
253 wgint expected_bytes = 0;
254 bool got_expected_bytes = false;
255 bool rest_failed = false;
260 assert (con != NULL);
261 assert (con->target != NULL);
263 /* Debug-check of the sanity of the request by making sure that LIST
264 and RETR are never both requested (since we can handle only one
266 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
267 /* Make sure that at least *something* is requested. */
268 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
274 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
275 user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
276 if (!user) user = "anonymous";
277 passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
278 if (!passwd) passwd = "-wget@";
284 if (!(cmd & DO_LOGIN))
286 else /* cmd & DO_LOGIN */
288 char *host = con->proxy ? con->proxy->host : u->host;
289 int port = con->proxy ? con->proxy->port : u->port;
290 char *logname = user;
294 /* If proxy is in use, log in as username@target-site. */
295 logname = concat_strings (user, "@", u->host, (char *) 0);
298 /* Login to the server: */
300 /* First: Establish the control connection. */
302 csock = connect_to_host (host, port);
315 return (retryable_socket_connect_error (errno)
316 ? CONERROR : CONIMPOSSIBLE);
319 if (cmd & LEAVE_PENDING)
324 /* Second: Login with proper USER/PASS sequence. */
325 logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
326 quotearg_style (escape_quoting_style, user));
327 if (opt.server_response)
328 logputs (LOG_ALWAYS, "\n");
329 err = ftp_login (csock, logname, passwd);
334 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
338 logputs (LOG_VERBOSE, "\n");
339 logputs (LOG_NOTQUIET, _("\
340 Error in server response, closing control connection.\n"));
345 logputs (LOG_VERBOSE, "\n");
346 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
351 logputs (LOG_VERBOSE, "\n");
352 logputs (LOG_NOTQUIET,
353 _("Write failed, closing control connection.\n"));
358 logputs (LOG_VERBOSE, "\n");
359 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
362 return FTPLOGREFUSED;
364 logputs (LOG_VERBOSE, "\n");
365 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
370 if (!opt.server_response)
371 logputs (LOG_VERBOSE, _("Logged in!\n"));
376 /* Third: Get the system type */
377 if (!opt.server_response)
378 logprintf (LOG_VERBOSE, "==> SYST ... ");
379 err = ftp_syst (csock, &con->rs);
384 logputs (LOG_VERBOSE, "\n");
385 logputs (LOG_NOTQUIET, _("\
386 Error in server response, closing control connection.\n"));
391 logputs (LOG_VERBOSE, "\n");
392 logputs (LOG_NOTQUIET,
393 _("Server error, can't determine system type.\n"));
396 /* Everything is OK. */
401 if (!opt.server_response && err != FTPSRVERR)
402 logputs (LOG_VERBOSE, _("done. "));
404 /* Fourth: Find the initial ftp directory */
406 if (!opt.server_response)
407 logprintf (LOG_VERBOSE, "==> PWD ... ");
408 err = ftp_pwd (csock, &con->id);
413 logputs (LOG_VERBOSE, "\n");
414 logputs (LOG_NOTQUIET, _("\
415 Error in server response, closing control connection.\n"));
420 /* PWD unsupported -- assume "/". */
421 xfree_null (con->id);
422 con->id = xstrdup ("/");
425 /* Everything is OK. */
433 Don't help me out. Please.
434 A reasonably recent VMS FTP server will cope just fine with
435 UNIX file specifications. This code just spoils things.
436 Discarding the device name, for example, is not a wise move.
437 This code was disabled but left in as an example of what not
441 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
442 Convert it to "/INITIAL/FOLDER" */
443 if (con->rs == ST_VMS)
445 char *path = strchr (con->id, '[');
446 char *pathend = path ? strchr (path + 1, ']') : NULL;
447 if (!path || !pathend)
448 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
451 char *idir = con->id;
452 DEBUGP (("Preprocessing the initial VMS directory\n"));
453 DEBUGP ((" old = '%s'\n", con->id));
454 /* We do the conversion in-place by copying the stuff
455 between [ and ] to the beginning, and changing dots
456 to slashes at the same time. */
458 for (++path; path < pathend; path++, idir++)
459 *idir = *path == '.' ? '/' : *path;
461 DEBUGP ((" new = '%s'\n\n", con->id));
466 if (!opt.server_response)
467 logputs (LOG_VERBOSE, _("done.\n"));
469 /* Fifth: Set the FTP type. */
470 type_char = ftp_process_type (u->params);
471 if (!opt.server_response)
472 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
473 err = ftp_type (csock, type_char);
474 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
478 logputs (LOG_VERBOSE, "\n");
479 logputs (LOG_NOTQUIET, _("\
480 Error in server response, closing control connection.\n"));
485 logputs (LOG_VERBOSE, "\n");
486 logputs (LOG_NOTQUIET,
487 _("Write failed, closing control connection.\n"));
492 logputs (LOG_VERBOSE, "\n");
493 logprintf (LOG_NOTQUIET,
494 _("Unknown type `%c', closing control connection.\n"),
500 /* Everything is OK. */
505 if (!opt.server_response)
506 logputs (LOG_VERBOSE, _("done. "));
512 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
520 char *target = u->dir;
522 DEBUGP (("changing working directory\n"));
524 /* Change working directory. To change to a non-absolute
525 Unix directory, we need to prepend initial directory
526 (con->id) to it. Absolute directories "just work".
528 A relative directory is one that does not begin with '/'
529 and, on non-Unix OS'es, one that doesn't begin with
532 This is not done for OS400, which doesn't use
533 "/"-delimited directories, nor does it support directory
534 hierarchies. "CWD foo" followed by "CWD bar" leaves us
535 in "bar", not in "foo/bar", as would be customary
539 Why is this wise even on UNIX? It certainly fouls VMS.
540 See below for a more reliable, more universal method.
544 I'm not crazy about it either. I'm informed it's useful
545 for misconfigured servers that have some dirs in the path
546 with +x but -r, but this method is not RFC-conformant. I
547 understand the need to deal with crappy server
548 configurations, but it's far better to use the canonical
549 method first, and fall back to kludges second.
553 && !(con->rs != ST_UNIX
554 && c_isalpha (target[0])
556 && (con->rs != ST_OS400)
557 && (con->rs != ST_VMS))
559 int idlen = strlen (con->id);
562 /* Strip trailing slash(es) from con->id. */
563 while (idlen > 0 && con->id[idlen - 1] == '/')
565 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
566 memcpy (p, con->id, idlen);
571 DEBUGP (("Prepended initial PWD to relative path:\n"));
572 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
573 con->id, target, ntarget));
579 Don't help me out. Please.
580 A reasonably recent VMS FTP server will cope just fine with
581 UNIX file specifications. This code just spoils things.
582 Discarding the device name, for example, is not a wise
584 This code was disabled but left in as an example of what
588 /* If the FTP host runs VMS, we will have to convert the absolute
589 directory path in UNIX notation to absolute directory path in
590 VMS notation as VMS FTP servers do not like UNIX notation of
591 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
593 if (con->rs == ST_VMS)
596 char *ntarget = (char *)alloca (strlen (target) + 2);
597 /* We use a converted initial dir, so directories in
598 TARGET will be separated with slashes, something like
599 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
600 "[INITIAL.FOLDER.DIR.SUBDIR]". */
601 strcpy (ntarget, target);
602 assert (*ntarget == '/');
604 for (tmpp = ntarget + 1; *tmpp; tmpp++)
609 DEBUGP (("Changed file name to VMS syntax:\n"));
610 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
616 A relative directory is relative to the initial directory.
617 Thus, what _is_ useful on VMS (and probably elsewhere) is
618 to CWD to the initial directory (ideally, whatever the
619 server reports, _exactly_, NOT badly UNIX-ixed), and then
620 CWD to the (new) relative directory. This should probably
621 be restructured as a function, called once or twice, but
622 I'm lazy enough to take the badly indented loop short-cut
626 /* Decide on one pass (absolute) or two (relative).
627 The VMS restriction may be relaxed when the squirrely code
630 if ((con->rs == ST_VMS) && (target[0] != '/'))
633 DEBUGP (("Using two-step CWD for relative path.\n"));
637 /* Go straight to the target. */
641 /* At least one VMS FTP server (TCPware V5.6-2) can switch to
642 a UNIX emulation mode when given a UNIX-like directory
643 specification (like "a/b/c"). If allowed to continue this
644 way, LIST interpretation will be confused, because the
645 system type (SYST response) will not be re-checked, and
646 future UNIX-format directory listings (for multiple URLs or
647 "-r") will be horribly misinterpreted.
649 The cheap and nasty work-around is to do a "CWD []" after a
650 UNIX-like directory specification is used. (A single-level
651 directory is harmless.) This puts the TCPware server back
652 into VMS mode, and does no harm on other servers.
654 Unlike the rest of this block, this particular behavior
655 _is_ VMS-specific, so it gets its own VMS test.
657 if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
660 DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
667 /* 2004-09-20 SMS. */
668 /* Sorry about the deviant indenting. Laziness. */
670 for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
675 /* Step one (optional): Go to the initial directory,
676 exactly as reported by the server.
682 /* Step two: Go to the target directory. (Absolute or
683 relative will work now.)
689 /* Step three (optional): "CWD []" to restore server
700 if (!opt.server_response)
701 logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
702 quotearg_style (escape_quoting_style, target));
703 err = ftp_cwd (csock, targ);
704 /* FTPRERR, WRITEFAILED, FTPNSFOD */
708 logputs (LOG_VERBOSE, "\n");
709 logputs (LOG_NOTQUIET, _("\
710 Error in server response, closing control connection.\n"));
715 logputs (LOG_VERBOSE, "\n");
716 logputs (LOG_NOTQUIET,
717 _("Write failed, closing control connection.\n"));
722 logputs (LOG_VERBOSE, "\n");
723 logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
733 if (!opt.server_response)
734 logputs (LOG_VERBOSE, _("done.\n"));
738 /* 2004-09-20 SMS. */
739 /* End of deviant indenting. */
743 else /* do not CWD */
744 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
746 if ((cmd & DO_RETR) && passed_expected_bytes == 0)
750 if (!opt.server_response)
751 logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
752 quotearg_style (escape_quoting_style, u->file));
755 err = ftp_size (csock, u->file, &expected_bytes);
761 logputs (LOG_VERBOSE, "\n");
762 logputs (LOG_NOTQUIET, _("\
763 Error in server response, closing control connection.\n"));
768 got_expected_bytes = true;
769 /* Everything is OK. */
774 if (!opt.server_response)
775 logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
776 number_to_static_string (expected_bytes));
779 if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
781 /* Server confirms that file has length restval. We should stop now.
782 Some servers (f.e. NcFTPd) return error when receive REST 0 */
783 logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
789 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
790 if (cmd & (DO_LIST | DO_RETR))
794 ip_address passive_addr;
796 err = ftp_do_pasv (csock, &passive_addr, &passive_port);
797 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
801 logputs (LOG_VERBOSE, "\n");
802 logputs (LOG_NOTQUIET, _("\
803 Error in server response, closing control connection.\n"));
808 logputs (LOG_VERBOSE, "\n");
809 logputs (LOG_NOTQUIET,
810 _("Write failed, closing control connection.\n"));
815 logputs (LOG_VERBOSE, "\n");
816 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
819 logputs (LOG_VERBOSE, "\n");
820 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
829 DEBUGP (("trying to connect to %s port %d\n",
830 print_address (&passive_addr), passive_port));
831 dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
834 int save_errno = errno;
837 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
838 print_address (&passive_addr), passive_port,
839 strerror (save_errno));
840 return (retryable_socket_connect_error (save_errno)
841 ? CONERROR : CONIMPOSSIBLE);
844 pasv_mode_open = true; /* Flag to avoid accept port */
845 if (!opt.server_response)
846 logputs (LOG_VERBOSE, _("done. "));
850 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
852 err = ftp_do_port (csock, &local_sock);
853 /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
858 logputs (LOG_VERBOSE, "\n");
859 logputs (LOG_NOTQUIET, _("\
860 Error in server response, closing control connection.\n"));
864 fd_close (local_sock);
867 logputs (LOG_VERBOSE, "\n");
868 logputs (LOG_NOTQUIET,
869 _("Write failed, closing control connection.\n"));
873 fd_close (local_sock);
876 logputs (LOG_VERBOSE, "\n");
877 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
881 fd_close (local_sock);
884 logputs (LOG_VERBOSE, "\n");
885 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
890 logputs (LOG_VERBOSE, "\n");
891 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
895 fd_close (local_sock);
902 if (!opt.server_response)
903 logputs (LOG_VERBOSE, _("done. "));
905 } /* cmd & (DO_LIST | DO_RETR) */
907 /* Restart if needed. */
908 if (restval && (cmd & DO_RETR))
910 if (!opt.server_response)
911 logprintf (LOG_VERBOSE, "==> REST %s ... ",
912 number_to_static_string (restval));
913 err = ftp_rest (csock, restval);
915 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
919 logputs (LOG_VERBOSE, "\n");
920 logputs (LOG_NOTQUIET, _("\
921 Error in server response, closing control connection.\n"));
925 fd_close (local_sock);
928 logputs (LOG_VERBOSE, "\n");
929 logputs (LOG_NOTQUIET,
930 _("Write failed, closing control connection.\n"));
934 fd_close (local_sock);
937 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
945 if (err != FTPRESTFAIL && !opt.server_response)
946 logputs (LOG_VERBOSE, _("done. "));
947 } /* restval && cmd & DO_RETR */
951 /* If we're in spider mode, don't really retrieve anything except
952 the directory listing and verify whether the given "file" exists. */
958 res = ftp_get_listing (u, con, &f);
959 /* Set the DO_RETR command flag again, because it gets unset when
960 calling ftp_get_listing() and would otherwise cause an assertion
961 failure earlier on when this function gets repeatedly called
962 (e.g., when recursing). */
968 if (!strcmp (f->name, u->file))
977 logputs (LOG_VERBOSE, "\n");
978 logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
983 logputs (LOG_VERBOSE, "\n");
984 logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
991 fd_close (local_sock);
997 if (!opt.server_response)
1000 logputs (LOG_VERBOSE, "\n");
1001 logprintf (LOG_VERBOSE, "==> RETR %s ... ",
1002 quotearg_style (escape_quoting_style, u->file));
1006 err = ftp_retr (csock, u->file);
1007 /* FTPRERR, WRITEFAILED, FTPNSFOD */
1011 logputs (LOG_VERBOSE, "\n");
1012 logputs (LOG_NOTQUIET, _("\
1013 Error in server response, closing control connection.\n"));
1017 fd_close (local_sock);
1020 logputs (LOG_VERBOSE, "\n");
1021 logputs (LOG_NOTQUIET,
1022 _("Write failed, closing control connection.\n"));
1026 fd_close (local_sock);
1029 logputs (LOG_VERBOSE, "\n");
1030 logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1033 fd_close (local_sock);
1041 if (!opt.server_response)
1042 logputs (LOG_VERBOSE, _("done.\n"));
1044 if (! got_expected_bytes)
1045 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1050 if (!opt.server_response)
1051 logputs (LOG_VERBOSE, "==> LIST ... ");
1052 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1053 without arguments is better than `LIST .'; confirmed by
1055 err = ftp_list (csock, NULL, con->rs);
1056 /* FTPRERR, WRITEFAILED */
1060 logputs (LOG_VERBOSE, "\n");
1061 logputs (LOG_NOTQUIET, _("\
1062 Error in server response, closing control connection.\n"));
1066 fd_close (local_sock);
1069 logputs (LOG_VERBOSE, "\n");
1070 logputs (LOG_NOTQUIET,
1071 _("Write failed, closing control connection.\n"));
1075 fd_close (local_sock);
1078 logputs (LOG_VERBOSE, "\n");
1079 logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1082 fd_close (local_sock);
1089 if (!opt.server_response)
1090 logputs (LOG_VERBOSE, _("done.\n"));
1092 if (! got_expected_bytes)
1093 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1094 } /* cmd & DO_LIST */
1096 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1097 return RETRFINISHED;
1099 /* Some FTP servers return the total length of file after REST
1100 command, others just return the remaining size. */
1101 if (passed_expected_bytes && restval && expected_bytes
1102 && (expected_bytes == passed_expected_bytes - restval))
1104 DEBUGP (("Lying FTP server found, adjusting.\n"));
1105 expected_bytes = passed_expected_bytes;
1108 /* If no transmission was required, then everything is OK. */
1109 if (!pasv_mode_open) /* we are not using pasive mode so we need
1112 /* Wait for the server to connect to the address we're waiting
1114 dtsock = accept_connection (local_sock);
1117 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1122 /* Open the file -- if output_stream is set, use it instead. */
1125 Note that having the output_stream ("-O") file opened in main()
1126 (main.c) rather limits the ability in VMS to open the file
1127 differently for ASCII versus binary FTP here. (Of course, doing it
1128 there allows a open failure to be detected immediately, without first
1129 connecting to the server.)
1131 if (!output_stream || con->cmd & DO_LIST)
1133 /* On VMS, alter the name as required. */
1137 targ = ods_conform (con->target);
1138 if (targ != con->target)
1140 xfree (con->target);
1143 #endif /* def __VMS */
1145 mkalldirs (con->target);
1147 rotate_backups (con->target);
1150 For VMS, define common fopen() optional arguments, and a handy macro
1151 for use as a variable "binary" flag.
1152 Elsewhere, define a constant "binary" flag.
1153 Isn't it nice to have distinct text and binary file types?
1156 Added listing files to the set of non-"binary" (text, Stream_LF)
1157 files. (Wget works either way, but other programs, like, say, text
1158 editors, work better on listing files which have text attributes.)
1159 Now we use "binary" attributes for a binary ("IMAGE") transfer,
1160 unless "--ftp-stmlf" was specified, and we always use non-"binary"
1161 (text, Stream_LF) attributes for a listing file, or for an ASCII
1163 Tidied the VMS-specific BIN_TYPE_xxx macros, and changed the call to
1164 fopen_excl() (restored?) to use BIN_TYPE_FILE instead of "true".
1167 # define BIN_TYPE_TRANSFER (type_char != 'A')
1168 # define BIN_TYPE_FILE \
1169 ((!(cmd & DO_LIST)) && BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1170 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1171 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1172 #else /* def __VMS */
1173 # define BIN_TYPE_FILE true
1174 #endif /* def __VMS [else] */
1176 if (restval && !(con->cmd & DO_LIST))
1184 fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1189 fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1191 #else /* def __VMS */
1192 fp = fopen (con->target, "ab");
1193 #endif /* def __VMS [else] */
1195 else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1196 || opt.output_document || count > 0)
1198 if (opt.unlink && file_exists_p (con->target))
1200 int res = unlink (con->target);
1203 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1208 fd_close (local_sock);
1219 fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1224 fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1226 #else /* def __VMS */
1227 fp = fopen (con->target, "wb");
1228 #endif /* def __VMS [else] */
1232 fp = fopen_excl (con->target, BIN_TYPE_FILE);
1233 if (!fp && errno == EEXIST)
1235 /* We cannot just invent a new name and use it (which is
1236 what functions like unique_create typically do)
1237 because we told the user we'd use this name.
1238 Instead, return and retry the download. */
1239 logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1244 fd_close (local_sock);
1245 return FOPEN_EXCL_ERR;
1250 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1254 fd_close (local_sock);
1261 if (passed_expected_bytes)
1263 print_length (passed_expected_bytes, restval, true);
1264 expected_bytes = passed_expected_bytes;
1265 /* for fd_read_body's progress bar */
1267 else if (expected_bytes)
1268 print_length (expected_bytes, restval, false);
1270 /* Get the contents of the document. */
1272 if (restval && rest_failed)
1273 flags |= rb_skip_startpos;
1275 res = fd_read_body (dtsock, fp,
1276 expected_bytes ? expected_bytes - restval : 0,
1277 restval, &rd_size, qtyread, &con->dltime, flags);
1279 tms = datetime_str (time (NULL));
1280 tmrate = retr_rate (rd_size, con->dltime);
1281 total_download_time += con->dltime;
1283 fd_close (local_sock);
1284 /* Close the local file. */
1285 if (!output_stream || con->cmd & DO_LIST)
1288 /* If fd_read_body couldn't write to fp, bail out. */
1291 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1292 con->target, strerror (errno));
1300 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1301 tms, tmrate, fd_errstr (dtsock));
1302 if (opt.server_response)
1303 logputs (LOG_ALWAYS, "\n");
1307 /* Get the server to tell us if everything is retrieved. */
1308 err = ftp_response (csock, &respline);
1311 /* The control connection is decidedly closed. Print the time
1312 only if it hasn't already been printed. */
1314 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1315 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1316 /* If there is an error on the control connection, close it, but
1317 return FTPRETRINT, since there is a possibility that the
1318 whole file was retrieved nevertheless (but that is for
1319 ftp_loop_internal to decide). */
1323 } /* err != FTPOK */
1324 /* If retrieval failed for any reason, return FTPRETRINT, but do not
1325 close socket, since the control connection is still alive. If
1326 there is something wrong with the control connection, it will
1327 become apparent later. */
1328 if (*respline != '2')
1332 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1333 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1340 /* What now? The data connection was erroneous, whereas the
1341 response says everything is OK. We shall play it safe. */
1345 if (!(cmd & LEAVE_PENDING))
1347 /* Closing the socket is faster than sending 'QUIT' and the
1348 effect is the same. */
1352 /* If it was a listing, and opt.server_response is true,
1354 if (opt.server_response && (con->cmd & DO_LIST))
1357 Much of this work may already have been done, but repeating it should
1358 do no damage beyond wasting time.
1360 /* On VMS, alter the name as required. */
1364 targ = ods_conform( con->target);
1365 if (targ != con->target)
1367 xfree( con->target);
1370 #endif /* def __VMS */
1372 mkalldirs (con->target);
1373 fp = fopen (con->target, "r");
1375 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1379 /* The lines are being read with read_whole_line because of
1380 no-buffering on opt.lfile. */
1381 while ((line = read_whole_line (fp)) != NULL)
1383 char *p = strchr (line, '\0');
1384 while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1386 logprintf (LOG_ALWAYS, "%s\n",
1387 quotearg_style (escape_quoting_style, line));
1392 } /* con->cmd & DO_LIST && server_response */
1394 return RETRFINISHED;
1397 /* A one-file FTP loop. This is the part where FTP retrieval is
1398 retried, and retried, and retried, and...
1400 This loop either gets commands from con, or (if ON_YOUR_OWN is
1401 set), makes them up to retrieve the file given by the URL. */
1403 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1406 wgint restval, len = 0, qtyread = 0;
1408 const char *tmrate = NULL;
1412 /* Get the target, and set the name for the message accordingly. */
1413 if ((f == NULL) && (con->target))
1415 /* Explicit file (like ".listing"). */
1420 /* URL-derived file. Consider "-O file" name. */
1421 con->target = url_file_name (u, NULL);
1422 if (!opt.output_document)
1425 locf = opt.output_document;
1428 /* If the output_document was given, then this check was already done and
1429 the file didn't exist. Hence the !opt.output_document */
1430 if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1432 logprintf (LOG_VERBOSE,
1433 _("File %s already there; not retrieving.\n"), quote (con->target));
1434 /* If the file is there, we suppose it's retrieved OK. */
1438 /* Remove it if it's a link. */
1439 remove_link (con->target);
1443 if (con->st & ON_YOUR_OWN)
1444 con->st = ON_YOUR_OWN;
1446 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1451 /* Increment the pass counter. */
1453 sleep_between_retrievals (count);
1454 if (con->st & ON_YOUR_OWN)
1457 con->cmd |= (DO_RETR | LEAVE_PENDING);
1458 if (con->csock != -1)
1459 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1461 con->cmd |= (DO_LOGIN | DO_CWD);
1463 else /* not on your own */
1465 if (con->csock != -1)
1466 con->cmd &= ~DO_LOGIN;
1468 con->cmd |= DO_LOGIN;
1469 if (con->st & DONE_CWD)
1470 con->cmd &= ~DO_CWD;
1475 /* Decide whether or not to restart. */
1476 if (con->cmd & DO_LIST)
1478 else if (opt.always_rest
1479 && stat (locf, &st) == 0
1480 && S_ISREG (st.st_mode))
1481 /* When -c is used, continue from on-disk size. (Can't use
1482 hstat.len even if count>1 because we don't want a failed
1483 first attempt to clobber existing data.) */
1484 restval = st.st_size;
1486 restval = qtyread; /* start where the previous run left off */
1490 /* Get the current time string. */
1491 tms = datetime_str (time (NULL));
1492 /* Print fetch message, if opt.verbose. */
1495 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1499 sprintf (tmp, _("(try:%2d)"), count);
1500 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => %s\n",
1501 tms, hurl, tmp, quote (locf));
1503 ws_changetitle (hurl);
1507 /* Send getftp the proper length, if fileinfo was provided. */
1508 if (f && f->type != FT_SYMLINK)
1512 err = getftp (u, len, &qtyread, restval, con, count);
1514 if (con->csock == -1)
1515 con->st &= ~DONE_CWD;
1517 con->st |= DONE_CWD;
1521 case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1522 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1524 /* Fatal errors, give up. */
1526 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1527 case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1528 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1529 case FOPEN_EXCL_ERR:
1530 printwhat (count, opt.ntry);
1531 /* non-fatal errors */
1532 if (err == FOPEN_EXCL_ERR)
1534 /* Re-determine the file name. */
1535 xfree_null (con->target);
1536 con->target = url_file_name (u, NULL);
1541 /* If the control connection was closed, the retrieval
1542 will be considered OK if f->size == len. */
1543 if (!f || qtyread != f->size)
1545 printwhat (count, opt.ntry);
1556 tms = datetime_str (time (NULL));
1558 tmrate = retr_rate (qtyread - restval, con->dltime);
1560 /* If we get out of the switch above without continue'ing, we've
1561 successfully downloaded a file. Remember this fact. */
1562 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1564 if (con->st & ON_YOUR_OWN)
1566 fd_close (con->csock);
1571 bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1573 logprintf (LOG_VERBOSE,
1575 ? _("%s (%s) - written to stdout %s[%s]\n\n")
1576 : _("%s (%s) - %s saved [%s]\n\n"),
1578 write_to_stdout ? "" : quote (locf),
1579 number_to_static_string (qtyread));
1581 if (!opt.verbose && !opt.quiet)
1583 /* Need to hide the password from the URL. The `if' is here
1584 so that we don't do the needless allocation every
1586 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1587 logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1588 tms, hurl, number_to_static_string (qtyread), locf, count);
1592 if ((con->cmd & DO_LIST))
1593 /* This is a directory listing file. */
1595 if (!opt.remove_listing)
1596 /* --dont-remove-listing was specified, so do count this towards the
1597 number of bytes and files downloaded. */
1599 total_downloaded_bytes += qtyread;
1603 /* Deletion of listing files is not controlled by --delete-after, but
1604 by the more specific option --dont-remove-listing, and the code
1605 to do this deletion is in another function. */
1607 else if (!opt.spider)
1608 /* This is not a directory listing file. */
1610 /* Unlike directory listing files, don't pretend normal files weren't
1611 downloaded if they're going to be deleted. People seeding proxies,
1612 for instance, may want to know how many bytes and files they've
1613 downloaded through it. */
1614 total_downloaded_bytes += qtyread;
1617 if (opt.delete_after && !input_file_url (opt.input_filename))
1620 Removing file due to --delete-after in ftp_loop_internal():\n"));
1621 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1623 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1627 /* Restore the original leave-pendingness. */
1629 con->cmd |= LEAVE_PENDING;
1631 con->cmd &= ~LEAVE_PENDING;
1634 *local_file = xstrdup (locf);
1637 } while (!opt.ntry || (count < opt.ntry));
1639 if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1641 fd_close (con->csock);
1647 /* Return the directory listing in a reusable format. The directory
1648 is specifed in u->dir. */
1650 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1653 char *uf; /* url file name */
1654 char *lf; /* list file name */
1655 char *old_target = con->target;
1657 con->st &= ~ON_YOUR_OWN;
1658 con->cmd |= (DO_LIST | LEAVE_PENDING);
1659 con->cmd &= ~DO_RETR;
1661 /* Find the listing file name. We do it by taking the file name of
1662 the URL and replacing the last component with the listing file
1664 uf = url_file_name (u, NULL);
1665 lf = file_merge (uf, LIST_FILENAME);
1667 DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1669 con->target = xstrdup (lf);
1671 err = ftp_loop_internal (u, NULL, con, NULL);
1672 lf = xstrdup (con->target);
1673 xfree (con->target);
1674 con->target = old_target;
1678 *f = ftp_parse_ls (lf, con->rs);
1679 if (opt.remove_listing)
1682 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1684 logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1690 con->cmd &= ~DO_LIST;
1694 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1695 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1696 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1697 static void freefileinfo (struct fileinfo *f);
1699 /* Retrieve a list of files given in struct fileinfo linked list. If
1700 a file is a symbolic link, do not retrieve it, but rather try to
1701 set up a similar link on the local disk, if the symlinks are
1704 If opt.recursive is set, after all files have been retrieved,
1705 ftp_retrieve_dirs will be called to retrieve the directories. */
1707 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1709 static int depth = 0;
1711 struct fileinfo *orig;
1714 bool dlthis; /* Download this (file). */
1715 const char *actual_target = NULL;
1717 /* Increase the depth. */
1719 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1721 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1722 depth, opt.reclevel));
1730 con->st &= ~ON_YOUR_OWN;
1731 if (!(con->st & DONE_CWD))
1734 con->cmd &= ~DO_CWD;
1735 con->cmd |= (DO_RETR | LEAVE_PENDING);
1738 con->cmd |= DO_LOGIN;
1740 con->cmd &= ~DO_LOGIN;
1742 err = RETROK; /* in case it's not used */
1746 char *old_target, *ofile;
1748 if (opt.quota && total_downloaded_bytes > opt.quota)
1753 old_target = con->target;
1755 ofile = xstrdup (u->file);
1756 url_set_file (u, f->name);
1758 con->target = url_file_name (u, NULL);
1762 if (opt.timestamping && f->type == FT_PLAINFILE)
1765 /* If conversion of HTML files retrieved via FTP is ever implemented,
1766 we'll need to stat() <file>.orig here when -K has been specified.
1767 I'm not implementing it now since files on an FTP server are much
1768 more likely than files on an HTTP server to legitimately have a
1770 if (!stat (con->target, &st))
1774 /* Else, get it from the file. */
1775 local_size = st.st_size;
1778 /* Modification time granularity is 2 seconds for Windows, so
1779 increase local time by 1 second for later comparison. */
1782 /* Compare file sizes only for servers that tell us correct
1783 values. Assume sizes being equal for servers that lie
1785 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1786 eq_size = cor_val ? (local_size == f->size) : true;
1787 if (f->tstamp <= tml && eq_size)
1789 /* Remote file is older, file sizes can be compared and
1791 logprintf (LOG_VERBOSE, _("\
1792 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1797 /* Remote file is newer or sizes cannot be matched */
1798 logprintf (LOG_VERBOSE, _("\
1799 Remote file is newer than local file %s -- retrieving.\n\n"),
1800 quote (con->target));
1804 /* Sizes do not match */
1805 logprintf (LOG_VERBOSE, _("\
1806 The sizes do not match (local %s) -- retrieving.\n\n"),
1807 number_to_static_string (local_size));
1810 } /* opt.timestamping && f->type == FT_PLAINFILE */
1814 /* If opt.retr_symlinks is defined, we treat symlinks as
1815 if they were normal files. There is currently no way
1816 to distinguish whether they might be directories, and
1818 if (!opt.retr_symlinks)
1822 logputs (LOG_NOTQUIET,
1823 _("Invalid name of the symlink, skipping.\n"));
1827 /* Check whether we already have the correct
1829 int rc = lstat (con->target, &st);
1832 size_t len = strlen (f->linkto) + 1;
1833 if (S_ISLNK (st.st_mode))
1835 char *link_target = (char *)alloca (len);
1836 size_t n = readlink (con->target, link_target, len);
1838 && (memcmp (link_target, f->linkto, n) == 0))
1840 logprintf (LOG_VERBOSE, _("\
1841 Already have correct symlink %s -> %s\n\n"),
1842 quote (con->target),
1849 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1850 quote (con->target), quote (f->linkto));
1851 /* Unlink before creating symlink! */
1852 unlink (con->target);
1853 if (symlink (f->linkto, con->target) == -1)
1854 logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1855 logputs (LOG_VERBOSE, "\n");
1856 } /* have f->linkto */
1857 #else /* not HAVE_SYMLINK */
1858 logprintf (LOG_NOTQUIET,
1859 _("Symlinks not supported, skipping symlink %s.\n"),
1860 quote (con->target));
1861 #endif /* not HAVE_SYMLINK */
1863 else /* opt.retr_symlinks */
1866 err = ftp_loop_internal (u, f, con, NULL);
1867 } /* opt.retr_symlinks */
1871 logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1875 /* Call the retrieve loop. */
1877 err = ftp_loop_internal (u, f, con, NULL);
1880 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1887 * Set permissions _before_ setting the times, as setting the
1888 * permissions changes the modified-time, at least on VMS.
1889 * Also, use the opt.output_document name here, too, as
1890 * appropriate. (Do the test once, and save the result.)
1893 set_local_file (&actual_target, con->target);
1895 /* If downloading a plain file, and the user requested it, then
1896 set valid (non-zero) permissions. */
1897 if (dlthis && (actual_target != NULL) &&
1898 (f->type == FT_PLAINFILE) && opt.preserve_perm)
1901 chmod (actual_target, f->perms);
1903 DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1906 /* Set the time-stamp information to the local file. Symlinks
1907 are not to be stamped because it sets the stamp on the
1909 if (actual_target != NULL)
1911 if (opt.useservertimestamps
1912 && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1915 && file_exists_p (con->target))
1917 touch (actual_target, f->tstamp);
1919 else if (f->tstamp == -1)
1920 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1924 xfree (con->target);
1925 con->target = old_target;
1927 url_set_file (u, ofile);
1930 /* Break on fatals. */
1931 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1933 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1937 /* We do not want to call ftp_retrieve_dirs here */
1938 if (opt.recursive &&
1939 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1940 err = ftp_retrieve_dirs (u, orig, con);
1941 else if (opt.recursive)
1942 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1943 depth, opt.reclevel));
1948 /* Retrieve the directories given in a file list. This function works
1949 by simply going through the linked list and calling
1950 ftp_retrieve_glob on each directory entry. The function knows
1951 about excluded directories. */
1953 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1955 char *container = NULL;
1956 int container_size = 0;
1958 for (; f; f = f->next)
1961 char *odir, *newdir;
1963 if (opt.quota && total_downloaded_bytes > opt.quota)
1965 if (f->type != FT_DIRECTORY)
1968 /* Allocate u->dir off stack, but reallocate only if a larger
1969 string is needed. It's a pity there's no "realloca" for an
1970 item on the bottom of the stack. */
1971 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1972 if (size > container_size)
1973 container = (char *)alloca (size);
1978 || (*odir == '/' && *(odir + 1) == '\0'))
1979 /* If ODIR is empty or just "/", simply append f->name to
1980 ODIR. (In the former case, to preserve u->dir being
1981 relative; in the latter case, to avoid double slash.) */
1982 sprintf (newdir, "%s%s", odir, f->name);
1984 /* Else, use a separator. */
1985 sprintf (newdir, "%s/%s", odir, f->name);
1987 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1988 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1989 odir, f->name, newdir));
1990 if (!accdir (newdir))
1992 logprintf (LOG_VERBOSE, _("\
1993 Not descending to %s as it is excluded/not-included.\n"),
1998 con->st &= ~DONE_CWD;
2000 odir = xstrdup (u->dir); /* because url_set_dir will free
2002 url_set_dir (u, newdir);
2003 ftp_retrieve_glob (u, con, GLOB_GETALL);
2004 url_set_dir (u, odir);
2007 /* Set the time-stamp? */
2010 if (opt.quota && total_downloaded_bytes > opt.quota)
2016 /* Return true if S has a leading '/' or contains '../' */
2018 has_insecure_name_p (const char *s)
2023 if (strstr (s, "../") != 0)
2029 /* A near-top-level function to retrieve the files in a directory.
2030 The function calls ftp_get_listing, to get a linked list of files.
2031 Then it weeds out the file names that do not match the pattern.
2032 ftp_retrieve_list is called with this updated list as an argument.
2034 If the argument ACTION is GLOB_GETONE, just download the file (but
2035 first get the listing, so that the time-stamp is heeded); if it's
2036 GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
2039 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2041 struct fileinfo *f, *start;
2044 con->cmd |= LEAVE_PENDING;
2046 res = ftp_get_listing (u, con, &start);
2049 /* First: weed out that do not conform the global rules given in
2050 opt.accepts and opt.rejects. */
2051 if (opt.accepts || opt.rejects)
2056 if (f->type != FT_DIRECTORY && !acceptable (f->name))
2058 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2060 f = delelement (f, &start);
2066 /* Remove all files with possible harmful names */
2070 if (has_insecure_name_p (f->name))
2072 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2074 f = delelement (f, &start);
2079 /* Now weed out the files that do not match our globbing pattern.
2080 If we are dealing with a globbing pattern, that is. */
2083 if (action == GLOB_GLOBALL)
2085 int (*matcher) (const char *, const char *, int)
2086 = opt.ignore_case ? fnmatch_nocase : fnmatch;
2092 matchres = matcher (u->file, f->name, 0);
2095 logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2096 u->file, quotearg_style (escape_quoting_style, f->name),
2100 if (matchres == FNM_NOMATCH)
2101 f = delelement (f, &start); /* delete the element from the list */
2103 f = f->next; /* leave the element in the list */
2107 freefileinfo (start);
2108 return RETRBADPATTERN;
2111 else if (action == GLOB_GETONE)
2115 * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2116 * bug causes spurious %CC-E-BADCONDIT complaint with this
2117 * "?:" statement. (Different linkage attributes for strcmp()
2118 * and strcasecmp().) Converting to "if" changes the
2119 * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
2120 * the senseless type cast clears the complaint, and looks
2123 int (*cmp) (const char *, const char *)
2124 = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2125 #else /* def __VMS */
2126 int (*cmp) (const char *, const char *)
2127 = opt.ignore_case ? strcasecmp : strcmp;
2128 #endif /* def __VMS [else] */
2132 if (0 != cmp(u->file, f->name))
2133 f = delelement (f, &start);
2141 /* Just get everything. */
2142 res = ftp_retrieve_list (u, start, con);
2146 if (action == GLOB_GLOBALL)
2149 /* #### This message SUCKS. We should see what was the
2150 reason that nothing was retrieved. */
2151 logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2154 else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2156 /* Let's try retrieving it anyway. */
2157 con->st |= ON_YOUR_OWN;
2158 res = ftp_loop_internal (u, NULL, con, NULL);
2162 /* If action == GLOB_GETALL, and the file list is empty, there's
2163 no point in trying to download anything or in complaining about
2164 it. (An empty directory should not cause complaints.)
2167 freefileinfo (start);
2168 if (opt.quota && total_downloaded_bytes > opt.quota)
2174 /* The wrapper that calls an appropriate routine according to contents
2175 of URL. Inherently, its capabilities are limited on what can be
2176 encoded into a URL. */
2178 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2179 bool recursive, bool glob)
2181 ccon con; /* FTP connection */
2189 con.st = ON_YOUR_OWN;
2194 /* If the file name is empty, the user probably wants a directory
2195 index. We'll provide one, properly HTML-ized. Unless
2196 opt.htmlify is 0, of course. :-) */
2197 if (!*u->file && !recursive)
2200 res = ftp_get_listing (u, &con, &f);
2204 if (opt.htmlify && !opt.spider)
2206 char *filename = (opt.output_document
2207 ? xstrdup (opt.output_document)
2208 : (con.target ? xstrdup (con.target)
2209 : url_file_name (u, NULL)));
2210 res = ftp_index (filename, u, f);
2211 if (res == FTPOK && opt.verbose)
2213 if (!opt.output_document)
2217 if (stat (filename, &st) == 0)
2221 logprintf (LOG_NOTQUIET,
2222 _("Wrote HTML-ized index to %s [%s].\n"),
2223 quote (filename), number_to_static_string (sz));
2226 logprintf (LOG_NOTQUIET,
2227 _("Wrote HTML-ized index to %s.\n"),
2237 bool ispattern = false;
2240 /* Treat the URL as a pattern if the file name part of the
2241 URL path contains wildcards. (Don't check for u->file
2242 because it is unescaped and therefore doesn't leave users
2243 the option to escape literal '*' as %2A.) */
2244 char *file_part = strrchr (u->path, '/');
2246 file_part = u->path;
2247 ispattern = has_wildcards_p (file_part);
2249 if (ispattern || recursive || opt.timestamping)
2251 /* ftp_retrieve_glob is a catch-all function that gets called
2252 if we need globbing, time-stamping or recursion. Its
2253 third argument is just what we really need. */
2254 res = ftp_retrieve_glob (u, &con,
2255 ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2258 res = ftp_loop_internal (u, NULL, &con, local_file);
2264 /* If a connection was left, quench it. */
2265 if (con.csock != -1)
2266 fd_close (con.csock);
2267 xfree_null (con.id);
2269 xfree_null (con.target);
2274 /* Delete an element from the fileinfo linked list. Returns the
2275 address of the next element, or NULL if the list is exhausted. It
2276 can modify the start of the list. */
2277 static struct fileinfo *
2278 delelement (struct fileinfo *f, struct fileinfo **start)
2280 struct fileinfo *prev = f->prev;
2281 struct fileinfo *next = f->next;
2284 xfree_null (f->linkto);
2296 /* Free the fileinfo linked list of files. */
2298 freefileinfo (struct fileinfo *f)
2302 struct fileinfo *next = f->next;