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);
306 return (retryable_socket_connect_error (errno)
307 ? CONERROR : CONIMPOSSIBLE);
309 if (cmd & LEAVE_PENDING)
314 /* Second: Login with proper USER/PASS sequence. */
315 logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
316 quotearg_style (escape_quoting_style, user));
317 if (opt.server_response)
318 logputs (LOG_ALWAYS, "\n");
319 err = ftp_login (csock, logname, passwd);
324 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
328 logputs (LOG_VERBOSE, "\n");
329 logputs (LOG_NOTQUIET, _("\
330 Error in server response, closing control connection.\n"));
335 logputs (LOG_VERBOSE, "\n");
336 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
341 logputs (LOG_VERBOSE, "\n");
342 logputs (LOG_NOTQUIET,
343 _("Write failed, closing control connection.\n"));
348 logputs (LOG_VERBOSE, "\n");
349 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
352 return FTPLOGREFUSED;
354 logputs (LOG_VERBOSE, "\n");
355 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
360 if (!opt.server_response)
361 logputs (LOG_VERBOSE, _("Logged in!\n"));
366 /* Third: Get the system type */
367 if (!opt.server_response)
368 logprintf (LOG_VERBOSE, "==> SYST ... ");
369 err = ftp_syst (csock, &con->rs);
374 logputs (LOG_VERBOSE, "\n");
375 logputs (LOG_NOTQUIET, _("\
376 Error in server response, closing control connection.\n"));
381 logputs (LOG_VERBOSE, "\n");
382 logputs (LOG_NOTQUIET,
383 _("Server error, can't determine system type.\n"));
386 /* Everything is OK. */
391 if (!opt.server_response && err != FTPSRVERR)
392 logputs (LOG_VERBOSE, _("done. "));
394 /* Fourth: Find the initial ftp directory */
396 if (!opt.server_response)
397 logprintf (LOG_VERBOSE, "==> PWD ... ");
398 err = ftp_pwd (csock, &con->id);
403 logputs (LOG_VERBOSE, "\n");
404 logputs (LOG_NOTQUIET, _("\
405 Error in server response, closing control connection.\n"));
410 /* PWD unsupported -- assume "/". */
411 xfree_null (con->id);
412 con->id = xstrdup ("/");
415 /* Everything is OK. */
423 Don't help me out. Please.
424 A reasonably recent VMS FTP server will cope just fine with
425 UNIX file specifications. This code just spoils things.
426 Discarding the device name, for example, is not a wise move.
427 This code was disabled but left in as an example of what not
431 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
432 Convert it to "/INITIAL/FOLDER" */
433 if (con->rs == ST_VMS)
435 char *path = strchr (con->id, '[');
436 char *pathend = path ? strchr (path + 1, ']') : NULL;
437 if (!path || !pathend)
438 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
441 char *idir = con->id;
442 DEBUGP (("Preprocessing the initial VMS directory\n"));
443 DEBUGP ((" old = '%s'\n", con->id));
444 /* We do the conversion in-place by copying the stuff
445 between [ and ] to the beginning, and changing dots
446 to slashes at the same time. */
448 for (++path; path < pathend; path++, idir++)
449 *idir = *path == '.' ? '/' : *path;
451 DEBUGP ((" new = '%s'\n\n", con->id));
456 if (!opt.server_response)
457 logputs (LOG_VERBOSE, _("done.\n"));
459 /* Fifth: Set the FTP type. */
460 type_char = ftp_process_type (u->params);
461 if (!opt.server_response)
462 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
463 err = ftp_type (csock, type_char);
464 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
468 logputs (LOG_VERBOSE, "\n");
469 logputs (LOG_NOTQUIET, _("\
470 Error in server response, closing control connection.\n"));
475 logputs (LOG_VERBOSE, "\n");
476 logputs (LOG_NOTQUIET,
477 _("Write failed, closing control connection.\n"));
482 logputs (LOG_VERBOSE, "\n");
483 logprintf (LOG_NOTQUIET,
484 _("Unknown type `%c', closing control connection.\n"),
490 /* Everything is OK. */
495 if (!opt.server_response)
496 logputs (LOG_VERBOSE, _("done. "));
502 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
510 char *target = u->dir;
512 DEBUGP (("changing working directory\n"));
514 /* Change working directory. To change to a non-absolute
515 Unix directory, we need to prepend initial directory
516 (con->id) to it. Absolute directories "just work".
518 A relative directory is one that does not begin with '/'
519 and, on non-Unix OS'es, one that doesn't begin with
522 This is not done for OS400, which doesn't use
523 "/"-delimited directories, nor does it support directory
524 hierarchies. "CWD foo" followed by "CWD bar" leaves us
525 in "bar", not in "foo/bar", as would be customary
529 Why is this wise even on UNIX? It certainly fouls VMS.
530 See below for a more reliable, more universal method.
534 I'm not crazy about it either. I'm informed it's useful
535 for misconfigured servers that have some dirs in the path
536 with +x but -r, but this method is not RFC-conformant. I
537 understand the need to deal with crappy server
538 configurations, but it's far better to use the canonical
539 method first, and fall back to kludges second.
543 && !(con->rs != ST_UNIX
544 && c_isalpha (target[0])
546 && (con->rs != ST_OS400)
547 && (con->rs != ST_VMS))
549 int idlen = strlen (con->id);
552 /* Strip trailing slash(es) from con->id. */
553 while (idlen > 0 && con->id[idlen - 1] == '/')
555 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
556 memcpy (p, con->id, idlen);
561 DEBUGP (("Prepended initial PWD to relative path:\n"));
562 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
563 con->id, target, ntarget));
569 Don't help me out. Please.
570 A reasonably recent VMS FTP server will cope just fine with
571 UNIX file specifications. This code just spoils things.
572 Discarding the device name, for example, is not a wise
574 This code was disabled but left in as an example of what
578 /* If the FTP host runs VMS, we will have to convert the absolute
579 directory path in UNIX notation to absolute directory path in
580 VMS notation as VMS FTP servers do not like UNIX notation of
581 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
583 if (con->rs == ST_VMS)
586 char *ntarget = (char *)alloca (strlen (target) + 2);
587 /* We use a converted initial dir, so directories in
588 TARGET will be separated with slashes, something like
589 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
590 "[INITIAL.FOLDER.DIR.SUBDIR]". */
591 strcpy (ntarget, target);
592 assert (*ntarget == '/');
594 for (tmpp = ntarget + 1; *tmpp; tmpp++)
599 DEBUGP (("Changed file name to VMS syntax:\n"));
600 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
606 A relative directory is relative to the initial directory.
607 Thus, what _is_ useful on VMS (and probably elsewhere) is
608 to CWD to the initial directory (ideally, whatever the
609 server reports, _exactly_, NOT badly UNIX-ixed), and then
610 CWD to the (new) relative directory. This should probably
611 be restructured as a function, called once or twice, but
612 I'm lazy enough to take the badly indented loop short-cut
616 /* Decide on one pass (absolute) or two (relative).
617 The VMS restriction may be relaxed when the squirrely code
620 if ((con->rs == ST_VMS) && (target[0] != '/'))
623 DEBUGP (("Using two-step CWD for relative path.\n"));
627 /* Go straight to the target. */
631 /* At least one VMS FTP server (TCPware V5.6-2) can switch to
632 a UNIX emulation mode when given a UNIX-like directory
633 specification (like "a/b/c"). If allowed to continue this
634 way, LIST interpretation will be confused, because the
635 system type (SYST response) will not be re-checked, and
636 future UNIX-format directory listings (for multiple URLs or
637 "-r") will be horribly misinterpreted.
639 The cheap and nasty work-around is to do a "CWD []" after a
640 UNIX-like directory specification is used. (A single-level
641 directory is harmless.) This puts the TCPware server back
642 into VMS mode, and does no harm on other servers.
644 Unlike the rest of this block, this particular behavior
645 _is_ VMS-specific, so it gets its own VMS test.
647 if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
650 DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
657 /* 2004-09-20 SMS. */
658 /* Sorry about the deviant indenting. Laziness. */
660 for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
665 /* Step one (optional): Go to the initial directory,
666 exactly as reported by the server.
672 /* Step two: Go to the target directory. (Absolute or
673 relative will work now.)
679 /* Step three (optional): "CWD []" to restore server
690 if (!opt.server_response)
691 logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
692 quotearg_style (escape_quoting_style, target));
693 err = ftp_cwd (csock, targ);
694 /* FTPRERR, WRITEFAILED, FTPNSFOD */
698 logputs (LOG_VERBOSE, "\n");
699 logputs (LOG_NOTQUIET, _("\
700 Error in server response, closing control connection.\n"));
705 logputs (LOG_VERBOSE, "\n");
706 logputs (LOG_NOTQUIET,
707 _("Write failed, closing control connection.\n"));
712 logputs (LOG_VERBOSE, "\n");
713 logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
723 if (!opt.server_response)
724 logputs (LOG_VERBOSE, _("done.\n"));
728 /* 2004-09-20 SMS. */
729 /* End of deviant indenting. */
733 else /* do not CWD */
734 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
736 if ((cmd & DO_RETR) && passed_expected_bytes == 0)
740 if (!opt.server_response)
741 logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
742 quotearg_style (escape_quoting_style, u->file));
745 err = ftp_size (csock, u->file, &expected_bytes);
751 logputs (LOG_VERBOSE, "\n");
752 logputs (LOG_NOTQUIET, _("\
753 Error in server response, closing control connection.\n"));
758 got_expected_bytes = true;
759 /* Everything is OK. */
764 if (!opt.server_response)
765 logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
766 number_to_static_string (expected_bytes));
769 if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
771 /* Server confirms that file has length restval. We should stop now.
772 Some servers (f.e. NcFTPd) return error when receive REST 0 */
773 logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
779 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
780 if (cmd & (DO_LIST | DO_RETR))
784 ip_address passive_addr;
786 err = ftp_do_pasv (csock, &passive_addr, &passive_port);
787 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
791 logputs (LOG_VERBOSE, "\n");
792 logputs (LOG_NOTQUIET, _("\
793 Error in server response, closing control connection.\n"));
798 logputs (LOG_VERBOSE, "\n");
799 logputs (LOG_NOTQUIET,
800 _("Write failed, closing control connection.\n"));
805 logputs (LOG_VERBOSE, "\n");
806 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
809 logputs (LOG_VERBOSE, "\n");
810 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
819 DEBUGP (("trying to connect to %s port %d\n",
820 print_address (&passive_addr), passive_port));
821 dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
824 int save_errno = errno;
827 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
828 print_address (&passive_addr), passive_port,
829 strerror (save_errno));
830 return (retryable_socket_connect_error (save_errno)
831 ? CONERROR : CONIMPOSSIBLE);
834 pasv_mode_open = true; /* Flag to avoid accept port */
835 if (!opt.server_response)
836 logputs (LOG_VERBOSE, _("done. "));
840 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
842 err = ftp_do_port (csock, &local_sock);
843 /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
848 logputs (LOG_VERBOSE, "\n");
849 logputs (LOG_NOTQUIET, _("\
850 Error in server response, closing control connection.\n"));
854 fd_close (local_sock);
857 logputs (LOG_VERBOSE, "\n");
858 logputs (LOG_NOTQUIET,
859 _("Write failed, closing control connection.\n"));
863 fd_close (local_sock);
866 logputs (LOG_VERBOSE, "\n");
867 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
871 fd_close (local_sock);
874 logputs (LOG_VERBOSE, "\n");
875 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
880 logputs (LOG_VERBOSE, "\n");
881 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
885 fd_close (local_sock);
892 if (!opt.server_response)
893 logputs (LOG_VERBOSE, _("done. "));
895 } /* cmd & (DO_LIST | DO_RETR) */
897 /* Restart if needed. */
898 if (restval && (cmd & DO_RETR))
900 if (!opt.server_response)
901 logprintf (LOG_VERBOSE, "==> REST %s ... ",
902 number_to_static_string (restval));
903 err = ftp_rest (csock, restval);
905 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
909 logputs (LOG_VERBOSE, "\n");
910 logputs (LOG_NOTQUIET, _("\
911 Error in server response, closing control connection.\n"));
915 fd_close (local_sock);
918 logputs (LOG_VERBOSE, "\n");
919 logputs (LOG_NOTQUIET,
920 _("Write failed, closing control connection.\n"));
924 fd_close (local_sock);
927 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
935 if (err != FTPRESTFAIL && !opt.server_response)
936 logputs (LOG_VERBOSE, _("done. "));
937 } /* restval && cmd & DO_RETR */
941 /* If we're in spider mode, don't really retrieve anything except
942 the directory listing and verify whether the given "file" exists. */
948 res = ftp_get_listing (u, con, &f);
949 /* Set the DO_RETR command flag again, because it gets unset when
950 calling ftp_get_listing() and would otherwise cause an assertion
951 failure earlier on when this function gets repeatedly called
952 (e.g., when recursing). */
958 if (!strcmp (f->name, u->file))
967 logputs (LOG_VERBOSE, "\n");
968 logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
973 logputs (LOG_VERBOSE, "\n");
974 logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
981 fd_close (local_sock);
987 if (!opt.server_response)
990 logputs (LOG_VERBOSE, "\n");
991 logprintf (LOG_VERBOSE, "==> RETR %s ... ",
992 quotearg_style (escape_quoting_style, u->file));
996 err = ftp_retr (csock, u->file);
997 /* FTPRERR, WRITEFAILED, FTPNSFOD */
1001 logputs (LOG_VERBOSE, "\n");
1002 logputs (LOG_NOTQUIET, _("\
1003 Error in server response, closing control connection.\n"));
1007 fd_close (local_sock);
1010 logputs (LOG_VERBOSE, "\n");
1011 logputs (LOG_NOTQUIET,
1012 _("Write failed, closing control connection.\n"));
1016 fd_close (local_sock);
1019 logputs (LOG_VERBOSE, "\n");
1020 logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1023 fd_close (local_sock);
1031 if (!opt.server_response)
1032 logputs (LOG_VERBOSE, _("done.\n"));
1034 if (! got_expected_bytes)
1035 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1040 if (!opt.server_response)
1041 logputs (LOG_VERBOSE, "==> LIST ... ");
1042 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1043 without arguments is better than `LIST .'; confirmed by
1045 err = ftp_list (csock, NULL, con->rs);
1046 /* FTPRERR, WRITEFAILED */
1050 logputs (LOG_VERBOSE, "\n");
1051 logputs (LOG_NOTQUIET, _("\
1052 Error in server response, closing control connection.\n"));
1056 fd_close (local_sock);
1059 logputs (LOG_VERBOSE, "\n");
1060 logputs (LOG_NOTQUIET,
1061 _("Write failed, closing control connection.\n"));
1065 fd_close (local_sock);
1068 logputs (LOG_VERBOSE, "\n");
1069 logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1072 fd_close (local_sock);
1079 if (!opt.server_response)
1080 logputs (LOG_VERBOSE, _("done.\n"));
1082 if (! got_expected_bytes)
1083 expected_bytes = ftp_expected_bytes (ftp_last_respline);
1084 } /* cmd & DO_LIST */
1086 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1087 return RETRFINISHED;
1089 /* Some FTP servers return the total length of file after REST
1090 command, others just return the remaining size. */
1091 if (passed_expected_bytes && restval && expected_bytes
1092 && (expected_bytes == passed_expected_bytes - restval))
1094 DEBUGP (("Lying FTP server found, adjusting.\n"));
1095 expected_bytes = passed_expected_bytes;
1098 /* If no transmission was required, then everything is OK. */
1099 if (!pasv_mode_open) /* we are not using pasive mode so we need
1102 /* Wait for the server to connect to the address we're waiting
1104 dtsock = accept_connection (local_sock);
1107 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1112 /* Open the file -- if output_stream is set, use it instead. */
1115 Note that having the output_stream ("-O") file opened in main()
1116 (main.c) rather limits the ability in VMS to open the file
1117 differently for ASCII versus binary FTP here. (Of course, doing it
1118 there allows a open failure to be detected immediately, without first
1119 connecting to the server.)
1121 if (!output_stream || con->cmd & DO_LIST)
1123 /* On VMS, alter the name as required. */
1127 targ = ods_conform (con->target);
1128 if (targ != con->target)
1130 xfree (con->target);
1133 #endif /* def __VMS */
1135 mkalldirs (con->target);
1137 rotate_backups (con->target);
1140 For VMS, define common fopen() optional arguments, and a handy macro
1141 for use as a variable "binary" flag.
1142 Elsewhere, define a constant "binary" flag.
1143 Isn't it nice to have distinct text and binary file types?
1145 # define BIN_TYPE_TRANSFER (type_char != 'A')
1147 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1148 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1149 # define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1150 #else /* def __VMS */
1151 # define BIN_TYPE_FILE 1
1152 #endif /* def __VMS [else] */
1154 if (restval && !(con->cmd & DO_LIST))
1162 fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1167 fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1169 #else /* def __VMS */
1170 fp = fopen (con->target, "ab");
1171 #endif /* def __VMS [else] */
1173 else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1174 || opt.output_document || count > 0)
1176 if (opt.unlink && file_exists_p (con->target))
1178 int res = unlink (con->target);
1181 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1186 fd_close (local_sock);
1197 fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1202 fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1204 #else /* def __VMS */
1205 fp = fopen (con->target, "wb");
1206 #endif /* def __VMS [else] */
1210 fp = fopen_excl (con->target, true);
1211 if (!fp && errno == EEXIST)
1213 /* We cannot just invent a new name and use it (which is
1214 what functions like unique_create typically do)
1215 because we told the user we'd use this name.
1216 Instead, return and retry the download. */
1217 logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1222 fd_close (local_sock);
1223 return FOPEN_EXCL_ERR;
1228 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1232 fd_close (local_sock);
1239 if (passed_expected_bytes)
1241 print_length (passed_expected_bytes, restval, true);
1242 expected_bytes = passed_expected_bytes;
1243 /* for fd_read_body's progress bar */
1245 else if (expected_bytes)
1246 print_length (expected_bytes, restval, false);
1248 /* Get the contents of the document. */
1250 if (restval && rest_failed)
1251 flags |= rb_skip_startpos;
1253 res = fd_read_body (dtsock, fp,
1254 expected_bytes ? expected_bytes - restval : 0,
1255 restval, &rd_size, qtyread, &con->dltime, flags);
1257 tms = datetime_str (time (NULL));
1258 tmrate = retr_rate (rd_size, con->dltime);
1259 total_download_time += con->dltime;
1261 fd_close (local_sock);
1262 /* Close the local file. */
1263 if (!output_stream || con->cmd & DO_LIST)
1266 /* If fd_read_body couldn't write to fp, bail out. */
1269 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1270 con->target, strerror (errno));
1278 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1279 tms, tmrate, fd_errstr (dtsock));
1280 if (opt.server_response)
1281 logputs (LOG_ALWAYS, "\n");
1285 /* Get the server to tell us if everything is retrieved. */
1286 err = ftp_response (csock, &respline);
1289 /* The control connection is decidedly closed. Print the time
1290 only if it hasn't already been printed. */
1292 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1293 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1294 /* If there is an error on the control connection, close it, but
1295 return FTPRETRINT, since there is a possibility that the
1296 whole file was retrieved nevertheless (but that is for
1297 ftp_loop_internal to decide). */
1301 } /* err != FTPOK */
1302 /* If retrieval failed for any reason, return FTPRETRINT, but do not
1303 close socket, since the control connection is still alive. If
1304 there is something wrong with the control connection, it will
1305 become apparent later. */
1306 if (*respline != '2')
1310 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1311 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1318 /* What now? The data connection was erroneous, whereas the
1319 response says everything is OK. We shall play it safe. */
1323 if (!(cmd & LEAVE_PENDING))
1325 /* Closing the socket is faster than sending 'QUIT' and the
1326 effect is the same. */
1330 /* If it was a listing, and opt.server_response is true,
1332 if (opt.server_response && (con->cmd & DO_LIST))
1335 Much of this work may already have been done, but repeating it should
1336 do no damage beyond wasting time.
1338 /* On VMS, alter the name as required. */
1342 targ = ods_conform( con->target);
1343 if (targ != con->target)
1345 xfree( con->target);
1348 #endif /* def __VMS */
1350 mkalldirs (con->target);
1351 fp = fopen (con->target, "r");
1353 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1357 /* The lines are being read with read_whole_line because of
1358 no-buffering on opt.lfile. */
1359 while ((line = read_whole_line (fp)) != NULL)
1361 char *p = strchr (line, '\0');
1362 while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1364 logprintf (LOG_ALWAYS, "%s\n",
1365 quotearg_style (escape_quoting_style, line));
1370 } /* con->cmd & DO_LIST && server_response */
1372 return RETRFINISHED;
1375 /* A one-file FTP loop. This is the part where FTP retrieval is
1376 retried, and retried, and retried, and...
1378 This loop either gets commands from con, or (if ON_YOUR_OWN is
1379 set), makes them up to retrieve the file given by the URL. */
1381 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1384 wgint restval, len = 0, qtyread = 0;
1386 const char *tmrate = NULL;
1390 /* Get the target, and set the name for the message accordingly. */
1391 if ((f == NULL) && (con->target))
1393 /* Explicit file (like ".listing"). */
1398 /* URL-derived file. Consider "-O file" name. */
1399 con->target = url_file_name (u, NULL);
1400 if (!opt.output_document)
1403 locf = opt.output_document;
1406 /* If the output_document was given, then this check was already done and
1407 the file didn't exist. Hence the !opt.output_document */
1408 if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1410 logprintf (LOG_VERBOSE,
1411 _("File %s already there; not retrieving.\n"), quote (con->target));
1412 /* If the file is there, we suppose it's retrieved OK. */
1416 /* Remove it if it's a link. */
1417 remove_link (con->target);
1421 if (con->st & ON_YOUR_OWN)
1422 con->st = ON_YOUR_OWN;
1424 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1429 /* Increment the pass counter. */
1431 sleep_between_retrievals (count);
1432 if (con->st & ON_YOUR_OWN)
1435 con->cmd |= (DO_RETR | LEAVE_PENDING);
1436 if (con->csock != -1)
1437 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1439 con->cmd |= (DO_LOGIN | DO_CWD);
1441 else /* not on your own */
1443 if (con->csock != -1)
1444 con->cmd &= ~DO_LOGIN;
1446 con->cmd |= DO_LOGIN;
1447 if (con->st & DONE_CWD)
1448 con->cmd &= ~DO_CWD;
1453 /* Decide whether or not to restart. */
1454 if (con->cmd & DO_LIST)
1456 else if (opt.always_rest
1457 && stat (locf, &st) == 0
1458 && S_ISREG (st.st_mode))
1459 /* When -c is used, continue from on-disk size. (Can't use
1460 hstat.len even if count>1 because we don't want a failed
1461 first attempt to clobber existing data.) */
1462 restval = st.st_size;
1464 restval = qtyread; /* start where the previous run left off */
1468 /* Get the current time string. */
1469 tms = datetime_str (time (NULL));
1470 /* Print fetch message, if opt.verbose. */
1473 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1477 sprintf (tmp, _("(try:%2d)"), count);
1478 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => %s\n",
1479 tms, hurl, tmp, quote (locf));
1481 ws_changetitle (hurl);
1485 /* Send getftp the proper length, if fileinfo was provided. */
1486 if (f && f->type != FT_SYMLINK)
1490 err = getftp (u, len, &qtyread, restval, con, count);
1492 if (con->csock == -1)
1493 con->st &= ~DONE_CWD;
1495 con->st |= DONE_CWD;
1499 case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1500 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1502 /* Fatal errors, give up. */
1504 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1505 case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1506 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1507 case FOPEN_EXCL_ERR:
1508 printwhat (count, opt.ntry);
1509 /* non-fatal errors */
1510 if (err == FOPEN_EXCL_ERR)
1512 /* Re-determine the file name. */
1513 xfree_null (con->target);
1514 con->target = url_file_name (u, NULL);
1519 /* If the control connection was closed, the retrieval
1520 will be considered OK if f->size == len. */
1521 if (!f || qtyread != f->size)
1523 printwhat (count, opt.ntry);
1534 tms = datetime_str (time (NULL));
1536 tmrate = retr_rate (qtyread - restval, con->dltime);
1538 /* If we get out of the switch above without continue'ing, we've
1539 successfully downloaded a file. Remember this fact. */
1540 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1542 if (con->st & ON_YOUR_OWN)
1544 fd_close (con->csock);
1549 bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1551 logprintf (LOG_VERBOSE,
1553 ? _("%s (%s) - written to stdout %s[%s]\n\n")
1554 : _("%s (%s) - %s saved [%s]\n\n"),
1556 write_to_stdout ? "" : quote (locf),
1557 number_to_static_string (qtyread));
1559 if (!opt.verbose && !opt.quiet)
1561 /* Need to hide the password from the URL. The `if' is here
1562 so that we don't do the needless allocation every
1564 char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1565 logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1566 tms, hurl, number_to_static_string (qtyread), locf, count);
1570 if ((con->cmd & DO_LIST))
1571 /* This is a directory listing file. */
1573 if (!opt.remove_listing)
1574 /* --dont-remove-listing was specified, so do count this towards the
1575 number of bytes and files downloaded. */
1577 total_downloaded_bytes += qtyread;
1581 /* Deletion of listing files is not controlled by --delete-after, but
1582 by the more specific option --dont-remove-listing, and the code
1583 to do this deletion is in another function. */
1585 else if (!opt.spider)
1586 /* This is not a directory listing file. */
1588 /* Unlike directory listing files, don't pretend normal files weren't
1589 downloaded if they're going to be deleted. People seeding proxies,
1590 for instance, may want to know how many bytes and files they've
1591 downloaded through it. */
1592 total_downloaded_bytes += qtyread;
1595 if (opt.delete_after && !input_file_url (opt.input_filename))
1598 Removing file due to --delete-after in ftp_loop_internal():\n"));
1599 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1601 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1605 /* Restore the original leave-pendingness. */
1607 con->cmd |= LEAVE_PENDING;
1609 con->cmd &= ~LEAVE_PENDING;
1612 *local_file = xstrdup (locf);
1615 } while (!opt.ntry || (count < opt.ntry));
1617 if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1619 fd_close (con->csock);
1625 /* Return the directory listing in a reusable format. The directory
1626 is specifed in u->dir. */
1628 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1631 char *uf; /* url file name */
1632 char *lf; /* list file name */
1633 char *old_target = con->target;
1635 con->st &= ~ON_YOUR_OWN;
1636 con->cmd |= (DO_LIST | LEAVE_PENDING);
1637 con->cmd &= ~DO_RETR;
1639 /* Find the listing file name. We do it by taking the file name of
1640 the URL and replacing the last component with the listing file
1642 uf = url_file_name (u, NULL);
1643 lf = file_merge (uf, LIST_FILENAME);
1645 DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1647 con->target = xstrdup (lf);
1649 err = ftp_loop_internal (u, NULL, con, NULL);
1650 lf = xstrdup (con->target);
1651 xfree (con->target);
1652 con->target = old_target;
1656 *f = ftp_parse_ls (lf, con->rs);
1657 if (opt.remove_listing)
1660 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1662 logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1668 con->cmd &= ~DO_LIST;
1672 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1673 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1674 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1675 static void freefileinfo (struct fileinfo *f);
1677 /* Retrieve a list of files given in struct fileinfo linked list. If
1678 a file is a symbolic link, do not retrieve it, but rather try to
1679 set up a similar link on the local disk, if the symlinks are
1682 If opt.recursive is set, after all files have been retrieved,
1683 ftp_retrieve_dirs will be called to retrieve the directories. */
1685 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1687 static int depth = 0;
1689 struct fileinfo *orig;
1692 bool dlthis; /* Download this (file). */
1693 const char *actual_target = NULL;
1695 /* Increase the depth. */
1697 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1699 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1700 depth, opt.reclevel));
1708 con->st &= ~ON_YOUR_OWN;
1709 if (!(con->st & DONE_CWD))
1712 con->cmd &= ~DO_CWD;
1713 con->cmd |= (DO_RETR | LEAVE_PENDING);
1716 con->cmd |= DO_LOGIN;
1718 con->cmd &= ~DO_LOGIN;
1720 err = RETROK; /* in case it's not used */
1724 char *old_target, *ofile;
1726 if (opt.quota && total_downloaded_bytes > opt.quota)
1731 old_target = con->target;
1733 ofile = xstrdup (u->file);
1734 url_set_file (u, f->name);
1736 con->target = url_file_name (u, NULL);
1740 if (opt.timestamping && f->type == FT_PLAINFILE)
1743 /* If conversion of HTML files retrieved via FTP is ever implemented,
1744 we'll need to stat() <file>.orig here when -K has been specified.
1745 I'm not implementing it now since files on an FTP server are much
1746 more likely than files on an HTTP server to legitimately have a
1748 if (!stat (con->target, &st))
1752 /* Else, get it from the file. */
1753 local_size = st.st_size;
1756 /* Modification time granularity is 2 seconds for Windows, so
1757 increase local time by 1 second for later comparison. */
1760 /* Compare file sizes only for servers that tell us correct
1761 values. Assume sizes being equal for servers that lie
1763 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1764 eq_size = cor_val ? (local_size == f->size) : true;
1765 if (f->tstamp <= tml && eq_size)
1767 /* Remote file is older, file sizes can be compared and
1769 logprintf (LOG_VERBOSE, _("\
1770 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1775 /* Remote file is newer or sizes cannot be matched */
1776 logprintf (LOG_VERBOSE, _("\
1777 Remote file is newer than local file %s -- retrieving.\n\n"),
1778 quote (con->target));
1782 /* Sizes do not match */
1783 logprintf (LOG_VERBOSE, _("\
1784 The sizes do not match (local %s) -- retrieving.\n\n"),
1785 number_to_static_string (local_size));
1788 } /* opt.timestamping && f->type == FT_PLAINFILE */
1792 /* If opt.retr_symlinks is defined, we treat symlinks as
1793 if they were normal files. There is currently no way
1794 to distinguish whether they might be directories, and
1796 if (!opt.retr_symlinks)
1800 logputs (LOG_NOTQUIET,
1801 _("Invalid name of the symlink, skipping.\n"));
1805 /* Check whether we already have the correct
1807 int rc = lstat (con->target, &st);
1810 size_t len = strlen (f->linkto) + 1;
1811 if (S_ISLNK (st.st_mode))
1813 char *link_target = (char *)alloca (len);
1814 size_t n = readlink (con->target, link_target, len);
1816 && (memcmp (link_target, f->linkto, n) == 0))
1818 logprintf (LOG_VERBOSE, _("\
1819 Already have correct symlink %s -> %s\n\n"),
1820 quote (con->target),
1827 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1828 quote (con->target), quote (f->linkto));
1829 /* Unlink before creating symlink! */
1830 unlink (con->target);
1831 if (symlink (f->linkto, con->target) == -1)
1832 logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1833 logputs (LOG_VERBOSE, "\n");
1834 } /* have f->linkto */
1835 #else /* not HAVE_SYMLINK */
1836 logprintf (LOG_NOTQUIET,
1837 _("Symlinks not supported, skipping symlink %s.\n"),
1838 quote (con->target));
1839 #endif /* not HAVE_SYMLINK */
1841 else /* opt.retr_symlinks */
1844 err = ftp_loop_internal (u, f, con, NULL);
1845 } /* opt.retr_symlinks */
1849 logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1853 /* Call the retrieve loop. */
1855 err = ftp_loop_internal (u, f, con, NULL);
1858 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1865 * Set permissions _before_ setting the times, as setting the
1866 * permissions changes the modified-time, at least on VMS.
1867 * Also, use the opt.output_document name here, too, as
1868 * appropriate. (Do the test once, and save the result.)
1871 set_local_file (&actual_target, con->target);
1873 /* If downloading a plain file, set valid (non-zero) permissions. */
1874 if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1877 chmod (actual_target, f->perms);
1879 DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1882 /* Set the time-stamp information to the local file. Symlinks
1883 are not to be stamped because it sets the stamp on the
1885 if (actual_target != NULL)
1887 if (opt.useservertimestamps
1888 && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1891 && file_exists_p (con->target))
1893 touch (actual_target, f->tstamp);
1895 else if (f->tstamp == -1)
1896 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1900 xfree (con->target);
1901 con->target = old_target;
1903 url_set_file (u, ofile);
1906 /* Break on fatals. */
1907 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1909 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1913 /* We do not want to call ftp_retrieve_dirs here */
1914 if (opt.recursive &&
1915 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1916 err = ftp_retrieve_dirs (u, orig, con);
1917 else if (opt.recursive)
1918 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1919 depth, opt.reclevel));
1924 /* Retrieve the directories given in a file list. This function works
1925 by simply going through the linked list and calling
1926 ftp_retrieve_glob on each directory entry. The function knows
1927 about excluded directories. */
1929 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1931 char *container = NULL;
1932 int container_size = 0;
1934 for (; f; f = f->next)
1937 char *odir, *newdir;
1939 if (opt.quota && total_downloaded_bytes > opt.quota)
1941 if (f->type != FT_DIRECTORY)
1944 /* Allocate u->dir off stack, but reallocate only if a larger
1945 string is needed. It's a pity there's no "realloca" for an
1946 item on the bottom of the stack. */
1947 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1948 if (size > container_size)
1949 container = (char *)alloca (size);
1954 || (*odir == '/' && *(odir + 1) == '\0'))
1955 /* If ODIR is empty or just "/", simply append f->name to
1956 ODIR. (In the former case, to preserve u->dir being
1957 relative; in the latter case, to avoid double slash.) */
1958 sprintf (newdir, "%s%s", odir, f->name);
1960 /* Else, use a separator. */
1961 sprintf (newdir, "%s/%s", odir, f->name);
1963 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1964 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1965 odir, f->name, newdir));
1966 if (!accdir (newdir))
1968 logprintf (LOG_VERBOSE, _("\
1969 Not descending to %s as it is excluded/not-included.\n"),
1974 con->st &= ~DONE_CWD;
1976 odir = xstrdup (u->dir); /* because url_set_dir will free
1978 url_set_dir (u, newdir);
1979 ftp_retrieve_glob (u, con, GLOB_GETALL);
1980 url_set_dir (u, odir);
1983 /* Set the time-stamp? */
1986 if (opt.quota && total_downloaded_bytes > opt.quota)
1992 /* Return true if S has a leading '/' or contains '../' */
1994 has_insecure_name_p (const char *s)
1999 if (strstr (s, "../") != 0)
2005 /* A near-top-level function to retrieve the files in a directory.
2006 The function calls ftp_get_listing, to get a linked list of files.
2007 Then it weeds out the file names that do not match the pattern.
2008 ftp_retrieve_list is called with this updated list as an argument.
2010 If the argument ACTION is GLOB_GETONE, just download the file (but
2011 first get the listing, so that the time-stamp is heeded); if it's
2012 GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
2015 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2017 struct fileinfo *f, *start;
2020 con->cmd |= LEAVE_PENDING;
2022 res = ftp_get_listing (u, con, &start);
2025 /* First: weed out that do not conform the global rules given in
2026 opt.accepts and opt.rejects. */
2027 if (opt.accepts || opt.rejects)
2032 if (f->type != FT_DIRECTORY && !acceptable (f->name))
2034 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2036 f = delelement (f, &start);
2042 /* Remove all files with possible harmful names */
2046 if (has_insecure_name_p (f->name))
2048 logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2050 f = delelement (f, &start);
2055 /* Now weed out the files that do not match our globbing pattern.
2056 If we are dealing with a globbing pattern, that is. */
2059 if (action == GLOB_GLOBALL)
2061 int (*matcher) (const char *, const char *, int)
2062 = opt.ignore_case ? fnmatch_nocase : fnmatch;
2068 matchres = matcher (u->file, f->name, 0);
2071 logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2072 u->file, quotearg_style (escape_quoting_style, f->name),
2076 if (matchres == FNM_NOMATCH)
2077 f = delelement (f, &start); /* delete the element from the list */
2079 f = f->next; /* leave the element in the list */
2083 freefileinfo (start);
2084 return RETRBADPATTERN;
2087 else if (action == GLOB_GETONE)
2091 * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2092 * bug causes spurious %CC-E-BADCONDIT complaint with this
2093 * "?:" statement. (Different linkage attributes for strcmp()
2094 * and strcasecmp().) Converting to "if" changes the
2095 * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;". Adding
2096 * the senseless type cast clears the complaint, and looks
2099 int (*cmp) (const char *, const char *)
2100 = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2101 #else /* def __VMS */
2102 int (*cmp) (const char *, const char *)
2103 = opt.ignore_case ? strcasecmp : strcmp;
2104 #endif /* def __VMS [else] */
2108 if (0 != cmp(u->file, f->name))
2109 f = delelement (f, &start);
2117 /* Just get everything. */
2118 ftp_retrieve_list (u, start, con);
2122 if (action == GLOB_GLOBALL)
2125 /* #### This message SUCKS. We should see what was the
2126 reason that nothing was retrieved. */
2127 logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2130 else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2132 /* Let's try retrieving it anyway. */
2133 con->st |= ON_YOUR_OWN;
2134 res = ftp_loop_internal (u, NULL, con, NULL);
2138 /* If action == GLOB_GETALL, and the file list is empty, there's
2139 no point in trying to download anything or in complaining about
2140 it. (An empty directory should not cause complaints.)
2143 freefileinfo (start);
2144 if (opt.quota && total_downloaded_bytes > opt.quota)
2147 /* #### Should we return `res' here? */
2151 /* The wrapper that calls an appropriate routine according to contents
2152 of URL. Inherently, its capabilities are limited on what can be
2153 encoded into a URL. */
2155 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2156 bool recursive, bool glob)
2158 ccon con; /* FTP connection */
2166 con.st = ON_YOUR_OWN;
2171 /* If the file name is empty, the user probably wants a directory
2172 index. We'll provide one, properly HTML-ized. Unless
2173 opt.htmlify is 0, of course. :-) */
2174 if (!*u->file && !recursive)
2177 res = ftp_get_listing (u, &con, &f);
2181 if (opt.htmlify && !opt.spider)
2183 char *filename = (opt.output_document
2184 ? xstrdup (opt.output_document)
2185 : (con.target ? xstrdup (con.target)
2186 : url_file_name (u, NULL)));
2187 res = ftp_index (filename, u, f);
2188 if (res == FTPOK && opt.verbose)
2190 if (!opt.output_document)
2194 if (stat (filename, &st) == 0)
2198 logprintf (LOG_NOTQUIET,
2199 _("Wrote HTML-ized index to %s [%s].\n"),
2200 quote (filename), number_to_static_string (sz));
2203 logprintf (LOG_NOTQUIET,
2204 _("Wrote HTML-ized index to %s.\n"),
2214 bool ispattern = false;
2217 /* Treat the URL as a pattern if the file name part of the
2218 URL path contains wildcards. (Don't check for u->file
2219 because it is unescaped and therefore doesn't leave users
2220 the option to escape literal '*' as %2A.) */
2221 char *file_part = strrchr (u->path, '/');
2223 file_part = u->path;
2224 ispattern = has_wildcards_p (file_part);
2226 if (ispattern || recursive || opt.timestamping)
2228 /* ftp_retrieve_glob is a catch-all function that gets called
2229 if we need globbing, time-stamping or recursion. Its
2230 third argument is just what we really need. */
2231 res = ftp_retrieve_glob (u, &con,
2232 ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2235 res = ftp_loop_internal (u, NULL, &con, local_file);
2241 /* If a connection was left, quench it. */
2242 if (con.csock != -1)
2243 fd_close (con.csock);
2244 xfree_null (con.id);
2246 xfree_null (con.target);
2251 /* Delete an element from the fileinfo linked list. Returns the
2252 address of the next element, or NULL if the list is exhausted. It
2253 can modify the start of the list. */
2254 static struct fileinfo *
2255 delelement (struct fileinfo *f, struct fileinfo **start)
2257 struct fileinfo *prev = f->prev;
2258 struct fileinfo *next = f->next;
2261 xfree_null (f->linkto);
2273 /* Free the fileinfo linked list of files. */
2275 freefileinfo (struct fileinfo *f)
2279 struct fileinfo *next = f->next;