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. */
33 #include <sys/types.h>
55 /* File where the "ls -al" listing will be saved. */
56 #define LIST_FILENAME ".listing"
58 extern char ftp_last_respline[];
60 /* #### Global variables?? These two should be members of struct
63 static enum stype host_type=ST_UNIX;
66 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
67 the string S, and return the number converted to long, if found, 0
70 ftp_expected_bytes (const char *s)
76 while (*s && *s != '(')
80 for (++s; *s && ISSPACE (*s); s++);
88 res = (*s - '0') + 10 * res;
91 while (*s && ISDIGIT (*s));
94 while (*s && ISSPACE (*s))
98 if (TOLOWER (*s) != 'b')
100 if (strncasecmp (s, "byte", 4))
108 /* Retrieves a file with denoted parameters through opening an FTP
109 connection to the server. It always closes the data connection,
110 and closes the control connection in case of error. */
112 getftp (const struct urlinfo *u, long *len, long restval, ccon *con)
114 int csock, dtsock, res;
117 char *user, *passwd, *respline;
119 unsigned char pasv_addr[6];
121 int passive_mode_open = 0;
122 long expected_bytes = 0L;
124 assert (con != NULL);
125 assert (u->local != NULL);
126 /* Debug-check of the sanity of the request by making sure that LIST
127 and RETR are never both requested (since we can handle only one
129 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
130 /* Make sure that at least *something* is requested. */
131 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
135 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
136 user = user ? user : opt.ftp_acc;
138 opt.ftp_pass = ftp_getaddress ();
139 passwd = passwd ? passwd : opt.ftp_pass;
140 assert (user && passwd);
145 if (!(cmd & DO_LOGIN))
146 csock = RBUF_FD (&con->rbuf);
147 else /* cmd & DO_LOGIN */
149 /* Login to the server: */
151 /* First: Establish the control connection. */
152 logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
153 err = make_connection (&csock, u->host, u->port);
154 if (cmd & LEAVE_PENDING)
155 rbuf_initialize (&con->rbuf, csock);
157 rbuf_uninitialize (&con->rbuf);
160 /* Do not close the socket in first several cases, since it
161 wasn't created at all. */
163 logputs (LOG_VERBOSE, "\n");
164 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
168 logputs (LOG_VERBOSE, "\n");
169 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
173 logputs (LOG_VERBOSE, "\n");
174 logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
177 rbuf_uninitialize (&con->rbuf);
180 logputs (LOG_VERBOSE, "\n");
181 logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
183 rbuf_uninitialize (&con->rbuf);
190 /* Since this is a new connection, we may safely discard
191 anything left in the buffer. */
192 rbuf_discard (&con->rbuf);
194 /* Second: Login with proper USER/PASS sequence. */
195 logputs (LOG_VERBOSE, _("connected!\n"));
196 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
197 if (opt.server_response)
198 logputs (LOG_ALWAYS, "\n");
199 err = ftp_login (&con->rbuf, user, passwd);
200 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
204 logputs (LOG_VERBOSE, "\n");
205 logputs (LOG_NOTQUIET, _("\
206 Error in server response, closing control connection.\n"));
208 rbuf_uninitialize (&con->rbuf);
212 logputs (LOG_VERBOSE, "\n");
213 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
215 rbuf_uninitialize (&con->rbuf);
219 logputs (LOG_VERBOSE, "\n");
220 logputs (LOG_NOTQUIET,
221 _("Write failed, closing control connection.\n"));
223 rbuf_uninitialize (&con->rbuf);
227 logputs (LOG_VERBOSE, "\n");
228 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
230 rbuf_uninitialize (&con->rbuf);
231 return FTPLOGREFUSED;
234 logputs (LOG_VERBOSE, "\n");
235 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
237 rbuf_uninitialize (&con->rbuf);
241 if (!opt.server_response)
242 logputs (LOG_VERBOSE, _("Logged in!\n"));
249 /* Third: Get the system type */
250 if (!opt.server_response)
251 logprintf (LOG_VERBOSE, "==> SYST ... ");
252 err = ftp_syst (&con->rbuf, &host_type);
257 logputs (LOG_VERBOSE, "\n");
258 logputs (LOG_NOTQUIET, _("\
259 Error in server response, closing control connection.\n"));
261 rbuf_uninitialize (&con->rbuf);
265 logputs (LOG_VERBOSE, "\n");
266 logputs (LOG_NOTQUIET,
267 _("Server error, can't determine system type.\n"));
270 /* Everything is OK. */
276 if (!opt.server_response)
277 logputs (LOG_VERBOSE, _("done. "));
279 /* Fourth: Find the initial ftp directory */
281 if (!opt.server_response)
282 logprintf (LOG_VERBOSE, "==> PWD ... ");
283 err = ftp_pwd(&con->rbuf, &pwd);
287 case FTPRERR || FTPSRVERR :
288 logputs (LOG_VERBOSE, "\n");
289 logputs (LOG_NOTQUIET, _("\
290 Error in server response, closing control connection.\n"));
292 rbuf_uninitialize (&con->rbuf);
296 /* Everything is OK. */
302 if (!opt.server_response)
303 logputs (LOG_VERBOSE, _("done.\n"));
305 /* Fifth: Set the FTP type. */
306 if (!opt.server_response)
307 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
308 err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
309 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
313 logputs (LOG_VERBOSE, "\n");
314 logputs (LOG_NOTQUIET, _("\
315 Error in server response, closing control connection.\n"));
317 rbuf_uninitialize (&con->rbuf);
321 logputs (LOG_VERBOSE, "\n");
322 logputs (LOG_NOTQUIET,
323 _("Write failed, closing control connection.\n"));
325 rbuf_uninitialize (&con->rbuf);
329 logputs (LOG_VERBOSE, "\n");
330 logprintf (LOG_NOTQUIET,
331 _("Unknown type `%c', closing control connection.\n"),
332 TOUPPER (u->ftp_type));
334 rbuf_uninitialize (&con->rbuf);
337 /* Everything is OK. */
343 if (!opt.server_response)
344 logputs (LOG_VERBOSE, _("done. "));
350 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
353 /* Change working directory. If the FTP host runs VMS and
354 the path specified is absolute, we will have to convert
355 it to VMS style as VMS does not like leading slashes */
356 DEBUGP (("changing working directory\n"));
357 if (*(u->dir) == '/')
359 int pwd_len = strlen (pwd);
360 char *result = (char *)alloca (strlen (u->dir) + pwd_len + 10);
366 char *tmp_dir, *tmpp;
367 STRDUP_ALLOCA (tmp_dir, u->dir);
368 for (tmpp = tmp_dir; *tmpp; tmpp++)
371 strcpy (result, pwd);
372 /* pwd ends with ']', we have to get rid of it */
373 result[pwd_len - 1]= '\0';
374 strcat (result, tmp_dir);
375 strcat (result, "]");
380 /* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
383 strcpy (result, pwd);
384 strcat (result, u->dir);
385 /* These look like debugging messages to me. */
387 logprintf (LOG_VERBOSE, "\npwd=\"%s\"", pwd);
388 logprintf (LOG_VERBOSE, "\nu->dir=\"%s\"", u->dir);
395 if (!opt.server_response)
396 logprintf (LOG_VERBOSE, "==> CWD %s ... ", result);
397 err = ftp_cwd (&con->rbuf, result);
401 if (!opt.server_response)
402 logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
403 err = ftp_cwd (&con->rbuf, u->dir);
405 /* FTPRERR, WRITEFAILED, FTPNSFOD */
409 logputs (LOG_VERBOSE, "\n");
410 logputs (LOG_NOTQUIET, _("\
411 Error in server response, closing control connection.\n"));
413 rbuf_uninitialize (&con->rbuf);
417 logputs (LOG_VERBOSE, "\n");
418 logputs (LOG_NOTQUIET,
419 _("Write failed, closing control connection.\n"));
421 rbuf_uninitialize (&con->rbuf);
425 logputs (LOG_VERBOSE, "\n");
426 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
429 rbuf_uninitialize (&con->rbuf);
439 if (!opt.server_response)
440 logputs (LOG_VERBOSE, _("done.\n"));
443 else /* do not CWD */
444 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
446 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
447 if (cmd & (DO_LIST | DO_RETR))
449 if (opt.ftp_pasv > 0)
452 unsigned short tport;
454 if (!opt.server_response)
455 logputs (LOG_VERBOSE, "==> PASV ... ");
456 err = ftp_pasv (&con->rbuf, pasv_addr);
457 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
461 logputs (LOG_VERBOSE, "\n");
462 logputs (LOG_NOTQUIET, _("\
463 Error in server response, closing control connection.\n"));
465 rbuf_uninitialize (&con->rbuf);
469 logputs (LOG_VERBOSE, "\n");
470 logputs (LOG_NOTQUIET,
471 _("Write failed, closing control connection.\n"));
473 rbuf_uninitialize (&con->rbuf);
477 logputs (LOG_VERBOSE, "\n");
478 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
481 logputs (LOG_VERBOSE, "\n");
482 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
493 sprintf (thost, "%d.%d.%d.%d",
494 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
495 tport = (pasv_addr[4] << 8) + pasv_addr[5];
496 DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
497 err = make_connection (&dtsock, thost, tport);
500 /* Do not close the socket in first several cases,
501 since it wasn't created at all. */
503 logputs (LOG_VERBOSE, "\n");
504 logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
507 rbuf_uninitialize (&con->rbuf);
511 logputs (LOG_VERBOSE, "\n");
512 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
514 rbuf_uninitialize (&con->rbuf);
518 logputs (LOG_VERBOSE, "\n");
519 logprintf (LOG_NOTQUIET,
520 _("Connection to %s:%hu refused.\n"),
523 rbuf_uninitialize (&con->rbuf);
527 logputs (LOG_VERBOSE, "\n");
528 logprintf (LOG_NOTQUIET, "connect: %s\n",
531 rbuf_uninitialize (&con->rbuf);
539 passive_mode_open= 1; /* Flag to avoid accept port */
540 if (!opt.server_response)
541 logputs (LOG_VERBOSE, _("done. "));
545 if (!passive_mode_open) /* Try to use a port command if PASV failed */
547 if (!opt.server_response)
548 logputs (LOG_VERBOSE, "==> PORT ... ");
549 err = ftp_port (&con->rbuf);
550 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
551 LISTENERR), HOSTERR, FTPPORTERR */
555 logputs (LOG_VERBOSE, "\n");
556 logputs (LOG_NOTQUIET, _("\
557 Error in server response, closing control connection.\n"));
560 rbuf_uninitialize (&con->rbuf);
564 logputs (LOG_VERBOSE, "\n");
565 logputs (LOG_NOTQUIET,
566 _("Write failed, closing control connection.\n"));
569 rbuf_uninitialize (&con->rbuf);
573 logputs (LOG_VERBOSE, "\n");
574 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
577 rbuf_uninitialize (&con->rbuf);
580 case CONPORTERR: case BINDERR: case LISTENERR:
581 /* What now? These problems are local... */
582 logputs (LOG_VERBOSE, "\n");
583 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
589 logputs (LOG_VERBOSE, "\n");
590 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
594 rbuf_uninitialize (&con->rbuf);
598 logputs (LOG_VERBOSE, "\n");
599 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
602 rbuf_uninitialize (&con->rbuf);
612 if (!opt.server_response)
613 logputs (LOG_VERBOSE, _("done. "));
615 } /* cmd & (DO_LIST | DO_RETR) */
617 /* Restart if needed. */
618 if (restval && (cmd & DO_RETR))
620 if (!opt.server_response)
621 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
622 err = ftp_rest (&con->rbuf, restval);
624 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
628 logputs (LOG_VERBOSE, "\n");
629 logputs (LOG_NOTQUIET, _("\
630 Error in server response, closing control connection.\n"));
633 rbuf_uninitialize (&con->rbuf);
637 logputs (LOG_VERBOSE, "\n");
638 logputs (LOG_NOTQUIET,
639 _("Write failed, closing control connection.\n"));
642 rbuf_uninitialize (&con->rbuf);
646 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
656 if (err != FTPRESTFAIL && !opt.server_response)
657 logputs (LOG_VERBOSE, _("done. "));
658 } /* restval && cmd & DO_RETR */
664 if (!opt.server_response)
667 logputs (LOG_VERBOSE, "\n");
668 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
671 err = ftp_retr (&con->rbuf, u->file);
672 /* FTPRERR, WRITEFAILED, FTPNSFOD */
676 logputs (LOG_VERBOSE, "\n");
677 logputs (LOG_NOTQUIET, _("\
678 Error in server response, closing control connection.\n"));
681 rbuf_uninitialize (&con->rbuf);
685 logputs (LOG_VERBOSE, "\n");
686 logputs (LOG_NOTQUIET,
687 _("Write failed, closing control connection.\n"));
690 rbuf_uninitialize (&con->rbuf);
694 logputs (LOG_VERBOSE, "\n");
695 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
707 if (!opt.server_response)
708 logputs (LOG_VERBOSE, _("done.\n"));
709 expected_bytes = ftp_expected_bytes (ftp_last_respline);
714 if (!opt.server_response)
715 logputs (LOG_VERBOSE, "==> LIST ... ");
716 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
717 without arguments is better than `LIST .'; confirmed by
719 err = ftp_list (&con->rbuf, NULL);
720 /* FTPRERR, WRITEFAILED */
724 logputs (LOG_VERBOSE, "\n");
725 logputs (LOG_NOTQUIET, _("\
726 Error in server response, closing control connection.\n"));
729 rbuf_uninitialize (&con->rbuf);
733 logputs (LOG_VERBOSE, "\n");
734 logputs (LOG_NOTQUIET,
735 _("Write failed, closing control connection.\n"));
738 rbuf_uninitialize (&con->rbuf);
742 logputs (LOG_VERBOSE, "\n");
743 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
755 if (!opt.server_response)
756 logputs (LOG_VERBOSE, _("done.\n"));
757 expected_bytes = ftp_expected_bytes (ftp_last_respline);
758 } /* cmd & DO_LIST */
760 /* Some FTP servers return the total length of file after REST
761 command, others just return the remaining size. */
762 if (*len && restval && expected_bytes
763 && (expected_bytes == *len - restval))
765 DEBUGP (("Lying FTP server found, adjusting.\n"));
766 expected_bytes = *len;
769 /* If no transmission was required, then everything is OK. */
770 if (!(cmd & (DO_LIST | DO_RETR)))
773 if (!passive_mode_open) /* we are not using pasive mode so we need
776 /* Open the data transmission socket by calling acceptport(). */
777 err = acceptport (&dtsock);
778 /* Possible errors: ACCEPTERR. */
779 if (err == ACCEPTERR)
781 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
786 /* Open the file -- if opt.dfp is set, use it instead. */
787 if (!opt.dfp || con->cmd & DO_LIST)
789 mkalldirs (u->local);
791 rotate_backups (u->local);
792 /* #### Is this correct? */
793 chmod (u->local, 0600);
795 fp = fopen (u->local, restval ? "ab" : "wb");
798 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
800 rbuf_uninitialize (&con->rbuf);
810 /* This will silently fail for streams that don't correspond
811 to regular files, but that's OK. */
819 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
821 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
822 logputs (LOG_VERBOSE, "\n");
824 else if (expected_bytes)
826 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
828 logprintf (LOG_VERBOSE, _(" [%s to go]"),
829 legible (expected_bytes - restval));
830 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
833 /* Get the contents of the document. */
834 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
835 con->dltime = elapsed_time ();
836 tms = time_str (NULL);
837 tmrate = rate (*len - restval, con->dltime);
838 /* Close data connection socket. */
840 /* Close the local file. */
842 /* Close or flush the file. We have to be careful to check for
843 error here. Checking the result of fwrite() is not enough --
844 errors could go unnoticed! */
846 if (!opt.dfp || con->cmd & DO_LIST)
847 flush_res = fclose (fp);
849 flush_res = fflush (fp);
850 if (flush_res == EOF)
853 /* If get_contents couldn't write to fp, bail out. */
856 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
857 u->local, strerror (errno));
859 rbuf_uninitialize (&con->rbuf);
864 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
865 tms, tmrate, strerror (errno));
866 if (opt.server_response)
867 logputs (LOG_ALWAYS, "\n");
870 /* Get the server to tell us if everything is retrieved. */
871 err = ftp_response (&con->rbuf, &respline);
872 /* ...and empty the buffer. */
873 rbuf_discard (&con->rbuf);
877 /* The control connection is decidedly closed. Print the time
878 only if it hasn't already been printed. */
880 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
881 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
882 /* If there is an error on the control connection, close it, but
883 return FTPRETRINT, since there is a possibility that the
884 whole file was retrieved nevertheless (but that is for
885 ftp_loop_internal to decide). */
887 rbuf_uninitialize (&con->rbuf);
890 /* If retrieval failed for any reason, return FTPRETRINT, but do not
891 close socket, since the control connection is still alive. If
892 there is something wrong with the control connection, it will
893 become apparent later. */
894 if (*respline != '2')
898 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
899 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
906 /* What now? The data connection was erroneous, whereas the
907 response says everything is OK. We shall play it safe. */
911 if (!(cmd & LEAVE_PENDING))
913 /* I should probably send 'QUIT' and check for a reply, but this
914 is faster. #### Is it OK, though? */
916 rbuf_uninitialize (&con->rbuf);
918 /* If it was a listing, and opt.server_response is true,
920 if (opt.server_response && (con->cmd & DO_LIST))
922 mkalldirs (u->local);
923 fp = fopen (u->local, "r");
925 logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
929 /* The lines are being read with read_whole_line because of
930 no-buffering on opt.lfile. */
931 while ((line = read_whole_line (fp)))
933 logprintf (LOG_ALWAYS, "%s\n", line);
938 } /* con->cmd & DO_LIST && server_response */
943 /* A one-file FTP loop. This is the part where FTP retrieval is
944 retried, and retried, and retried, and...
946 This loop either gets commands from con, or (if ON_YOUR_OWN is
947 set), makes them up to retrieve the file given by the URL. */
949 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
953 char *tms, *tmrate, *locf;
958 u->local = url_filename (u);
960 if (opt.noclobber && file_exists_p (u->local))
962 logprintf (LOG_VERBOSE,
963 _("File `%s' already there, not retrieving.\n"), u->local);
964 /* If the file is there, we suppose it's retrieved OK. */
968 /* Remove it if it's a link. */
969 remove_link (u->local);
970 if (!opt.output_document)
973 locf = opt.output_document;
977 if (con->st & ON_YOUR_OWN)
978 con->st = ON_YOUR_OWN;
980 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
985 /* Increment the pass counter. */
987 sleep_between_retrievals (count);
988 if (con->st & ON_YOUR_OWN)
991 con->cmd |= (DO_RETR | LEAVE_PENDING);
992 if (rbuf_initialized_p (&con->rbuf))
993 con->cmd &= ~ (DO_LOGIN | DO_CWD);
995 con->cmd |= (DO_LOGIN | DO_CWD);
997 else /* not on your own */
999 if (rbuf_initialized_p (&con->rbuf))
1000 con->cmd &= ~DO_LOGIN;
1002 con->cmd |= DO_LOGIN;
1003 if (con->st & DONE_CWD)
1004 con->cmd &= ~DO_CWD;
1008 /* Assume no restarting. */
1010 if ((count > 1 || opt.always_rest)
1011 && !(con->cmd & DO_LIST)
1012 && file_exists_p (u->local))
1013 if (stat (u->local, &st) == 0)
1014 restval = st.st_size;
1015 /* Get the current time string. */
1016 tms = time_str (NULL);
1017 /* Print fetch message, if opt.verbose. */
1020 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1024 sprintf (tmp, _("(try:%2d)"), count);
1025 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1026 tms, hurl, tmp, locf);
1028 ws_changetitle (hurl, 1);
1032 /* Send getftp the proper length, if fileinfo was provided. */
1037 err = getftp (u, &len, restval, con);
1039 tms = time_str (NULL);
1040 tmrate = rate (len - restval, con->dltime);
1042 if (!rbuf_initialized_p (&con->rbuf))
1043 con->st &= ~DONE_CWD;
1045 con->st |= DONE_CWD;
1049 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1050 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV:
1051 /* Fatal errors, give up. */
1054 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1055 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1056 case BINDERR: case LISTENERR: case ACCEPTERR:
1057 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1058 printwhat (count, opt.ntry);
1059 /* non-fatal errors */
1063 /* If the control connection was closed, the retrieval
1064 will be considered OK if f->size == len. */
1065 if (!f || len != f->size)
1067 printwhat (count, opt.ntry);
1079 /* If we get out of the switch above without continue'ing, we've
1080 successfully downloaded a file. Remember this fact. */
1081 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1083 if (con->st & ON_YOUR_OWN)
1085 CLOSE (RBUF_FD (&con->rbuf));
1086 rbuf_uninitialize (&con->rbuf);
1088 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1089 tms, tmrate, locf, len);
1090 if (!opt.verbose && !opt.quiet)
1092 /* Need to hide the password from the URL. The `if' is here
1093 so that we don't do the needless allocation every
1095 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1096 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1097 tms, hurl, len, locf, count);
1101 if ((con->cmd & DO_LIST))
1102 /* This is a directory listing file. */
1104 if (!opt.remove_listing)
1105 /* --dont-remove-listing was specified, so do count this towards the
1106 number of bytes and files downloaded. */
1108 downloaded_increase (len);
1112 /* Deletion of listing files is not controlled by --delete-after, but
1113 by the more specific option --dont-remove-listing, and the code
1114 to do this deletion is in another function. */
1117 /* This is not a directory listing file. */
1119 /* Unlike directory listing files, don't pretend normal files weren't
1120 downloaded if they're going to be deleted. People seeding proxies,
1121 for instance, may want to know how many bytes and files they've
1122 downloaded through it. */
1123 downloaded_increase (len);
1126 if (opt.delete_after)
1128 DEBUGP (("Removing file due to --delete-after in"
1129 " ftp_loop_internal():\n"));
1130 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1132 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1136 /* Restore the original leave-pendingness. */
1138 con->cmd |= LEAVE_PENDING;
1140 con->cmd &= ~LEAVE_PENDING;
1142 } while (!opt.ntry || (count < opt.ntry));
1144 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1146 CLOSE (RBUF_FD (&con->rbuf));
1147 rbuf_uninitialize (&con->rbuf);
1152 /* Return the directory listing in a reusable format. The directory
1153 is specifed in u->dir. */
1154 static struct fileinfo *
1155 ftp_get_listing (struct urlinfo *u, ccon *con)
1159 char *olocal = u->local;
1160 char *list_filename, *ofile;
1162 con->st &= ~ON_YOUR_OWN;
1163 con->cmd |= (DO_LIST | LEAVE_PENDING);
1164 con->cmd &= ~DO_RETR;
1165 /* Get the listing filename. */
1167 u->file = LIST_FILENAME;
1168 list_filename = url_filename (u);
1170 u->local = list_filename;
1171 DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1172 err = ftp_loop_internal (u, NULL, con);
1175 f = ftp_parse_ls (list_filename, host_type);
1178 if (opt.remove_listing)
1180 if (unlink (list_filename))
1181 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1183 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1185 xfree (list_filename);
1186 con->cmd &= ~DO_LIST;
1190 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1192 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1193 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1194 struct fileinfo **));
1195 static void freefileinfo PARAMS ((struct fileinfo *f));
1197 /* Retrieve a list of files given in struct fileinfo linked list. If
1198 a file is a symbolic link, do not retrieve it, but rather try to
1199 set up a similar link on the local disk, if the symlinks are
1202 If opt.recursive is set, after all files have been retrieved,
1203 ftp_retrieve_dirs will be called to retrieve the directories. */
1205 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1207 static int depth = 0;
1209 char *olocal, *ofile;
1210 struct fileinfo *orig;
1215 /* Increase the depth. */
1217 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1219 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1220 depth, opt.reclevel));
1228 con->st &= ~ON_YOUR_OWN;
1229 if (!(con->st & DONE_CWD))
1232 con->cmd &= ~DO_CWD;
1233 con->cmd |= (DO_RETR | LEAVE_PENDING);
1235 if (!rbuf_initialized_p (&con->rbuf))
1236 con->cmd |= DO_LOGIN;
1238 con->cmd &= ~DO_LOGIN;
1240 err = RETROK; /* in case it's not used */
1244 if (downloaded_exceeds_quota ())
1252 u->local = url_filename (u);
1256 if (opt.timestamping && f->type == FT_PLAINFILE)
1259 /* If conversion of HTML files retrieved via FTP is ever implemented,
1260 we'll need to stat() <file>.orig here when -K has been specified.
1261 I'm not implementing it now since files on an FTP server are much
1262 more likely than files on an HTTP server to legitimately have a
1264 if (!stat (u->local, &st))
1266 /* Else, get it from the file. */
1267 local_size = st.st_size;
1269 if (local_size == f->size && tml >= f->tstamp)
1271 logprintf (LOG_VERBOSE, _("\
1272 Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
1275 else if (local_size != f->size)
1277 if (host_type == ST_VMS)
1279 logprintf (LOG_VERBOSE, _("\
1280 Cannot compare sizes, remote system is VMS.\n"));
1285 logprintf (LOG_VERBOSE, _("\
1286 The sizes do not match (local %ld) -- retrieving.\n"), local_size);
1290 } /* opt.timestamping && f->type == FT_PLAINFILE */
1294 /* If opt.retr_symlinks is defined, we treat symlinks as
1295 if they were normal files. There is currently no way
1296 to distinguish whether they might be directories, and
1298 if (!opt.retr_symlinks)
1302 logputs (LOG_NOTQUIET,
1303 _("Invalid name of the symlink, skipping.\n"));
1307 /* Check whether we already have the correct
1309 int rc = lstat (u->local, &st);
1312 size_t len = strlen (f->linkto) + 1;
1313 if (S_ISLNK (st.st_mode))
1315 char *link_target = (char *)alloca (len);
1316 size_t n = readlink (u->local, link_target, len);
1318 && (memcmp (link_target, f->linkto, n) == 0))
1320 logprintf (LOG_VERBOSE, _("\
1321 Already have correct symlink %s -> %s\n\n"),
1322 u->local, f->linkto);
1328 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1329 u->local, f->linkto);
1330 /* Unlink before creating symlink! */
1332 if (symlink (f->linkto, u->local) == -1)
1333 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1335 logputs (LOG_VERBOSE, "\n");
1336 } /* have f->linkto */
1337 #else /* not HAVE_SYMLINK */
1338 logprintf (LOG_NOTQUIET,
1339 _("Symlinks not supported, skipping symlink `%s'.\n"),
1341 #endif /* not HAVE_SYMLINK */
1343 else /* opt.retr_symlinks */
1346 err = ftp_loop_internal (u, f, con);
1347 } /* opt.retr_symlinks */
1351 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1355 /* Call the retrieve loop. */
1357 err = ftp_loop_internal (u, f, con);
1360 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1365 /* Set the time-stamp information to the local file. Symlinks
1366 are not to be stamped because it sets the stamp on the
1368 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1371 && file_exists_p (u->local))
1373 const char *fl = opt.output_document ? opt.output_document : u->local;
1374 touch (fl, f->tstamp);
1376 else if (f->tstamp == -1)
1377 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1379 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1380 chmod (u->local, f->perms);
1382 DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1387 /* Break on fatals. */
1388 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1390 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1393 /* We do not want to call ftp_retrieve_dirs here */
1394 if (opt.recursive &&
1395 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1396 err = ftp_retrieve_dirs (u, orig, con);
1397 else if (opt.recursive)
1398 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1399 depth, opt.reclevel));
1404 /* Retrieve the directories given in a file list. This function works
1405 by simply going through the linked list and calling
1406 ftp_retrieve_glob on each directory entry. The function knows
1407 about excluded directories. */
1409 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1412 char *current_container = NULL;
1413 int current_length = 0;
1415 for (; f; f = f->next)
1419 if (downloaded_exceeds_quota ())
1421 if (f->type != FT_DIRECTORY)
1424 len = 1 + strlen (u->dir) + 1 + strlen (f->name) + 1;
1425 /* Allocate u->dir off stack, but reallocate only if a larger
1426 string is needed. */
1427 if (len > current_length)
1428 current_container = (char *)alloca (len);
1429 u->dir = current_container;
1430 /* When retrieving recursively, all directories must be
1431 absolute. This restriction will (hopefully!) be lifted in
1433 sprintf (u->dir, "/%s%s%s", odir + (*odir == '/'),
1434 (!*odir || (*odir == '/' && !* (odir + 1))) ? "" : "/", f->name);
1435 if (!accdir (u->dir, ALLABS))
1437 logprintf (LOG_VERBOSE, _("\
1438 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1442 con->st &= ~DONE_CWD;
1443 ftp_retrieve_glob (u, con, GETALL);
1444 /* Set the time-stamp? */
1447 if (opt.quota && opt.downloaded > opt.quota)
1454 /* A near-top-level function to retrieve the files in a directory.
1455 The function calls ftp_get_listing, to get a linked list of files.
1456 Then it weeds out the file names that do not match the pattern.
1457 ftp_retrieve_list is called with this updated list as an argument.
1459 If the argument ACTION is GETONE, just download the file (but first
1460 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1461 use globbing; if it's GETALL, download the whole directory. */
1463 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1465 struct fileinfo *orig, *start;
1468 con->cmd |= LEAVE_PENDING;
1470 orig = ftp_get_listing (u, con);
1472 /* First: weed out that do not conform the global rules given in
1473 opt.accepts and opt.rejects. */
1474 if (opt.accepts || opt.rejects)
1476 struct fileinfo *f = orig;
1480 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1482 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1483 f = delelement (f, &start);
1489 /* Now weed out the files that do not match our globbing pattern.
1490 If we are dealing with a globbing pattern, that is. */
1491 if (*u->file && (action == GLOBALL || action == GETONE))
1494 struct fileinfo *f = start;
1498 matchres = fnmatch (u->file, f->name, 0);
1501 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1505 if (matchres == FNM_NOMATCH)
1506 f = delelement (f, &start); /* delete the element from the list */
1508 f = f->next; /* leave the element in the list */
1512 freefileinfo (start);
1513 return RETRBADPATTERN;
1519 /* Just get everything. */
1520 ftp_retrieve_list (u, start, con);
1524 if (action == GLOBALL)
1527 /* #### This message SUCKS. We should see what was the
1528 reason that nothing was retrieved. */
1529 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1531 else /* GETONE or GETALL */
1533 /* Let's try retrieving it anyway. */
1534 con->st |= ON_YOUR_OWN;
1535 res = ftp_loop_internal (u, NULL, con);
1539 freefileinfo (start);
1540 if (downloaded_exceeds_quota ())
1543 /* #### Should we return `res' here? */
1547 /* The wrapper that calls an appropriate routine according to contents
1548 of URL. Inherently, its capabilities are limited on what can be
1549 encoded into a URL. */
1551 ftp_loop (struct urlinfo *u, int *dt)
1553 ccon con; /* FTP connection */
1558 rbuf_uninitialize (&con.rbuf);
1559 con.st = ON_YOUR_OWN;
1560 res = RETROK; /* in case it's not used */
1562 /* If the file name is empty, the user probably wants a directory
1563 index. We'll provide one, properly HTML-ized. Unless
1564 opt.htmlify is 0, of course. :-) */
1565 if (!*u->file && !opt.recursive)
1567 struct fileinfo *f = ftp_get_listing (u, &con);
1573 char *filename = (opt.output_document
1574 ? xstrdup (opt.output_document)
1575 : (u->local ? xstrdup (u->local)
1576 : url_filename (u)));
1577 res = ftp_index (filename, u, f);
1578 if (res == FTPOK && opt.verbose)
1580 if (!opt.output_document)
1584 if (stat (filename, &st) == 0)
1588 logprintf (LOG_NOTQUIET,
1589 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1593 logprintf (LOG_NOTQUIET,
1594 _("Wrote HTML-ized index to `%s'.\n"),
1604 int wild = has_wildcards_p (u->file);
1605 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1607 /* ftp_retrieve_glob is a catch-all function that gets called
1608 if we need globbing, time-stamping or recursion. Its
1609 third argument is just what we really need. */
1610 ftp_retrieve_glob (u, &con,
1611 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1614 res = ftp_loop_internal (u, NULL, &con);
1620 /* If a connection was left, quench it. */
1621 if (rbuf_initialized_p (&con.rbuf))
1622 CLOSE (RBUF_FD (&con.rbuf));
1628 /* Delete an element from the fileinfo linked list. Returns the
1629 address of the next element, or NULL if the list is exhausted. It
1630 can modify the start of the list. */
1631 static struct fileinfo *
1632 delelement (struct fileinfo *f, struct fileinfo **start)
1634 struct fileinfo *prev = f->prev;
1635 struct fileinfo *next = f->next;
1638 FREE_MAYBE (f->linkto);
1650 /* Free the fileinfo linked list of files. */
1652 freefileinfo (struct fileinfo *f)
1656 struct fileinfo *next = f->next;