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");
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"));
873 /* Get the contents of the document. */
874 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
875 con->dltime = elapsed_time ();
876 tms = time_str (NULL);
877 tmrate = rate (*len - restval, con->dltime, 0);
878 /* Close data connection socket. */
880 /* Close the local file. */
882 /* Close or flush the file. We have to be careful to check for
883 error here. Checking the result of fwrite() is not enough --
884 errors could go unnoticed! */
886 if (!opt.dfp || con->cmd & DO_LIST)
887 flush_res = fclose (fp);
889 flush_res = fflush (fp);
890 if (flush_res == EOF)
893 /* If get_contents couldn't write to fp, bail out. */
896 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
897 u->local, strerror (errno));
899 rbuf_uninitialize (&con->rbuf);
904 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
905 tms, tmrate, strerror (errno));
906 if (opt.server_response)
907 logputs (LOG_ALWAYS, "\n");
910 /* Get the server to tell us if everything is retrieved. */
911 err = ftp_response (&con->rbuf, &respline);
912 /* ...and empty the buffer. */
913 rbuf_discard (&con->rbuf);
917 /* The control connection is decidedly closed. Print the time
918 only if it hasn't already been printed. */
920 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
921 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
922 /* If there is an error on the control connection, close it, but
923 return FTPRETRINT, since there is a possibility that the
924 whole file was retrieved nevertheless (but that is for
925 ftp_loop_internal to decide). */
927 rbuf_uninitialize (&con->rbuf);
930 /* If retrieval failed for any reason, return FTPRETRINT, but do not
931 close socket, since the control connection is still alive. If
932 there is something wrong with the control connection, it will
933 become apparent later. */
934 if (*respline != '2')
938 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
939 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
946 /* What now? The data connection was erroneous, whereas the
947 response says everything is OK. We shall play it safe. */
951 if (!(cmd & LEAVE_PENDING))
953 /* I should probably send 'QUIT' and check for a reply, but this
954 is faster. #### Is it OK, though? */
956 rbuf_uninitialize (&con->rbuf);
958 /* If it was a listing, and opt.server_response is true,
960 if (opt.server_response && (con->cmd & DO_LIST))
962 mkalldirs (u->local);
963 fp = fopen (u->local, "r");
965 logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
969 /* The lines are being read with read_whole_line because of
970 no-buffering on opt.lfile. */
971 while ((line = read_whole_line (fp)))
973 logprintf (LOG_ALWAYS, "%s\n", line);
978 } /* con->cmd & DO_LIST && server_response */
983 /* A one-file FTP loop. This is the part where FTP retrieval is
984 retried, and retried, and retried, and...
986 This loop either gets commands from con, or (if ON_YOUR_OWN is
987 set), makes them up to retrieve the file given by the URL. */
989 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
991 int count, orig_lp, no_truncate;
993 char *tms, *tmrate, *locf;
998 u->local = url_filename (u);
1000 if (opt.noclobber && file_exists_p (u->local))
1002 logprintf (LOG_VERBOSE,
1003 _("File `%s' already there, not retrieving.\n"), u->local);
1004 /* If the file is there, we suppose it's retrieved OK. */
1008 /* Remove it if it's a link. */
1009 remove_link (u->local);
1010 if (!opt.output_document)
1013 locf = opt.output_document;
1017 if (con->st & ON_YOUR_OWN)
1018 con->st = ON_YOUR_OWN;
1020 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1022 /* In `-c' is used, check whether the file we're writing to exists
1023 before we've done anything. If so, we'll refuse to truncate it
1024 if the server doesn't support continued downloads. */
1026 if (opt.always_rest)
1027 no_truncate = file_exists_p (locf);
1032 /* Increment the pass counter. */
1034 sleep_between_retrievals (count);
1035 if (con->st & ON_YOUR_OWN)
1038 con->cmd |= (DO_RETR | LEAVE_PENDING);
1039 if (rbuf_initialized_p (&con->rbuf))
1040 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1042 con->cmd |= (DO_LOGIN | DO_CWD);
1044 else /* not on your own */
1046 if (rbuf_initialized_p (&con->rbuf))
1047 con->cmd &= ~DO_LOGIN;
1049 con->cmd |= DO_LOGIN;
1050 if (con->st & DONE_CWD)
1051 con->cmd &= ~DO_CWD;
1056 con->cmd |= NO_TRUNCATE;
1057 /* Assume no restarting. */
1059 if ((count > 1 || opt.always_rest)
1060 && !(con->cmd & DO_LIST)
1061 && file_exists_p (locf))
1062 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1063 restval = st.st_size;
1064 /* Get the current time string. */
1065 tms = time_str (NULL);
1066 /* Print fetch message, if opt.verbose. */
1069 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1073 sprintf (tmp, _("(try:%2d)"), count);
1074 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1075 tms, hurl, tmp, locf);
1077 ws_changetitle (hurl, 1);
1081 /* Send getftp the proper length, if fileinfo was provided. */
1086 err = getftp (u, &len, restval, con);
1088 tms = time_str (NULL);
1089 tmrate = rate (len - restval, con->dltime, 0);
1091 if (!rbuf_initialized_p (&con->rbuf))
1092 con->st &= ~DONE_CWD;
1094 con->st |= DONE_CWD;
1098 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1099 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1100 /* Fatal errors, give up. */
1103 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1104 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1105 case BINDERR: case LISTENERR: case ACCEPTERR:
1106 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1107 printwhat (count, opt.ntry);
1108 /* non-fatal errors */
1112 /* If the control connection was closed, the retrieval
1113 will be considered OK if f->size == len. */
1114 if (!f || len != f->size)
1116 printwhat (count, opt.ntry);
1128 /* If we get out of the switch above without continue'ing, we've
1129 successfully downloaded a file. Remember this fact. */
1130 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1132 if (con->st & ON_YOUR_OWN)
1134 CLOSE (RBUF_FD (&con->rbuf));
1135 rbuf_uninitialize (&con->rbuf);
1137 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1138 tms, tmrate, locf, len);
1139 if (!opt.verbose && !opt.quiet)
1141 /* Need to hide the password from the URL. The `if' is here
1142 so that we don't do the needless allocation every
1144 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1145 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1146 tms, hurl, len, locf, count);
1150 if ((con->cmd & DO_LIST))
1151 /* This is a directory listing file. */
1153 if (!opt.remove_listing)
1154 /* --dont-remove-listing was specified, so do count this towards the
1155 number of bytes and files downloaded. */
1157 downloaded_increase (len);
1161 /* Deletion of listing files is not controlled by --delete-after, but
1162 by the more specific option --dont-remove-listing, and the code
1163 to do this deletion is in another function. */
1166 /* This is not a directory listing file. */
1168 /* Unlike directory listing files, don't pretend normal files weren't
1169 downloaded if they're going to be deleted. People seeding proxies,
1170 for instance, may want to know how many bytes and files they've
1171 downloaded through it. */
1172 downloaded_increase (len);
1175 if (opt.delete_after)
1177 DEBUGP (("Removing file due to --delete-after in"
1178 " ftp_loop_internal():\n"));
1179 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1181 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1185 /* Restore the original leave-pendingness. */
1187 con->cmd |= LEAVE_PENDING;
1189 con->cmd &= ~LEAVE_PENDING;
1191 } while (!opt.ntry || (count < opt.ntry));
1193 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1195 CLOSE (RBUF_FD (&con->rbuf));
1196 rbuf_uninitialize (&con->rbuf);
1201 /* Return the directory listing in a reusable format. The directory
1202 is specifed in u->dir. */
1204 ftp_get_listing (struct urlinfo *u, ccon *con, struct fileinfo **f)
1207 char *olocal = u->local;
1208 char *list_filename, *ofile;
1210 con->st &= ~ON_YOUR_OWN;
1211 con->cmd |= (DO_LIST | LEAVE_PENDING);
1212 con->cmd &= ~DO_RETR;
1213 /* Get the listing filename. */
1215 u->file = LIST_FILENAME;
1216 list_filename = url_filename (u);
1218 u->local = list_filename;
1219 DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1220 err = ftp_loop_internal (u, NULL, con);
1223 *f = ftp_parse_ls (list_filename, con->rs);
1226 if (opt.remove_listing)
1228 if (unlink (list_filename))
1229 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1231 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1233 xfree (list_filename);
1234 con->cmd &= ~DO_LIST;
1238 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1240 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1241 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1242 struct fileinfo **));
1243 static void freefileinfo PARAMS ((struct fileinfo *f));
1245 /* Retrieve a list of files given in struct fileinfo linked list. If
1246 a file is a symbolic link, do not retrieve it, but rather try to
1247 set up a similar link on the local disk, if the symlinks are
1250 If opt.recursive is set, after all files have been retrieved,
1251 ftp_retrieve_dirs will be called to retrieve the directories. */
1253 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1255 static int depth = 0;
1257 char *olocal, *ofile;
1258 struct fileinfo *orig;
1263 /* Increase the depth. */
1265 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1267 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1268 depth, opt.reclevel));
1276 con->st &= ~ON_YOUR_OWN;
1277 if (!(con->st & DONE_CWD))
1280 con->cmd &= ~DO_CWD;
1281 con->cmd |= (DO_RETR | LEAVE_PENDING);
1283 if (!rbuf_initialized_p (&con->rbuf))
1284 con->cmd |= DO_LOGIN;
1286 con->cmd &= ~DO_LOGIN;
1288 err = RETROK; /* in case it's not used */
1292 if (downloaded_exceeds_quota ())
1300 u->local = url_filename (u);
1304 if (opt.timestamping && f->type == FT_PLAINFILE)
1307 /* If conversion of HTML files retrieved via FTP is ever implemented,
1308 we'll need to stat() <file>.orig here when -K has been specified.
1309 I'm not implementing it now since files on an FTP server are much
1310 more likely than files on an HTTP server to legitimately have a
1312 if (!stat (u->local, &st))
1316 /* Else, get it from the file. */
1317 local_size = st.st_size;
1319 /* Compare file sizes only for servers that tell us correct
1320 values. Assumme sizes being equal for servers that lie
1322 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1323 eq_size = cor_val ? (local_size == f->size) : 1 ;
1324 if (f->tstamp <= tml && eq_size)
1326 /* Remote file is older, file sizes can be compared and
1328 logprintf (LOG_VERBOSE, _("\
1329 Remote file no newer than local file `%s' -- not retrieving.\n"), u->local);
1334 /* Remote file is newer or sizes cannot be matched */
1335 logprintf (LOG_VERBOSE, _("\
1336 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1341 /* Sizes do not match */
1342 logprintf (LOG_VERBOSE, _("\
1343 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1346 } /* opt.timestamping && f->type == FT_PLAINFILE */
1350 /* If opt.retr_symlinks is defined, we treat symlinks as
1351 if they were normal files. There is currently no way
1352 to distinguish whether they might be directories, and
1354 if (!opt.retr_symlinks)
1358 logputs (LOG_NOTQUIET,
1359 _("Invalid name of the symlink, skipping.\n"));
1363 /* Check whether we already have the correct
1365 int rc = lstat (u->local, &st);
1368 size_t len = strlen (f->linkto) + 1;
1369 if (S_ISLNK (st.st_mode))
1371 char *link_target = (char *)alloca (len);
1372 size_t n = readlink (u->local, link_target, len);
1374 && (memcmp (link_target, f->linkto, n) == 0))
1376 logprintf (LOG_VERBOSE, _("\
1377 Already have correct symlink %s -> %s\n\n"),
1378 u->local, f->linkto);
1384 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1385 u->local, f->linkto);
1386 /* Unlink before creating symlink! */
1388 if (symlink (f->linkto, u->local) == -1)
1389 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1391 logputs (LOG_VERBOSE, "\n");
1392 } /* have f->linkto */
1393 #else /* not HAVE_SYMLINK */
1394 logprintf (LOG_NOTQUIET,
1395 _("Symlinks not supported, skipping symlink `%s'.\n"),
1397 #endif /* not HAVE_SYMLINK */
1399 else /* opt.retr_symlinks */
1402 err = ftp_loop_internal (u, f, con);
1403 } /* opt.retr_symlinks */
1407 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1411 /* Call the retrieve loop. */
1413 err = ftp_loop_internal (u, f, con);
1416 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1421 /* Set the time-stamp information to the local file. Symlinks
1422 are not to be stamped because it sets the stamp on the
1424 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1427 && file_exists_p (u->local))
1429 /* #### This code repeats in http.c and ftp.c. Move it to a
1431 const char *fl = NULL;
1432 if (opt.output_document)
1434 if (opt.od_known_regular)
1435 fl = opt.output_document;
1440 touch (fl, f->tstamp);
1442 else if (f->tstamp == -1)
1443 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1445 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1446 chmod (u->local, f->perms);
1448 DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1453 /* Break on fatals. */
1454 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1456 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1459 /* We do not want to call ftp_retrieve_dirs here */
1460 if (opt.recursive &&
1461 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1462 err = ftp_retrieve_dirs (u, orig, con);
1463 else if (opt.recursive)
1464 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1465 depth, opt.reclevel));
1470 /* Retrieve the directories given in a file list. This function works
1471 by simply going through the linked list and calling
1472 ftp_retrieve_glob on each directory entry. The function knows
1473 about excluded directories. */
1475 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1478 char *current_container = NULL;
1479 int current_length = 0;
1481 for (; f; f = f->next)
1485 if (downloaded_exceeds_quota ())
1487 if (f->type != FT_DIRECTORY)
1490 len = strlen (u->dir) + 1 + strlen (f->name) + 1;
1491 /* Allocate u->dir off stack, but reallocate only if a larger
1492 string is needed. */
1493 if (len > current_length)
1494 current_container = (char *)alloca (len);
1495 u->dir = current_container;
1497 || (*odir == '/' && *(odir + 1) == '\0'))
1498 /* If ODIR is empty or just "/", simply append f->name to
1499 ODIR. (In the former case, to preserve u->dir being
1500 relative; in the latter case, to avoid double slash.) */
1501 sprintf (u->dir, "%s%s", odir, f->name);
1503 /* Else, use a separator. */
1504 sprintf (u->dir, "%s/%s", odir, f->name);
1505 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1506 DEBUGP ((" odir = '%s'\n f->name = '%s'\n u->dir = '%s'\n\n",
1507 odir, f->name, u->dir));
1508 if (!accdir (u->dir, ALLABS))
1510 logprintf (LOG_VERBOSE, _("\
1511 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1515 con->st &= ~DONE_CWD;
1516 ftp_retrieve_glob (u, con, GETALL);
1517 /* Set the time-stamp? */
1520 if (opt.quota && opt.downloaded > opt.quota)
1527 /* A near-top-level function to retrieve the files in a directory.
1528 The function calls ftp_get_listing, to get a linked list of files.
1529 Then it weeds out the file names that do not match the pattern.
1530 ftp_retrieve_list is called with this updated list as an argument.
1532 If the argument ACTION is GETONE, just download the file (but first
1533 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1534 use globbing; if it's GETALL, download the whole directory. */
1536 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1538 struct fileinfo *orig, *start;
1541 con->cmd |= LEAVE_PENDING;
1543 res = ftp_get_listing (u, con, &orig);
1547 /* First: weed out that do not conform the global rules given in
1548 opt.accepts and opt.rejects. */
1549 if (opt.accepts || opt.rejects)
1551 struct fileinfo *f = orig;
1555 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1557 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1558 f = delelement (f, &start);
1564 /* Now weed out the files that do not match our globbing pattern.
1565 If we are dealing with a globbing pattern, that is. */
1566 if (*u->file && (action == GLOBALL || action == GETONE))
1569 struct fileinfo *f = start;
1573 matchres = fnmatch (u->file, f->name, 0);
1576 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1580 if (matchres == FNM_NOMATCH)
1581 f = delelement (f, &start); /* delete the element from the list */
1583 f = f->next; /* leave the element in the list */
1587 freefileinfo (start);
1588 return RETRBADPATTERN;
1594 /* Just get everything. */
1595 ftp_retrieve_list (u, start, con);
1599 if (action == GLOBALL)
1602 /* #### This message SUCKS. We should see what was the
1603 reason that nothing was retrieved. */
1604 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1606 else /* GETONE or GETALL */
1608 /* Let's try retrieving it anyway. */
1609 con->st |= ON_YOUR_OWN;
1610 res = ftp_loop_internal (u, NULL, con);
1614 freefileinfo (start);
1615 if (downloaded_exceeds_quota ())
1618 /* #### Should we return `res' here? */
1622 /* The wrapper that calls an appropriate routine according to contents
1623 of URL. Inherently, its capabilities are limited on what can be
1624 encoded into a URL. */
1626 ftp_loop (struct urlinfo *u, int *dt)
1628 ccon con; /* FTP connection */
1633 memset (&con, 0, sizeof (con));
1635 rbuf_uninitialize (&con.rbuf);
1636 con.st = ON_YOUR_OWN;
1639 res = RETROK; /* in case it's not used */
1641 /* If the file name is empty, the user probably wants a directory
1642 index. We'll provide one, properly HTML-ized. Unless
1643 opt.htmlify is 0, of course. :-) */
1644 if (!*u->file && !opt.recursive)
1647 res = ftp_get_listing (u, &con, &f);
1653 char *filename = (opt.output_document
1654 ? xstrdup (opt.output_document)
1655 : (u->local ? xstrdup (u->local)
1656 : url_filename (u)));
1657 res = ftp_index (filename, u, f);
1658 if (res == FTPOK && opt.verbose)
1660 if (!opt.output_document)
1664 if (stat (filename, &st) == 0)
1668 logprintf (LOG_NOTQUIET,
1669 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1673 logprintf (LOG_NOTQUIET,
1674 _("Wrote HTML-ized index to `%s'.\n"),
1684 int wild = has_wildcards_p (u->file);
1685 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1687 /* ftp_retrieve_glob is a catch-all function that gets called
1688 if we need globbing, time-stamping or recursion. Its
1689 third argument is just what we really need. */
1690 ftp_retrieve_glob (u, &con,
1691 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1694 res = ftp_loop_internal (u, NULL, &con);
1700 /* If a connection was left, quench it. */
1701 if (rbuf_initialized_p (&con.rbuf))
1702 CLOSE (RBUF_FD (&con.rbuf));
1703 FREE_MAYBE (con.id);
1708 /* Delete an element from the fileinfo linked list. Returns the
1709 address of the next element, or NULL if the list is exhausted. It
1710 can modify the start of the list. */
1711 static struct fileinfo *
1712 delelement (struct fileinfo *f, struct fileinfo **start)
1714 struct fileinfo *prev = f->prev;
1715 struct fileinfo *next = f->next;
1718 FREE_MAYBE (f->linkto);
1730 /* Free the fileinfo linked list of files. */
1732 freefileinfo (struct fileinfo *f)
1736 struct fileinfo *next = f->next;