1 /* File Transfer Protocol support.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 This file is part of Wget.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
32 #include <sys/types.h>
36 # include <netdb.h> /* for h_errno */
59 /* File where the "ls -al" listing will be saved. */
60 #define LIST_FILENAME ".listing"
62 extern char ftp_last_respline[];
64 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
65 the string S, and return the number converted to long, if found, 0
68 ftp_expected_bytes (const char *s)
74 while (*s && *s != '(')
78 for (++s; *s && ISSPACE (*s); s++);
86 res = (*s - '0') + 10 * res;
89 while (*s && ISDIGIT (*s));
92 while (*s && ISSPACE (*s))
96 if (TOLOWER (*s) != 'b')
98 if (strncasecmp (s, "byte", 4))
106 /* Retrieves a file with denoted parameters through opening an FTP
107 connection to the server. It always closes the data connection,
108 and closes the control connection in case of error. */
110 getftp (struct urlinfo *u, long *len, long restval, ccon *con)
112 int csock, dtsock, res;
115 char *user, *passwd, *respline;
117 struct wget_timer *timer;
118 unsigned char pasv_addr[6];
120 int passive_mode_open = 0;
121 long expected_bytes = 0L;
123 assert (con != NULL);
124 assert (u->local != NULL);
125 /* Debug-check of the sanity of the request by making sure that LIST
126 and RETR are never both requested (since we can handle only one
128 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
129 /* Make sure that at least *something* is requested. */
130 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
134 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
135 user = user ? user : opt.ftp_acc;
136 passwd = passwd ? passwd : opt.ftp_pass;
137 assert (user && passwd);
142 if (!(cmd & DO_LOGIN))
143 csock = RBUF_FD (&con->rbuf);
144 else /* cmd & DO_LOGIN */
146 /* Login to the server: */
148 /* First: Establish the control connection. */
149 logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
150 err = make_connection (&csock, u->host, u->port);
151 if (cmd & LEAVE_PENDING)
152 rbuf_initialize (&con->rbuf, csock);
154 rbuf_uninitialize (&con->rbuf);
157 /* Do not close the socket in first several cases, since it
158 wasn't created at all. */
160 logputs (LOG_VERBOSE, "\n");
161 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
165 logputs (LOG_VERBOSE, "\n");
166 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
170 logputs (LOG_VERBOSE, "\n");
171 logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
174 rbuf_uninitialize (&con->rbuf);
177 logputs (LOG_VERBOSE, "\n");
178 logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
180 rbuf_uninitialize (&con->rbuf);
187 /* Since this is a new connection, we may safely discard
188 anything left in the buffer. */
189 rbuf_discard (&con->rbuf);
191 /* Second: Login with proper USER/PASS sequence. */
192 logputs (LOG_VERBOSE, _("connected!\n"));
193 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
194 if (opt.server_response)
195 logputs (LOG_ALWAYS, "\n");
196 err = ftp_login (&con->rbuf, user, passwd);
197 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
201 logputs (LOG_VERBOSE, "\n");
202 logputs (LOG_NOTQUIET, _("\
203 Error in server response, closing control connection.\n"));
205 rbuf_uninitialize (&con->rbuf);
209 logputs (LOG_VERBOSE, "\n");
210 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
212 rbuf_uninitialize (&con->rbuf);
216 logputs (LOG_VERBOSE, "\n");
217 logputs (LOG_NOTQUIET,
218 _("Write failed, closing control connection.\n"));
220 rbuf_uninitialize (&con->rbuf);
224 logputs (LOG_VERBOSE, "\n");
225 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
227 rbuf_uninitialize (&con->rbuf);
228 return FTPLOGREFUSED;
231 logputs (LOG_VERBOSE, "\n");
232 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
234 rbuf_uninitialize (&con->rbuf);
238 if (!opt.server_response)
239 logputs (LOG_VERBOSE, _("Logged in!\n"));
246 /* Third: Get the system type */
247 if (!opt.server_response)
248 logprintf (LOG_VERBOSE, "==> SYST ... ");
249 err = ftp_syst (&con->rbuf, &con->rs);
254 logputs (LOG_VERBOSE, "\n");
255 logputs (LOG_NOTQUIET, _("\
256 Error in server response, closing control connection.\n"));
258 rbuf_uninitialize (&con->rbuf);
262 logputs (LOG_VERBOSE, "\n");
263 logputs (LOG_NOTQUIET,
264 _("Server error, can't determine system type.\n"));
267 /* Everything is OK. */
273 if (!opt.server_response)
274 logputs (LOG_VERBOSE, _("done. "));
276 /* Fourth: Find the initial ftp directory */
278 if (!opt.server_response)
279 logprintf (LOG_VERBOSE, "==> PWD ... ");
280 err = ftp_pwd(&con->rbuf, &con->id);
286 logputs (LOG_VERBOSE, "\n");
287 logputs (LOG_NOTQUIET, _("\
288 Error in server response, closing control connection.\n"));
290 rbuf_uninitialize (&con->rbuf);
294 /* Everything is OK. */
300 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
301 Convert it to "/INITIAL/FOLDER" */
302 if (con->rs == ST_VMS)
304 char *path = strchr (con->id, '[');
305 char *pathend = path ? strchr (path + 1, ']') : NULL;
306 if (!path || !pathend)
307 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
310 char *idir = con->id;
311 DEBUGP (("Preprocessing the initial VMS directory\n"));
312 DEBUGP ((" old = '%s'\n", con->id));
313 /* We do the conversion in-place by copying the stuff
314 between [ and ] to the beginning, and changing dots
315 to slashes at the same time. */
317 for (++path; path < pathend; path++, idir++)
318 *idir = *path == '.' ? '/' : *path;
320 DEBUGP ((" new = '%s'\n\n", con->id));
323 if (!opt.server_response)
324 logputs (LOG_VERBOSE, _("done.\n"));
326 /* Fifth: Set the FTP type. */
327 if (!opt.server_response)
328 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
329 err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
330 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
334 logputs (LOG_VERBOSE, "\n");
335 logputs (LOG_NOTQUIET, _("\
336 Error in server response, closing control connection.\n"));
338 rbuf_uninitialize (&con->rbuf);
342 logputs (LOG_VERBOSE, "\n");
343 logputs (LOG_NOTQUIET,
344 _("Write failed, closing control connection.\n"));
346 rbuf_uninitialize (&con->rbuf);
350 logputs (LOG_VERBOSE, "\n");
351 logprintf (LOG_NOTQUIET,
352 _("Unknown type `%c', closing control connection.\n"),
353 TOUPPER (u->ftp_type));
355 rbuf_uninitialize (&con->rbuf);
358 /* Everything is OK. */
364 if (!opt.server_response)
365 logputs (LOG_VERBOSE, _("done. "));
371 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
374 char *target = u->dir;
376 DEBUGP (("changing working directory\n"));
378 /* Change working directory. To change to a non-absolute
379 Unix directory, we need to prepend initial directory
380 (con->id) to it. Absolute directories "just work". */
384 int idlen = strlen (con->id);
385 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
386 /* idlen == 1 means con->id = "/" */
387 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
389 DEBUGP (("Prepended initial PWD to relative path:\n"));
390 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
394 /* If the FTP host runs VMS, we will have to convert the absolute
395 directory path in UNIX notation to absolute directory path in
396 VMS notation as VMS FTP servers do not like UNIX notation of
397 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
399 if (con->rs == ST_VMS)
402 char *ntarget = (char *)alloca (strlen (target) + 2);
403 /* We use a converted initial dir, so directories in
404 TARGET will be separated with slashes, something like
405 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
406 "[INITIAL.FOLDER.DIR.SUBDIR]". */
407 strcpy (ntarget, target);
408 assert (*ntarget == '/');
410 for (tmpp = ntarget + 1; *tmpp; tmpp++)
415 DEBUGP (("Changed file name to VMS syntax:\n"));
416 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
420 if (!opt.server_response)
421 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
422 err = ftp_cwd (&con->rbuf, target);
423 /* FTPRERR, WRITEFAILED, FTPNSFOD */
427 logputs (LOG_VERBOSE, "\n");
428 logputs (LOG_NOTQUIET, _("\
429 Error in server response, closing control connection.\n"));
431 rbuf_uninitialize (&con->rbuf);
435 logputs (LOG_VERBOSE, "\n");
436 logputs (LOG_NOTQUIET,
437 _("Write failed, closing control connection.\n"));
439 rbuf_uninitialize (&con->rbuf);
443 logputs (LOG_VERBOSE, "\n");
444 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
447 rbuf_uninitialize (&con->rbuf);
457 if (!opt.server_response)
458 logputs (LOG_VERBOSE, _("done.\n"));
461 else /* do not CWD */
462 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
464 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
465 if (cmd & (DO_LIST | DO_RETR))
467 if (opt.ftp_pasv > 0)
470 unsigned short tport;
472 if (!opt.server_response)
473 logputs (LOG_VERBOSE, "==> PASV ... ");
474 err = ftp_pasv (&con->rbuf, pasv_addr);
475 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
479 logputs (LOG_VERBOSE, "\n");
480 logputs (LOG_NOTQUIET, _("\
481 Error in server response, closing control connection.\n"));
483 rbuf_uninitialize (&con->rbuf);
487 logputs (LOG_VERBOSE, "\n");
488 logputs (LOG_NOTQUIET,
489 _("Write failed, closing control connection.\n"));
491 rbuf_uninitialize (&con->rbuf);
495 logputs (LOG_VERBOSE, "\n");
496 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
499 logputs (LOG_VERBOSE, "\n");
500 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
511 sprintf (thost, "%d.%d.%d.%d",
512 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
513 tport = (pasv_addr[4] << 8) + pasv_addr[5];
514 DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
515 err = make_connection (&dtsock, thost, tport);
518 /* Do not close the socket in first several cases,
519 since it wasn't created at all. */
521 logputs (LOG_VERBOSE, "\n");
522 logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
525 rbuf_uninitialize (&con->rbuf);
529 logputs (LOG_VERBOSE, "\n");
530 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
532 rbuf_uninitialize (&con->rbuf);
536 logputs (LOG_VERBOSE, "\n");
537 logprintf (LOG_NOTQUIET,
538 _("Connection to %s:%hu refused.\n"),
541 rbuf_uninitialize (&con->rbuf);
545 logputs (LOG_VERBOSE, "\n");
546 logprintf (LOG_NOTQUIET, "connect: %s\n",
549 rbuf_uninitialize (&con->rbuf);
557 passive_mode_open= 1; /* Flag to avoid accept port */
558 if (!opt.server_response)
559 logputs (LOG_VERBOSE, _("done. "));
563 if (!passive_mode_open) /* Try to use a port command if PASV failed */
565 if (!opt.server_response)
566 logputs (LOG_VERBOSE, "==> PORT ... ");
567 err = ftp_port (&con->rbuf);
568 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
569 LISTENERR), HOSTERR, FTPPORTERR */
573 logputs (LOG_VERBOSE, "\n");
574 logputs (LOG_NOTQUIET, _("\
575 Error in server response, closing control connection.\n"));
578 rbuf_uninitialize (&con->rbuf);
582 logputs (LOG_VERBOSE, "\n");
583 logputs (LOG_NOTQUIET,
584 _("Write failed, closing control connection.\n"));
587 rbuf_uninitialize (&con->rbuf);
591 logputs (LOG_VERBOSE, "\n");
592 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
595 rbuf_uninitialize (&con->rbuf);
598 case CONPORTERR: case BINDERR: case LISTENERR:
599 /* What now? These problems are local... */
600 logputs (LOG_VERBOSE, "\n");
601 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
607 logputs (LOG_VERBOSE, "\n");
608 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
612 rbuf_uninitialize (&con->rbuf);
616 logputs (LOG_VERBOSE, "\n");
617 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
620 rbuf_uninitialize (&con->rbuf);
630 if (!opt.server_response)
631 logputs (LOG_VERBOSE, _("done. "));
633 } /* cmd & (DO_LIST | DO_RETR) */
635 /* Restart if needed. */
636 if (restval && (cmd & DO_RETR))
638 if (!opt.server_response)
639 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
640 err = ftp_rest (&con->rbuf, restval);
642 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
646 logputs (LOG_VERBOSE, "\n");
647 logputs (LOG_NOTQUIET, _("\
648 Error in server response, closing control connection.\n"));
651 rbuf_uninitialize (&con->rbuf);
655 logputs (LOG_VERBOSE, "\n");
656 logputs (LOG_NOTQUIET,
657 _("Write failed, closing control connection.\n"));
660 rbuf_uninitialize (&con->rbuf);
664 /* If `-c' is specified and the file already existed when
665 Wget was started, it would be a bad idea for us to start
666 downloading it from scratch, effectively truncating it. */
667 if (opt.always_rest && (cmd & NO_TRUNCATE))
669 logprintf (LOG_NOTQUIET,
670 _("\nREST failed; will not truncate `%s'.\n"),
674 rbuf_uninitialize (&con->rbuf);
675 return CONTNOTSUPPORTED;
677 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
687 if (err != FTPRESTFAIL && !opt.server_response)
688 logputs (LOG_VERBOSE, _("done. "));
689 } /* restval && cmd & DO_RETR */
695 if (!opt.server_response)
698 logputs (LOG_VERBOSE, "\n");
699 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
702 err = ftp_retr (&con->rbuf, u->file);
703 /* FTPRERR, WRITEFAILED, FTPNSFOD */
707 logputs (LOG_VERBOSE, "\n");
708 logputs (LOG_NOTQUIET, _("\
709 Error in server response, closing control connection.\n"));
712 rbuf_uninitialize (&con->rbuf);
716 logputs (LOG_VERBOSE, "\n");
717 logputs (LOG_NOTQUIET,
718 _("Write failed, closing control connection.\n"));
721 rbuf_uninitialize (&con->rbuf);
725 logputs (LOG_VERBOSE, "\n");
726 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
738 if (!opt.server_response)
739 logputs (LOG_VERBOSE, _("done.\n"));
740 expected_bytes = ftp_expected_bytes (ftp_last_respline);
745 if (!opt.server_response)
746 logputs (LOG_VERBOSE, "==> LIST ... ");
747 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
748 without arguments is better than `LIST .'; confirmed by
750 err = ftp_list (&con->rbuf, NULL);
751 /* FTPRERR, WRITEFAILED */
755 logputs (LOG_VERBOSE, "\n");
756 logputs (LOG_NOTQUIET, _("\
757 Error in server response, closing control connection.\n"));
760 rbuf_uninitialize (&con->rbuf);
764 logputs (LOG_VERBOSE, "\n");
765 logputs (LOG_NOTQUIET,
766 _("Write failed, closing control connection.\n"));
769 rbuf_uninitialize (&con->rbuf);
773 logputs (LOG_VERBOSE, "\n");
774 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
786 if (!opt.server_response)
787 logputs (LOG_VERBOSE, _("done.\n"));
788 expected_bytes = ftp_expected_bytes (ftp_last_respline);
789 } /* cmd & DO_LIST */
791 /* Some FTP servers return the total length of file after REST
792 command, others just return the remaining size. */
793 if (*len && restval && expected_bytes
794 && (expected_bytes == *len - restval))
796 DEBUGP (("Lying FTP server found, adjusting.\n"));
797 expected_bytes = *len;
800 /* If no transmission was required, then everything is OK. */
801 if (!(cmd & (DO_LIST | DO_RETR)))
804 if (!passive_mode_open) /* we are not using pasive mode so we need
807 /* Open the data transmission socket by calling acceptport(). */
808 err = acceptport (&dtsock);
809 /* Possible errors: ACCEPTERR. */
810 if (err == ACCEPTERR)
812 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
817 /* Open the file -- if opt.dfp is set, use it instead. */
818 if (!opt.dfp || con->cmd & DO_LIST)
820 mkalldirs (u->local);
822 rotate_backups (u->local);
823 /* #### Is this correct? */
824 chmod (u->local, 0600);
826 fp = fopen (u->local, restval ? "ab" : "wb");
829 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
831 rbuf_uninitialize (&con->rbuf);
838 extern int global_download_count;
841 /* Rewind the output document if the download starts over and if
842 this is the first download. See gethttp() for a longer
844 if (!restval && global_download_count == 0)
846 /* This will silently fail for streams that don't correspond
847 to regular files, but that's OK. */
849 /* ftruncate is needed because opt.dfp is opened in append
850 mode if opt.always_rest is set. */
851 ftruncate (fileno (fp), 0);
858 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
860 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
861 logputs (LOG_VERBOSE, "\n");
862 expected_bytes = *len; /* for get_contents/show_progress */
864 else if (expected_bytes)
866 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
868 logprintf (LOG_VERBOSE, _(" [%s to go]"),
869 legible (expected_bytes - restval));
870 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
872 timer = wtimer_new ();
873 /* Get the contents of the document. */
874 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
875 con->dltime = wtimer_elapsed (timer);
876 wtimer_delete (timer);
877 tms = time_str (NULL);
878 tmrate = rate (*len - restval, con->dltime, 0);
879 /* Close data connection socket. */
881 /* Close the local file. */
883 /* Close or flush the file. We have to be careful to check for
884 error here. Checking the result of fwrite() is not enough --
885 errors could go unnoticed! */
887 if (!opt.dfp || con->cmd & DO_LIST)
888 flush_res = fclose (fp);
890 flush_res = fflush (fp);
891 if (flush_res == EOF)
894 /* If get_contents couldn't write to fp, bail out. */
897 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
898 u->local, strerror (errno));
900 rbuf_uninitialize (&con->rbuf);
905 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
906 tms, tmrate, strerror (errno));
907 if (opt.server_response)
908 logputs (LOG_ALWAYS, "\n");
911 /* Get the server to tell us if everything is retrieved. */
912 err = ftp_response (&con->rbuf, &respline);
913 /* ...and empty the buffer. */
914 rbuf_discard (&con->rbuf);
918 /* The control connection is decidedly closed. Print the time
919 only if it hasn't already been printed. */
921 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
922 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
923 /* If there is an error on the control connection, close it, but
924 return FTPRETRINT, since there is a possibility that the
925 whole file was retrieved nevertheless (but that is for
926 ftp_loop_internal to decide). */
928 rbuf_uninitialize (&con->rbuf);
931 /* If retrieval failed for any reason, return FTPRETRINT, but do not
932 close socket, since the control connection is still alive. If
933 there is something wrong with the control connection, it will
934 become apparent later. */
935 if (*respline != '2')
939 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
940 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
947 /* What now? The data connection was erroneous, whereas the
948 response says everything is OK. We shall play it safe. */
952 if (!(cmd & LEAVE_PENDING))
954 /* I should probably send 'QUIT' and check for a reply, but this
955 is faster. #### Is it OK, though? */
957 rbuf_uninitialize (&con->rbuf);
959 /* If it was a listing, and opt.server_response is true,
961 if (opt.server_response && (con->cmd & DO_LIST))
963 mkalldirs (u->local);
964 fp = fopen (u->local, "r");
966 logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
970 /* The lines are being read with read_whole_line because of
971 no-buffering on opt.lfile. */
972 while ((line = read_whole_line (fp)))
974 logprintf (LOG_ALWAYS, "%s\n", line);
979 } /* con->cmd & DO_LIST && server_response */
984 /* A one-file FTP loop. This is the part where FTP retrieval is
985 retried, and retried, and retried, and...
987 This loop either gets commands from con, or (if ON_YOUR_OWN is
988 set), makes them up to retrieve the file given by the URL. */
990 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
994 char *tms, *tmrate, *locf;
999 u->local = url_filename (u);
1001 if (opt.noclobber && file_exists_p (u->local))
1003 logprintf (LOG_VERBOSE,
1004 _("File `%s' already there, not retrieving.\n"), u->local);
1005 /* If the file is there, we suppose it's retrieved OK. */
1009 /* Remove it if it's a link. */
1010 remove_link (u->local);
1011 if (!opt.output_document)
1014 locf = opt.output_document;
1018 if (con->st & ON_YOUR_OWN)
1019 con->st = ON_YOUR_OWN;
1021 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1026 /* Increment the pass counter. */
1028 sleep_between_retrievals (count);
1029 if (con->st & ON_YOUR_OWN)
1032 con->cmd |= (DO_RETR | LEAVE_PENDING);
1033 if (rbuf_initialized_p (&con->rbuf))
1034 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1036 con->cmd |= (DO_LOGIN | DO_CWD);
1038 else /* not on your own */
1040 if (rbuf_initialized_p (&con->rbuf))
1041 con->cmd &= ~DO_LOGIN;
1043 con->cmd |= DO_LOGIN;
1044 if (con->st & DONE_CWD)
1045 con->cmd &= ~DO_CWD;
1050 /* Assume no restarting. */
1052 if ((count > 1 || opt.always_rest)
1053 && !(con->cmd & DO_LIST)
1054 && file_exists_p (locf))
1055 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1056 restval = st.st_size;
1058 /* In `-c' is used, check whether the file we're writing to
1059 exists and is of non-zero length. If so, we'll refuse to
1060 truncate it if the server doesn't support continued
1062 if (opt.always_rest && restval > 0)
1063 con->cmd |= NO_TRUNCATE;
1065 /* Get the current time string. */
1066 tms = time_str (NULL);
1067 /* Print fetch message, if opt.verbose. */
1070 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1074 sprintf (tmp, _("(try:%2d)"), count);
1075 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1076 tms, hurl, tmp, locf);
1078 ws_changetitle (hurl, 1);
1082 /* Send getftp the proper length, if fileinfo was provided. */
1087 err = getftp (u, &len, restval, con);
1089 tms = time_str (NULL);
1090 tmrate = rate (len - restval, con->dltime, 0);
1092 if (!rbuf_initialized_p (&con->rbuf))
1093 con->st &= ~DONE_CWD;
1095 con->st |= DONE_CWD;
1099 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1100 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1101 /* Fatal errors, give up. */
1104 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1105 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1106 case BINDERR: case LISTENERR: case ACCEPTERR:
1107 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1108 printwhat (count, opt.ntry);
1109 /* non-fatal errors */
1113 /* If the control connection was closed, the retrieval
1114 will be considered OK if f->size == len. */
1115 if (!f || len != f->size)
1117 printwhat (count, opt.ntry);
1129 /* If we get out of the switch above without continue'ing, we've
1130 successfully downloaded a file. Remember this fact. */
1131 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1133 if (con->st & ON_YOUR_OWN)
1135 CLOSE (RBUF_FD (&con->rbuf));
1136 rbuf_uninitialize (&con->rbuf);
1138 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1139 tms, tmrate, locf, len);
1140 if (!opt.verbose && !opt.quiet)
1142 /* Need to hide the password from the URL. The `if' is here
1143 so that we don't do the needless allocation every
1145 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1146 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1147 tms, hurl, len, locf, count);
1151 if ((con->cmd & DO_LIST))
1152 /* This is a directory listing file. */
1154 if (!opt.remove_listing)
1155 /* --dont-remove-listing was specified, so do count this towards the
1156 number of bytes and files downloaded. */
1158 downloaded_increase (len);
1162 /* Deletion of listing files is not controlled by --delete-after, but
1163 by the more specific option --dont-remove-listing, and the code
1164 to do this deletion is in another function. */
1167 /* This is not a directory listing file. */
1169 /* Unlike directory listing files, don't pretend normal files weren't
1170 downloaded if they're going to be deleted. People seeding proxies,
1171 for instance, may want to know how many bytes and files they've
1172 downloaded through it. */
1173 downloaded_increase (len);
1176 if (opt.delete_after)
1178 DEBUGP (("Removing file due to --delete-after in"
1179 " ftp_loop_internal():\n"));
1180 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1182 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1186 /* Restore the original leave-pendingness. */
1188 con->cmd |= LEAVE_PENDING;
1190 con->cmd &= ~LEAVE_PENDING;
1192 } while (!opt.ntry || (count < opt.ntry));
1194 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1196 CLOSE (RBUF_FD (&con->rbuf));
1197 rbuf_uninitialize (&con->rbuf);
1202 /* Return the directory listing in a reusable format. The directory
1203 is specifed in u->dir. */
1205 ftp_get_listing (struct urlinfo *u, ccon *con, struct fileinfo **f)
1208 char *olocal = u->local;
1209 char *list_filename, *ofile;
1211 con->st &= ~ON_YOUR_OWN;
1212 con->cmd |= (DO_LIST | LEAVE_PENDING);
1213 con->cmd &= ~DO_RETR;
1214 /* Get the listing filename. */
1216 u->file = LIST_FILENAME;
1217 list_filename = url_filename (u);
1219 u->local = list_filename;
1220 DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1221 err = ftp_loop_internal (u, NULL, con);
1224 *f = ftp_parse_ls (list_filename, con->rs);
1227 if (opt.remove_listing)
1229 if (unlink (list_filename))
1230 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1232 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1234 xfree (list_filename);
1235 con->cmd &= ~DO_LIST;
1239 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1241 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1242 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1243 struct fileinfo **));
1244 static void freefileinfo PARAMS ((struct fileinfo *f));
1246 /* Retrieve a list of files given in struct fileinfo linked list. If
1247 a file is a symbolic link, do not retrieve it, but rather try to
1248 set up a similar link on the local disk, if the symlinks are
1251 If opt.recursive is set, after all files have been retrieved,
1252 ftp_retrieve_dirs will be called to retrieve the directories. */
1254 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1256 static int depth = 0;
1258 char *olocal, *ofile;
1259 struct fileinfo *orig;
1264 /* Increase the depth. */
1266 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1268 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1269 depth, opt.reclevel));
1277 con->st &= ~ON_YOUR_OWN;
1278 if (!(con->st & DONE_CWD))
1281 con->cmd &= ~DO_CWD;
1282 con->cmd |= (DO_RETR | LEAVE_PENDING);
1284 if (!rbuf_initialized_p (&con->rbuf))
1285 con->cmd |= DO_LOGIN;
1287 con->cmd &= ~DO_LOGIN;
1289 err = RETROK; /* in case it's not used */
1293 if (downloaded_exceeds_quota ())
1301 u->local = url_filename (u);
1305 if (opt.timestamping && f->type == FT_PLAINFILE)
1308 /* If conversion of HTML files retrieved via FTP is ever implemented,
1309 we'll need to stat() <file>.orig here when -K has been specified.
1310 I'm not implementing it now since files on an FTP server are much
1311 more likely than files on an HTTP server to legitimately have a
1313 if (!stat (u->local, &st))
1317 /* Else, get it from the file. */
1318 local_size = st.st_size;
1320 /* Compare file sizes only for servers that tell us correct
1321 values. Assumme sizes being equal for servers that lie
1323 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1324 eq_size = cor_val ? (local_size == f->size) : 1 ;
1325 if (f->tstamp <= tml && eq_size)
1327 /* Remote file is older, file sizes can be compared and
1329 logprintf (LOG_VERBOSE, _("\
1330 Remote file no newer than local file `%s' -- not retrieving.\n"), u->local);
1335 /* Remote file is newer or sizes cannot be matched */
1336 logprintf (LOG_VERBOSE, _("\
1337 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1342 /* Sizes do not match */
1343 logprintf (LOG_VERBOSE, _("\
1344 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1347 } /* opt.timestamping && f->type == FT_PLAINFILE */
1351 /* If opt.retr_symlinks is defined, we treat symlinks as
1352 if they were normal files. There is currently no way
1353 to distinguish whether they might be directories, and
1355 if (!opt.retr_symlinks)
1359 logputs (LOG_NOTQUIET,
1360 _("Invalid name of the symlink, skipping.\n"));
1364 /* Check whether we already have the correct
1366 int rc = lstat (u->local, &st);
1369 size_t len = strlen (f->linkto) + 1;
1370 if (S_ISLNK (st.st_mode))
1372 char *link_target = (char *)alloca (len);
1373 size_t n = readlink (u->local, link_target, len);
1375 && (memcmp (link_target, f->linkto, n) == 0))
1377 logprintf (LOG_VERBOSE, _("\
1378 Already have correct symlink %s -> %s\n\n"),
1379 u->local, f->linkto);
1385 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1386 u->local, f->linkto);
1387 /* Unlink before creating symlink! */
1389 if (symlink (f->linkto, u->local) == -1)
1390 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1392 logputs (LOG_VERBOSE, "\n");
1393 } /* have f->linkto */
1394 #else /* not HAVE_SYMLINK */
1395 logprintf (LOG_NOTQUIET,
1396 _("Symlinks not supported, skipping symlink `%s'.\n"),
1398 #endif /* not HAVE_SYMLINK */
1400 else /* opt.retr_symlinks */
1403 err = ftp_loop_internal (u, f, con);
1404 } /* opt.retr_symlinks */
1408 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1412 /* Call the retrieve loop. */
1414 err = ftp_loop_internal (u, f, con);
1417 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1422 /* Set the time-stamp information to the local file. Symlinks
1423 are not to be stamped because it sets the stamp on the
1425 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1428 && file_exists_p (u->local))
1430 /* #### This code repeats in http.c and ftp.c. Move it to a
1432 const char *fl = NULL;
1433 if (opt.output_document)
1435 if (opt.od_known_regular)
1436 fl = opt.output_document;
1441 touch (fl, f->tstamp);
1443 else if (f->tstamp == -1)
1444 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1446 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1447 chmod (u->local, f->perms);
1449 DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1454 /* Break on fatals. */
1455 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1457 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1460 /* We do not want to call ftp_retrieve_dirs here */
1461 if (opt.recursive &&
1462 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1463 err = ftp_retrieve_dirs (u, orig, con);
1464 else if (opt.recursive)
1465 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1466 depth, opt.reclevel));
1471 /* Retrieve the directories given in a file list. This function works
1472 by simply going through the linked list and calling
1473 ftp_retrieve_glob on each directory entry. The function knows
1474 about excluded directories. */
1476 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1479 char *current_container = NULL;
1480 int current_length = 0;
1482 for (; f; f = f->next)
1486 if (downloaded_exceeds_quota ())
1488 if (f->type != FT_DIRECTORY)
1491 len = strlen (u->dir) + 1 + strlen (f->name) + 1;
1492 /* Allocate u->dir off stack, but reallocate only if a larger
1493 string is needed. */
1494 if (len > current_length)
1495 current_container = (char *)alloca (len);
1496 u->dir = current_container;
1498 || (*odir == '/' && *(odir + 1) == '\0'))
1499 /* If ODIR is empty or just "/", simply append f->name to
1500 ODIR. (In the former case, to preserve u->dir being
1501 relative; in the latter case, to avoid double slash.) */
1502 sprintf (u->dir, "%s%s", odir, f->name);
1504 /* Else, use a separator. */
1505 sprintf (u->dir, "%s/%s", odir, f->name);
1506 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1507 DEBUGP ((" odir = '%s'\n f->name = '%s'\n u->dir = '%s'\n\n",
1508 odir, f->name, u->dir));
1509 if (!accdir (u->dir, ALLABS))
1511 logprintf (LOG_VERBOSE, _("\
1512 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1516 con->st &= ~DONE_CWD;
1517 ftp_retrieve_glob (u, con, GETALL);
1518 /* Set the time-stamp? */
1521 if (opt.quota && opt.downloaded > opt.quota)
1528 /* A near-top-level function to retrieve the files in a directory.
1529 The function calls ftp_get_listing, to get a linked list of files.
1530 Then it weeds out the file names that do not match the pattern.
1531 ftp_retrieve_list is called with this updated list as an argument.
1533 If the argument ACTION is GETONE, just download the file (but first
1534 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1535 use globbing; if it's GETALL, download the whole directory. */
1537 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1539 struct fileinfo *orig, *start;
1542 con->cmd |= LEAVE_PENDING;
1544 res = ftp_get_listing (u, con, &orig);
1548 /* First: weed out that do not conform the global rules given in
1549 opt.accepts and opt.rejects. */
1550 if (opt.accepts || opt.rejects)
1552 struct fileinfo *f = orig;
1556 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1558 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1559 f = delelement (f, &start);
1565 /* Now weed out the files that do not match our globbing pattern.
1566 If we are dealing with a globbing pattern, that is. */
1567 if (*u->file && (action == GLOBALL || action == GETONE))
1570 struct fileinfo *f = start;
1574 matchres = fnmatch (u->file, f->name, 0);
1577 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1581 if (matchres == FNM_NOMATCH)
1582 f = delelement (f, &start); /* delete the element from the list */
1584 f = f->next; /* leave the element in the list */
1588 freefileinfo (start);
1589 return RETRBADPATTERN;
1595 /* Just get everything. */
1596 ftp_retrieve_list (u, start, con);
1600 if (action == GLOBALL)
1603 /* #### This message SUCKS. We should see what was the
1604 reason that nothing was retrieved. */
1605 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1607 else /* GETONE or GETALL */
1609 /* Let's try retrieving it anyway. */
1610 con->st |= ON_YOUR_OWN;
1611 res = ftp_loop_internal (u, NULL, con);
1615 freefileinfo (start);
1616 if (downloaded_exceeds_quota ())
1619 /* #### Should we return `res' here? */
1623 /* The wrapper that calls an appropriate routine according to contents
1624 of URL. Inherently, its capabilities are limited on what can be
1625 encoded into a URL. */
1627 ftp_loop (struct urlinfo *u, int *dt)
1629 ccon con; /* FTP connection */
1634 memset (&con, 0, sizeof (con));
1636 rbuf_uninitialize (&con.rbuf);
1637 con.st = ON_YOUR_OWN;
1640 res = RETROK; /* in case it's not used */
1642 /* If the file name is empty, the user probably wants a directory
1643 index. We'll provide one, properly HTML-ized. Unless
1644 opt.htmlify is 0, of course. :-) */
1645 if (!*u->file && !opt.recursive)
1648 res = ftp_get_listing (u, &con, &f);
1654 char *filename = (opt.output_document
1655 ? xstrdup (opt.output_document)
1656 : (u->local ? xstrdup (u->local)
1657 : url_filename (u)));
1658 res = ftp_index (filename, u, f);
1659 if (res == FTPOK && opt.verbose)
1661 if (!opt.output_document)
1665 if (stat (filename, &st) == 0)
1669 logprintf (LOG_NOTQUIET,
1670 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1674 logprintf (LOG_NOTQUIET,
1675 _("Wrote HTML-ized index to `%s'.\n"),
1685 int wild = has_wildcards_p (u->file);
1686 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1688 /* ftp_retrieve_glob is a catch-all function that gets called
1689 if we need globbing, time-stamping or recursion. Its
1690 third argument is just what we really need. */
1691 ftp_retrieve_glob (u, &con,
1692 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1695 res = ftp_loop_internal (u, NULL, &con);
1701 /* If a connection was left, quench it. */
1702 if (rbuf_initialized_p (&con.rbuf))
1703 CLOSE (RBUF_FD (&con.rbuf));
1704 FREE_MAYBE (con.id);
1709 /* Delete an element from the fileinfo linked list. Returns the
1710 address of the next element, or NULL if the list is exhausted. It
1711 can modify the start of the list. */
1712 static struct fileinfo *
1713 delelement (struct fileinfo *f, struct fileinfo **start)
1715 struct fileinfo *prev = f->prev;
1716 struct fileinfo *next = f->next;
1719 FREE_MAYBE (f->linkto);
1731 /* Free the fileinfo linked list of files. */
1733 freefileinfo (struct fileinfo *f)
1737 struct fileinfo *next = f->next;