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 unsigned char pasv_addr[6];
119 int passive_mode_open = 0;
120 long expected_bytes = 0L;
122 assert (con != NULL);
123 assert (u->local != NULL);
124 /* Debug-check of the sanity of the request by making sure that LIST
125 and RETR are never both requested (since we can handle only one
127 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
128 /* Make sure that at least *something* is requested. */
129 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
133 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
134 user = user ? user : opt.ftp_acc;
136 opt.ftp_pass = ftp_getaddress ();
137 passwd = passwd ? passwd : opt.ftp_pass;
138 assert (user && passwd);
143 if (!(cmd & DO_LOGIN))
144 csock = RBUF_FD (&con->rbuf);
145 else /* cmd & DO_LOGIN */
147 /* Login to the server: */
149 /* First: Establish the control connection. */
150 logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
151 err = make_connection (&csock, u->host, u->port);
152 if (cmd & LEAVE_PENDING)
153 rbuf_initialize (&con->rbuf, csock);
155 rbuf_uninitialize (&con->rbuf);
158 /* Do not close the socket in first several cases, since it
159 wasn't created at all. */
161 logputs (LOG_VERBOSE, "\n");
162 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
166 logputs (LOG_VERBOSE, "\n");
167 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
171 logputs (LOG_VERBOSE, "\n");
172 logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
175 rbuf_uninitialize (&con->rbuf);
178 logputs (LOG_VERBOSE, "\n");
179 logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
181 rbuf_uninitialize (&con->rbuf);
188 /* Since this is a new connection, we may safely discard
189 anything left in the buffer. */
190 rbuf_discard (&con->rbuf);
192 /* Second: Login with proper USER/PASS sequence. */
193 logputs (LOG_VERBOSE, _("connected!\n"));
194 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
195 if (opt.server_response)
196 logputs (LOG_ALWAYS, "\n");
197 err = ftp_login (&con->rbuf, user, passwd);
198 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
202 logputs (LOG_VERBOSE, "\n");
203 logputs (LOG_NOTQUIET, _("\
204 Error in server response, closing control connection.\n"));
206 rbuf_uninitialize (&con->rbuf);
210 logputs (LOG_VERBOSE, "\n");
211 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
213 rbuf_uninitialize (&con->rbuf);
217 logputs (LOG_VERBOSE, "\n");
218 logputs (LOG_NOTQUIET,
219 _("Write failed, closing control connection.\n"));
221 rbuf_uninitialize (&con->rbuf);
225 logputs (LOG_VERBOSE, "\n");
226 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
228 rbuf_uninitialize (&con->rbuf);
229 return FTPLOGREFUSED;
232 logputs (LOG_VERBOSE, "\n");
233 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
235 rbuf_uninitialize (&con->rbuf);
239 if (!opt.server_response)
240 logputs (LOG_VERBOSE, _("Logged in!\n"));
247 /* Third: Get the system type */
248 if (!opt.server_response)
249 logprintf (LOG_VERBOSE, "==> SYST ... ");
250 err = ftp_syst (&con->rbuf, &con->rs);
255 logputs (LOG_VERBOSE, "\n");
256 logputs (LOG_NOTQUIET, _("\
257 Error in server response, closing control connection.\n"));
259 rbuf_uninitialize (&con->rbuf);
263 logputs (LOG_VERBOSE, "\n");
264 logputs (LOG_NOTQUIET,
265 _("Server error, can't determine system type.\n"));
268 /* Everything is OK. */
274 if (!opt.server_response)
275 logputs (LOG_VERBOSE, _("done. "));
277 /* Fourth: Find the initial ftp directory */
279 if (!opt.server_response)
280 logprintf (LOG_VERBOSE, "==> PWD ... ");
281 err = ftp_pwd(&con->rbuf, &con->id);
287 logputs (LOG_VERBOSE, "\n");
288 logputs (LOG_NOTQUIET, _("\
289 Error in server response, closing control connection.\n"));
291 rbuf_uninitialize (&con->rbuf);
295 /* Everything is OK. */
301 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
302 Convert it to "/INITIAL/FOLDER" */
303 if (con->rs == ST_VMS)
305 char *path = strchr (con->id, '[');
306 char *pathend = path ? strchr (path + 1, ']') : NULL;
307 if (!path || !pathend)
308 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
311 char *idir = con->id;
312 DEBUGP (("Preprocessing the initial VMS directory\n"));
313 DEBUGP ((" old = '%s'\n", con->id));
314 /* We do the conversion in-place by copying the stuff
315 between [ and ] to the beginning, and changing dots
316 to slashes at the same time. */
318 for (++path; path < pathend; path++, idir++)
319 *idir = *path == '.' ? '/' : *path;
321 DEBUGP ((" new = '%s'\n\n", con->id));
324 if (!opt.server_response)
325 logputs (LOG_VERBOSE, _("done.\n"));
327 /* Fifth: Set the FTP type. */
328 if (!opt.server_response)
329 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
330 err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
331 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
335 logputs (LOG_VERBOSE, "\n");
336 logputs (LOG_NOTQUIET, _("\
337 Error in server response, closing control connection.\n"));
339 rbuf_uninitialize (&con->rbuf);
343 logputs (LOG_VERBOSE, "\n");
344 logputs (LOG_NOTQUIET,
345 _("Write failed, closing control connection.\n"));
347 rbuf_uninitialize (&con->rbuf);
351 logputs (LOG_VERBOSE, "\n");
352 logprintf (LOG_NOTQUIET,
353 _("Unknown type `%c', closing control connection.\n"),
354 TOUPPER (u->ftp_type));
356 rbuf_uninitialize (&con->rbuf);
359 /* Everything is OK. */
365 if (!opt.server_response)
366 logputs (LOG_VERBOSE, _("done. "));
372 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
375 char *target = u->dir;
377 DEBUGP (("changing working directory\n"));
379 /* Change working directory. To change to a non-absolute
380 Unix directory, we need to prepend initial directory
381 (con->id) to it. Absolute directories "just work". */
385 int idlen = strlen (con->id);
386 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
387 /* idlen == 1 means con->id = "/" */
388 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
390 DEBUGP (("Prepended initial PWD to relative path:\n"));
391 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
395 /* If the FTP host runs VMS, we will have to convert the absolute
396 directory path in UNIX notation to absolute directory path in
397 VMS notation as VMS FTP servers do not like UNIX notation of
398 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
400 if (con->rs == ST_VMS)
403 char *ntarget = (char *)alloca (strlen (target) + 2);
404 /* We use a converted initial dir, so directories in
405 TARGET will be separated with slashes, something like
406 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
407 "[INITIAL.FOLDER.DIR.SUBDIR]". */
408 strcpy (ntarget, target);
409 assert (*ntarget == '/');
411 for (tmpp = ntarget + 1; *tmpp; tmpp++)
416 DEBUGP (("Changed file name to VMS syntax:\n"));
417 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
421 if (!opt.server_response)
422 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
423 err = ftp_cwd (&con->rbuf, target);
424 /* FTPRERR, WRITEFAILED, FTPNSFOD */
428 logputs (LOG_VERBOSE, "\n");
429 logputs (LOG_NOTQUIET, _("\
430 Error in server response, closing control connection.\n"));
432 rbuf_uninitialize (&con->rbuf);
436 logputs (LOG_VERBOSE, "\n");
437 logputs (LOG_NOTQUIET,
438 _("Write failed, closing control connection.\n"));
440 rbuf_uninitialize (&con->rbuf);
444 logputs (LOG_VERBOSE, "\n");
445 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
448 rbuf_uninitialize (&con->rbuf);
458 if (!opt.server_response)
459 logputs (LOG_VERBOSE, _("done.\n"));
462 else /* do not CWD */
463 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
465 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
466 if (cmd & (DO_LIST | DO_RETR))
468 if (opt.ftp_pasv > 0)
471 unsigned short tport;
473 if (!opt.server_response)
474 logputs (LOG_VERBOSE, "==> PASV ... ");
475 err = ftp_pasv (&con->rbuf, pasv_addr);
476 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
480 logputs (LOG_VERBOSE, "\n");
481 logputs (LOG_NOTQUIET, _("\
482 Error in server response, closing control connection.\n"));
484 rbuf_uninitialize (&con->rbuf);
488 logputs (LOG_VERBOSE, "\n");
489 logputs (LOG_NOTQUIET,
490 _("Write failed, closing control connection.\n"));
492 rbuf_uninitialize (&con->rbuf);
496 logputs (LOG_VERBOSE, "\n");
497 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
500 logputs (LOG_VERBOSE, "\n");
501 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
512 sprintf (thost, "%d.%d.%d.%d",
513 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
514 tport = (pasv_addr[4] << 8) + pasv_addr[5];
515 DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
516 err = make_connection (&dtsock, thost, tport);
519 /* Do not close the socket in first several cases,
520 since it wasn't created at all. */
522 logputs (LOG_VERBOSE, "\n");
523 logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
526 rbuf_uninitialize (&con->rbuf);
530 logputs (LOG_VERBOSE, "\n");
531 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
533 rbuf_uninitialize (&con->rbuf);
537 logputs (LOG_VERBOSE, "\n");
538 logprintf (LOG_NOTQUIET,
539 _("Connection to %s:%hu refused.\n"),
542 rbuf_uninitialize (&con->rbuf);
546 logputs (LOG_VERBOSE, "\n");
547 logprintf (LOG_NOTQUIET, "connect: %s\n",
550 rbuf_uninitialize (&con->rbuf);
558 passive_mode_open= 1; /* Flag to avoid accept port */
559 if (!opt.server_response)
560 logputs (LOG_VERBOSE, _("done. "));
564 if (!passive_mode_open) /* Try to use a port command if PASV failed */
566 if (!opt.server_response)
567 logputs (LOG_VERBOSE, "==> PORT ... ");
568 err = ftp_port (&con->rbuf);
569 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
570 LISTENERR), HOSTERR, FTPPORTERR */
574 logputs (LOG_VERBOSE, "\n");
575 logputs (LOG_NOTQUIET, _("\
576 Error in server response, closing control connection.\n"));
579 rbuf_uninitialize (&con->rbuf);
583 logputs (LOG_VERBOSE, "\n");
584 logputs (LOG_NOTQUIET,
585 _("Write failed, closing control connection.\n"));
588 rbuf_uninitialize (&con->rbuf);
592 logputs (LOG_VERBOSE, "\n");
593 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
596 rbuf_uninitialize (&con->rbuf);
599 case CONPORTERR: case BINDERR: case LISTENERR:
600 /* What now? These problems are local... */
601 logputs (LOG_VERBOSE, "\n");
602 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
608 logputs (LOG_VERBOSE, "\n");
609 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
613 rbuf_uninitialize (&con->rbuf);
617 logputs (LOG_VERBOSE, "\n");
618 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
621 rbuf_uninitialize (&con->rbuf);
631 if (!opt.server_response)
632 logputs (LOG_VERBOSE, _("done. "));
634 } /* cmd & (DO_LIST | DO_RETR) */
636 /* Restart if needed. */
637 if (restval && (cmd & DO_RETR))
639 if (!opt.server_response)
640 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
641 err = ftp_rest (&con->rbuf, restval);
643 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
647 logputs (LOG_VERBOSE, "\n");
648 logputs (LOG_NOTQUIET, _("\
649 Error in server response, closing control connection.\n"));
652 rbuf_uninitialize (&con->rbuf);
656 logputs (LOG_VERBOSE, "\n");
657 logputs (LOG_NOTQUIET,
658 _("Write failed, closing control connection.\n"));
661 rbuf_uninitialize (&con->rbuf);
665 /* If `-c' is specified and the file already existed when
666 Wget was started, it would be a bad idea for us to start
667 downloading it from scratch, effectively truncating it. */
668 if (opt.always_rest && (cmd & NO_TRUNCATE))
670 logprintf (LOG_NOTQUIET,
671 _("\nREST failed; will not truncate `%s'.\n"),
675 rbuf_uninitialize (&con->rbuf);
676 return CONTNOTSUPPORTED;
678 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
688 if (err != FTPRESTFAIL && !opt.server_response)
689 logputs (LOG_VERBOSE, _("done. "));
690 } /* restval && cmd & DO_RETR */
696 if (!opt.server_response)
699 logputs (LOG_VERBOSE, "\n");
700 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
703 err = ftp_retr (&con->rbuf, u->file);
704 /* FTPRERR, WRITEFAILED, FTPNSFOD */
708 logputs (LOG_VERBOSE, "\n");
709 logputs (LOG_NOTQUIET, _("\
710 Error in server response, closing control connection.\n"));
713 rbuf_uninitialize (&con->rbuf);
717 logputs (LOG_VERBOSE, "\n");
718 logputs (LOG_NOTQUIET,
719 _("Write failed, closing control connection.\n"));
722 rbuf_uninitialize (&con->rbuf);
726 logputs (LOG_VERBOSE, "\n");
727 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
739 if (!opt.server_response)
740 logputs (LOG_VERBOSE, _("done.\n"));
741 expected_bytes = ftp_expected_bytes (ftp_last_respline);
746 if (!opt.server_response)
747 logputs (LOG_VERBOSE, "==> LIST ... ");
748 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
749 without arguments is better than `LIST .'; confirmed by
751 err = ftp_list (&con->rbuf, NULL);
752 /* FTPRERR, WRITEFAILED */
756 logputs (LOG_VERBOSE, "\n");
757 logputs (LOG_NOTQUIET, _("\
758 Error in server response, closing control connection.\n"));
761 rbuf_uninitialize (&con->rbuf);
765 logputs (LOG_VERBOSE, "\n");
766 logputs (LOG_NOTQUIET,
767 _("Write failed, closing control connection.\n"));
770 rbuf_uninitialize (&con->rbuf);
774 logputs (LOG_VERBOSE, "\n");
775 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
787 if (!opt.server_response)
788 logputs (LOG_VERBOSE, _("done.\n"));
789 expected_bytes = ftp_expected_bytes (ftp_last_respline);
790 } /* cmd & DO_LIST */
792 /* Some FTP servers return the total length of file after REST
793 command, others just return the remaining size. */
794 if (*len && restval && expected_bytes
795 && (expected_bytes == *len - restval))
797 DEBUGP (("Lying FTP server found, adjusting.\n"));
798 expected_bytes = *len;
801 /* If no transmission was required, then everything is OK. */
802 if (!(cmd & (DO_LIST | DO_RETR)))
805 if (!passive_mode_open) /* we are not using pasive mode so we need
808 /* Open the data transmission socket by calling acceptport(). */
809 err = acceptport (&dtsock);
810 /* Possible errors: ACCEPTERR. */
811 if (err == ACCEPTERR)
813 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
818 /* Open the file -- if opt.dfp is set, use it instead. */
819 if (!opt.dfp || con->cmd & DO_LIST)
821 mkalldirs (u->local);
823 rotate_backups (u->local);
824 /* #### Is this correct? */
825 chmod (u->local, 0600);
827 fp = fopen (u->local, restval ? "ab" : "wb");
830 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
832 rbuf_uninitialize (&con->rbuf);
839 extern int global_download_count;
842 /* Rewind the output document if the download starts over and if
843 this is the first download. See gethttp() for a longer
845 if (!restval && global_download_count == 0)
847 /* This will silently fail for streams that don't correspond
848 to regular files, but that's OK. */
850 /* ftruncate is needed because opt.dfp is opened in append
851 mode if opt.always_rest is set. */
852 ftruncate (fileno (fp), 0);
859 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
861 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
862 logputs (LOG_VERBOSE, "\n");
863 expected_bytes = *len; /* for get_contents/show_progress */
865 else if (expected_bytes)
867 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
869 logprintf (LOG_VERBOSE, _(" [%s to go]"),
870 legible (expected_bytes - restval));
871 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
874 /* Get the contents of the document. */
875 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
876 con->dltime = elapsed_time ();
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)
992 int count, orig_lp, no_truncate;
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;
1023 /* In `-c' is used, check whether the file we're writing to exists
1024 before we've done anything. If so, we'll refuse to truncate it
1025 if the server doesn't support continued downloads. */
1027 if (opt.always_rest)
1028 no_truncate = file_exists_p (locf);
1033 /* Increment the pass counter. */
1035 sleep_between_retrievals (count);
1036 if (con->st & ON_YOUR_OWN)
1039 con->cmd |= (DO_RETR | LEAVE_PENDING);
1040 if (rbuf_initialized_p (&con->rbuf))
1041 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1043 con->cmd |= (DO_LOGIN | DO_CWD);
1045 else /* not on your own */
1047 if (rbuf_initialized_p (&con->rbuf))
1048 con->cmd &= ~DO_LOGIN;
1050 con->cmd |= DO_LOGIN;
1051 if (con->st & DONE_CWD)
1052 con->cmd &= ~DO_CWD;
1057 con->cmd |= NO_TRUNCATE;
1058 /* Assume no restarting. */
1060 if ((count > 1 || opt.always_rest)
1061 && !(con->cmd & DO_LIST)
1062 && file_exists_p (locf))
1063 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1064 restval = st.st_size;
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;