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. */
33 #include <sys/types.h>
52 /* File where the "ls -al" listing will be saved. */
53 #define LIST_FILENAME ".listing"
55 extern char ftp_last_respline[];
59 int st; /* connection status */
60 int cmd; /* command code */
61 struct rbuf rbuf; /* control connection buffer */
62 long dltime; /* time of the download */
63 enum stype rs; /* remote system reported by ftp server */
64 char *id; /* initial directory */
65 char *target; /* target file name */
69 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
70 the string S, and return the number converted to long, if found, 0
73 ftp_expected_bytes (const char *s)
79 while (*s && *s != '(')
83 for (++s; *s && ISSPACE (*s); s++);
91 res = (*s - '0') + 10 * res;
94 while (*s && ISDIGIT (*s));
97 while (*s && ISSPACE (*s))
101 if (TOLOWER (*s) != 'b')
103 if (strncasecmp (s, "byte", 4))
111 /* Retrieves a file with denoted parameters through opening an FTP
112 connection to the server. It always closes the data connection,
113 and closes the control connection in case of error. */
115 getftp (struct url *u, long *len, long restval, ccon *con)
117 int csock, dtsock, res;
120 char *user, *passwd, *respline;
122 unsigned char pasv_addr[6];
124 int passive_mode_open = 0;
125 long expected_bytes = 0L;
127 assert (con != NULL);
128 assert (con->target != NULL);
130 /* Debug-check of the sanity of the request by making sure that LIST
131 and RETR are never both requested (since we can handle only one
133 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
134 /* Make sure that at least *something* is requested. */
135 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
139 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
140 user = user ? user : opt.ftp_acc;
141 passwd = passwd ? passwd : opt.ftp_pass;
142 assert (user && passwd);
147 if (!(cmd & DO_LOGIN))
148 csock = RBUF_FD (&con->rbuf);
149 else /* cmd & DO_LOGIN */
152 struct address_list *al;
154 /* Login to the server: */
156 /* First: Establish the control connection. */
158 al = lookup_host (u->host, 0);
161 set_connection_host_name (u->host);
162 csock = connect_to_many (al, u->port, 0);
163 set_connection_host_name (NULL);
164 address_list_release (al);
167 return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
169 if (cmd & LEAVE_PENDING)
170 rbuf_initialize (&con->rbuf, csock);
172 rbuf_uninitialize (&con->rbuf);
174 /* Since this is a new connection, we may safely discard
175 anything left in the buffer. */
176 rbuf_discard (&con->rbuf);
178 /* Second: Login with proper USER/PASS sequence. */
179 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
180 if (opt.server_response)
181 logputs (LOG_ALWAYS, "\n");
182 err = ftp_login (&con->rbuf, user, passwd);
183 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
187 logputs (LOG_VERBOSE, "\n");
188 logputs (LOG_NOTQUIET, _("\
189 Error in server response, closing control connection.\n"));
191 rbuf_uninitialize (&con->rbuf);
195 logputs (LOG_VERBOSE, "\n");
196 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
198 rbuf_uninitialize (&con->rbuf);
202 logputs (LOG_VERBOSE, "\n");
203 logputs (LOG_NOTQUIET,
204 _("Write failed, closing control connection.\n"));
206 rbuf_uninitialize (&con->rbuf);
210 logputs (LOG_VERBOSE, "\n");
211 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
213 rbuf_uninitialize (&con->rbuf);
214 return FTPLOGREFUSED;
217 logputs (LOG_VERBOSE, "\n");
218 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
220 rbuf_uninitialize (&con->rbuf);
224 if (!opt.server_response)
225 logputs (LOG_VERBOSE, _("Logged in!\n"));
232 /* Third: Get the system type */
233 if (!opt.server_response)
234 logprintf (LOG_VERBOSE, "==> SYST ... ");
235 err = ftp_syst (&con->rbuf, &con->rs);
240 logputs (LOG_VERBOSE, "\n");
241 logputs (LOG_NOTQUIET, _("\
242 Error in server response, closing control connection.\n"));
244 rbuf_uninitialize (&con->rbuf);
248 logputs (LOG_VERBOSE, "\n");
249 logputs (LOG_NOTQUIET,
250 _("Server error, can't determine system type.\n"));
253 /* Everything is OK. */
259 if (!opt.server_response && err != FTPSRVERR)
260 logputs (LOG_VERBOSE, _("done. "));
262 /* Fourth: Find the initial ftp directory */
264 if (!opt.server_response)
265 logprintf (LOG_VERBOSE, "==> PWD ... ");
266 err = ftp_pwd(&con->rbuf, &con->id);
271 logputs (LOG_VERBOSE, "\n");
272 logputs (LOG_NOTQUIET, _("\
273 Error in server response, closing control connection.\n"));
275 rbuf_uninitialize (&con->rbuf);
279 /* PWD unsupported -- assume "/". */
280 FREE_MAYBE (con->id);
281 con->id = xstrdup ("/");
284 /* Everything is OK. */
290 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
291 Convert it to "/INITIAL/FOLDER" */
292 if (con->rs == ST_VMS)
294 char *path = strchr (con->id, '[');
295 char *pathend = path ? strchr (path + 1, ']') : NULL;
296 if (!path || !pathend)
297 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
300 char *idir = con->id;
301 DEBUGP (("Preprocessing the initial VMS directory\n"));
302 DEBUGP ((" old = '%s'\n", con->id));
303 /* We do the conversion in-place by copying the stuff
304 between [ and ] to the beginning, and changing dots
305 to slashes at the same time. */
307 for (++path; path < pathend; path++, idir++)
308 *idir = *path == '.' ? '/' : *path;
310 DEBUGP ((" new = '%s'\n\n", con->id));
313 if (!opt.server_response)
314 logputs (LOG_VERBOSE, _("done.\n"));
316 /* Fifth: Set the FTP type. */
317 type_char = ftp_process_type (u->params);
318 if (!opt.server_response)
319 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
320 err = ftp_type (&con->rbuf, type_char);
321 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
325 logputs (LOG_VERBOSE, "\n");
326 logputs (LOG_NOTQUIET, _("\
327 Error in server response, closing control connection.\n"));
329 rbuf_uninitialize (&con->rbuf);
333 logputs (LOG_VERBOSE, "\n");
334 logputs (LOG_NOTQUIET,
335 _("Write failed, closing control connection.\n"));
337 rbuf_uninitialize (&con->rbuf);
341 logputs (LOG_VERBOSE, "\n");
342 logprintf (LOG_NOTQUIET,
343 _("Unknown type `%c', closing control connection.\n"),
346 rbuf_uninitialize (&con->rbuf);
349 /* Everything is OK. */
355 if (!opt.server_response)
356 logputs (LOG_VERBOSE, _("done. "));
362 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
365 char *target = u->dir;
367 DEBUGP (("changing working directory\n"));
369 /* Change working directory. To change to a non-absolute
370 Unix directory, we need to prepend initial directory
371 (con->id) to it. Absolute directories "just work". */
375 int idlen = strlen (con->id);
376 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
377 /* idlen == 1 means con->id = "/" */
378 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
380 DEBUGP (("Prepended initial PWD to relative path:\n"));
381 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
385 /* If the FTP host runs VMS, we will have to convert the absolute
386 directory path in UNIX notation to absolute directory path in
387 VMS notation as VMS FTP servers do not like UNIX notation of
388 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
390 if (con->rs == ST_VMS)
393 char *ntarget = (char *)alloca (strlen (target) + 2);
394 /* We use a converted initial dir, so directories in
395 TARGET will be separated with slashes, something like
396 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
397 "[INITIAL.FOLDER.DIR.SUBDIR]". */
398 strcpy (ntarget, target);
399 assert (*ntarget == '/');
401 for (tmpp = ntarget + 1; *tmpp; tmpp++)
406 DEBUGP (("Changed file name to VMS syntax:\n"));
407 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
411 if (!opt.server_response)
412 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
413 err = ftp_cwd (&con->rbuf, target);
414 /* FTPRERR, WRITEFAILED, FTPNSFOD */
418 logputs (LOG_VERBOSE, "\n");
419 logputs (LOG_NOTQUIET, _("\
420 Error in server response, closing control connection.\n"));
422 rbuf_uninitialize (&con->rbuf);
426 logputs (LOG_VERBOSE, "\n");
427 logputs (LOG_NOTQUIET,
428 _("Write failed, closing control connection.\n"));
430 rbuf_uninitialize (&con->rbuf);
434 logputs (LOG_VERBOSE, "\n");
435 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
438 rbuf_uninitialize (&con->rbuf);
448 if (!opt.server_response)
449 logputs (LOG_VERBOSE, _("done.\n"));
452 else /* do not CWD */
453 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
455 if ((cmd & DO_RETR) && restval && *len == 0)
459 if (!opt.server_response)
460 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
463 err = ftp_size(&con->rbuf, u->file, len);
469 logputs (LOG_VERBOSE, "\n");
470 logputs (LOG_NOTQUIET, _("\
471 Error in server response, closing control connection.\n"));
473 rbuf_uninitialize (&con->rbuf);
477 /* Everything is OK. */
483 if (!opt.server_response)
484 logputs (LOG_VERBOSE, _("done.\n"));
487 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
488 if (cmd & (DO_LIST | DO_RETR))
490 if (opt.ftp_pasv > 0)
492 if (!opt.server_response)
493 logputs (LOG_VERBOSE, "==> PASV ... ");
494 err = ftp_pasv (&con->rbuf, pasv_addr);
495 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
499 logputs (LOG_VERBOSE, "\n");
500 logputs (LOG_NOTQUIET, _("\
501 Error in server response, closing control connection.\n"));
503 rbuf_uninitialize (&con->rbuf);
507 logputs (LOG_VERBOSE, "\n");
508 logputs (LOG_NOTQUIET,
509 _("Write failed, closing control connection.\n"));
511 rbuf_uninitialize (&con->rbuf);
515 logputs (LOG_VERBOSE, "\n");
516 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
519 logputs (LOG_VERBOSE, "\n");
520 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
531 unsigned short tport;
533 tport = (pasv_addr[4] << 8) + pasv_addr[5];
534 dtsock = connect_to_one (pasv_addr, tport, 1);
538 int save_errno = errno;
540 rbuf_uninitialize (&con->rbuf);
541 logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
542 pretty_print_address (pasv_addr), tport,
543 strerror (save_errno));
544 return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
547 passive_mode_open = 1; /* Flag to avoid accept port */
548 if (!opt.server_response)
549 logputs (LOG_VERBOSE, _("done. "));
553 if (!passive_mode_open) /* Try to use a port command if PASV failed */
555 if (!opt.server_response)
556 logputs (LOG_VERBOSE, "==> PORT ... ");
557 err = ftp_port (&con->rbuf);
558 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
559 LISTENERR), HOSTERR, FTPPORTERR */
563 logputs (LOG_VERBOSE, "\n");
564 logputs (LOG_NOTQUIET, _("\
565 Error in server response, closing control connection.\n"));
568 rbuf_uninitialize (&con->rbuf);
572 logputs (LOG_VERBOSE, "\n");
573 logputs (LOG_NOTQUIET,
574 _("Write failed, closing control connection.\n"));
577 rbuf_uninitialize (&con->rbuf);
581 logputs (LOG_VERBOSE, "\n");
582 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
585 rbuf_uninitialize (&con->rbuf);
588 case CONPORTERR: case BINDERR: case LISTENERR:
589 /* What now? These problems are local... */
590 logputs (LOG_VERBOSE, "\n");
591 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
597 logputs (LOG_VERBOSE, "\n");
598 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
601 rbuf_uninitialize (&con->rbuf);
611 if (!opt.server_response)
612 logputs (LOG_VERBOSE, _("done. "));
614 } /* cmd & (DO_LIST | DO_RETR) */
616 /* Restart if needed. */
617 if (restval && (cmd & DO_RETR))
619 if (!opt.server_response)
620 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
621 err = ftp_rest (&con->rbuf, restval);
623 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
627 logputs (LOG_VERBOSE, "\n");
628 logputs (LOG_NOTQUIET, _("\
629 Error in server response, closing control connection.\n"));
632 rbuf_uninitialize (&con->rbuf);
636 logputs (LOG_VERBOSE, "\n");
637 logputs (LOG_NOTQUIET,
638 _("Write failed, closing control connection.\n"));
641 rbuf_uninitialize (&con->rbuf);
645 /* If `-c' is specified and the file already existed when
646 Wget was started, it would be a bad idea for us to start
647 downloading it from scratch, effectively truncating it. */
648 if (opt.always_rest && (cmd & NO_TRUNCATE))
650 logprintf (LOG_NOTQUIET,
651 _("\nREST failed; will not truncate `%s'.\n"),
655 rbuf_uninitialize (&con->rbuf);
656 return CONTNOTSUPPORTED;
658 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
668 if (err != FTPRESTFAIL && !opt.server_response)
669 logputs (LOG_VERBOSE, _("done. "));
670 } /* restval && cmd & DO_RETR */
676 if (!opt.server_response)
679 logputs (LOG_VERBOSE, "\n");
680 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
683 err = ftp_retr (&con->rbuf, u->file);
684 /* FTPRERR, WRITEFAILED, FTPNSFOD */
688 logputs (LOG_VERBOSE, "\n");
689 logputs (LOG_NOTQUIET, _("\
690 Error in server response, closing control connection.\n"));
693 rbuf_uninitialize (&con->rbuf);
697 logputs (LOG_VERBOSE, "\n");
698 logputs (LOG_NOTQUIET,
699 _("Write failed, closing control connection.\n"));
702 rbuf_uninitialize (&con->rbuf);
706 logputs (LOG_VERBOSE, "\n");
707 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
719 if (!opt.server_response)
720 logputs (LOG_VERBOSE, _("done.\n"));
721 expected_bytes = ftp_expected_bytes (ftp_last_respline);
726 if (!opt.server_response)
727 logputs (LOG_VERBOSE, "==> LIST ... ");
728 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
729 without arguments is better than `LIST .'; confirmed by
731 err = ftp_list (&con->rbuf, NULL);
732 /* FTPRERR, WRITEFAILED */
736 logputs (LOG_VERBOSE, "\n");
737 logputs (LOG_NOTQUIET, _("\
738 Error in server response, closing control connection.\n"));
741 rbuf_uninitialize (&con->rbuf);
745 logputs (LOG_VERBOSE, "\n");
746 logputs (LOG_NOTQUIET,
747 _("Write failed, closing control connection.\n"));
750 rbuf_uninitialize (&con->rbuf);
754 logputs (LOG_VERBOSE, "\n");
755 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
767 if (!opt.server_response)
768 logputs (LOG_VERBOSE, _("done.\n"));
769 expected_bytes = ftp_expected_bytes (ftp_last_respline);
770 } /* cmd & DO_LIST */
772 /* Some FTP servers return the total length of file after REST
773 command, others just return the remaining size. */
774 if (*len && restval && expected_bytes
775 && (expected_bytes == *len - restval))
777 DEBUGP (("Lying FTP server found, adjusting.\n"));
778 expected_bytes = *len;
781 /* If no transmission was required, then everything is OK. */
782 if (!(cmd & (DO_LIST | DO_RETR)))
785 if (!passive_mode_open) /* we are not using pasive mode so we need
788 /* Open the data transmission socket by calling acceptport(). */
789 err = acceptport (&dtsock);
790 /* Possible errors: ACCEPTERR. */
791 if (err == ACCEPTERR)
793 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
798 /* Open the file -- if opt.dfp is set, use it instead. */
799 if (!opt.dfp || con->cmd & DO_LIST)
801 mkalldirs (con->target);
803 rotate_backups (con->target);
804 /* #### Is this correct? */
805 chmod (con->target, 0600);
807 fp = fopen (con->target, restval ? "ab" : "wb");
810 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
812 rbuf_uninitialize (&con->rbuf);
819 extern int global_download_count;
822 /* Rewind the output document if the download starts over and if
823 this is the first download. See gethttp() for a longer
825 if (!restval && global_download_count == 0)
827 /* This will silently fail for streams that don't correspond
828 to regular files, but that's OK. */
830 /* ftruncate is needed because opt.dfp is opened in append
831 mode if opt.always_rest is set. */
832 ftruncate (fileno (fp), 0);
839 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
841 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
842 logputs (LOG_VERBOSE, "\n");
843 expected_bytes = *len; /* for get_contents/show_progress */
845 else if (expected_bytes)
847 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
849 logprintf (LOG_VERBOSE, _(" [%s to go]"),
850 legible (expected_bytes - restval));
851 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
854 /* Get the contents of the document. */
855 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
857 tms = time_str (NULL);
858 tmrate = retr_rate (*len - restval, con->dltime, 0);
859 /* Close data connection socket. */
861 /* Close the local file. */
863 /* Close or flush the file. We have to be careful to check for
864 error here. Checking the result of fwrite() is not enough --
865 errors could go unnoticed! */
867 if (!opt.dfp || con->cmd & DO_LIST)
868 flush_res = fclose (fp);
870 flush_res = fflush (fp);
871 if (flush_res == EOF)
874 /* If get_contents couldn't write to fp, bail out. */
877 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
878 con->target, strerror (errno));
880 rbuf_uninitialize (&con->rbuf);
885 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
886 tms, tmrate, strerror (errno));
887 if (opt.server_response)
888 logputs (LOG_ALWAYS, "\n");
891 /* Get the server to tell us if everything is retrieved. */
892 err = ftp_response (&con->rbuf, &respline);
893 /* ...and empty the buffer. */
894 rbuf_discard (&con->rbuf);
898 /* The control connection is decidedly closed. Print the time
899 only if it hasn't already been printed. */
901 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
902 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
903 /* If there is an error on the control connection, close it, but
904 return FTPRETRINT, since there is a possibility that the
905 whole file was retrieved nevertheless (but that is for
906 ftp_loop_internal to decide). */
908 rbuf_uninitialize (&con->rbuf);
911 /* If retrieval failed for any reason, return FTPRETRINT, but do not
912 close socket, since the control connection is still alive. If
913 there is something wrong with the control connection, it will
914 become apparent later. */
915 if (*respline != '2')
919 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
920 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
927 /* What now? The data connection was erroneous, whereas the
928 response says everything is OK. We shall play it safe. */
932 if (!(cmd & LEAVE_PENDING))
934 /* I should probably send 'QUIT' and check for a reply, but this
935 is faster. #### Is it OK, though? */
937 rbuf_uninitialize (&con->rbuf);
939 /* If it was a listing, and opt.server_response is true,
941 if (opt.server_response && (con->cmd & DO_LIST))
943 mkalldirs (con->target);
944 fp = fopen (con->target, "r");
946 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
950 /* The lines are being read with read_whole_line because of
951 no-buffering on opt.lfile. */
952 while ((line = read_whole_line (fp)))
954 logprintf (LOG_ALWAYS, "%s\n", line);
959 } /* con->cmd & DO_LIST && server_response */
964 /* A one-file FTP loop. This is the part where FTP retrieval is
965 retried, and retried, and retried, and...
967 This loop either gets commands from con, or (if ON_YOUR_OWN is
968 set), makes them up to retrieve the file given by the URL. */
970 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
974 char *tms, *tmrate, *locf;
979 con->target = url_filename (u);
981 if (opt.noclobber && file_exists_p (con->target))
983 logprintf (LOG_VERBOSE,
984 _("File `%s' already there, not retrieving.\n"), con->target);
985 /* If the file is there, we suppose it's retrieved OK. */
989 /* Remove it if it's a link. */
990 remove_link (con->target);
991 if (!opt.output_document)
994 locf = opt.output_document;
998 if (con->st & ON_YOUR_OWN)
999 con->st = ON_YOUR_OWN;
1001 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1006 /* Increment the pass counter. */
1008 sleep_between_retrievals (count);
1009 if (con->st & ON_YOUR_OWN)
1012 con->cmd |= (DO_RETR | LEAVE_PENDING);
1013 if (rbuf_initialized_p (&con->rbuf))
1014 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1016 con->cmd |= (DO_LOGIN | DO_CWD);
1018 else /* not on your own */
1020 if (rbuf_initialized_p (&con->rbuf))
1021 con->cmd &= ~DO_LOGIN;
1023 con->cmd |= DO_LOGIN;
1024 if (con->st & DONE_CWD)
1025 con->cmd &= ~DO_CWD;
1030 /* Assume no restarting. */
1032 if ((count > 1 || opt.always_rest)
1033 && !(con->cmd & DO_LIST)
1034 && file_exists_p (locf))
1035 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1036 restval = st.st_size;
1038 /* In `-c' is used, check whether the file we're writing to
1039 exists and is of non-zero length. If so, we'll refuse to
1040 truncate it if the server doesn't support continued
1042 if (opt.always_rest && restval > 0)
1043 con->cmd |= NO_TRUNCATE;
1045 /* Get the current time string. */
1046 tms = time_str (NULL);
1047 /* Print fetch message, if opt.verbose. */
1050 char *hurl = url_string (u, 1);
1054 sprintf (tmp, _("(try:%2d)"), count);
1055 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1056 tms, hurl, tmp, locf);
1058 ws_changetitle (hurl, 1);
1062 /* Send getftp the proper length, if fileinfo was provided. */
1067 err = getftp (u, &len, restval, con);
1069 if (!rbuf_initialized_p (&con->rbuf))
1070 con->st &= ~DONE_CWD;
1072 con->st |= DONE_CWD;
1076 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1077 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1078 /* Fatal errors, give up. */
1081 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1082 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1083 case BINDERR: case LISTENERR: case ACCEPTERR:
1084 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1085 printwhat (count, opt.ntry);
1086 /* non-fatal errors */
1090 /* If the control connection was closed, the retrieval
1091 will be considered OK if f->size == len. */
1092 if (!f || len != f->size)
1094 printwhat (count, opt.ntry);
1106 tms = time_str (NULL);
1107 tmrate = retr_rate (len - restval, con->dltime, 0);
1109 /* If we get out of the switch above without continue'ing, we've
1110 successfully downloaded a file. Remember this fact. */
1111 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1113 if (con->st & ON_YOUR_OWN)
1115 CLOSE (RBUF_FD (&con->rbuf));
1116 rbuf_uninitialize (&con->rbuf);
1118 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1119 tms, tmrate, locf, len);
1120 if (!opt.verbose && !opt.quiet)
1122 /* Need to hide the password from the URL. The `if' is here
1123 so that we don't do the needless allocation every
1125 char *hurl = url_string (u, 1);
1126 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1127 tms, hurl, len, locf, count);
1131 if ((con->cmd & DO_LIST))
1132 /* This is a directory listing file. */
1134 if (!opt.remove_listing)
1135 /* --dont-remove-listing was specified, so do count this towards the
1136 number of bytes and files downloaded. */
1138 downloaded_increase (len);
1142 /* Deletion of listing files is not controlled by --delete-after, but
1143 by the more specific option --dont-remove-listing, and the code
1144 to do this deletion is in another function. */
1147 /* This is not a directory listing file. */
1149 /* Unlike directory listing files, don't pretend normal files weren't
1150 downloaded if they're going to be deleted. People seeding proxies,
1151 for instance, may want to know how many bytes and files they've
1152 downloaded through it. */
1153 downloaded_increase (len);
1156 if (opt.delete_after)
1158 DEBUGP (("Removing file due to --delete-after in"
1159 " ftp_loop_internal():\n"));
1160 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1162 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1166 /* Restore the original leave-pendingness. */
1168 con->cmd |= LEAVE_PENDING;
1170 con->cmd &= ~LEAVE_PENDING;
1172 } while (!opt.ntry || (count < opt.ntry));
1174 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1176 CLOSE (RBUF_FD (&con->rbuf));
1177 rbuf_uninitialize (&con->rbuf);
1182 /* Return the directory listing in a reusable format. The directory
1183 is specifed in u->dir. */
1185 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1188 char *uf; /* url file name */
1189 char *lf; /* list file name */
1190 char *old_target = con->target;
1192 con->st &= ~ON_YOUR_OWN;
1193 con->cmd |= (DO_LIST | LEAVE_PENDING);
1194 con->cmd &= ~DO_RETR;
1196 /* Find the listing file name. We do it by taking the file name of
1197 the URL and replacing the last component with the listing file
1199 uf = url_filename (u);
1200 lf = file_merge (uf, LIST_FILENAME);
1202 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1205 err = ftp_loop_internal (u, NULL, con);
1206 con->target = old_target;
1209 *f = ftp_parse_ls (lf, con->rs);
1212 if (opt.remove_listing)
1215 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1217 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1220 con->cmd &= ~DO_LIST;
1224 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1226 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1227 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1228 struct fileinfo **));
1229 static void freefileinfo PARAMS ((struct fileinfo *f));
1231 /* Retrieve a list of files given in struct fileinfo linked list. If
1232 a file is a symbolic link, do not retrieve it, but rather try to
1233 set up a similar link on the local disk, if the symlinks are
1236 If opt.recursive is set, after all files have been retrieved,
1237 ftp_retrieve_dirs will be called to retrieve the directories. */
1239 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1241 static int depth = 0;
1243 struct fileinfo *orig;
1248 /* Increase the depth. */
1250 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1252 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1253 depth, opt.reclevel));
1261 con->st &= ~ON_YOUR_OWN;
1262 if (!(con->st & DONE_CWD))
1265 con->cmd &= ~DO_CWD;
1266 con->cmd |= (DO_RETR | LEAVE_PENDING);
1268 if (!rbuf_initialized_p (&con->rbuf))
1269 con->cmd |= DO_LOGIN;
1271 con->cmd &= ~DO_LOGIN;
1273 err = RETROK; /* in case it's not used */
1277 char *old_target, *ofile;
1279 if (downloaded_exceeds_quota ())
1284 old_target = con->target;
1286 ofile = xstrdup (u->file);
1287 url_set_file (u, f->name);
1289 con->target = url_filename (u);
1293 if (opt.timestamping && f->type == FT_PLAINFILE)
1296 /* If conversion of HTML files retrieved via FTP is ever implemented,
1297 we'll need to stat() <file>.orig here when -K has been specified.
1298 I'm not implementing it now since files on an FTP server are much
1299 more likely than files on an HTTP server to legitimately have a
1301 if (!stat (con->target, &st))
1305 /* Else, get it from the file. */
1306 local_size = st.st_size;
1308 /* Compare file sizes only for servers that tell us correct
1309 values. Assumme sizes being equal for servers that lie
1311 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1312 eq_size = cor_val ? (local_size == f->size) : 1 ;
1313 if (f->tstamp <= tml && eq_size)
1315 /* Remote file is older, file sizes can be compared and
1317 logprintf (LOG_VERBOSE, _("\
1318 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1323 /* Remote file is newer or sizes cannot be matched */
1324 logprintf (LOG_VERBOSE, _("\
1325 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1330 /* Sizes do not match */
1331 logprintf (LOG_VERBOSE, _("\
1332 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1335 } /* opt.timestamping && f->type == FT_PLAINFILE */
1339 /* If opt.retr_symlinks is defined, we treat symlinks as
1340 if they were normal files. There is currently no way
1341 to distinguish whether they might be directories, and
1343 if (!opt.retr_symlinks)
1347 logputs (LOG_NOTQUIET,
1348 _("Invalid name of the symlink, skipping.\n"));
1352 /* Check whether we already have the correct
1354 int rc = lstat (con->target, &st);
1357 size_t len = strlen (f->linkto) + 1;
1358 if (S_ISLNK (st.st_mode))
1360 char *link_target = (char *)alloca (len);
1361 size_t n = readlink (con->target, link_target, len);
1363 && (memcmp (link_target, f->linkto, n) == 0))
1365 logprintf (LOG_VERBOSE, _("\
1366 Already have correct symlink %s -> %s\n\n"),
1367 con->target, f->linkto);
1373 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1374 con->target, f->linkto);
1375 /* Unlink before creating symlink! */
1376 unlink (con->target);
1377 if (symlink (f->linkto, con->target) == -1)
1378 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1380 logputs (LOG_VERBOSE, "\n");
1381 } /* have f->linkto */
1382 #else /* not HAVE_SYMLINK */
1383 logprintf (LOG_NOTQUIET,
1384 _("Symlinks not supported, skipping symlink `%s'.\n"),
1386 #endif /* not HAVE_SYMLINK */
1388 else /* opt.retr_symlinks */
1391 err = ftp_loop_internal (u, f, con);
1392 } /* opt.retr_symlinks */
1396 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1400 /* Call the retrieve loop. */
1402 err = ftp_loop_internal (u, f, con);
1405 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1410 /* Set the time-stamp information to the local file. Symlinks
1411 are not to be stamped because it sets the stamp on the
1413 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1416 && file_exists_p (con->target))
1418 /* #### This code repeats in http.c and ftp.c. Move it to a
1420 const char *fl = NULL;
1421 if (opt.output_document)
1423 if (opt.od_known_regular)
1424 fl = opt.output_document;
1429 touch (fl, f->tstamp);
1431 else if (f->tstamp == -1)
1432 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1434 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1435 chmod (con->target, f->perms);
1437 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1439 xfree (con->target);
1440 con->target = old_target;
1442 url_set_file (u, ofile);
1445 /* Break on fatals. */
1446 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1448 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1452 /* We do not want to call ftp_retrieve_dirs here */
1453 if (opt.recursive &&
1454 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1455 err = ftp_retrieve_dirs (u, orig, con);
1456 else if (opt.recursive)
1457 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1458 depth, opt.reclevel));
1463 /* Retrieve the directories given in a file list. This function works
1464 by simply going through the linked list and calling
1465 ftp_retrieve_glob on each directory entry. The function knows
1466 about excluded directories. */
1468 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1470 char *container = NULL;
1471 int container_size = 0;
1473 for (; f; f = f->next)
1476 char *odir, *newdir;
1478 if (downloaded_exceeds_quota ())
1480 if (f->type != FT_DIRECTORY)
1483 /* Allocate u->dir off stack, but reallocate only if a larger
1484 string is needed. It's a pity there's no "realloca" for an
1485 item on the bottom of the stack. */
1486 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1487 if (size > container_size)
1488 container = (char *)alloca (size);
1493 || (*odir == '/' && *(odir + 1) == '\0'))
1494 /* If ODIR is empty or just "/", simply append f->name to
1495 ODIR. (In the former case, to preserve u->dir being
1496 relative; in the latter case, to avoid double slash.) */
1497 sprintf (newdir, "%s%s", odir, f->name);
1499 /* Else, use a separator. */
1500 sprintf (newdir, "%s/%s", odir, f->name);
1502 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1503 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1504 odir, f->name, newdir));
1505 if (!accdir (newdir, ALLABS))
1507 logprintf (LOG_VERBOSE, _("\
1508 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1512 con->st &= ~DONE_CWD;
1514 odir = xstrdup (u->dir); /* because url_set_dir will free
1516 url_set_dir (u, newdir);
1517 ftp_retrieve_glob (u, con, GETALL);
1518 url_set_dir (u, odir);
1521 /* Set the time-stamp? */
1524 if (opt.quota && opt.downloaded > opt.quota)
1531 /* A near-top-level function to retrieve the files in a directory.
1532 The function calls ftp_get_listing, to get a linked list of files.
1533 Then it weeds out the file names that do not match the pattern.
1534 ftp_retrieve_list is called with this updated list as an argument.
1536 If the argument ACTION is GETONE, just download the file (but first
1537 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1538 use globbing; if it's GETALL, download the whole directory. */
1540 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1542 struct fileinfo *orig, *start;
1545 con->cmd |= LEAVE_PENDING;
1547 res = ftp_get_listing (u, con, &orig);
1551 /* First: weed out that do not conform the global rules given in
1552 opt.accepts and opt.rejects. */
1553 if (opt.accepts || opt.rejects)
1555 struct fileinfo *f = orig;
1559 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1561 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1562 f = delelement (f, &start);
1568 /* Now weed out the files that do not match our globbing pattern.
1569 If we are dealing with a globbing pattern, that is. */
1570 if (*u->file && (action == GLOBALL || action == GETONE))
1573 struct fileinfo *f = start;
1577 matchres = fnmatch (u->file, f->name, 0);
1580 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1584 if (matchres == FNM_NOMATCH)
1585 f = delelement (f, &start); /* delete the element from the list */
1587 f = f->next; /* leave the element in the list */
1591 freefileinfo (start);
1592 return RETRBADPATTERN;
1598 /* Just get everything. */
1599 ftp_retrieve_list (u, start, con);
1603 if (action == GLOBALL)
1606 /* #### This message SUCKS. We should see what was the
1607 reason that nothing was retrieved. */
1608 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1610 else /* GETONE or GETALL */
1612 /* Let's try retrieving it anyway. */
1613 con->st |= ON_YOUR_OWN;
1614 res = ftp_loop_internal (u, NULL, con);
1618 freefileinfo (start);
1619 if (downloaded_exceeds_quota ())
1622 /* #### Should we return `res' here? */
1626 /* The wrapper that calls an appropriate routine according to contents
1627 of URL. Inherently, its capabilities are limited on what can be
1628 encoded into a URL. */
1630 ftp_loop (struct url *u, int *dt)
1632 ccon con; /* FTP connection */
1637 memset (&con, 0, sizeof (con));
1639 rbuf_uninitialize (&con.rbuf);
1640 con.st = ON_YOUR_OWN;
1643 res = RETROK; /* in case it's not used */
1645 /* If the file name is empty, the user probably wants a directory
1646 index. We'll provide one, properly HTML-ized. Unless
1647 opt.htmlify is 0, of course. :-) */
1648 if (!*u->file && !opt.recursive)
1651 res = ftp_get_listing (u, &con, &f);
1657 char *filename = (opt.output_document
1658 ? xstrdup (opt.output_document)
1659 : (con.target ? xstrdup (con.target)
1660 : url_filename (u)));
1661 res = ftp_index (filename, u, f);
1662 if (res == FTPOK && opt.verbose)
1664 if (!opt.output_document)
1668 if (stat (filename, &st) == 0)
1672 logprintf (LOG_NOTQUIET,
1673 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1677 logprintf (LOG_NOTQUIET,
1678 _("Wrote HTML-ized index to `%s'.\n"),
1688 int wild = has_wildcards_p (u->file);
1689 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1691 /* ftp_retrieve_glob is a catch-all function that gets called
1692 if we need globbing, time-stamping or recursion. Its
1693 third argument is just what we really need. */
1694 ftp_retrieve_glob (u, &con,
1695 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1698 res = ftp_loop_internal (u, NULL, &con);
1704 /* If a connection was left, quench it. */
1705 if (rbuf_initialized_p (&con.rbuf))
1706 CLOSE (RBUF_FD (&con.rbuf));
1707 FREE_MAYBE (con.id);
1709 FREE_MAYBE (con.target);
1714 /* Delete an element from the fileinfo linked list. Returns the
1715 address of the next element, or NULL if the list is exhausted. It
1716 can modify the start of the list. */
1717 static struct fileinfo *
1718 delelement (struct fileinfo *f, struct fileinfo **start)
1720 struct fileinfo *prev = f->prev;
1721 struct fileinfo *next = f->next;
1724 FREE_MAYBE (f->linkto);
1736 /* Free the fileinfo linked list of files. */
1738 freefileinfo (struct fileinfo *f)
1742 struct fileinfo *next = f->next;