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>
57 #include "convert.h" /* for downloaded_file */
63 /* File where the "ls -al" listing will be saved. */
64 #define LIST_FILENAME ".listing"
66 extern char ftp_last_respline[];
70 int st; /* connection status */
71 int cmd; /* command code */
72 struct rbuf rbuf; /* control connection buffer */
73 double dltime; /* time of the download in msecs */
74 enum stype rs; /* remote system reported by ftp server */
75 char *id; /* initial directory */
76 char *target; /* target file name */
77 struct url *proxy; /* FTWK-style proxy */
81 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
82 the string S, and return the number converted to long, if found, 0
85 ftp_expected_bytes (const char *s)
91 while (*s && *s != '(')
95 for (++s; *s && ISSPACE (*s); s++);
103 res = (*s - '0') + 10 * res;
106 while (*s && ISDIGIT (*s));
109 while (*s && ISSPACE (*s))
113 if (TOLOWER (*s) != 'b')
115 if (strncasecmp (s, "byte", 4))
123 /* Retrieves a file with denoted parameters through opening an FTP
124 connection to the server. It always closes the data connection,
125 and closes the control connection in case of error. */
127 getftp (struct url *u, long *len, long restval, ccon *con)
129 int csock, dtsock, res;
132 char *user, *passwd, *respline;
135 int pasv_mode_open = 0;
136 long expected_bytes = 0L;
138 assert (con != NULL);
139 assert (con->target != NULL);
141 /* Debug-check of the sanity of the request by making sure that LIST
142 and RETR are never both requested (since we can handle only one
144 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
145 /* Make sure that at least *something* is requested. */
146 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
150 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
151 user = user ? user : opt.ftp_acc;
152 passwd = passwd ? passwd : opt.ftp_pass;
153 assert (user && passwd);
158 if (!(cmd & DO_LOGIN))
159 csock = RBUF_FD (&con->rbuf);
160 else /* cmd & DO_LOGIN */
163 struct address_list *al;
165 char *host = con->proxy ? con->proxy->host : u->host;
166 int port = con->proxy ? con->proxy->port : u->port;
167 char *logname = user;
171 /* If proxy is in use, log in as username@target-site. */
172 logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
173 sprintf (logname, "%s@%s", user, u->host);
176 /* Login to the server: */
178 /* First: Establish the control connection. */
180 al = lookup_host (host, 0);
183 set_connection_host_name (host);
184 csock = connect_to_many (al, port, 0);
185 set_connection_host_name (NULL);
186 address_list_release (al);
189 return CONNECT_ERROR (errno);
191 if (cmd & LEAVE_PENDING)
192 rbuf_initialize (&con->rbuf, csock);
194 rbuf_uninitialize (&con->rbuf);
196 /* Since this is a new connection, we may safely discard
197 anything left in the buffer. */
198 rbuf_discard (&con->rbuf);
200 /* Second: Login with proper USER/PASS sequence. */
201 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
202 if (opt.server_response)
203 logputs (LOG_ALWAYS, "\n");
204 err = ftp_login (&con->rbuf, logname, passwd);
209 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
213 logputs (LOG_VERBOSE, "\n");
214 logputs (LOG_NOTQUIET, _("\
215 Error in server response, closing control connection.\n"));
217 rbuf_uninitialize (&con->rbuf);
221 logputs (LOG_VERBOSE, "\n");
222 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
224 rbuf_uninitialize (&con->rbuf);
228 logputs (LOG_VERBOSE, "\n");
229 logputs (LOG_NOTQUIET,
230 _("Write failed, closing control connection.\n"));
232 rbuf_uninitialize (&con->rbuf);
236 logputs (LOG_VERBOSE, "\n");
237 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
239 rbuf_uninitialize (&con->rbuf);
240 return FTPLOGREFUSED;
243 logputs (LOG_VERBOSE, "\n");
244 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
246 rbuf_uninitialize (&con->rbuf);
250 if (!opt.server_response)
251 logputs (LOG_VERBOSE, _("Logged in!\n"));
258 /* Third: Get the system type */
259 if (!opt.server_response)
260 logprintf (LOG_VERBOSE, "==> SYST ... ");
261 err = ftp_syst (&con->rbuf, &con->rs);
266 logputs (LOG_VERBOSE, "\n");
267 logputs (LOG_NOTQUIET, _("\
268 Error in server response, closing control connection.\n"));
270 rbuf_uninitialize (&con->rbuf);
274 logputs (LOG_VERBOSE, "\n");
275 logputs (LOG_NOTQUIET,
276 _("Server error, can't determine system type.\n"));
279 /* Everything is OK. */
285 if (!opt.server_response && err != FTPSRVERR)
286 logputs (LOG_VERBOSE, _("done. "));
288 /* Fourth: Find the initial ftp directory */
290 if (!opt.server_response)
291 logprintf (LOG_VERBOSE, "==> PWD ... ");
292 err = ftp_pwd(&con->rbuf, &con->id);
297 logputs (LOG_VERBOSE, "\n");
298 logputs (LOG_NOTQUIET, _("\
299 Error in server response, closing control connection.\n"));
301 rbuf_uninitialize (&con->rbuf);
305 /* PWD unsupported -- assume "/". */
306 FREE_MAYBE (con->id);
307 con->id = xstrdup ("/");
310 /* Everything is OK. */
316 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
317 Convert it to "/INITIAL/FOLDER" */
318 if (con->rs == ST_VMS)
320 char *path = strchr (con->id, '[');
321 char *pathend = path ? strchr (path + 1, ']') : NULL;
322 if (!path || !pathend)
323 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
326 char *idir = con->id;
327 DEBUGP (("Preprocessing the initial VMS directory\n"));
328 DEBUGP ((" old = '%s'\n", con->id));
329 /* We do the conversion in-place by copying the stuff
330 between [ and ] to the beginning, and changing dots
331 to slashes at the same time. */
333 for (++path; path < pathend; path++, idir++)
334 *idir = *path == '.' ? '/' : *path;
336 DEBUGP ((" new = '%s'\n\n", con->id));
339 if (!opt.server_response)
340 logputs (LOG_VERBOSE, _("done.\n"));
342 /* Fifth: Set the FTP type. */
343 type_char = ftp_process_type (u->params);
344 if (!opt.server_response)
345 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
346 err = ftp_type (&con->rbuf, type_char);
347 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
351 logputs (LOG_VERBOSE, "\n");
352 logputs (LOG_NOTQUIET, _("\
353 Error in server response, closing control connection.\n"));
355 rbuf_uninitialize (&con->rbuf);
359 logputs (LOG_VERBOSE, "\n");
360 logputs (LOG_NOTQUIET,
361 _("Write failed, closing control connection.\n"));
363 rbuf_uninitialize (&con->rbuf);
367 logputs (LOG_VERBOSE, "\n");
368 logprintf (LOG_NOTQUIET,
369 _("Unknown type `%c', closing control connection.\n"),
372 rbuf_uninitialize (&con->rbuf);
375 /* Everything is OK. */
381 if (!opt.server_response)
382 logputs (LOG_VERBOSE, _("done. "));
388 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
391 char *target = u->dir;
393 DEBUGP (("changing working directory\n"));
395 /* Change working directory. To change to a non-absolute
396 Unix directory, we need to prepend initial directory
397 (con->id) to it. Absolute directories "just work".
399 A relative directory is one that does not begin with '/'
400 and, on non-Unix OS'es, one that doesn't begin with
403 This is not done for OS400, which doesn't use
404 "/"-delimited directories, nor does it support directory
405 hierarchies. "CWD foo" followed by "CWD bar" leaves us
406 in "bar", not in "foo/bar", as would be customary
410 && !(con->rs != ST_UNIX
411 && ISALPHA (target[0])
413 && con->rs != ST_OS400)
415 int idlen = strlen (con->id);
418 /* Strip trailing slash(es) from con->id. */
419 while (idlen > 0 && con->id[idlen - 1] == '/')
421 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
422 memcpy (p, con->id, idlen);
427 DEBUGP (("Prepended initial PWD to relative path:\n"));
428 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
429 con->id, target, ntarget));
433 /* If the FTP host runs VMS, we will have to convert the absolute
434 directory path in UNIX notation to absolute directory path in
435 VMS notation as VMS FTP servers do not like UNIX notation of
436 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
438 if (con->rs == ST_VMS)
441 char *ntarget = (char *)alloca (strlen (target) + 2);
442 /* We use a converted initial dir, so directories in
443 TARGET will be separated with slashes, something like
444 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
445 "[INITIAL.FOLDER.DIR.SUBDIR]". */
446 strcpy (ntarget, target);
447 assert (*ntarget == '/');
449 for (tmpp = ntarget + 1; *tmpp; tmpp++)
454 DEBUGP (("Changed file name to VMS syntax:\n"));
455 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
459 if (!opt.server_response)
460 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
461 err = ftp_cwd (&con->rbuf, target);
462 /* FTPRERR, WRITEFAILED, FTPNSFOD */
466 logputs (LOG_VERBOSE, "\n");
467 logputs (LOG_NOTQUIET, _("\
468 Error in server response, closing control connection.\n"));
470 rbuf_uninitialize (&con->rbuf);
474 logputs (LOG_VERBOSE, "\n");
475 logputs (LOG_NOTQUIET,
476 _("Write failed, closing control connection.\n"));
478 rbuf_uninitialize (&con->rbuf);
482 logputs (LOG_VERBOSE, "\n");
483 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
486 rbuf_uninitialize (&con->rbuf);
496 if (!opt.server_response)
497 logputs (LOG_VERBOSE, _("done.\n"));
500 else /* do not CWD */
501 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
503 if ((cmd & DO_RETR) && restval && *len == 0)
507 if (!opt.server_response)
508 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
511 err = ftp_size(&con->rbuf, u->file, len);
517 logputs (LOG_VERBOSE, "\n");
518 logputs (LOG_NOTQUIET, _("\
519 Error in server response, closing control connection.\n"));
521 rbuf_uninitialize (&con->rbuf);
525 /* Everything is OK. */
531 if (!opt.server_response)
532 logputs (LOG_VERBOSE, _("done.\n"));
535 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
536 if (cmd & (DO_LIST | DO_RETR))
538 if (opt.ftp_pasv > 0)
540 ip_address passive_addr;
541 unsigned short passive_port;
542 if (!opt.server_response)
543 logputs (LOG_VERBOSE, "==> PASV ... ");
544 err = ftp_pasv (&con->rbuf, &passive_addr, &passive_port);
545 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
549 logputs (LOG_VERBOSE, "\n");
550 logputs (LOG_NOTQUIET, _("\
551 Error in server response, closing control connection.\n"));
553 rbuf_uninitialize (&con->rbuf);
557 logputs (LOG_VERBOSE, "\n");
558 logputs (LOG_NOTQUIET,
559 _("Write failed, closing control connection.\n"));
561 rbuf_uninitialize (&con->rbuf);
565 logputs (LOG_VERBOSE, "\n");
566 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
569 logputs (LOG_VERBOSE, "\n");
570 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
581 dtsock = connect_to_one (&passive_addr, passive_port, 1);
584 int save_errno = errno;
586 rbuf_uninitialize (&con->rbuf);
587 logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
588 pretty_print_address (&passive_addr), passive_port,
589 strerror (save_errno));
590 return CONNECT_ERROR (save_errno);
593 pasv_mode_open = 1; /* Flag to avoid accept port */
594 if (!opt.server_response)
595 logputs (LOG_VERBOSE, _("done. "));
599 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
601 if (!opt.server_response)
602 logputs (LOG_VERBOSE, "==> PORT ... ");
603 err = ftp_port (&con->rbuf);
604 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
605 LISTENERR), HOSTERR, FTPPORTERR */
609 logputs (LOG_VERBOSE, "\n");
610 logputs (LOG_NOTQUIET, _("\
611 Error in server response, closing control connection.\n"));
614 rbuf_uninitialize (&con->rbuf);
618 logputs (LOG_VERBOSE, "\n");
619 logputs (LOG_NOTQUIET,
620 _("Write failed, closing control connection.\n"));
623 rbuf_uninitialize (&con->rbuf);
627 logputs (LOG_VERBOSE, "\n");
628 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
631 rbuf_uninitialize (&con->rbuf);
634 case CONPORTERR: case BINDERR: case LISTENERR:
635 /* What now? These problems are local... */
636 logputs (LOG_VERBOSE, "\n");
637 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
643 logputs (LOG_VERBOSE, "\n");
644 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
647 rbuf_uninitialize (&con->rbuf);
657 if (!opt.server_response)
658 logputs (LOG_VERBOSE, _("done. "));
660 } /* cmd & (DO_LIST | DO_RETR) */
662 /* Restart if needed. */
663 if (restval && (cmd & DO_RETR))
665 if (!opt.server_response)
666 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
667 err = ftp_rest (&con->rbuf, restval);
669 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
673 logputs (LOG_VERBOSE, "\n");
674 logputs (LOG_NOTQUIET, _("\
675 Error in server response, closing control connection.\n"));
678 rbuf_uninitialize (&con->rbuf);
682 logputs (LOG_VERBOSE, "\n");
683 logputs (LOG_NOTQUIET,
684 _("Write failed, closing control connection.\n"));
687 rbuf_uninitialize (&con->rbuf);
691 /* If `-c' is specified and the file already existed when
692 Wget was started, it would be a bad idea for us to start
693 downloading it from scratch, effectively truncating it. */
694 if (opt.always_rest && (cmd & NO_TRUNCATE))
696 logprintf (LOG_NOTQUIET,
697 _("\nREST failed; will not truncate `%s'.\n"),
701 rbuf_uninitialize (&con->rbuf);
702 return CONTNOTSUPPORTED;
704 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
714 if (err != FTPRESTFAIL && !opt.server_response)
715 logputs (LOG_VERBOSE, _("done. "));
716 } /* restval && cmd & DO_RETR */
720 /* If we're in spider mode, don't really retrieve anything. The
721 fact that we got to this point should be proof enough that
722 the file exists, vaguely akin to HTTP's concept of a "HEAD"
728 rbuf_uninitialize (&con->rbuf);
734 if (!opt.server_response)
737 logputs (LOG_VERBOSE, "\n");
738 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
741 err = ftp_retr (&con->rbuf, u->file);
742 /* FTPRERR, WRITEFAILED, FTPNSFOD */
746 logputs (LOG_VERBOSE, "\n");
747 logputs (LOG_NOTQUIET, _("\
748 Error in server response, closing control connection.\n"));
751 rbuf_uninitialize (&con->rbuf);
755 logputs (LOG_VERBOSE, "\n");
756 logputs (LOG_NOTQUIET,
757 _("Write failed, closing control connection.\n"));
760 rbuf_uninitialize (&con->rbuf);
764 logputs (LOG_VERBOSE, "\n");
765 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
777 if (!opt.server_response)
778 logputs (LOG_VERBOSE, _("done.\n"));
779 expected_bytes = ftp_expected_bytes (ftp_last_respline);
784 if (!opt.server_response)
785 logputs (LOG_VERBOSE, "==> LIST ... ");
786 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
787 without arguments is better than `LIST .'; confirmed by
789 err = ftp_list (&con->rbuf, NULL);
790 /* FTPRERR, WRITEFAILED */
794 logputs (LOG_VERBOSE, "\n");
795 logputs (LOG_NOTQUIET, _("\
796 Error in server response, closing control connection.\n"));
799 rbuf_uninitialize (&con->rbuf);
803 logputs (LOG_VERBOSE, "\n");
804 logputs (LOG_NOTQUIET,
805 _("Write failed, closing control connection.\n"));
808 rbuf_uninitialize (&con->rbuf);
812 logputs (LOG_VERBOSE, "\n");
813 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
825 if (!opt.server_response)
826 logputs (LOG_VERBOSE, _("done.\n"));
827 expected_bytes = ftp_expected_bytes (ftp_last_respline);
828 } /* cmd & DO_LIST */
830 if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
833 /* Some FTP servers return the total length of file after REST
834 command, others just return the remaining size. */
835 if (*len && restval && expected_bytes
836 && (expected_bytes == *len - restval))
838 DEBUGP (("Lying FTP server found, adjusting.\n"));
839 expected_bytes = *len;
842 /* If no transmission was required, then everything is OK. */
843 if (!pasv_mode_open) /* we are not using pasive mode so we need
846 /* Open the data transmission socket by calling acceptport(). */
847 err = acceptport (&dtsock);
848 /* Possible errors: ACCEPTERR. */
849 if (err == ACCEPTERR)
851 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
856 /* Open the file -- if opt.dfp is set, use it instead. */
857 if (!opt.dfp || con->cmd & DO_LIST)
859 mkalldirs (con->target);
861 rotate_backups (con->target);
862 /* #### Is this correct? */
863 chmod (con->target, 0600);
865 fp = fopen (con->target, restval ? "ab" : "wb");
868 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
870 rbuf_uninitialize (&con->rbuf);
877 extern int global_download_count;
880 /* Rewind the output document if the download starts over and if
881 this is the first download. See gethttp() for a longer
883 if (!restval && global_download_count == 0 && opt.dfp != stdout)
885 /* This will silently fail for streams that don't correspond
886 to regular files, but that's OK. */
888 /* ftruncate is needed because opt.dfp is opened in append
889 mode if opt.always_rest is set. */
890 ftruncate (fileno (fp), 0);
897 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
899 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
900 logputs (LOG_VERBOSE, "\n");
901 expected_bytes = *len; /* for get_contents/show_progress */
903 else if (expected_bytes)
905 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
907 logprintf (LOG_VERBOSE, _(" [%s to go]"),
908 legible (expected_bytes - restval));
909 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
912 /* Get the contents of the document. */
913 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
915 tms = time_str (NULL);
916 tmrate = retr_rate (*len - restval, con->dltime, 0);
917 /* Close data connection socket. */
919 /* Close the local file. */
921 /* Close or flush the file. We have to be careful to check for
922 error here. Checking the result of fwrite() is not enough --
923 errors could go unnoticed! */
925 if (!opt.dfp || con->cmd & DO_LIST)
926 flush_res = fclose (fp);
928 flush_res = fflush (fp);
929 if (flush_res == EOF)
932 /* If get_contents couldn't write to fp, bail out. */
935 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
936 con->target, strerror (errno));
938 rbuf_uninitialize (&con->rbuf);
943 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
944 tms, tmrate, strerror (errno));
945 if (opt.server_response)
946 logputs (LOG_ALWAYS, "\n");
949 /* Get the server to tell us if everything is retrieved. */
950 err = ftp_response (&con->rbuf, &respline);
951 /* ...and empty the buffer. */
952 rbuf_discard (&con->rbuf);
956 /* The control connection is decidedly closed. Print the time
957 only if it hasn't already been printed. */
959 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
960 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
961 /* If there is an error on the control connection, close it, but
962 return FTPRETRINT, since there is a possibility that the
963 whole file was retrieved nevertheless (but that is for
964 ftp_loop_internal to decide). */
966 rbuf_uninitialize (&con->rbuf);
969 /* If retrieval failed for any reason, return FTPRETRINT, but do not
970 close socket, since the control connection is still alive. If
971 there is something wrong with the control connection, it will
972 become apparent later. */
973 if (*respline != '2')
977 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
978 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
985 /* What now? The data connection was erroneous, whereas the
986 response says everything is OK. We shall play it safe. */
990 if (!(cmd & LEAVE_PENDING))
992 /* I should probably send 'QUIT' and check for a reply, but this
993 is faster. #### Is it OK, though? */
995 rbuf_uninitialize (&con->rbuf);
997 /* If it was a listing, and opt.server_response is true,
999 if (opt.server_response && (con->cmd & DO_LIST))
1001 mkalldirs (con->target);
1002 fp = fopen (con->target, "r");
1004 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1008 /* The lines are being read with read_whole_line because of
1009 no-buffering on opt.lfile. */
1010 while ((line = read_whole_line (fp)))
1012 logprintf (LOG_ALWAYS, "%s\n", line);
1017 } /* con->cmd & DO_LIST && server_response */
1019 return RETRFINISHED;
1022 /* A one-file FTP loop. This is the part where FTP retrieval is
1023 retried, and retried, and retried, and...
1025 This loop either gets commands from con, or (if ON_YOUR_OWN is
1026 set), makes them up to retrieve the file given by the URL. */
1028 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1033 char *tmrate = NULL;
1038 con->target = url_file_name (u);
1040 if (opt.noclobber && file_exists_p (con->target))
1042 logprintf (LOG_VERBOSE,
1043 _("File `%s' already there, not retrieving.\n"), con->target);
1044 /* If the file is there, we suppose it's retrieved OK. */
1048 /* Remove it if it's a link. */
1049 remove_link (con->target);
1050 if (!opt.output_document)
1053 locf = opt.output_document;
1057 if (con->st & ON_YOUR_OWN)
1058 con->st = ON_YOUR_OWN;
1060 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1065 /* Increment the pass counter. */
1067 sleep_between_retrievals (count);
1068 if (con->st & ON_YOUR_OWN)
1071 con->cmd |= (DO_RETR | LEAVE_PENDING);
1072 if (rbuf_initialized_p (&con->rbuf))
1073 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1075 con->cmd |= (DO_LOGIN | DO_CWD);
1077 else /* not on your own */
1079 if (rbuf_initialized_p (&con->rbuf))
1080 con->cmd &= ~DO_LOGIN;
1082 con->cmd |= DO_LOGIN;
1083 if (con->st & DONE_CWD)
1084 con->cmd &= ~DO_CWD;
1089 /* Assume no restarting. */
1091 if ((count > 1 || opt.always_rest)
1092 && !(con->cmd & DO_LIST)
1093 && file_exists_p (locf))
1094 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1095 restval = st.st_size;
1097 /* In `-c' is used, check whether the file we're writing to
1098 exists and is of non-zero length. If so, we'll refuse to
1099 truncate it if the server doesn't support continued
1101 if (opt.always_rest && restval > 0)
1102 con->cmd |= NO_TRUNCATE;
1104 /* Get the current time string. */
1105 tms = time_str (NULL);
1106 /* Print fetch message, if opt.verbose. */
1109 char *hurl = url_string (u, 1);
1113 sprintf (tmp, _("(try:%2d)"), count);
1114 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1115 tms, hurl, tmp, locf);
1117 ws_changetitle (hurl, 1);
1121 /* Send getftp the proper length, if fileinfo was provided. */
1126 err = getftp (u, &len, restval, con);
1128 if (!rbuf_initialized_p (&con->rbuf))
1129 con->st &= ~DONE_CWD;
1131 con->st |= DONE_CWD;
1135 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1136 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1137 /* Fatal errors, give up. */
1140 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1141 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1142 case BINDERR: case LISTENERR: case ACCEPTERR:
1143 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1144 printwhat (count, opt.ntry);
1145 /* non-fatal errors */
1149 /* If the control connection was closed, the retrieval
1150 will be considered OK if f->size == len. */
1151 if (!f || len != f->size)
1153 printwhat (count, opt.ntry);
1165 tms = time_str (NULL);
1167 tmrate = retr_rate (len - restval, con->dltime, 0);
1169 /* If we get out of the switch above without continue'ing, we've
1170 successfully downloaded a file. Remember this fact. */
1171 downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1173 if (con->st & ON_YOUR_OWN)
1175 CLOSE (RBUF_FD (&con->rbuf));
1176 rbuf_uninitialize (&con->rbuf);
1179 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1180 tms, tmrate, locf, len);
1181 if (!opt.verbose && !opt.quiet)
1183 /* Need to hide the password from the URL. The `if' is here
1184 so that we don't do the needless allocation every
1186 char *hurl = url_string (u, 1);
1187 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1188 tms, hurl, len, locf, count);
1192 if ((con->cmd & DO_LIST))
1193 /* This is a directory listing file. */
1195 if (!opt.remove_listing)
1196 /* --dont-remove-listing was specified, so do count this towards the
1197 number of bytes and files downloaded. */
1199 downloaded_increase (len);
1203 /* Deletion of listing files is not controlled by --delete-after, but
1204 by the more specific option --dont-remove-listing, and the code
1205 to do this deletion is in another function. */
1207 else if (!opt.spider)
1208 /* This is not a directory listing file. */
1210 /* Unlike directory listing files, don't pretend normal files weren't
1211 downloaded if they're going to be deleted. People seeding proxies,
1212 for instance, may want to know how many bytes and files they've
1213 downloaded through it. */
1214 downloaded_increase (len);
1217 if (opt.delete_after)
1219 DEBUGP (("Removing file due to --delete-after in"
1220 " ftp_loop_internal():\n"));
1221 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1223 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1227 /* Restore the original leave-pendingness. */
1229 con->cmd |= LEAVE_PENDING;
1231 con->cmd &= ~LEAVE_PENDING;
1233 } while (!opt.ntry || (count < opt.ntry));
1235 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1237 CLOSE (RBUF_FD (&con->rbuf));
1238 rbuf_uninitialize (&con->rbuf);
1243 /* Return the directory listing in a reusable format. The directory
1244 is specifed in u->dir. */
1246 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1249 char *uf; /* url file name */
1250 char *lf; /* list file name */
1251 char *old_target = con->target;
1253 con->st &= ~ON_YOUR_OWN;
1254 con->cmd |= (DO_LIST | LEAVE_PENDING);
1255 con->cmd &= ~DO_RETR;
1257 /* Find the listing file name. We do it by taking the file name of
1258 the URL and replacing the last component with the listing file
1260 uf = url_file_name (u);
1261 lf = file_merge (uf, LIST_FILENAME);
1263 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1266 err = ftp_loop_internal (u, NULL, con);
1267 con->target = old_target;
1270 *f = ftp_parse_ls (lf, con->rs);
1273 if (opt.remove_listing)
1276 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1278 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1281 con->cmd &= ~DO_LIST;
1285 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1287 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1288 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1289 struct fileinfo **));
1290 static void freefileinfo PARAMS ((struct fileinfo *f));
1292 /* Retrieve a list of files given in struct fileinfo linked list. If
1293 a file is a symbolic link, do not retrieve it, but rather try to
1294 set up a similar link on the local disk, if the symlinks are
1297 If opt.recursive is set, after all files have been retrieved,
1298 ftp_retrieve_dirs will be called to retrieve the directories. */
1300 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1302 static int depth = 0;
1304 struct fileinfo *orig;
1309 /* Increase the depth. */
1311 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1313 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1314 depth, opt.reclevel));
1322 con->st &= ~ON_YOUR_OWN;
1323 if (!(con->st & DONE_CWD))
1326 con->cmd &= ~DO_CWD;
1327 con->cmd |= (DO_RETR | LEAVE_PENDING);
1329 if (!rbuf_initialized_p (&con->rbuf))
1330 con->cmd |= DO_LOGIN;
1332 con->cmd &= ~DO_LOGIN;
1334 err = RETROK; /* in case it's not used */
1338 char *old_target, *ofile;
1340 if (downloaded_exceeds_quota ())
1345 old_target = con->target;
1347 ofile = xstrdup (u->file);
1348 url_set_file (u, f->name);
1350 con->target = url_file_name (u);
1354 if (opt.timestamping && f->type == FT_PLAINFILE)
1357 /* If conversion of HTML files retrieved via FTP is ever implemented,
1358 we'll need to stat() <file>.orig here when -K has been specified.
1359 I'm not implementing it now since files on an FTP server are much
1360 more likely than files on an HTTP server to legitimately have a
1362 if (!stat (con->target, &st))
1366 /* Else, get it from the file. */
1367 local_size = st.st_size;
1370 /* Modification time granularity is 2 seconds for Windows, so
1371 increase local time by 1 second for later comparison. */
1374 /* Compare file sizes only for servers that tell us correct
1375 values. Assumme sizes being equal for servers that lie
1377 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1378 eq_size = cor_val ? (local_size == f->size) : 1 ;
1379 if (f->tstamp <= tml && eq_size)
1381 /* Remote file is older, file sizes can be compared and
1383 logprintf (LOG_VERBOSE, _("\
1384 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1389 /* Remote file is newer or sizes cannot be matched */
1390 logprintf (LOG_VERBOSE, _("\
1391 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1396 /* Sizes do not match */
1397 logprintf (LOG_VERBOSE, _("\
1398 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1401 } /* opt.timestamping && f->type == FT_PLAINFILE */
1405 /* If opt.retr_symlinks is defined, we treat symlinks as
1406 if they were normal files. There is currently no way
1407 to distinguish whether they might be directories, and
1409 if (!opt.retr_symlinks)
1413 logputs (LOG_NOTQUIET,
1414 _("Invalid name of the symlink, skipping.\n"));
1418 /* Check whether we already have the correct
1420 int rc = lstat (con->target, &st);
1423 size_t len = strlen (f->linkto) + 1;
1424 if (S_ISLNK (st.st_mode))
1426 char *link_target = (char *)alloca (len);
1427 size_t n = readlink (con->target, link_target, len);
1429 && (memcmp (link_target, f->linkto, n) == 0))
1431 logprintf (LOG_VERBOSE, _("\
1432 Already have correct symlink %s -> %s\n\n"),
1433 con->target, f->linkto);
1439 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1440 con->target, f->linkto);
1441 /* Unlink before creating symlink! */
1442 unlink (con->target);
1443 if (symlink (f->linkto, con->target) == -1)
1444 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1446 logputs (LOG_VERBOSE, "\n");
1447 } /* have f->linkto */
1448 #else /* not HAVE_SYMLINK */
1449 logprintf (LOG_NOTQUIET,
1450 _("Symlinks not supported, skipping symlink `%s'.\n"),
1452 #endif /* not HAVE_SYMLINK */
1454 else /* opt.retr_symlinks */
1457 err = ftp_loop_internal (u, f, con);
1458 } /* opt.retr_symlinks */
1462 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1466 /* Call the retrieve loop. */
1468 err = ftp_loop_internal (u, f, con);
1471 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1476 /* Set the time-stamp information to the local file. Symlinks
1477 are not to be stamped because it sets the stamp on the
1479 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1482 && file_exists_p (con->target))
1484 /* #### This code repeats in http.c and ftp.c. Move it to a
1486 const char *fl = NULL;
1487 if (opt.output_document)
1489 if (opt.od_known_regular)
1490 fl = opt.output_document;
1495 touch (fl, f->tstamp);
1497 else if (f->tstamp == -1)
1498 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1500 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1501 chmod (con->target, f->perms);
1503 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1505 xfree (con->target);
1506 con->target = old_target;
1508 url_set_file (u, ofile);
1511 /* Break on fatals. */
1512 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1514 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1518 /* We do not want to call ftp_retrieve_dirs here */
1519 if (opt.recursive &&
1520 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1521 err = ftp_retrieve_dirs (u, orig, con);
1522 else if (opt.recursive)
1523 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1524 depth, opt.reclevel));
1529 /* Retrieve the directories given in a file list. This function works
1530 by simply going through the linked list and calling
1531 ftp_retrieve_glob on each directory entry. The function knows
1532 about excluded directories. */
1534 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1536 char *container = NULL;
1537 int container_size = 0;
1539 for (; f; f = f->next)
1542 char *odir, *newdir;
1544 if (downloaded_exceeds_quota ())
1546 if (f->type != FT_DIRECTORY)
1549 /* Allocate u->dir off stack, but reallocate only if a larger
1550 string is needed. It's a pity there's no "realloca" for an
1551 item on the bottom of the stack. */
1552 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1553 if (size > container_size)
1554 container = (char *)alloca (size);
1559 || (*odir == '/' && *(odir + 1) == '\0'))
1560 /* If ODIR is empty or just "/", simply append f->name to
1561 ODIR. (In the former case, to preserve u->dir being
1562 relative; in the latter case, to avoid double slash.) */
1563 sprintf (newdir, "%s%s", odir, f->name);
1565 /* Else, use a separator. */
1566 sprintf (newdir, "%s/%s", odir, f->name);
1568 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1569 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1570 odir, f->name, newdir));
1571 if (!accdir (newdir, ALLABS))
1573 logprintf (LOG_VERBOSE, _("\
1574 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1578 con->st &= ~DONE_CWD;
1580 odir = xstrdup (u->dir); /* because url_set_dir will free
1582 url_set_dir (u, newdir);
1583 ftp_retrieve_glob (u, con, GETALL);
1584 url_set_dir (u, odir);
1587 /* Set the time-stamp? */
1590 if (opt.quota && opt.downloaded > opt.quota)
1597 /* A near-top-level function to retrieve the files in a directory.
1598 The function calls ftp_get_listing, to get a linked list of files.
1599 Then it weeds out the file names that do not match the pattern.
1600 ftp_retrieve_list is called with this updated list as an argument.
1602 If the argument ACTION is GETONE, just download the file (but first
1603 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1604 use globbing; if it's GETALL, download the whole directory. */
1606 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1608 struct fileinfo *f, *orig, *start;
1611 con->cmd |= LEAVE_PENDING;
1613 res = ftp_get_listing (u, con, &orig);
1617 /* First: weed out that do not conform the global rules given in
1618 opt.accepts and opt.rejects. */
1619 if (opt.accepts || opt.rejects)
1624 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1626 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1627 f = delelement (f, &start);
1633 /* Remove all files with possible harmful names */
1637 if (has_insecure_name_p(f->name))
1639 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1640 f = delelement (f, &start);
1645 /* Now weed out the files that do not match our globbing pattern.
1646 If we are dealing with a globbing pattern, that is. */
1647 if (*u->file && (action == GLOBALL || action == GETONE))
1654 matchres = fnmatch (u->file, f->name, 0);
1657 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1661 if (matchres == FNM_NOMATCH)
1662 f = delelement (f, &start); /* delete the element from the list */
1664 f = f->next; /* leave the element in the list */
1668 freefileinfo (start);
1669 return RETRBADPATTERN;
1675 /* Just get everything. */
1676 ftp_retrieve_list (u, start, con);
1680 if (action == GLOBALL)
1683 /* #### This message SUCKS. We should see what was the
1684 reason that nothing was retrieved. */
1685 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1687 else /* GETONE or GETALL */
1689 /* Let's try retrieving it anyway. */
1690 con->st |= ON_YOUR_OWN;
1691 res = ftp_loop_internal (u, NULL, con);
1695 freefileinfo (start);
1696 if (downloaded_exceeds_quota ())
1699 /* #### Should we return `res' here? */
1703 /* The wrapper that calls an appropriate routine according to contents
1704 of URL. Inherently, its capabilities are limited on what can be
1705 encoded into a URL. */
1707 ftp_loop (struct url *u, int *dt, struct url *proxy)
1709 ccon con; /* FTP connection */
1714 memset (&con, 0, sizeof (con));
1716 rbuf_uninitialize (&con.rbuf);
1717 con.st = ON_YOUR_OWN;
1721 res = RETROK; /* in case it's not used */
1723 /* If the file name is empty, the user probably wants a directory
1724 index. We'll provide one, properly HTML-ized. Unless
1725 opt.htmlify is 0, of course. :-) */
1726 if (!*u->file && !opt.recursive)
1729 res = ftp_get_listing (u, &con, &f);
1733 if (opt.htmlify && !opt.spider)
1735 char *filename = (opt.output_document
1736 ? xstrdup (opt.output_document)
1737 : (con.target ? xstrdup (con.target)
1738 : url_file_name (u)));
1739 res = ftp_index (filename, u, f);
1740 if (res == FTPOK && opt.verbose)
1742 if (!opt.output_document)
1746 if (stat (filename, &st) == 0)
1750 logprintf (LOG_NOTQUIET,
1751 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1755 logprintf (LOG_NOTQUIET,
1756 _("Wrote HTML-ized index to `%s'.\n"),
1766 int wild = has_wildcards_p (u->file);
1767 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1769 /* ftp_retrieve_glob is a catch-all function that gets called
1770 if we need globbing, time-stamping or recursion. Its
1771 third argument is just what we really need. */
1772 res = ftp_retrieve_glob (u, &con,
1773 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1776 res = ftp_loop_internal (u, NULL, &con);
1782 /* If a connection was left, quench it. */
1783 if (rbuf_initialized_p (&con.rbuf))
1784 CLOSE (RBUF_FD (&con.rbuf));
1785 FREE_MAYBE (con.id);
1787 FREE_MAYBE (con.target);
1792 /* Delete an element from the fileinfo linked list. Returns the
1793 address of the next element, or NULL if the list is exhausted. It
1794 can modify the start of the list. */
1795 static struct fileinfo *
1796 delelement (struct fileinfo *f, struct fileinfo **start)
1798 struct fileinfo *prev = f->prev;
1799 struct fileinfo *next = f->next;
1802 FREE_MAYBE (f->linkto);
1814 /* Free the fileinfo linked list of files. */
1816 freefileinfo (struct fileinfo *f)
1820 struct fileinfo *next = f->next;