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 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
61 the string S, and return the number converted to long, if found, 0
64 ftp_expected_bytes (const char *s)
70 while (*s && *s != '(')
74 for (++s; *s && ISSPACE (*s); s++);
82 res = (*s - '0') + 10 * res;
85 while (*s && ISDIGIT (*s));
88 while (*s && ISSPACE (*s))
92 if (TOLOWER (*s) != 'b')
94 if (strncasecmp (s, "byte", 4))
102 /* Retrieves a file with denoted parameters through opening an FTP
103 connection to the server. It always closes the data connection,
104 and closes the control connection in case of error. */
106 getftp (const struct urlinfo *u, long *len, long restval, ccon *con)
108 int csock, dtsock, res;
111 char *user, *passwd, *respline;
113 unsigned char pasv_addr[6];
115 int passive_mode_open = 0;
116 long expected_bytes = 0L;
118 assert (con != NULL);
119 assert (u->local != NULL);
120 /* Debug-check of the sanity of the request by making sure that LIST
121 and RETR are never both requested (since we can handle only one
123 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
124 /* Make sure that at least *something* is requested. */
125 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
129 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
130 user = user ? user : opt.ftp_acc;
132 opt.ftp_pass = xstrdup (ftp_getaddress ());
133 passwd = passwd ? passwd : opt.ftp_pass;
134 assert (user && passwd);
139 if (!(cmd & DO_LOGIN))
140 csock = RBUF_FD (&con->rbuf);
141 else /* cmd & DO_LOGIN */
143 /* Login to the server: */
145 /* First: Establish the control connection. */
146 logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
147 err = make_connection (&csock, u->host, u->port);
148 if (cmd & LEAVE_PENDING)
149 rbuf_initialize (&con->rbuf, csock);
151 rbuf_uninitialize (&con->rbuf);
154 /* Do not close the socket in first several cases, since it
155 wasn't created at all. */
157 logputs (LOG_VERBOSE, "\n");
158 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
162 logputs (LOG_VERBOSE, "\n");
163 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
167 logputs (LOG_VERBOSE, "\n");
168 logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
171 rbuf_uninitialize (&con->rbuf);
174 logputs (LOG_VERBOSE, "\n");
175 logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
177 rbuf_uninitialize (&con->rbuf);
184 /* Since this is a new connection, we may safely discard
185 anything left in the buffer. */
186 rbuf_discard (&con->rbuf);
188 /* Second: Login with proper USER/PASS sequence. */
189 logputs (LOG_VERBOSE, _("connected!\n"));
190 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
191 if (opt.server_response)
192 logputs (LOG_ALWAYS, "\n");
193 err = ftp_login (&con->rbuf, user, passwd);
194 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
198 logputs (LOG_VERBOSE, "\n");
199 logputs (LOG_NOTQUIET, _("\
200 Error in server response, closing control connection.\n"));
202 rbuf_uninitialize (&con->rbuf);
206 logputs (LOG_VERBOSE, "\n");
207 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
209 rbuf_uninitialize (&con->rbuf);
213 logputs (LOG_VERBOSE, "\n");
214 logputs (LOG_NOTQUIET,
215 _("Write failed, closing control connection.\n"));
217 rbuf_uninitialize (&con->rbuf);
221 logputs (LOG_VERBOSE, "\n");
222 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
224 rbuf_uninitialize (&con->rbuf);
225 return FTPLOGREFUSED;
228 logputs (LOG_VERBOSE, "\n");
229 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
231 rbuf_uninitialize (&con->rbuf);
235 if (!opt.server_response)
236 logputs (LOG_VERBOSE, _("Logged in!\n"));
243 /* Third: Set type to Image (binary). */
244 if (!opt.server_response)
245 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
246 err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
247 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
251 logputs (LOG_VERBOSE, "\n");
252 logputs (LOG_NOTQUIET, _("\
253 Error in server response, closing control connection.\n"));
255 rbuf_uninitialize (&con->rbuf);
259 logputs (LOG_VERBOSE, "\n");
260 logputs (LOG_NOTQUIET,
261 _("Write failed, closing control connection.\n"));
263 rbuf_uninitialize (&con->rbuf);
267 logputs (LOG_VERBOSE, "\n");
268 logprintf (LOG_NOTQUIET,
269 _("Unknown type `%c', closing control connection.\n"),
270 TOUPPER (u->ftp_type));
272 rbuf_uninitialize (&con->rbuf);
275 /* Everything is OK. */
281 if (!opt.server_response)
282 logputs (LOG_VERBOSE, _("done. "));
288 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
291 /* Change working directory. */
292 if (!opt.server_response)
293 logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
294 err = ftp_cwd (&con->rbuf, u->dir);
295 /* FTPRERR, WRITEFAILED, FTPNSFOD */
299 logputs (LOG_VERBOSE, "\n");
300 logputs (LOG_NOTQUIET, _("\
301 Error in server response, closing control connection.\n"));
303 rbuf_uninitialize (&con->rbuf);
307 logputs (LOG_VERBOSE, "\n");
308 logputs (LOG_NOTQUIET,
309 _("Write failed, closing control connection.\n"));
311 rbuf_uninitialize (&con->rbuf);
315 logputs (LOG_VERBOSE, "\n");
316 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
319 rbuf_uninitialize (&con->rbuf);
329 if (!opt.server_response)
330 logputs (LOG_VERBOSE, _("done.\n"));
333 else /* do not CWD */
334 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
336 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
337 if (cmd & (DO_LIST | DO_RETR))
339 if (opt.ftp_pasv > 0)
342 unsigned short tport;
344 if (!opt.server_response)
345 logputs (LOG_VERBOSE, "==> PASV ... ");
346 err = ftp_pasv (&con->rbuf, pasv_addr);
347 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
351 logputs (LOG_VERBOSE, "\n");
352 logputs (LOG_NOTQUIET, _("\
353 Error in server response, closing control connection.\n"));
355 rbuf_uninitialize (&con->rbuf);
359 logputs (LOG_VERBOSE, "\n");
360 logputs (LOG_NOTQUIET,
361 _("Write failed, closing control connection.\n"));
363 rbuf_uninitialize (&con->rbuf);
367 logputs (LOG_VERBOSE, "\n");
368 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
371 logputs (LOG_VERBOSE, "\n");
372 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
383 sprintf (thost, "%d.%d.%d.%d",
384 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
385 tport = (pasv_addr[4] << 8) + pasv_addr[5];
386 DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
387 err = make_connection (&dtsock, thost, tport);
390 /* Do not close the socket in first several cases,
391 since it wasn't created at all. */
393 logputs (LOG_VERBOSE, "\n");
394 logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
397 rbuf_uninitialize (&con->rbuf);
401 logputs (LOG_VERBOSE, "\n");
402 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
404 rbuf_uninitialize (&con->rbuf);
408 logputs (LOG_VERBOSE, "\n");
409 logprintf (LOG_NOTQUIET,
410 _("Connection to %s:%hu refused.\n"),
413 rbuf_uninitialize (&con->rbuf);
417 logputs (LOG_VERBOSE, "\n");
418 logprintf (LOG_NOTQUIET, "connect: %s\n",
421 rbuf_uninitialize (&con->rbuf);
429 passive_mode_open= 1; /* Flag to avoid accept port */
430 if (!opt.server_response)
431 logputs (LOG_VERBOSE, _("done. "));
435 if (!passive_mode_open) /* Try to use a port command if PASV failed */
437 if (!opt.server_response)
438 logputs (LOG_VERBOSE, "==> PORT ... ");
439 err = ftp_port (&con->rbuf);
440 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
441 LISTENERR), HOSTERR, FTPPORTERR */
445 logputs (LOG_VERBOSE, "\n");
446 logputs (LOG_NOTQUIET, _("\
447 Error in server response, closing control connection.\n"));
450 rbuf_uninitialize (&con->rbuf);
454 logputs (LOG_VERBOSE, "\n");
455 logputs (LOG_NOTQUIET,
456 _("Write failed, closing control connection.\n"));
459 rbuf_uninitialize (&con->rbuf);
463 logputs (LOG_VERBOSE, "\n");
464 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
467 rbuf_uninitialize (&con->rbuf);
470 case CONPORTERR: case BINDERR: case LISTENERR:
471 /* What now? These problems are local... */
472 logputs (LOG_VERBOSE, "\n");
473 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
479 logputs (LOG_VERBOSE, "\n");
480 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
484 rbuf_uninitialize (&con->rbuf);
488 logputs (LOG_VERBOSE, "\n");
489 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
492 rbuf_uninitialize (&con->rbuf);
502 if (!opt.server_response)
503 logputs (LOG_VERBOSE, _("done. "));
505 } /* cmd & (DO_LIST | DO_RETR) */
507 /* Restart if needed. */
508 if (restval && (cmd & DO_RETR))
510 if (!opt.server_response)
511 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
512 err = ftp_rest (&con->rbuf, restval);
514 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
518 logputs (LOG_VERBOSE, "\n");
519 logputs (LOG_NOTQUIET, _("\
520 Error in server response, closing control connection.\n"));
523 rbuf_uninitialize (&con->rbuf);
527 logputs (LOG_VERBOSE, "\n");
528 logputs (LOG_NOTQUIET,
529 _("Write failed, closing control connection.\n"));
532 rbuf_uninitialize (&con->rbuf);
536 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
546 if (err != FTPRESTFAIL && !opt.server_response)
547 logputs (LOG_VERBOSE, _("done. "));
548 } /* restval && cmd & DO_RETR */
554 if (!opt.server_response)
557 logputs (LOG_VERBOSE, "\n");
558 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
561 err = ftp_retr (&con->rbuf, u->file);
562 /* FTPRERR, WRITEFAILED, FTPNSFOD */
566 logputs (LOG_VERBOSE, "\n");
567 logputs (LOG_NOTQUIET, _("\
568 Error in server response, closing control connection.\n"));
571 rbuf_uninitialize (&con->rbuf);
575 logputs (LOG_VERBOSE, "\n");
576 logputs (LOG_NOTQUIET,
577 _("Write failed, closing control connection.\n"));
580 rbuf_uninitialize (&con->rbuf);
584 logputs (LOG_VERBOSE, "\n");
585 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
597 if (!opt.server_response)
598 logputs (LOG_VERBOSE, _("done.\n"));
599 expected_bytes = ftp_expected_bytes (ftp_last_respline);
604 if (!opt.server_response)
605 logputs (LOG_VERBOSE, "==> LIST ... ");
606 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
607 without arguments is better than `LIST .'; confirmed by
609 err = ftp_list (&con->rbuf, NULL);
610 /* FTPRERR, WRITEFAILED */
614 logputs (LOG_VERBOSE, "\n");
615 logputs (LOG_NOTQUIET, _("\
616 Error in server response, closing control connection.\n"));
619 rbuf_uninitialize (&con->rbuf);
623 logputs (LOG_VERBOSE, "\n");
624 logputs (LOG_NOTQUIET,
625 _("Write failed, closing control connection.\n"));
628 rbuf_uninitialize (&con->rbuf);
632 logputs (LOG_VERBOSE, "\n");
633 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
645 if (!opt.server_response)
646 logputs (LOG_VERBOSE, _("done.\n"));
647 expected_bytes = ftp_expected_bytes (ftp_last_respline);
648 } /* cmd & DO_LIST */
650 /* Some FTP servers return the total length of file after REST
651 command, others just return the remaining size. */
652 if (*len && restval && expected_bytes
653 && (expected_bytes == *len - restval))
655 DEBUGP (("Lying FTP server found, adjusting.\n"));
656 expected_bytes = *len;
659 /* If no transmission was required, then everything is OK. */
660 if (!(cmd & (DO_LIST | DO_RETR)))
663 if (!passive_mode_open) /* we are not using pasive mode so we need
666 /* Open the data transmission socket by calling acceptport(). */
667 err = acceptport (&dtsock);
668 /* Possible errors: ACCEPTERR. */
669 if (err == ACCEPTERR)
671 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
676 /* Open the file -- if opt.dfp is set, use it instead. */
677 if (!opt.dfp || con->cmd & DO_LIST)
679 mkalldirs (u->local);
681 rotate_backups (u->local);
682 /* #### Is this correct? */
683 chmod (u->local, 0600);
685 fp = fopen (u->local, restval ? "ab" : "wb");
688 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
690 rbuf_uninitialize (&con->rbuf);
700 /* This will silently fail for streams that don't correspond
701 to regular files, but that's OK. */
709 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
711 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
712 logputs (LOG_VERBOSE, "\n");
714 else if (expected_bytes)
716 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
718 logprintf (LOG_VERBOSE, _(" [%s to go]"),
719 legible (expected_bytes - restval));
720 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
723 /* Get the contents of the document. */
724 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
725 con->dltime = elapsed_time ();
726 tms = time_str (NULL);
727 tmrate = rate (*len - restval, con->dltime);
728 /* Close data connection socket. */
730 /* Close the local file. */
732 /* Close or flush the file. We have to be careful to check for
733 error here. Checking the result of fwrite() is not enough --
734 errors could go unnoticed! */
736 if (!opt.dfp || con->cmd & DO_LIST)
737 flush_res = fclose (fp);
739 flush_res = fflush (fp);
740 if (flush_res == EOF)
743 /* If get_contents couldn't write to fp, bail out. */
746 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
747 u->local, strerror (errno));
749 rbuf_uninitialize (&con->rbuf);
754 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
755 tms, tmrate, strerror (errno));
756 if (opt.server_response)
757 logputs (LOG_ALWAYS, "\n");
760 /* Get the server to tell us if everything is retrieved. */
761 err = ftp_response (&con->rbuf, &respline);
762 /* ...and empty the buffer. */
763 rbuf_discard (&con->rbuf);
767 /* The control connection is decidedly closed. Print the time
768 only if it hasn't already been printed. */
770 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
771 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
772 /* If there is an error on the control connection, close it, but
773 return FTPRETRINT, since there is a possibility that the
774 whole file was retrieved nevertheless (but that is for
775 ftp_loop_internal to decide). */
777 rbuf_uninitialize (&con->rbuf);
780 /* If retrieval failed for any reason, return FTPRETRINT, but do not
781 close socket, since the control connection is still alive. If
782 there is something wrong with the control connection, it will
783 become apparent later. */
784 if (*respline != '2')
788 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
789 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
796 /* What now? The data connection was erroneous, whereas the
797 response says everything is OK. We shall play it safe. */
801 if (!(cmd & LEAVE_PENDING))
803 /* I should probably send 'QUIT' and check for a reply, but this
804 is faster. #### Is it OK, though? */
806 rbuf_uninitialize (&con->rbuf);
808 /* If it was a listing, and opt.server_response is true,
810 if (opt.server_response && (con->cmd & DO_LIST))
812 mkalldirs (u->local);
813 fp = fopen (u->local, "r");
815 logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
819 /* The lines are being read with read_whole_line because of
820 no-buffering on opt.lfile. */
821 while ((line = read_whole_line (fp)))
823 logprintf (LOG_ALWAYS, "%s\n", line);
828 } /* con->cmd & DO_LIST && server_response */
833 /* A one-file FTP loop. This is the part where FTP retrieval is
834 retried, and retried, and retried, and...
836 This loop either gets commands from con, or (if ON_YOUR_OWN is
837 set), makes them up to retrieve the file given by the URL. */
839 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
841 static int first_retrieval = 1;
845 char *tms, *tmrate, *locf;
850 u->local = url_filename (u);
852 if (opt.noclobber && file_exists_p (u->local))
854 logprintf (LOG_VERBOSE,
855 _("File `%s' already there, not retrieving.\n"), u->local);
856 /* If the file is there, we suppose it's retrieved OK. */
860 /* Remove it if it's a link. */
861 remove_link (u->local);
862 if (!opt.output_document)
865 locf = opt.output_document;
869 if (con->st & ON_YOUR_OWN)
870 con->st = ON_YOUR_OWN;
872 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
877 /* Increment the pass counter. */
879 /* Wait before the retrieval (unless this is the very first
881 Check if we are retrying or not, wait accordingly - HEH */
882 if (!first_retrieval && (opt.wait || (count && opt.waitretry)))
886 if (count<opt.waitretry)
889 sleep(opt.waitretry);
896 if (con->st & ON_YOUR_OWN)
899 con->cmd |= (DO_RETR | LEAVE_PENDING);
900 if (rbuf_initialized_p (&con->rbuf))
901 con->cmd &= ~ (DO_LOGIN | DO_CWD);
903 con->cmd |= (DO_LOGIN | DO_CWD);
905 else /* not on your own */
907 if (rbuf_initialized_p (&con->rbuf))
908 con->cmd &= ~DO_LOGIN;
910 con->cmd |= DO_LOGIN;
911 if (con->st & DONE_CWD)
916 /* Assume no restarting. */
918 if ((count > 1 || opt.always_rest)
919 && !(con->cmd & DO_LIST)
920 && file_exists_p (u->local))
921 if (stat (u->local, &st) == 0)
922 restval = st.st_size;
923 /* Get the current time string. */
924 tms = time_str (NULL);
925 /* Print fetch message, if opt.verbose. */
928 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
932 sprintf (tmp, _("(try:%2d)"), count);
933 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
934 tms, hurl, tmp, locf);
936 ws_changetitle (hurl, 1);
940 /* Send getftp the proper length, if fileinfo was provided. */
945 err = getftp (u, &len, restval, con);
947 tms = time_str (NULL);
948 tmrate = rate (len - restval, con->dltime);
950 if (!rbuf_initialized_p (&con->rbuf))
951 con->st &= ~DONE_CWD;
957 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
958 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV:
959 /* Fatal errors, give up. */
962 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
963 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
964 case BINDERR: case LISTENERR: case ACCEPTERR:
965 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
966 printwhat (count, opt.ntry);
967 /* non-fatal errors */
971 /* If the control connection was closed, the retrieval
972 will be considered OK if f->size == len. */
973 if (!f || len != f->size)
975 printwhat (count, opt.ntry);
987 /* If we get out of the switch above without continue'ing, we've
988 successfully downloaded a file. Remember this fact. */
989 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
991 if (con->st & ON_YOUR_OWN)
993 CLOSE (RBUF_FD (&con->rbuf));
994 rbuf_uninitialize (&con->rbuf);
996 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
997 tms, tmrate, locf, len);
998 if (!opt.verbose && !opt.quiet)
1000 /* Need to hide the password from the URL. The `if' is here
1001 so that we don't do the needless allocation every
1003 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1004 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1005 tms, hurl, len, locf, count);
1009 if ((con->cmd & DO_LIST))
1010 /* This is a directory listing file. */
1012 if (!opt.remove_listing)
1013 /* --dont-remove-listing was specified, so do count this towards the
1014 number of bytes and files downloaded. */
1016 downloaded_increase (len);
1020 /* Deletion of listing files is not controlled by --delete-after, but
1021 by the more specific option --dont-remove-listing, and the code
1022 to do this deletion is in another function. */
1025 /* This is not a directory listing file. */
1027 /* Unlike directory listing files, don't pretend normal files weren't
1028 downloaded if they're going to be deleted. People seeding proxies,
1029 for instance, may want to know how many bytes and files they've
1030 downloaded through it. */
1031 downloaded_increase (len);
1034 if (opt.delete_after)
1036 DEBUGP (("Removing file due to --delete-after in"
1037 " ftp_loop_internal():\n"));
1038 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1040 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1044 /* Restore the original leave-pendingness. */
1046 con->cmd |= LEAVE_PENDING;
1048 con->cmd &= ~LEAVE_PENDING;
1050 } while (!opt.ntry || (count < opt.ntry));
1052 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1054 CLOSE (RBUF_FD (&con->rbuf));
1055 rbuf_uninitialize (&con->rbuf);
1060 /* Return the directory listing in a reusable format. The directory
1061 is specifed in u->dir. */
1062 static struct fileinfo *
1063 ftp_get_listing (struct urlinfo *u, ccon *con)
1067 char *olocal = u->local;
1068 char *list_filename, *ofile;
1070 con->st &= ~ON_YOUR_OWN;
1071 con->cmd |= (DO_LIST | LEAVE_PENDING);
1072 con->cmd &= ~DO_RETR;
1073 /* Get the listing filename. */
1075 u->file = LIST_FILENAME;
1076 list_filename = url_filename (u);
1078 u->local = list_filename;
1079 DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1080 err = ftp_loop_internal (u, NULL, con);
1083 f = ftp_parse_ls (list_filename);
1086 if (opt.remove_listing)
1088 if (unlink (list_filename))
1089 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1091 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1093 free (list_filename);
1094 con->cmd &= ~DO_LIST;
1098 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1100 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1101 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1102 struct fileinfo **));
1103 static void freefileinfo PARAMS ((struct fileinfo *f));
1105 /* Retrieve a list of files given in struct fileinfo linked list. If
1106 a file is a symbolic link, do not retrieve it, but rather try to
1107 set up a similar link on the local disk, if the symlinks are
1110 If opt.recursive is set, after all files have been retrieved,
1111 ftp_retrieve_dirs will be called to retrieve the directories. */
1113 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1115 static int depth = 0;
1117 char *olocal, *ofile;
1118 struct fileinfo *orig;
1123 /* Increase the depth. */
1125 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1127 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1128 depth, opt.reclevel));
1136 con->st &= ~ON_YOUR_OWN;
1137 if (!(con->st & DONE_CWD))
1140 con->cmd &= ~DO_CWD;
1141 con->cmd |= (DO_RETR | LEAVE_PENDING);
1143 if (!rbuf_initialized_p (&con->rbuf))
1144 con->cmd |= DO_LOGIN;
1146 con->cmd &= ~DO_LOGIN;
1148 err = RETROK; /* in case it's not used */
1152 if (downloaded_exceeds_quota ())
1160 u->local = url_filename (u);
1164 if (opt.timestamping && f->type == FT_PLAINFILE)
1167 /* If conversion of HTML files retrieved via FTP is ever implemented,
1168 we'll need to stat() <file>.orig here when -K has been specified.
1169 I'm not implementing it now since files on an FTP server are much
1170 more likely than files on an HTTP server to legitimately have a
1172 if (!stat (u->local, &st))
1174 /* Else, get it from the file. */
1175 local_size = st.st_size;
1177 if (local_size == f->size && tml >= f->tstamp)
1179 logprintf (LOG_VERBOSE, _("\
1180 Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
1183 else if (local_size != f->size)
1185 logprintf (LOG_VERBOSE, _("\
1186 The sizes do not match (local %ld) -- retrieving.\n"), local_size);
1189 } /* opt.timestamping && f->type == FT_PLAINFILE */
1193 /* If opt.retr_symlinks is defined, we treat symlinks as
1194 if they were normal files. There is currently no way
1195 to distinguish whether they might be directories, and
1197 if (!opt.retr_symlinks)
1201 logputs (LOG_NOTQUIET,
1202 _("Invalid name of the symlink, skipping.\n"));
1206 /* Check whether we already have the correct
1208 int rc = lstat (u->local, &st);
1211 size_t len = strlen (f->linkto) + 1;
1212 if (S_ISLNK (st.st_mode))
1214 char *link_target = (char *)alloca (len);
1215 size_t n = readlink (u->local, link_target, len);
1217 && (memcmp (link_target, f->linkto, n) == 0))
1219 logprintf (LOG_VERBOSE, _("\
1220 Already have correct symlink %s -> %s\n\n"),
1221 u->local, f->linkto);
1227 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1228 u->local, f->linkto);
1229 /* Unlink before creating symlink! */
1231 if (symlink (f->linkto, u->local) == -1)
1232 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1234 logputs (LOG_VERBOSE, "\n");
1235 } /* have f->linkto */
1236 #else /* not HAVE_SYMLINK */
1237 logprintf (LOG_NOTQUIET,
1238 _("Symlinks not supported, skipping symlink `%s'.\n"),
1240 #endif /* not HAVE_SYMLINK */
1242 else /* opt.retr_symlinks */
1245 err = ftp_loop_internal (u, f, con);
1246 } /* opt.retr_symlinks */
1250 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1254 /* Call the retrieve loop. */
1256 err = ftp_loop_internal (u, f, con);
1259 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1264 /* Set the time-stamp information to the local file. Symlinks
1265 are not to be stamped because it sets the stamp on the
1268 && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1271 && file_exists_p (u->local))
1273 touch (u->local, f->tstamp);
1275 else if (f->tstamp == -1)
1276 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1278 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1279 chmod (u->local, f->perms);
1281 DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1286 /* Break on fatals. */
1287 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1289 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1292 /* We do not want to call ftp_retrieve_dirs here */
1293 if (opt.recursive &&
1294 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1295 err = ftp_retrieve_dirs (u, orig, con);
1296 else if (opt.recursive)
1297 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1298 depth, opt.reclevel));
1303 /* Retrieve the directories given in a file list. This function works
1304 by simply going through the linked list and calling
1305 ftp_retrieve_glob on each directory entry. The function knows
1306 about excluded directories. */
1308 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1311 char *current_container = NULL;
1312 int current_length = 0;
1314 for (; f; f = f->next)
1318 if (downloaded_exceeds_quota ())
1320 if (f->type != FT_DIRECTORY)
1323 len = 1 + strlen (u->dir) + 1 + strlen (f->name) + 1;
1324 /* Allocate u->dir off stack, but reallocate only if a larger
1325 string is needed. */
1326 if (len > current_length)
1327 current_container = (char *)alloca (len);
1328 u->dir = current_container;
1329 /* When retrieving recursively, all directories must be
1330 absolute. This restriction will (hopefully!) be lifted in
1332 sprintf (u->dir, "/%s%s%s", odir + (*odir == '/'),
1333 (!*odir || (*odir == '/' && !* (odir + 1))) ? "" : "/", f->name);
1334 if (!accdir (u->dir, ALLABS))
1336 logprintf (LOG_VERBOSE, _("\
1337 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1341 con->st &= ~DONE_CWD;
1342 ftp_retrieve_glob (u, con, GETALL);
1343 /* Set the time-stamp? */
1346 if (opt.quota && opt.downloaded > opt.quota)
1353 /* A near-top-level function to retrieve the files in a directory.
1354 The function calls ftp_get_listing, to get a linked list of files.
1355 Then it weeds out the file names that do not match the pattern.
1356 ftp_retrieve_list is called with this updated list as an argument.
1358 If the argument ACTION is GETONE, just download the file (but first
1359 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1360 use globbing; if it's GETALL, download the whole directory. */
1362 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1364 struct fileinfo *orig, *start;
1367 con->cmd |= LEAVE_PENDING;
1369 orig = ftp_get_listing (u, con);
1371 /* First: weed out that do not conform the global rules given in
1372 opt.accepts and opt.rejects. */
1373 if (opt.accepts || opt.rejects)
1375 struct fileinfo *f = orig;
1379 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1381 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1382 f = delelement (f, &start);
1388 /* Now weed out the files that do not match our globbing pattern.
1389 If we are dealing with a globbing pattern, that is. */
1390 if (*u->file && (action == GLOBALL || action == GETONE))
1393 struct fileinfo *f = start;
1397 matchres = fnmatch (u->file, f->name, 0);
1400 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1404 if (matchres == FNM_NOMATCH)
1405 f = delelement (f, &start); /* delete the element from the list */
1407 f = f->next; /* leave the element in the list */
1411 freefileinfo (start);
1412 return RETRBADPATTERN;
1418 /* Just get everything. */
1419 ftp_retrieve_list (u, start, con);
1423 if (action == GLOBALL)
1426 /* #### This message SUCKS. We should see what was the
1427 reason that nothing was retrieved. */
1428 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1430 else /* GETONE or GETALL */
1432 /* Let's try retrieving it anyway. */
1433 con->st |= ON_YOUR_OWN;
1434 res = ftp_loop_internal (u, NULL, con);
1438 freefileinfo (start);
1439 if (downloaded_exceeds_quota ())
1442 /* #### Should we return `res' here? */
1446 /* The wrapper that calls an appropriate routine according to contents
1447 of URL. Inherently, its capabilities are limited on what can be
1448 encoded into a URL. */
1450 ftp_loop (struct urlinfo *u, int *dt)
1452 ccon con; /* FTP connection */
1457 rbuf_uninitialize (&con.rbuf);
1458 con.st = ON_YOUR_OWN;
1459 res = RETROK; /* in case it's not used */
1461 /* If the file name is empty, the user probably wants a directory
1462 index. We'll provide one, properly HTML-ized. Unless
1463 opt.htmlify is 0, of course. :-) */
1464 if (!*u->file && !opt.recursive)
1466 struct fileinfo *f = ftp_get_listing (u, &con);
1472 char *filename = (opt.output_document
1473 ? xstrdup (opt.output_document)
1474 : (u->local ? xstrdup (u->local)
1475 : url_filename (u)));
1476 res = ftp_index (filename, u, f);
1477 if (res == FTPOK && opt.verbose)
1479 if (!opt.output_document)
1483 if (stat (filename, &st) == 0)
1487 logprintf (LOG_NOTQUIET,
1488 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1492 logprintf (LOG_NOTQUIET,
1493 _("Wrote HTML-ized index to `%s'.\n"),
1503 int wild = has_wildcards_p (u->file);
1504 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1506 /* ftp_retrieve_glob is a catch-all function that gets called
1507 if we need globbing, time-stamping or recursion. Its
1508 third argument is just what we really need. */
1509 ftp_retrieve_glob (u, &con,
1510 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1513 res = ftp_loop_internal (u, NULL, &con);
1519 /* If a connection was left, quench it. */
1520 if (rbuf_initialized_p (&con.rbuf))
1521 CLOSE (RBUF_FD (&con.rbuf));
1525 /* Delete an element from the fileinfo linked list. Returns the
1526 address of the next element, or NULL if the list is exhausted. It
1527 can modify the start of the list. */
1528 static struct fileinfo *
1529 delelement (struct fileinfo *f, struct fileinfo **start)
1531 struct fileinfo *prev = f->prev;
1532 struct fileinfo *next = f->next;
1535 FREE_MAYBE (f->linkto);
1547 /* Free the fileinfo linked list of files. */
1549 freefileinfo (struct fileinfo *f)
1553 struct fileinfo *next = f->next;