1 /* File Transfer Protocol support.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
33 #include <sys/types.h>
37 # include <netdb.h> /* for h_errno */
60 /* File where the "ls -al" listing will be saved. */
61 #define LIST_FILENAME ".listing"
63 extern char ftp_last_respline[];
67 int st; /* connection status */
68 int cmd; /* command code */
69 struct rbuf rbuf; /* control connection buffer */
70 long dltime; /* time of the download */
71 enum stype rs; /* remote system reported by ftp server */
72 char *id; /* initial directory */
73 char *target; /* target file name */
77 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
78 the string S, and return the number converted to long, if found, 0
81 ftp_expected_bytes (const char *s)
87 while (*s && *s != '(')
91 for (++s; *s && ISSPACE (*s); s++);
99 res = (*s - '0') + 10 * res;
102 while (*s && ISDIGIT (*s));
105 while (*s && ISSPACE (*s))
109 if (TOLOWER (*s) != 'b')
111 if (strncasecmp (s, "byte", 4))
119 /* Retrieves a file with denoted parameters through opening an FTP
120 connection to the server. It always closes the data connection,
121 and closes the control connection in case of error. */
123 getftp (struct url *u, long *len, long restval, ccon *con)
125 int csock, dtsock, res;
128 char *user, *passwd, *respline;
130 unsigned char pasv_addr[6];
132 int passive_mode_open = 0;
133 long expected_bytes = 0L;
135 assert (con != NULL);
136 assert (con->target != NULL);
138 /* Debug-check of the sanity of the request by making sure that LIST
139 and RETR are never both requested (since we can handle only one
141 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
142 /* Make sure that at least *something* is requested. */
143 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
147 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
148 user = user ? user : opt.ftp_acc;
149 passwd = passwd ? passwd : opt.ftp_pass;
150 assert (user && passwd);
155 if (!(cmd & DO_LOGIN))
156 csock = RBUF_FD (&con->rbuf);
157 else /* cmd & DO_LOGIN */
160 struct address_list *al;
162 /* Login to the server: */
164 /* First: Establish the control connection. */
166 al = lookup_host (u->host, 0);
169 set_connection_host_name (u->host);
170 csock = connect_to_many (al, u->port, 0);
171 set_connection_host_name (NULL);
172 address_list_release (al);
175 return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
177 if (cmd & LEAVE_PENDING)
178 rbuf_initialize (&con->rbuf, csock);
180 rbuf_uninitialize (&con->rbuf);
182 /* Since this is a new connection, we may safely discard
183 anything left in the buffer. */
184 rbuf_discard (&con->rbuf);
186 /* Second: Login with proper USER/PASS sequence. */
187 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
188 if (opt.server_response)
189 logputs (LOG_ALWAYS, "\n");
190 err = ftp_login (&con->rbuf, user, passwd);
191 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
195 logputs (LOG_VERBOSE, "\n");
196 logputs (LOG_NOTQUIET, _("\
197 Error in server response, closing control connection.\n"));
199 rbuf_uninitialize (&con->rbuf);
203 logputs (LOG_VERBOSE, "\n");
204 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
206 rbuf_uninitialize (&con->rbuf);
210 logputs (LOG_VERBOSE, "\n");
211 logputs (LOG_NOTQUIET,
212 _("Write failed, closing control connection.\n"));
214 rbuf_uninitialize (&con->rbuf);
218 logputs (LOG_VERBOSE, "\n");
219 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
221 rbuf_uninitialize (&con->rbuf);
222 return FTPLOGREFUSED;
225 logputs (LOG_VERBOSE, "\n");
226 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
228 rbuf_uninitialize (&con->rbuf);
232 if (!opt.server_response)
233 logputs (LOG_VERBOSE, _("Logged in!\n"));
240 /* Third: Get the system type */
241 if (!opt.server_response)
242 logprintf (LOG_VERBOSE, "==> SYST ... ");
243 err = ftp_syst (&con->rbuf, &con->rs);
248 logputs (LOG_VERBOSE, "\n");
249 logputs (LOG_NOTQUIET, _("\
250 Error in server response, closing control connection.\n"));
252 rbuf_uninitialize (&con->rbuf);
256 logputs (LOG_VERBOSE, "\n");
257 logputs (LOG_NOTQUIET,
258 _("Server error, can't determine system type.\n"));
261 /* Everything is OK. */
267 if (!opt.server_response && err != FTPSRVERR)
268 logputs (LOG_VERBOSE, _("done. "));
270 /* Fourth: Find the initial ftp directory */
272 if (!opt.server_response)
273 logprintf (LOG_VERBOSE, "==> PWD ... ");
274 err = ftp_pwd(&con->rbuf, &con->id);
279 logputs (LOG_VERBOSE, "\n");
280 logputs (LOG_NOTQUIET, _("\
281 Error in server response, closing control connection.\n"));
283 rbuf_uninitialize (&con->rbuf);
287 /* PWD unsupported -- assume "/". */
288 FREE_MAYBE (con->id);
289 con->id = xstrdup ("/");
292 /* Everything is OK. */
298 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
299 Convert it to "/INITIAL/FOLDER" */
300 if (con->rs == ST_VMS)
302 char *path = strchr (con->id, '[');
303 char *pathend = path ? strchr (path + 1, ']') : NULL;
304 if (!path || !pathend)
305 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
308 char *idir = con->id;
309 DEBUGP (("Preprocessing the initial VMS directory\n"));
310 DEBUGP ((" old = '%s'\n", con->id));
311 /* We do the conversion in-place by copying the stuff
312 between [ and ] to the beginning, and changing dots
313 to slashes at the same time. */
315 for (++path; path < pathend; path++, idir++)
316 *idir = *path == '.' ? '/' : *path;
318 DEBUGP ((" new = '%s'\n\n", con->id));
321 if (!opt.server_response)
322 logputs (LOG_VERBOSE, _("done.\n"));
324 /* Fifth: Set the FTP type. */
325 type_char = ftp_process_type (u->params);
326 if (!opt.server_response)
327 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
328 err = ftp_type (&con->rbuf, type_char);
329 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
333 logputs (LOG_VERBOSE, "\n");
334 logputs (LOG_NOTQUIET, _("\
335 Error in server response, closing control connection.\n"));
337 rbuf_uninitialize (&con->rbuf);
341 logputs (LOG_VERBOSE, "\n");
342 logputs (LOG_NOTQUIET,
343 _("Write failed, closing control connection.\n"));
345 rbuf_uninitialize (&con->rbuf);
349 logputs (LOG_VERBOSE, "\n");
350 logprintf (LOG_NOTQUIET,
351 _("Unknown type `%c', closing control connection.\n"),
354 rbuf_uninitialize (&con->rbuf);
357 /* Everything is OK. */
363 if (!opt.server_response)
364 logputs (LOG_VERBOSE, _("done. "));
370 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
373 char *target = u->dir;
375 DEBUGP (("changing working directory\n"));
377 /* Change working directory. To change to a non-absolute
378 Unix directory, we need to prepend initial directory
379 (con->id) to it. Absolute directories "just work". */
383 int idlen = strlen (con->id);
384 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
385 /* idlen == 1 means con->id = "/" */
386 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
388 DEBUGP (("Prepended initial PWD to relative path:\n"));
389 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
393 /* If the FTP host runs VMS, we will have to convert the absolute
394 directory path in UNIX notation to absolute directory path in
395 VMS notation as VMS FTP servers do not like UNIX notation of
396 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
398 if (con->rs == ST_VMS)
401 char *ntarget = (char *)alloca (strlen (target) + 2);
402 /* We use a converted initial dir, so directories in
403 TARGET will be separated with slashes, something like
404 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
405 "[INITIAL.FOLDER.DIR.SUBDIR]". */
406 strcpy (ntarget, target);
407 assert (*ntarget == '/');
409 for (tmpp = ntarget + 1; *tmpp; tmpp++)
414 DEBUGP (("Changed file name to VMS syntax:\n"));
415 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
419 if (!opt.server_response)
420 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
421 err = ftp_cwd (&con->rbuf, target);
422 /* FTPRERR, WRITEFAILED, FTPNSFOD */
426 logputs (LOG_VERBOSE, "\n");
427 logputs (LOG_NOTQUIET, _("\
428 Error in server response, closing control connection.\n"));
430 rbuf_uninitialize (&con->rbuf);
434 logputs (LOG_VERBOSE, "\n");
435 logputs (LOG_NOTQUIET,
436 _("Write failed, closing control connection.\n"));
438 rbuf_uninitialize (&con->rbuf);
442 logputs (LOG_VERBOSE, "\n");
443 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
446 rbuf_uninitialize (&con->rbuf);
456 if (!opt.server_response)
457 logputs (LOG_VERBOSE, _("done.\n"));
460 else /* do not CWD */
461 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
463 if ((cmd & DO_RETR) && restval && *len == 0)
467 if (!opt.server_response)
468 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
471 err = ftp_size(&con->rbuf, u->file, len);
477 logputs (LOG_VERBOSE, "\n");
478 logputs (LOG_NOTQUIET, _("\
479 Error in server response, closing control connection.\n"));
481 rbuf_uninitialize (&con->rbuf);
485 /* Everything is OK. */
491 if (!opt.server_response)
492 logputs (LOG_VERBOSE, _("done.\n"));
495 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
496 if (cmd & (DO_LIST | DO_RETR))
498 if (opt.ftp_pasv > 0)
500 if (!opt.server_response)
501 logputs (LOG_VERBOSE, "==> PASV ... ");
502 err = ftp_pasv (&con->rbuf, pasv_addr);
503 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
507 logputs (LOG_VERBOSE, "\n");
508 logputs (LOG_NOTQUIET, _("\
509 Error in server response, closing control connection.\n"));
511 rbuf_uninitialize (&con->rbuf);
515 logputs (LOG_VERBOSE, "\n");
516 logputs (LOG_NOTQUIET,
517 _("Write failed, closing control connection.\n"));
519 rbuf_uninitialize (&con->rbuf);
523 logputs (LOG_VERBOSE, "\n");
524 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
527 logputs (LOG_VERBOSE, "\n");
528 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
539 unsigned short tport;
541 tport = (pasv_addr[4] << 8) + pasv_addr[5];
542 dtsock = connect_to_one (pasv_addr, tport, 1);
546 int save_errno = errno;
548 rbuf_uninitialize (&con->rbuf);
549 logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
550 pretty_print_address (pasv_addr), tport,
551 strerror (save_errno));
552 return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
555 passive_mode_open = 1; /* Flag to avoid accept port */
556 if (!opt.server_response)
557 logputs (LOG_VERBOSE, _("done. "));
561 if (!passive_mode_open) /* Try to use a port command if PASV failed */
563 if (!opt.server_response)
564 logputs (LOG_VERBOSE, "==> PORT ... ");
565 err = ftp_port (&con->rbuf);
566 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
567 LISTENERR), HOSTERR, FTPPORTERR */
571 logputs (LOG_VERBOSE, "\n");
572 logputs (LOG_NOTQUIET, _("\
573 Error in server response, closing control connection.\n"));
576 rbuf_uninitialize (&con->rbuf);
580 logputs (LOG_VERBOSE, "\n");
581 logputs (LOG_NOTQUIET,
582 _("Write failed, closing control connection.\n"));
585 rbuf_uninitialize (&con->rbuf);
589 logputs (LOG_VERBOSE, "\n");
590 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
593 rbuf_uninitialize (&con->rbuf);
596 case CONPORTERR: case BINDERR: case LISTENERR:
597 /* What now? These problems are local... */
598 logputs (LOG_VERBOSE, "\n");
599 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
605 logputs (LOG_VERBOSE, "\n");
606 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
610 rbuf_uninitialize (&con->rbuf);
614 logputs (LOG_VERBOSE, "\n");
615 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
618 rbuf_uninitialize (&con->rbuf);
628 if (!opt.server_response)
629 logputs (LOG_VERBOSE, _("done. "));
631 } /* cmd & (DO_LIST | DO_RETR) */
633 /* Restart if needed. */
634 if (restval && (cmd & DO_RETR))
636 if (!opt.server_response)
637 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
638 err = ftp_rest (&con->rbuf, restval);
640 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
644 logputs (LOG_VERBOSE, "\n");
645 logputs (LOG_NOTQUIET, _("\
646 Error in server response, closing control connection.\n"));
649 rbuf_uninitialize (&con->rbuf);
653 logputs (LOG_VERBOSE, "\n");
654 logputs (LOG_NOTQUIET,
655 _("Write failed, closing control connection.\n"));
658 rbuf_uninitialize (&con->rbuf);
662 /* If `-c' is specified and the file already existed when
663 Wget was started, it would be a bad idea for us to start
664 downloading it from scratch, effectively truncating it. */
665 if (opt.always_rest && (cmd & NO_TRUNCATE))
667 logprintf (LOG_NOTQUIET,
668 _("\nREST failed; will not truncate `%s'.\n"),
672 rbuf_uninitialize (&con->rbuf);
673 return CONTNOTSUPPORTED;
675 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
685 if (err != FTPRESTFAIL && !opt.server_response)
686 logputs (LOG_VERBOSE, _("done. "));
687 } /* restval && cmd & DO_RETR */
693 if (!opt.server_response)
696 logputs (LOG_VERBOSE, "\n");
697 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
700 err = ftp_retr (&con->rbuf, u->file);
701 /* FTPRERR, WRITEFAILED, FTPNSFOD */
705 logputs (LOG_VERBOSE, "\n");
706 logputs (LOG_NOTQUIET, _("\
707 Error in server response, closing control connection.\n"));
710 rbuf_uninitialize (&con->rbuf);
714 logputs (LOG_VERBOSE, "\n");
715 logputs (LOG_NOTQUIET,
716 _("Write failed, closing control connection.\n"));
719 rbuf_uninitialize (&con->rbuf);
723 logputs (LOG_VERBOSE, "\n");
724 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
736 if (!opt.server_response)
737 logputs (LOG_VERBOSE, _("done.\n"));
738 expected_bytes = ftp_expected_bytes (ftp_last_respline);
743 if (!opt.server_response)
744 logputs (LOG_VERBOSE, "==> LIST ... ");
745 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
746 without arguments is better than `LIST .'; confirmed by
748 err = ftp_list (&con->rbuf, NULL);
749 /* FTPRERR, WRITEFAILED */
753 logputs (LOG_VERBOSE, "\n");
754 logputs (LOG_NOTQUIET, _("\
755 Error in server response, closing control connection.\n"));
758 rbuf_uninitialize (&con->rbuf);
762 logputs (LOG_VERBOSE, "\n");
763 logputs (LOG_NOTQUIET,
764 _("Write failed, closing control connection.\n"));
767 rbuf_uninitialize (&con->rbuf);
771 logputs (LOG_VERBOSE, "\n");
772 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
784 if (!opt.server_response)
785 logputs (LOG_VERBOSE, _("done.\n"));
786 expected_bytes = ftp_expected_bytes (ftp_last_respline);
787 } /* cmd & DO_LIST */
789 /* Some FTP servers return the total length of file after REST
790 command, others just return the remaining size. */
791 if (*len && restval && expected_bytes
792 && (expected_bytes == *len - restval))
794 DEBUGP (("Lying FTP server found, adjusting.\n"));
795 expected_bytes = *len;
798 /* If no transmission was required, then everything is OK. */
799 if (!(cmd & (DO_LIST | DO_RETR)))
802 if (!passive_mode_open) /* we are not using pasive mode so we need
805 /* Open the data transmission socket by calling acceptport(). */
806 err = acceptport (&dtsock);
807 /* Possible errors: ACCEPTERR. */
808 if (err == ACCEPTERR)
810 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
815 /* Open the file -- if opt.dfp is set, use it instead. */
816 if (!opt.dfp || con->cmd & DO_LIST)
818 mkalldirs (con->target);
820 rotate_backups (con->target);
821 /* #### Is this correct? */
822 chmod (con->target, 0600);
824 fp = fopen (con->target, restval ? "ab" : "wb");
827 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
829 rbuf_uninitialize (&con->rbuf);
836 extern int global_download_count;
839 /* Rewind the output document if the download starts over and if
840 this is the first download. See gethttp() for a longer
842 if (!restval && global_download_count == 0)
844 /* This will silently fail for streams that don't correspond
845 to regular files, but that's OK. */
847 /* ftruncate is needed because opt.dfp is opened in append
848 mode if opt.always_rest is set. */
849 ftruncate (fileno (fp), 0);
856 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
858 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
859 logputs (LOG_VERBOSE, "\n");
860 expected_bytes = *len; /* for get_contents/show_progress */
862 else if (expected_bytes)
864 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
866 logprintf (LOG_VERBOSE, _(" [%s to go]"),
867 legible (expected_bytes - restval));
868 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
871 /* Get the contents of the document. */
872 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
874 tms = time_str (NULL);
875 tmrate = retr_rate (*len - restval, con->dltime, 0);
876 /* Close data connection socket. */
878 /* Close the local file. */
880 /* Close or flush the file. We have to be careful to check for
881 error here. Checking the result of fwrite() is not enough --
882 errors could go unnoticed! */
884 if (!opt.dfp || con->cmd & DO_LIST)
885 flush_res = fclose (fp);
887 flush_res = fflush (fp);
888 if (flush_res == EOF)
891 /* If get_contents couldn't write to fp, bail out. */
894 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
895 con->target, strerror (errno));
897 rbuf_uninitialize (&con->rbuf);
902 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
903 tms, tmrate, strerror (errno));
904 if (opt.server_response)
905 logputs (LOG_ALWAYS, "\n");
908 /* Get the server to tell us if everything is retrieved. */
909 err = ftp_response (&con->rbuf, &respline);
910 /* ...and empty the buffer. */
911 rbuf_discard (&con->rbuf);
915 /* The control connection is decidedly closed. Print the time
916 only if it hasn't already been printed. */
918 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
919 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
920 /* If there is an error on the control connection, close it, but
921 return FTPRETRINT, since there is a possibility that the
922 whole file was retrieved nevertheless (but that is for
923 ftp_loop_internal to decide). */
925 rbuf_uninitialize (&con->rbuf);
928 /* If retrieval failed for any reason, return FTPRETRINT, but do not
929 close socket, since the control connection is still alive. If
930 there is something wrong with the control connection, it will
931 become apparent later. */
932 if (*respline != '2')
936 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
937 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
944 /* What now? The data connection was erroneous, whereas the
945 response says everything is OK. We shall play it safe. */
949 if (!(cmd & LEAVE_PENDING))
951 /* I should probably send 'QUIT' and check for a reply, but this
952 is faster. #### Is it OK, though? */
954 rbuf_uninitialize (&con->rbuf);
956 /* If it was a listing, and opt.server_response is true,
958 if (opt.server_response && (con->cmd & DO_LIST))
960 mkalldirs (con->target);
961 fp = fopen (con->target, "r");
963 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
967 /* The lines are being read with read_whole_line because of
968 no-buffering on opt.lfile. */
969 while ((line = read_whole_line (fp)))
971 logprintf (LOG_ALWAYS, "%s\n", line);
976 } /* con->cmd & DO_LIST && server_response */
981 /* A one-file FTP loop. This is the part where FTP retrieval is
982 retried, and retried, and retried, and...
984 This loop either gets commands from con, or (if ON_YOUR_OWN is
985 set), makes them up to retrieve the file given by the URL. */
987 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
991 char *tms, *tmrate, *locf;
996 con->target = url_filename (u);
998 if (opt.noclobber && file_exists_p (con->target))
1000 logprintf (LOG_VERBOSE,
1001 _("File `%s' already there, not retrieving.\n"), con->target);
1002 /* If the file is there, we suppose it's retrieved OK. */
1006 /* Remove it if it's a link. */
1007 remove_link (con->target);
1008 if (!opt.output_document)
1011 locf = opt.output_document;
1015 if (con->st & ON_YOUR_OWN)
1016 con->st = ON_YOUR_OWN;
1018 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1023 /* Increment the pass counter. */
1025 sleep_between_retrievals (count);
1026 if (con->st & ON_YOUR_OWN)
1029 con->cmd |= (DO_RETR | LEAVE_PENDING);
1030 if (rbuf_initialized_p (&con->rbuf))
1031 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1033 con->cmd |= (DO_LOGIN | DO_CWD);
1035 else /* not on your own */
1037 if (rbuf_initialized_p (&con->rbuf))
1038 con->cmd &= ~DO_LOGIN;
1040 con->cmd |= DO_LOGIN;
1041 if (con->st & DONE_CWD)
1042 con->cmd &= ~DO_CWD;
1047 /* Assume no restarting. */
1049 if ((count > 1 || opt.always_rest)
1050 && !(con->cmd & DO_LIST)
1051 && file_exists_p (locf))
1052 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1053 restval = st.st_size;
1055 /* In `-c' is used, check whether the file we're writing to
1056 exists and is of non-zero length. If so, we'll refuse to
1057 truncate it if the server doesn't support continued
1059 if (opt.always_rest && restval > 0)
1060 con->cmd |= NO_TRUNCATE;
1062 /* Get the current time string. */
1063 tms = time_str (NULL);
1064 /* Print fetch message, if opt.verbose. */
1067 char *hurl = url_string (u, 1);
1071 sprintf (tmp, _("(try:%2d)"), count);
1072 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1073 tms, hurl, tmp, locf);
1075 ws_changetitle (hurl, 1);
1079 /* Send getftp the proper length, if fileinfo was provided. */
1084 err = getftp (u, &len, restval, con);
1086 if (!rbuf_initialized_p (&con->rbuf))
1087 con->st &= ~DONE_CWD;
1089 con->st |= DONE_CWD;
1093 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1094 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1095 /* Fatal errors, give up. */
1098 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1099 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1100 case BINDERR: case LISTENERR: case ACCEPTERR:
1101 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1102 printwhat (count, opt.ntry);
1103 /* non-fatal errors */
1107 /* If the control connection was closed, the retrieval
1108 will be considered OK if f->size == len. */
1109 if (!f || len != f->size)
1111 printwhat (count, opt.ntry);
1123 tms = time_str (NULL);
1124 tmrate = retr_rate (len - restval, con->dltime, 0);
1126 /* If we get out of the switch above without continue'ing, we've
1127 successfully downloaded a file. Remember this fact. */
1128 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1130 if (con->st & ON_YOUR_OWN)
1132 CLOSE (RBUF_FD (&con->rbuf));
1133 rbuf_uninitialize (&con->rbuf);
1135 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1136 tms, tmrate, locf, len);
1137 if (!opt.verbose && !opt.quiet)
1139 /* Need to hide the password from the URL. The `if' is here
1140 so that we don't do the needless allocation every
1142 char *hurl = url_string (u, 1);
1143 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1144 tms, hurl, len, locf, count);
1148 if ((con->cmd & DO_LIST))
1149 /* This is a directory listing file. */
1151 if (!opt.remove_listing)
1152 /* --dont-remove-listing was specified, so do count this towards the
1153 number of bytes and files downloaded. */
1155 downloaded_increase (len);
1159 /* Deletion of listing files is not controlled by --delete-after, but
1160 by the more specific option --dont-remove-listing, and the code
1161 to do this deletion is in another function. */
1164 /* This is not a directory listing file. */
1166 /* Unlike directory listing files, don't pretend normal files weren't
1167 downloaded if they're going to be deleted. People seeding proxies,
1168 for instance, may want to know how many bytes and files they've
1169 downloaded through it. */
1170 downloaded_increase (len);
1173 if (opt.delete_after)
1175 DEBUGP (("Removing file due to --delete-after in"
1176 " ftp_loop_internal():\n"));
1177 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1179 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1183 /* Restore the original leave-pendingness. */
1185 con->cmd |= LEAVE_PENDING;
1187 con->cmd &= ~LEAVE_PENDING;
1189 } while (!opt.ntry || (count < opt.ntry));
1191 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1193 CLOSE (RBUF_FD (&con->rbuf));
1194 rbuf_uninitialize (&con->rbuf);
1199 /* Return the directory listing in a reusable format. The directory
1200 is specifed in u->dir. */
1202 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1205 char *uf; /* url file name */
1206 char *lf; /* list file name */
1207 char *old_target = con->target;
1209 con->st &= ~ON_YOUR_OWN;
1210 con->cmd |= (DO_LIST | LEAVE_PENDING);
1211 con->cmd &= ~DO_RETR;
1213 /* Find the listing file name. We do it by taking the file name of
1214 the URL and replacing the last component with the listing file
1216 uf = url_filename (u);
1217 lf = file_merge (uf, LIST_FILENAME);
1219 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1222 err = ftp_loop_internal (u, NULL, con);
1223 con->target = old_target;
1226 *f = ftp_parse_ls (lf, con->rs);
1229 if (opt.remove_listing)
1232 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1234 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1237 con->cmd &= ~DO_LIST;
1241 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1243 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1244 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1245 struct fileinfo **));
1246 static void freefileinfo PARAMS ((struct fileinfo *f));
1248 /* Retrieve a list of files given in struct fileinfo linked list. If
1249 a file is a symbolic link, do not retrieve it, but rather try to
1250 set up a similar link on the local disk, if the symlinks are
1253 If opt.recursive is set, after all files have been retrieved,
1254 ftp_retrieve_dirs will be called to retrieve the directories. */
1256 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1258 static int depth = 0;
1260 struct fileinfo *orig;
1265 /* Increase the depth. */
1267 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1269 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1270 depth, opt.reclevel));
1278 con->st &= ~ON_YOUR_OWN;
1279 if (!(con->st & DONE_CWD))
1282 con->cmd &= ~DO_CWD;
1283 con->cmd |= (DO_RETR | LEAVE_PENDING);
1285 if (!rbuf_initialized_p (&con->rbuf))
1286 con->cmd |= DO_LOGIN;
1288 con->cmd &= ~DO_LOGIN;
1290 err = RETROK; /* in case it's not used */
1294 char *old_target, *ofile;
1296 if (downloaded_exceeds_quota ())
1301 old_target = con->target;
1303 ofile = xstrdup (u->file);
1304 url_set_file (u, f->name);
1306 con->target = url_filename (u);
1310 if (opt.timestamping && f->type == FT_PLAINFILE)
1313 /* If conversion of HTML files retrieved via FTP is ever implemented,
1314 we'll need to stat() <file>.orig here when -K has been specified.
1315 I'm not implementing it now since files on an FTP server are much
1316 more likely than files on an HTTP server to legitimately have a
1318 if (!stat (con->target, &st))
1322 /* Else, get it from the file. */
1323 local_size = st.st_size;
1325 /* Compare file sizes only for servers that tell us correct
1326 values. Assumme sizes being equal for servers that lie
1328 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1329 eq_size = cor_val ? (local_size == f->size) : 1 ;
1330 if (f->tstamp <= tml && eq_size)
1332 /* Remote file is older, file sizes can be compared and
1334 logprintf (LOG_VERBOSE, _("\
1335 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1340 /* Remote file is newer or sizes cannot be matched */
1341 logprintf (LOG_VERBOSE, _("\
1342 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1347 /* Sizes do not match */
1348 logprintf (LOG_VERBOSE, _("\
1349 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1352 } /* opt.timestamping && f->type == FT_PLAINFILE */
1356 /* If opt.retr_symlinks is defined, we treat symlinks as
1357 if they were normal files. There is currently no way
1358 to distinguish whether they might be directories, and
1360 if (!opt.retr_symlinks)
1364 logputs (LOG_NOTQUIET,
1365 _("Invalid name of the symlink, skipping.\n"));
1369 /* Check whether we already have the correct
1371 int rc = lstat (con->target, &st);
1374 size_t len = strlen (f->linkto) + 1;
1375 if (S_ISLNK (st.st_mode))
1377 char *link_target = (char *)alloca (len);
1378 size_t n = readlink (con->target, link_target, len);
1380 && (memcmp (link_target, f->linkto, n) == 0))
1382 logprintf (LOG_VERBOSE, _("\
1383 Already have correct symlink %s -> %s\n\n"),
1384 con->target, f->linkto);
1390 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1391 con->target, f->linkto);
1392 /* Unlink before creating symlink! */
1393 unlink (con->target);
1394 if (symlink (f->linkto, con->target) == -1)
1395 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1397 logputs (LOG_VERBOSE, "\n");
1398 } /* have f->linkto */
1399 #else /* not HAVE_SYMLINK */
1400 logprintf (LOG_NOTQUIET,
1401 _("Symlinks not supported, skipping symlink `%s'.\n"),
1403 #endif /* not HAVE_SYMLINK */
1405 else /* opt.retr_symlinks */
1408 err = ftp_loop_internal (u, f, con);
1409 } /* opt.retr_symlinks */
1413 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1417 /* Call the retrieve loop. */
1419 err = ftp_loop_internal (u, f, con);
1422 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1427 /* Set the time-stamp information to the local file. Symlinks
1428 are not to be stamped because it sets the stamp on the
1430 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1433 && file_exists_p (con->target))
1435 /* #### This code repeats in http.c and ftp.c. Move it to a
1437 const char *fl = NULL;
1438 if (opt.output_document)
1440 if (opt.od_known_regular)
1441 fl = opt.output_document;
1446 touch (fl, f->tstamp);
1448 else if (f->tstamp == -1)
1449 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1451 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1452 chmod (con->target, f->perms);
1454 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1456 xfree (con->target);
1457 con->target = old_target;
1459 url_set_file (u, ofile);
1462 /* Break on fatals. */
1463 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1465 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1469 /* We do not want to call ftp_retrieve_dirs here */
1470 if (opt.recursive &&
1471 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1472 err = ftp_retrieve_dirs (u, orig, con);
1473 else if (opt.recursive)
1474 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1475 depth, opt.reclevel));
1480 /* Retrieve the directories given in a file list. This function works
1481 by simply going through the linked list and calling
1482 ftp_retrieve_glob on each directory entry. The function knows
1483 about excluded directories. */
1485 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1487 char *container = NULL;
1488 int container_size = 0;
1490 for (; f; f = f->next)
1493 char *odir, *newdir;
1495 if (downloaded_exceeds_quota ())
1497 if (f->type != FT_DIRECTORY)
1500 /* Allocate u->dir off stack, but reallocate only if a larger
1501 string is needed. It's a pity there's no "realloca" for an
1502 item on the bottom of the stack. */
1503 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1504 if (size > container_size)
1505 container = (char *)alloca (size);
1510 || (*odir == '/' && *(odir + 1) == '\0'))
1511 /* If ODIR is empty or just "/", simply append f->name to
1512 ODIR. (In the former case, to preserve u->dir being
1513 relative; in the latter case, to avoid double slash.) */
1514 sprintf (newdir, "%s%s", odir, f->name);
1516 /* Else, use a separator. */
1517 sprintf (newdir, "%s/%s", odir, f->name);
1519 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1520 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1521 odir, f->name, newdir));
1522 if (!accdir (newdir, ALLABS))
1524 logprintf (LOG_VERBOSE, _("\
1525 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1529 con->st &= ~DONE_CWD;
1531 odir = xstrdup (u->dir); /* because url_set_dir will free
1533 url_set_dir (u, newdir);
1534 ftp_retrieve_glob (u, con, GETALL);
1535 url_set_dir (u, odir);
1538 /* Set the time-stamp? */
1541 if (opt.quota && opt.downloaded > opt.quota)
1548 /* A near-top-level function to retrieve the files in a directory.
1549 The function calls ftp_get_listing, to get a linked list of files.
1550 Then it weeds out the file names that do not match the pattern.
1551 ftp_retrieve_list is called with this updated list as an argument.
1553 If the argument ACTION is GETONE, just download the file (but first
1554 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1555 use globbing; if it's GETALL, download the whole directory. */
1557 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1559 struct fileinfo *orig, *start;
1562 con->cmd |= LEAVE_PENDING;
1564 res = ftp_get_listing (u, con, &orig);
1568 /* First: weed out that do not conform the global rules given in
1569 opt.accepts and opt.rejects. */
1570 if (opt.accepts || opt.rejects)
1572 struct fileinfo *f = orig;
1576 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1578 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1579 f = delelement (f, &start);
1585 /* Now weed out the files that do not match our globbing pattern.
1586 If we are dealing with a globbing pattern, that is. */
1587 if (*u->file && (action == GLOBALL || action == GETONE))
1590 struct fileinfo *f = start;
1594 matchres = fnmatch (u->file, f->name, 0);
1597 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1601 if (matchres == FNM_NOMATCH)
1602 f = delelement (f, &start); /* delete the element from the list */
1604 f = f->next; /* leave the element in the list */
1608 freefileinfo (start);
1609 return RETRBADPATTERN;
1615 /* Just get everything. */
1616 ftp_retrieve_list (u, start, con);
1620 if (action == GLOBALL)
1623 /* #### This message SUCKS. We should see what was the
1624 reason that nothing was retrieved. */
1625 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1627 else /* GETONE or GETALL */
1629 /* Let's try retrieving it anyway. */
1630 con->st |= ON_YOUR_OWN;
1631 res = ftp_loop_internal (u, NULL, con);
1635 freefileinfo (start);
1636 if (downloaded_exceeds_quota ())
1639 /* #### Should we return `res' here? */
1643 /* The wrapper that calls an appropriate routine according to contents
1644 of URL. Inherently, its capabilities are limited on what can be
1645 encoded into a URL. */
1647 ftp_loop (struct url *u, int *dt)
1649 ccon con; /* FTP connection */
1654 memset (&con, 0, sizeof (con));
1656 rbuf_uninitialize (&con.rbuf);
1657 con.st = ON_YOUR_OWN;
1660 res = RETROK; /* in case it's not used */
1662 /* If the file name is empty, the user probably wants a directory
1663 index. We'll provide one, properly HTML-ized. Unless
1664 opt.htmlify is 0, of course. :-) */
1665 if (!*u->file && !opt.recursive)
1668 res = ftp_get_listing (u, &con, &f);
1674 char *filename = (opt.output_document
1675 ? xstrdup (opt.output_document)
1676 : (con.target ? xstrdup (con.target)
1677 : url_filename (u)));
1678 res = ftp_index (filename, u, f);
1679 if (res == FTPOK && opt.verbose)
1681 if (!opt.output_document)
1685 if (stat (filename, &st) == 0)
1689 logprintf (LOG_NOTQUIET,
1690 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1694 logprintf (LOG_NOTQUIET,
1695 _("Wrote HTML-ized index to `%s'.\n"),
1705 int wild = has_wildcards_p (u->file);
1706 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1708 /* ftp_retrieve_glob is a catch-all function that gets called
1709 if we need globbing, time-stamping or recursion. Its
1710 third argument is just what we really need. */
1711 ftp_retrieve_glob (u, &con,
1712 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1715 res = ftp_loop_internal (u, NULL, &con);
1721 /* If a connection was left, quench it. */
1722 if (rbuf_initialized_p (&con.rbuf))
1723 CLOSE (RBUF_FD (&con.rbuf));
1724 FREE_MAYBE (con.id);
1726 FREE_MAYBE (con.target);
1731 /* Delete an element from the fileinfo linked list. Returns the
1732 address of the next element, or NULL if the list is exhausted. It
1733 can modify the start of the list. */
1734 static struct fileinfo *
1735 delelement (struct fileinfo *f, struct fileinfo **start)
1737 struct fileinfo *prev = f->prev;
1738 struct fileinfo *next = f->next;
1741 FREE_MAYBE (f->linkto);
1753 /* Free the fileinfo linked list of files. */
1755 freefileinfo (struct fileinfo *f)
1759 struct fileinfo *next = f->next;