1 /* File Transfer Protocol support.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables. You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL". If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so. If you do not wish to do
29 so, delete this exception statement from your version. */
43 #include <sys/types.h>
55 #include "convert.h" /* for downloaded_file */
56 #include "recur.h" /* for INFINITE_RECURSION */
62 extern LARGE_INT total_downloaded_bytes;
64 /* File where the "ls -al" listing will be saved. */
65 #define LIST_FILENAME ".listing"
67 extern char ftp_last_respline[];
71 int st; /* connection status */
72 int cmd; /* command code */
73 int csock; /* control connection socket */
74 double dltime; /* time of the download in msecs */
75 enum stype rs; /* remote system reported by ftp server */
76 char *id; /* initial directory */
77 char *target; /* target file name */
78 struct url *proxy; /* FTWK-style proxy */
82 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
83 the string S, and return the number converted to long, if found, 0
86 ftp_expected_bytes (const char *s)
92 while (*s && *s != '(')
96 for (++s; *s && ISSPACE (*s); s++);
104 res = (*s - '0') + 10 * res;
107 while (*s && ISDIGIT (*s));
110 while (*s && ISSPACE (*s))
114 if (TOLOWER (*s) != 'b')
116 if (strncasecmp (s, "byte", 4))
126 * This function sets up a passive data connection with the FTP server.
127 * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
130 ftp_do_pasv (int csock, ip_address *addr, int *port)
134 /* We need to determine the address family and need to call
135 getpeername, so while we're at it, store the address to ADDR.
136 ftp_pasv and ftp_lpsv can simply override it. */
137 if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
140 /* If our control connection is over IPv6, then we first try EPSV and then
141 * LPSV if the former is not supported. If the control connection is over
142 * IPv4, we simply issue the good old PASV request. */
146 if (!opt.server_response)
147 logputs (LOG_VERBOSE, "==> PASV ... ");
148 err = ftp_pasv (csock, addr, port);
151 if (!opt.server_response)
152 logputs (LOG_VERBOSE, "==> EPSV ... ");
153 err = ftp_epsv (csock, addr, port);
155 /* If EPSV is not supported try LPSV */
156 if (err == FTPNOPASV)
158 if (!opt.server_response)
159 logputs (LOG_VERBOSE, "==> LPSV ... ");
160 err = ftp_lpsv (csock, addr, port);
171 * This function sets up an active data connection with the FTP server.
172 * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
175 ftp_do_port (int csock, int *local_sock)
180 if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
183 /* If our control connection is over IPv6, then we first try EPRT and then
184 * LPRT if the former is not supported. If the control connection is over
185 * IPv4, we simply issue the good old PORT request. */
189 if (!opt.server_response)
190 logputs (LOG_VERBOSE, "==> PORT ... ");
191 err = ftp_port (csock, local_sock);
194 if (!opt.server_response)
195 logputs (LOG_VERBOSE, "==> EPRT ... ");
196 err = ftp_eprt (csock, local_sock);
198 /* If EPRT is not supported try LPRT */
199 if (err == FTPPORTERR)
201 if (!opt.server_response)
202 logputs (LOG_VERBOSE, "==> LPRT ... ");
203 err = ftp_lprt (csock, local_sock);
214 ftp_do_pasv (int csock, ip_address *addr, int *port)
216 if (!opt.server_response)
217 logputs (LOG_VERBOSE, "==> PASV ... ");
218 return ftp_pasv (csock, addr, port);
222 ftp_do_port (int csock, int *local_sock)
224 if (!opt.server_response)
225 logputs (LOG_VERBOSE, "==> PORT ... ");
226 return ftp_port (csock, local_sock);
230 /* Retrieves a file with denoted parameters through opening an FTP
231 connection to the server. It always closes the data connection,
232 and closes the control connection in case of error. */
234 getftp (struct url *u, long *len, long restval, ccon *con)
236 int csock, dtsock, local_sock, res;
239 char *user, *passwd, *respline;
242 int pasv_mode_open = 0;
243 long expected_bytes = 0L;
245 assert (con != NULL);
246 assert (con->target != NULL);
248 /* Debug-check of the sanity of the request by making sure that LIST
249 and RETR are never both requested (since we can handle only one
251 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
252 /* Make sure that at least *something* is requested. */
253 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
257 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
258 user = user ? user : opt.ftp_acc;
259 passwd = passwd ? passwd : opt.ftp_pass;
260 assert (user && passwd);
266 if (!(cmd & DO_LOGIN))
268 else /* cmd & DO_LOGIN */
271 char *host = con->proxy ? con->proxy->host : u->host;
272 int port = con->proxy ? con->proxy->port : u->port;
273 char *logname = user;
277 /* If proxy is in use, log in as username@target-site. */
278 logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
279 sprintf (logname, "%s@%s", user, u->host);
282 /* Login to the server: */
284 /* First: Establish the control connection. */
286 csock = connect_to_host (host, port);
290 return (retryable_socket_connect_error (errno)
291 ? CONERROR : CONIMPOSSIBLE);
293 /* Second: Login with proper USER/PASS sequence. */
294 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
295 if (opt.server_response)
296 logputs (LOG_ALWAYS, "\n");
297 err = ftp_login (csock, logname, passwd);
302 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
306 logputs (LOG_VERBOSE, "\n");
307 logputs (LOG_NOTQUIET, _("\
308 Error in server response, closing control connection.\n"));
313 logputs (LOG_VERBOSE, "\n");
314 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
319 logputs (LOG_VERBOSE, "\n");
320 logputs (LOG_NOTQUIET,
321 _("Write failed, closing control connection.\n"));
326 logputs (LOG_VERBOSE, "\n");
327 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
329 return FTPLOGREFUSED;
332 logputs (LOG_VERBOSE, "\n");
333 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
338 if (!opt.server_response)
339 logputs (LOG_VERBOSE, _("Logged in!\n"));
346 /* Third: Get the system type */
347 if (!opt.server_response)
348 logprintf (LOG_VERBOSE, "==> SYST ... ");
349 err = ftp_syst (csock, &con->rs);
354 logputs (LOG_VERBOSE, "\n");
355 logputs (LOG_NOTQUIET, _("\
356 Error in server response, closing control connection.\n"));
361 logputs (LOG_VERBOSE, "\n");
362 logputs (LOG_NOTQUIET,
363 _("Server error, can't determine system type.\n"));
366 /* Everything is OK. */
372 if (!opt.server_response && err != FTPSRVERR)
373 logputs (LOG_VERBOSE, _("done. "));
375 /* Fourth: Find the initial ftp directory */
377 if (!opt.server_response)
378 logprintf (LOG_VERBOSE, "==> PWD ... ");
379 err = ftp_pwd(csock, &con->id);
384 logputs (LOG_VERBOSE, "\n");
385 logputs (LOG_NOTQUIET, _("\
386 Error in server response, closing control connection.\n"));
391 /* PWD unsupported -- assume "/". */
392 xfree_null (con->id);
393 con->id = xstrdup ("/");
396 /* Everything is OK. */
402 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
403 Convert it to "/INITIAL/FOLDER" */
404 if (con->rs == ST_VMS)
406 char *path = strchr (con->id, '[');
407 char *pathend = path ? strchr (path + 1, ']') : NULL;
408 if (!path || !pathend)
409 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
412 char *idir = con->id;
413 DEBUGP (("Preprocessing the initial VMS directory\n"));
414 DEBUGP ((" old = '%s'\n", con->id));
415 /* We do the conversion in-place by copying the stuff
416 between [ and ] to the beginning, and changing dots
417 to slashes at the same time. */
419 for (++path; path < pathend; path++, idir++)
420 *idir = *path == '.' ? '/' : *path;
422 DEBUGP ((" new = '%s'\n\n", con->id));
425 if (!opt.server_response)
426 logputs (LOG_VERBOSE, _("done.\n"));
428 /* Fifth: Set the FTP type. */
429 type_char = ftp_process_type (u->params);
430 if (!opt.server_response)
431 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
432 err = ftp_type (csock, type_char);
433 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
437 logputs (LOG_VERBOSE, "\n");
438 logputs (LOG_NOTQUIET, _("\
439 Error in server response, closing control connection.\n"));
444 logputs (LOG_VERBOSE, "\n");
445 logputs (LOG_NOTQUIET,
446 _("Write failed, closing control connection.\n"));
451 logputs (LOG_VERBOSE, "\n");
452 logprintf (LOG_NOTQUIET,
453 _("Unknown type `%c', closing control connection.\n"),
458 /* Everything is OK. */
464 if (!opt.server_response)
465 logputs (LOG_VERBOSE, _("done. "));
471 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
474 char *target = u->dir;
476 DEBUGP (("changing working directory\n"));
478 /* Change working directory. To change to a non-absolute
479 Unix directory, we need to prepend initial directory
480 (con->id) to it. Absolute directories "just work".
482 A relative directory is one that does not begin with '/'
483 and, on non-Unix OS'es, one that doesn't begin with
486 This is not done for OS400, which doesn't use
487 "/"-delimited directories, nor does it support directory
488 hierarchies. "CWD foo" followed by "CWD bar" leaves us
489 in "bar", not in "foo/bar", as would be customary
493 && !(con->rs != ST_UNIX
494 && ISALPHA (target[0])
496 && con->rs != ST_OS400)
498 int idlen = strlen (con->id);
501 /* Strip trailing slash(es) from con->id. */
502 while (idlen > 0 && con->id[idlen - 1] == '/')
504 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
505 memcpy (p, con->id, idlen);
510 DEBUGP (("Prepended initial PWD to relative path:\n"));
511 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
512 con->id, target, ntarget));
516 /* If the FTP host runs VMS, we will have to convert the absolute
517 directory path in UNIX notation to absolute directory path in
518 VMS notation as VMS FTP servers do not like UNIX notation of
519 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
521 if (con->rs == ST_VMS)
524 char *ntarget = (char *)alloca (strlen (target) + 2);
525 /* We use a converted initial dir, so directories in
526 TARGET will be separated with slashes, something like
527 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
528 "[INITIAL.FOLDER.DIR.SUBDIR]". */
529 strcpy (ntarget, target);
530 assert (*ntarget == '/');
532 for (tmpp = ntarget + 1; *tmpp; tmpp++)
537 DEBUGP (("Changed file name to VMS syntax:\n"));
538 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
542 if (!opt.server_response)
543 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
544 err = ftp_cwd (csock, target);
545 /* FTPRERR, WRITEFAILED, FTPNSFOD */
549 logputs (LOG_VERBOSE, "\n");
550 logputs (LOG_NOTQUIET, _("\
551 Error in server response, closing control connection.\n"));
556 logputs (LOG_VERBOSE, "\n");
557 logputs (LOG_NOTQUIET,
558 _("Write failed, closing control connection.\n"));
563 logputs (LOG_VERBOSE, "\n");
564 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
576 if (!opt.server_response)
577 logputs (LOG_VERBOSE, _("done.\n"));
580 else /* do not CWD */
581 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
583 if ((cmd & DO_RETR) && restval && *len == 0)
587 if (!opt.server_response)
588 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
591 err = ftp_size(csock, u->file, len);
597 logputs (LOG_VERBOSE, "\n");
598 logputs (LOG_NOTQUIET, _("\
599 Error in server response, closing control connection.\n"));
604 /* Everything is OK. */
610 if (!opt.server_response)
611 logputs (LOG_VERBOSE, _("done.\n"));
614 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
615 if (cmd & (DO_LIST | DO_RETR))
617 if (opt.ftp_pasv > 0)
619 ip_address passive_addr;
621 err = ftp_do_pasv (csock, &passive_addr, &passive_port);
622 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
626 logputs (LOG_VERBOSE, "\n");
627 logputs (LOG_NOTQUIET, _("\
628 Error in server response, closing control connection.\n"));
633 logputs (LOG_VERBOSE, "\n");
634 logputs (LOG_NOTQUIET,
635 _("Write failed, closing control connection.\n"));
640 logputs (LOG_VERBOSE, "\n");
641 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
644 logputs (LOG_VERBOSE, "\n");
645 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
656 DEBUGP (("trying to connect to %s port %d\n",
657 pretty_print_address (&passive_addr),
659 dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
662 int save_errno = errno;
664 logprintf (LOG_VERBOSE, _("couldn't connect to %s port %hu: %s\n"),
665 pretty_print_address (&passive_addr), passive_port,
666 strerror (save_errno));
667 return (retryable_socket_connect_error (save_errno)
668 ? CONERROR : CONIMPOSSIBLE);
671 pasv_mode_open = 1; /* Flag to avoid accept port */
672 if (!opt.server_response)
673 logputs (LOG_VERBOSE, _("done. "));
677 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
679 err = ftp_do_port (csock, &local_sock);
680 /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
685 logputs (LOG_VERBOSE, "\n");
686 logputs (LOG_NOTQUIET, _("\
687 Error in server response, closing control connection.\n"));
690 fd_close (local_sock);
694 logputs (LOG_VERBOSE, "\n");
695 logputs (LOG_NOTQUIET,
696 _("Write failed, closing control connection.\n"));
699 fd_close (local_sock);
703 logputs (LOG_VERBOSE, "\n");
704 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
707 fd_close (local_sock);
711 logputs (LOG_VERBOSE, "\n");
712 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
718 logputs (LOG_VERBOSE, "\n");
719 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
722 fd_close (local_sock);
732 if (!opt.server_response)
733 logputs (LOG_VERBOSE, _("done. "));
735 } /* cmd & (DO_LIST | DO_RETR) */
737 /* Restart if needed. */
738 if (restval && (cmd & DO_RETR))
740 if (!opt.server_response)
741 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
742 err = ftp_rest (csock, restval);
744 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
748 logputs (LOG_VERBOSE, "\n");
749 logputs (LOG_NOTQUIET, _("\
750 Error in server response, closing control connection.\n"));
753 fd_close (local_sock);
757 logputs (LOG_VERBOSE, "\n");
758 logputs (LOG_NOTQUIET,
759 _("Write failed, closing control connection.\n"));
762 fd_close (local_sock);
766 /* If `-c' is specified and the file already existed when
767 Wget was started, it would be a bad idea for us to start
768 downloading it from scratch, effectively truncating it. */
769 if (opt.always_rest && (cmd & NO_TRUNCATE))
771 logprintf (LOG_NOTQUIET,
772 _("\nREST failed; will not truncate `%s'.\n"),
776 fd_close (local_sock);
777 return CONTNOTSUPPORTED;
779 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
789 if (err != FTPRESTFAIL && !opt.server_response)
790 logputs (LOG_VERBOSE, _("done. "));
791 } /* restval && cmd & DO_RETR */
795 /* If we're in spider mode, don't really retrieve anything. The
796 fact that we got to this point should be proof enough that
797 the file exists, vaguely akin to HTTP's concept of a "HEAD"
803 fd_close (local_sock);
809 if (!opt.server_response)
812 logputs (LOG_VERBOSE, "\n");
813 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
817 err = ftp_retr (csock, u->file);
818 /* FTPRERR, WRITEFAILED, FTPNSFOD */
822 logputs (LOG_VERBOSE, "\n");
823 logputs (LOG_NOTQUIET, _("\
824 Error in server response, closing control connection.\n"));
827 fd_close (local_sock);
831 logputs (LOG_VERBOSE, "\n");
832 logputs (LOG_NOTQUIET,
833 _("Write failed, closing control connection.\n"));
836 fd_close (local_sock);
840 logputs (LOG_VERBOSE, "\n");
841 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
843 fd_close (local_sock);
854 if (!opt.server_response)
855 logputs (LOG_VERBOSE, _("done.\n"));
856 expected_bytes = ftp_expected_bytes (ftp_last_respline);
861 if (!opt.server_response)
862 logputs (LOG_VERBOSE, "==> LIST ... ");
863 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
864 without arguments is better than `LIST .'; confirmed by
866 err = ftp_list (csock, NULL);
867 /* FTPRERR, WRITEFAILED */
871 logputs (LOG_VERBOSE, "\n");
872 logputs (LOG_NOTQUIET, _("\
873 Error in server response, closing control connection.\n"));
876 fd_close (local_sock);
880 logputs (LOG_VERBOSE, "\n");
881 logputs (LOG_NOTQUIET,
882 _("Write failed, closing control connection.\n"));
885 fd_close (local_sock);
889 logputs (LOG_VERBOSE, "\n");
890 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
893 fd_close (local_sock);
903 if (!opt.server_response)
904 logputs (LOG_VERBOSE, _("done.\n"));
905 expected_bytes = ftp_expected_bytes (ftp_last_respline);
906 } /* cmd & DO_LIST */
908 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
911 /* Some FTP servers return the total length of file after REST
912 command, others just return the remaining size. */
913 if (*len && restval && expected_bytes
914 && (expected_bytes == *len - restval))
916 DEBUGP (("Lying FTP server found, adjusting.\n"));
917 expected_bytes = *len;
920 /* If no transmission was required, then everything is OK. */
921 if (!pasv_mode_open) /* we are not using pasive mode so we need
924 /* Wait for the server to connect to the address we're waiting
926 dtsock = accept_connection (local_sock);
929 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
934 /* Open the file -- if opt.dfp is set, use it instead. */
935 if (!opt.dfp || con->cmd & DO_LIST)
937 mkalldirs (con->target);
939 rotate_backups (con->target);
940 /* #### Is this correct? */
941 chmod (con->target, 0600);
943 fp = fopen (con->target, restval ? "ab" : "wb");
946 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
949 fd_close (local_sock);
955 extern int global_download_count;
958 /* Rewind the output document if the download starts over and if
959 this is the first download. See gethttp() for a longer
961 if (!restval && global_download_count == 0 && opt.dfp != stdout)
963 /* This will silently fail for streams that don't correspond
964 to regular files, but that's OK. */
966 /* ftruncate is needed because opt.dfp is opened in append
967 mode if opt.always_rest is set. */
968 ftruncate (fileno (fp), 0);
975 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
977 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
978 logputs (LOG_VERBOSE, "\n");
979 expected_bytes = *len; /* for get_contents/show_progress */
981 else if (expected_bytes)
983 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
985 logprintf (LOG_VERBOSE, _(" [%s to go]"),
986 legible (expected_bytes - restval));
987 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
990 /* Get the contents of the document. */
991 res = fd_read_body (dtsock, fp, len, restval, expected_bytes, 0,
993 tms = time_str (NULL);
994 tmrate = retr_rate (*len - restval, con->dltime, 0);
995 /* Close data connection socket. */
997 fd_close (local_sock);
998 /* Close the local file. */
1000 /* Close or flush the file. We have to be careful to check for
1001 error here. Checking the result of fwrite() is not enough --
1002 errors could go unnoticed! */
1004 if (!opt.dfp || con->cmd & DO_LIST)
1005 flush_res = fclose (fp);
1007 flush_res = fflush (fp);
1008 if (flush_res == EOF)
1012 /* If get_contents couldn't write to fp, bail out. */
1015 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1016 con->target, strerror (errno));
1022 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1023 tms, tmrate, strerror (errno));
1024 if (opt.server_response)
1025 logputs (LOG_ALWAYS, "\n");
1028 /* Get the server to tell us if everything is retrieved. */
1029 err = ftp_response (csock, &respline);
1033 /* The control connection is decidedly closed. Print the time
1034 only if it hasn't already been printed. */
1036 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1037 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1038 /* If there is an error on the control connection, close it, but
1039 return FTPRETRINT, since there is a possibility that the
1040 whole file was retrieved nevertheless (but that is for
1041 ftp_loop_internal to decide). */
1044 } /* err != FTPOK */
1045 /* If retrieval failed for any reason, return FTPRETRINT, but do not
1046 close socket, since the control connection is still alive. If
1047 there is something wrong with the control connection, it will
1048 become apparent later. */
1049 if (*respline != '2')
1053 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1054 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1061 /* What now? The data connection was erroneous, whereas the
1062 response says everything is OK. We shall play it safe. */
1066 if (!(cmd & LEAVE_PENDING))
1068 /* I should probably send 'QUIT' and check for a reply, but this
1069 is faster. #### Is it OK, though? */
1072 /* If it was a listing, and opt.server_response is true,
1074 if (opt.server_response && (con->cmd & DO_LIST))
1076 mkalldirs (con->target);
1077 fp = fopen (con->target, "r");
1079 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1083 /* The lines are being read with read_whole_line because of
1084 no-buffering on opt.lfile. */
1085 while ((line = read_whole_line (fp)))
1087 logprintf (LOG_ALWAYS, "%s\n", line);
1092 } /* con->cmd & DO_LIST && server_response */
1094 return RETRFINISHED;
1097 /* A one-file FTP loop. This is the part where FTP retrieval is
1098 retried, and retried, and retried, and...
1100 This loop either gets commands from con, or (if ON_YOUR_OWN is
1101 set), makes them up to retrieve the file given by the URL. */
1103 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1108 char *tmrate = NULL;
1113 con->target = url_file_name (u);
1115 if (opt.noclobber && file_exists_p (con->target))
1117 logprintf (LOG_VERBOSE,
1118 _("File `%s' already there, not retrieving.\n"), con->target);
1119 /* If the file is there, we suppose it's retrieved OK. */
1123 /* Remove it if it's a link. */
1124 remove_link (con->target);
1125 if (!opt.output_document)
1128 locf = opt.output_document;
1132 if (con->st & ON_YOUR_OWN)
1133 con->st = ON_YOUR_OWN;
1135 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1140 /* Increment the pass counter. */
1142 sleep_between_retrievals (count);
1143 if (con->st & ON_YOUR_OWN)
1146 con->cmd |= (DO_RETR | LEAVE_PENDING);
1147 if (con->csock != -1)
1148 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1150 con->cmd |= (DO_LOGIN | DO_CWD);
1152 else /* not on your own */
1154 if (con->csock != -1)
1155 con->cmd &= ~DO_LOGIN;
1157 con->cmd |= DO_LOGIN;
1158 if (con->st & DONE_CWD)
1159 con->cmd &= ~DO_CWD;
1164 /* Assume no restarting. */
1166 if ((count > 1 || opt.always_rest)
1167 && !(con->cmd & DO_LIST)
1168 && file_exists_p (locf))
1169 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1170 restval = st.st_size;
1172 /* In `-c' is used, check whether the file we're writing to
1173 exists and is of non-zero length. If so, we'll refuse to
1174 truncate it if the server doesn't support continued
1176 if (opt.always_rest && restval > 0)
1177 con->cmd |= NO_TRUNCATE;
1179 /* Get the current time string. */
1180 tms = time_str (NULL);
1181 /* Print fetch message, if opt.verbose. */
1184 char *hurl = url_string (u, 1);
1188 sprintf (tmp, _("(try:%2d)"), count);
1189 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1190 tms, hurl, tmp, locf);
1192 ws_changetitle (hurl, 1);
1196 /* Send getftp the proper length, if fileinfo was provided. */
1201 err = getftp (u, &len, restval, con);
1203 if (con->csock != -1)
1204 con->st &= ~DONE_CWD;
1206 con->st |= DONE_CWD;
1210 case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1211 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1212 /* Fatal errors, give up. */
1215 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1216 case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1217 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1218 printwhat (count, opt.ntry);
1219 /* non-fatal errors */
1223 /* If the control connection was closed, the retrieval
1224 will be considered OK if f->size == len. */
1225 if (!f || len != f->size)
1227 printwhat (count, opt.ntry);
1239 tms = time_str (NULL);
1241 tmrate = retr_rate (len - restval, con->dltime, 0);
1243 /* If we get out of the switch above without continue'ing, we've
1244 successfully downloaded a file. Remember this fact. */
1245 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1247 if (con->st & ON_YOUR_OWN)
1249 fd_close (con->csock);
1253 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1254 tms, tmrate, locf, len);
1255 if (!opt.verbose && !opt.quiet)
1257 /* Need to hide the password from the URL. The `if' is here
1258 so that we don't do the needless allocation every
1260 char *hurl = url_string (u, 1);
1261 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1262 tms, hurl, len, locf, count);
1266 if ((con->cmd & DO_LIST))
1267 /* This is a directory listing file. */
1269 if (!opt.remove_listing)
1270 /* --dont-remove-listing was specified, so do count this towards the
1271 number of bytes and files downloaded. */
1273 total_downloaded_bytes += len;
1277 /* Deletion of listing files is not controlled by --delete-after, but
1278 by the more specific option --dont-remove-listing, and the code
1279 to do this deletion is in another function. */
1281 else if (!opt.spider)
1282 /* This is not a directory listing file. */
1284 /* Unlike directory listing files, don't pretend normal files weren't
1285 downloaded if they're going to be deleted. People seeding proxies,
1286 for instance, may want to know how many bytes and files they've
1287 downloaded through it. */
1288 total_downloaded_bytes += len;
1291 if (opt.delete_after)
1293 DEBUGP (("Removing file due to --delete-after in"
1294 " ftp_loop_internal():\n"));
1295 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1297 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1301 /* Restore the original leave-pendingness. */
1303 con->cmd |= LEAVE_PENDING;
1305 con->cmd &= ~LEAVE_PENDING;
1307 } while (!opt.ntry || (count < opt.ntry));
1309 if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1311 fd_close (con->csock);
1317 /* Return the directory listing in a reusable format. The directory
1318 is specifed in u->dir. */
1320 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1323 char *uf; /* url file name */
1324 char *lf; /* list file name */
1325 char *old_target = con->target;
1327 con->st &= ~ON_YOUR_OWN;
1328 con->cmd |= (DO_LIST | LEAVE_PENDING);
1329 con->cmd &= ~DO_RETR;
1331 /* Find the listing file name. We do it by taking the file name of
1332 the URL and replacing the last component with the listing file
1334 uf = url_file_name (u);
1335 lf = file_merge (uf, LIST_FILENAME);
1337 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1340 err = ftp_loop_internal (u, NULL, con);
1341 con->target = old_target;
1344 *f = ftp_parse_ls (lf, con->rs);
1347 if (opt.remove_listing)
1350 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1352 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1355 con->cmd &= ~DO_LIST;
1359 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1361 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1362 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1363 struct fileinfo **));
1364 static void freefileinfo PARAMS ((struct fileinfo *f));
1366 /* Retrieve a list of files given in struct fileinfo linked list. If
1367 a file is a symbolic link, do not retrieve it, but rather try to
1368 set up a similar link on the local disk, if the symlinks are
1371 If opt.recursive is set, after all files have been retrieved,
1372 ftp_retrieve_dirs will be called to retrieve the directories. */
1374 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1376 static int depth = 0;
1378 struct fileinfo *orig;
1383 /* Increase the depth. */
1385 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1387 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1388 depth, opt.reclevel));
1396 con->st &= ~ON_YOUR_OWN;
1397 if (!(con->st & DONE_CWD))
1400 con->cmd &= ~DO_CWD;
1401 con->cmd |= (DO_RETR | LEAVE_PENDING);
1404 con->cmd |= DO_LOGIN;
1406 con->cmd &= ~DO_LOGIN;
1408 err = RETROK; /* in case it's not used */
1412 char *old_target, *ofile;
1414 if (opt.quota && total_downloaded_bytes > opt.quota)
1419 old_target = con->target;
1421 ofile = xstrdup (u->file);
1422 url_set_file (u, f->name);
1424 con->target = url_file_name (u);
1428 if (opt.timestamping && f->type == FT_PLAINFILE)
1431 /* If conversion of HTML files retrieved via FTP is ever implemented,
1432 we'll need to stat() <file>.orig here when -K has been specified.
1433 I'm not implementing it now since files on an FTP server are much
1434 more likely than files on an HTTP server to legitimately have a
1436 if (!stat (con->target, &st))
1440 /* Else, get it from the file. */
1441 local_size = st.st_size;
1444 /* Modification time granularity is 2 seconds for Windows, so
1445 increase local time by 1 second for later comparison. */
1448 /* Compare file sizes only for servers that tell us correct
1449 values. Assumme sizes being equal for servers that lie
1451 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1452 eq_size = cor_val ? (local_size == f->size) : 1 ;
1453 if (f->tstamp <= tml && eq_size)
1455 /* Remote file is older, file sizes can be compared and
1457 logprintf (LOG_VERBOSE, _("\
1458 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1463 /* Remote file is newer or sizes cannot be matched */
1464 logprintf (LOG_VERBOSE, _("\
1465 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1470 /* Sizes do not match */
1471 logprintf (LOG_VERBOSE, _("\
1472 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1475 } /* opt.timestamping && f->type == FT_PLAINFILE */
1479 /* If opt.retr_symlinks is defined, we treat symlinks as
1480 if they were normal files. There is currently no way
1481 to distinguish whether they might be directories, and
1483 if (!opt.retr_symlinks)
1487 logputs (LOG_NOTQUIET,
1488 _("Invalid name of the symlink, skipping.\n"));
1492 /* Check whether we already have the correct
1494 int rc = lstat (con->target, &st);
1497 size_t len = strlen (f->linkto) + 1;
1498 if (S_ISLNK (st.st_mode))
1500 char *link_target = (char *)alloca (len);
1501 size_t n = readlink (con->target, link_target, len);
1503 && (memcmp (link_target, f->linkto, n) == 0))
1505 logprintf (LOG_VERBOSE, _("\
1506 Already have correct symlink %s -> %s\n\n"),
1507 con->target, f->linkto);
1513 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1514 con->target, f->linkto);
1515 /* Unlink before creating symlink! */
1516 unlink (con->target);
1517 if (symlink (f->linkto, con->target) == -1)
1518 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1520 logputs (LOG_VERBOSE, "\n");
1521 } /* have f->linkto */
1522 #else /* not HAVE_SYMLINK */
1523 logprintf (LOG_NOTQUIET,
1524 _("Symlinks not supported, skipping symlink `%s'.\n"),
1526 #endif /* not HAVE_SYMLINK */
1528 else /* opt.retr_symlinks */
1531 err = ftp_loop_internal (u, f, con);
1532 } /* opt.retr_symlinks */
1536 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1540 /* Call the retrieve loop. */
1542 err = ftp_loop_internal (u, f, con);
1545 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1550 /* Set the time-stamp information to the local file. Symlinks
1551 are not to be stamped because it sets the stamp on the
1553 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1556 && file_exists_p (con->target))
1558 /* #### This code repeats in http.c and ftp.c. Move it to a
1560 const char *fl = NULL;
1561 if (opt.output_document)
1563 if (opt.od_known_regular)
1564 fl = opt.output_document;
1569 touch (fl, f->tstamp);
1571 else if (f->tstamp == -1)
1572 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1574 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1576 if (opt.preserve_perm)
1577 chmod (con->target, f->perms);
1580 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1582 xfree (con->target);
1583 con->target = old_target;
1585 url_set_file (u, ofile);
1588 /* Break on fatals. */
1589 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1591 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1595 /* We do not want to call ftp_retrieve_dirs here */
1596 if (opt.recursive &&
1597 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1598 err = ftp_retrieve_dirs (u, orig, con);
1599 else if (opt.recursive)
1600 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1601 depth, opt.reclevel));
1606 /* Retrieve the directories given in a file list. This function works
1607 by simply going through the linked list and calling
1608 ftp_retrieve_glob on each directory entry. The function knows
1609 about excluded directories. */
1611 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1613 char *container = NULL;
1614 int container_size = 0;
1616 for (; f; f = f->next)
1619 char *odir, *newdir;
1621 if (opt.quota && total_downloaded_bytes > opt.quota)
1623 if (f->type != FT_DIRECTORY)
1626 /* Allocate u->dir off stack, but reallocate only if a larger
1627 string is needed. It's a pity there's no "realloca" for an
1628 item on the bottom of the stack. */
1629 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1630 if (size > container_size)
1631 container = (char *)alloca (size);
1636 || (*odir == '/' && *(odir + 1) == '\0'))
1637 /* If ODIR is empty or just "/", simply append f->name to
1638 ODIR. (In the former case, to preserve u->dir being
1639 relative; in the latter case, to avoid double slash.) */
1640 sprintf (newdir, "%s%s", odir, f->name);
1642 /* Else, use a separator. */
1643 sprintf (newdir, "%s/%s", odir, f->name);
1645 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1646 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1647 odir, f->name, newdir));
1648 if (!accdir (newdir, ALLABS))
1650 logprintf (LOG_VERBOSE, _("\
1651 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1655 con->st &= ~DONE_CWD;
1657 odir = xstrdup (u->dir); /* because url_set_dir will free
1659 url_set_dir (u, newdir);
1660 ftp_retrieve_glob (u, con, GETALL);
1661 url_set_dir (u, odir);
1664 /* Set the time-stamp? */
1667 if (opt.quota && total_downloaded_bytes > opt.quota)
1673 /* Return non-zero if S has a leading '/' or contains '../' */
1675 has_insecure_name_p (const char *s)
1680 if (strstr(s, "../") != 0)
1686 /* A near-top-level function to retrieve the files in a directory.
1687 The function calls ftp_get_listing, to get a linked list of files.
1688 Then it weeds out the file names that do not match the pattern.
1689 ftp_retrieve_list is called with this updated list as an argument.
1691 If the argument ACTION is GETONE, just download the file (but first
1692 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1693 use globbing; if it's GETALL, download the whole directory. */
1695 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1697 struct fileinfo *f, *start;
1700 con->cmd |= LEAVE_PENDING;
1702 res = ftp_get_listing (u, con, &start);
1705 /* First: weed out that do not conform the global rules given in
1706 opt.accepts and opt.rejects. */
1707 if (opt.accepts || opt.rejects)
1712 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1714 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1715 f = delelement (f, &start);
1721 /* Remove all files with possible harmful names */
1725 if (has_insecure_name_p (f->name))
1727 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1728 f = delelement (f, &start);
1733 /* Now weed out the files that do not match our globbing pattern.
1734 If we are dealing with a globbing pattern, that is. */
1735 if (*u->file && (action == GLOBALL || action == GETONE))
1742 matchres = fnmatch (u->file, f->name, 0);
1745 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1749 if (matchres == FNM_NOMATCH)
1750 f = delelement (f, &start); /* delete the element from the list */
1752 f = f->next; /* leave the element in the list */
1756 freefileinfo (start);
1757 return RETRBADPATTERN;
1763 /* Just get everything. */
1764 ftp_retrieve_list (u, start, con);
1768 if (action == GLOBALL)
1771 /* #### This message SUCKS. We should see what was the
1772 reason that nothing was retrieved. */
1773 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1775 else /* GETONE or GETALL */
1777 /* Let's try retrieving it anyway. */
1778 con->st |= ON_YOUR_OWN;
1779 res = ftp_loop_internal (u, NULL, con);
1783 freefileinfo (start);
1784 if (opt.quota && total_downloaded_bytes > opt.quota)
1787 /* #### Should we return `res' here? */
1791 /* The wrapper that calls an appropriate routine according to contents
1792 of URL. Inherently, its capabilities are limited on what can be
1793 encoded into a URL. */
1795 ftp_loop (struct url *u, int *dt, struct url *proxy)
1797 ccon con; /* FTP connection */
1802 memset (&con, 0, sizeof (con));
1805 con.st = ON_YOUR_OWN;
1809 res = RETROK; /* in case it's not used */
1811 /* If the file name is empty, the user probably wants a directory
1812 index. We'll provide one, properly HTML-ized. Unless
1813 opt.htmlify is 0, of course. :-) */
1814 if (!*u->file && !opt.recursive)
1817 res = ftp_get_listing (u, &con, &f);
1821 if (opt.htmlify && !opt.spider)
1823 char *filename = (opt.output_document
1824 ? xstrdup (opt.output_document)
1825 : (con.target ? xstrdup (con.target)
1826 : url_file_name (u)));
1827 res = ftp_index (filename, u, f);
1828 if (res == FTPOK && opt.verbose)
1830 if (!opt.output_document)
1834 if (stat (filename, &st) == 0)
1838 logprintf (LOG_NOTQUIET,
1839 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1843 logprintf (LOG_NOTQUIET,
1844 _("Wrote HTML-ized index to `%s'.\n"),
1854 int wild = has_wildcards_p (u->file);
1855 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1857 /* ftp_retrieve_glob is a catch-all function that gets called
1858 if we need globbing, time-stamping or recursion. Its
1859 third argument is just what we really need. */
1860 res = ftp_retrieve_glob (u, &con,
1861 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1864 res = ftp_loop_internal (u, NULL, &con);
1870 /* If a connection was left, quench it. */
1871 if (con.csock != -1)
1872 fd_close (con.csock);
1873 xfree_null (con.id);
1875 xfree_null (con.target);
1880 /* Delete an element from the fileinfo linked list. Returns the
1881 address of the next element, or NULL if the list is exhausted. It
1882 can modify the start of the list. */
1883 static struct fileinfo *
1884 delelement (struct fileinfo *f, struct fileinfo **start)
1886 struct fileinfo *prev = f->prev;
1887 struct fileinfo *next = f->next;
1890 xfree_null (f->linkto);
1902 /* Free the fileinfo linked list of files. */
1904 freefileinfo (struct fileinfo *f)
1908 struct fileinfo *next = f->next;