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)
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);
280 logputs (LOG_VERBOSE, "\n");
281 logputs (LOG_NOTQUIET, _("\
282 Error in server response, closing control connection.\n"));
284 rbuf_uninitialize (&con->rbuf);
288 /* Everything is OK. */
294 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
295 Convert it to "/INITIAL/FOLDER" */
296 if (con->rs == ST_VMS)
298 char *path = strchr (con->id, '[');
299 char *pathend = path ? strchr (path + 1, ']') : NULL;
300 if (!path || !pathend)
301 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
304 char *idir = con->id;
305 DEBUGP (("Preprocessing the initial VMS directory\n"));
306 DEBUGP ((" old = '%s'\n", con->id));
307 /* We do the conversion in-place by copying the stuff
308 between [ and ] to the beginning, and changing dots
309 to slashes at the same time. */
311 for (++path; path < pathend; path++, idir++)
312 *idir = *path == '.' ? '/' : *path;
314 DEBUGP ((" new = '%s'\n\n", con->id));
317 if (!opt.server_response)
318 logputs (LOG_VERBOSE, _("done.\n"));
320 /* Fifth: Set the FTP type. */
321 type_char = ftp_process_type (u->params);
322 if (!opt.server_response)
323 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
324 err = ftp_type (&con->rbuf, type_char);
325 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
329 logputs (LOG_VERBOSE, "\n");
330 logputs (LOG_NOTQUIET, _("\
331 Error in server response, closing control connection.\n"));
333 rbuf_uninitialize (&con->rbuf);
337 logputs (LOG_VERBOSE, "\n");
338 logputs (LOG_NOTQUIET,
339 _("Write failed, closing control connection.\n"));
341 rbuf_uninitialize (&con->rbuf);
345 logputs (LOG_VERBOSE, "\n");
346 logprintf (LOG_NOTQUIET,
347 _("Unknown type `%c', closing control connection.\n"),
350 rbuf_uninitialize (&con->rbuf);
353 /* Everything is OK. */
359 if (!opt.server_response)
360 logputs (LOG_VERBOSE, _("done. "));
366 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
369 char *target = u->dir;
371 DEBUGP (("changing working directory\n"));
373 /* Change working directory. To change to a non-absolute
374 Unix directory, we need to prepend initial directory
375 (con->id) to it. Absolute directories "just work". */
379 int idlen = strlen (con->id);
380 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
381 /* idlen == 1 means con->id = "/" */
382 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
384 DEBUGP (("Prepended initial PWD to relative path:\n"));
385 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
389 /* If the FTP host runs VMS, we will have to convert the absolute
390 directory path in UNIX notation to absolute directory path in
391 VMS notation as VMS FTP servers do not like UNIX notation of
392 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
394 if (con->rs == ST_VMS)
397 char *ntarget = (char *)alloca (strlen (target) + 2);
398 /* We use a converted initial dir, so directories in
399 TARGET will be separated with slashes, something like
400 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
401 "[INITIAL.FOLDER.DIR.SUBDIR]". */
402 strcpy (ntarget, target);
403 assert (*ntarget == '/');
405 for (tmpp = ntarget + 1; *tmpp; tmpp++)
410 DEBUGP (("Changed file name to VMS syntax:\n"));
411 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
415 if (!opt.server_response)
416 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
417 err = ftp_cwd (&con->rbuf, target);
418 /* FTPRERR, WRITEFAILED, FTPNSFOD */
422 logputs (LOG_VERBOSE, "\n");
423 logputs (LOG_NOTQUIET, _("\
424 Error in server response, closing control connection.\n"));
426 rbuf_uninitialize (&con->rbuf);
430 logputs (LOG_VERBOSE, "\n");
431 logputs (LOG_NOTQUIET,
432 _("Write failed, closing control connection.\n"));
434 rbuf_uninitialize (&con->rbuf);
438 logputs (LOG_VERBOSE, "\n");
439 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
442 rbuf_uninitialize (&con->rbuf);
452 if (!opt.server_response)
453 logputs (LOG_VERBOSE, _("done.\n"));
456 else /* do not CWD */
457 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
459 if ((cmd & DO_RETR) && restval && *len == 0)
463 if (!opt.server_response)
464 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
467 err = ftp_size(&con->rbuf, u->file, len);
473 logputs (LOG_VERBOSE, "\n");
474 logputs (LOG_NOTQUIET, _("\
475 Error in server response, closing control connection.\n"));
477 rbuf_uninitialize (&con->rbuf);
481 /* Everything is OK. */
487 if (!opt.server_response)
488 logputs (LOG_VERBOSE, _("done.\n"));
491 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
492 if (cmd & (DO_LIST | DO_RETR))
494 if (opt.ftp_pasv > 0)
497 unsigned short tport;
499 if (!opt.server_response)
500 logputs (LOG_VERBOSE, "==> PASV ... ");
501 err = ftp_pasv (&con->rbuf, pasv_addr);
502 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
506 logputs (LOG_VERBOSE, "\n");
507 logputs (LOG_NOTQUIET, _("\
508 Error in server response, closing control connection.\n"));
510 rbuf_uninitialize (&con->rbuf);
514 logputs (LOG_VERBOSE, "\n");
515 logputs (LOG_NOTQUIET,
516 _("Write failed, closing control connection.\n"));
518 rbuf_uninitialize (&con->rbuf);
522 logputs (LOG_VERBOSE, "\n");
523 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
526 logputs (LOG_VERBOSE, "\n");
527 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
538 struct address_list *al;
540 sprintf (thost, "%d.%d.%d.%d",
541 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
542 tport = (pasv_addr[4] << 8) + pasv_addr[5];
544 al = lookup_host (thost, 0);
548 rbuf_uninitialize (&con->rbuf);
551 dtsock = connect_to_many (al, tport, 0);
552 address_list_release (al);
556 int save_errno = errno;
558 rbuf_uninitialize (&con->rbuf);
559 return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
562 passive_mode_open= 1; /* Flag to avoid accept port */
563 if (!opt.server_response)
564 logputs (LOG_VERBOSE, _("done. "));
568 if (!passive_mode_open) /* Try to use a port command if PASV failed */
570 if (!opt.server_response)
571 logputs (LOG_VERBOSE, "==> PORT ... ");
572 err = ftp_port (&con->rbuf);
573 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
574 LISTENERR), HOSTERR, FTPPORTERR */
578 logputs (LOG_VERBOSE, "\n");
579 logputs (LOG_NOTQUIET, _("\
580 Error in server response, closing control connection.\n"));
583 rbuf_uninitialize (&con->rbuf);
587 logputs (LOG_VERBOSE, "\n");
588 logputs (LOG_NOTQUIET,
589 _("Write failed, closing control connection.\n"));
592 rbuf_uninitialize (&con->rbuf);
596 logputs (LOG_VERBOSE, "\n");
597 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
600 rbuf_uninitialize (&con->rbuf);
603 case CONPORTERR: case BINDERR: case LISTENERR:
604 /* What now? These problems are local... */
605 logputs (LOG_VERBOSE, "\n");
606 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
612 logputs (LOG_VERBOSE, "\n");
613 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
617 rbuf_uninitialize (&con->rbuf);
621 logputs (LOG_VERBOSE, "\n");
622 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
625 rbuf_uninitialize (&con->rbuf);
635 if (!opt.server_response)
636 logputs (LOG_VERBOSE, _("done. "));
638 } /* cmd & (DO_LIST | DO_RETR) */
640 /* Restart if needed. */
641 if (restval && (cmd & DO_RETR))
643 if (!opt.server_response)
644 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
645 err = ftp_rest (&con->rbuf, restval);
647 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
651 logputs (LOG_VERBOSE, "\n");
652 logputs (LOG_NOTQUIET, _("\
653 Error in server response, closing control connection.\n"));
656 rbuf_uninitialize (&con->rbuf);
660 logputs (LOG_VERBOSE, "\n");
661 logputs (LOG_NOTQUIET,
662 _("Write failed, closing control connection.\n"));
665 rbuf_uninitialize (&con->rbuf);
669 /* If `-c' is specified and the file already existed when
670 Wget was started, it would be a bad idea for us to start
671 downloading it from scratch, effectively truncating it. */
672 if (opt.always_rest && (cmd & NO_TRUNCATE))
674 logprintf (LOG_NOTQUIET,
675 _("\nREST failed; will not truncate `%s'.\n"),
679 rbuf_uninitialize (&con->rbuf);
680 return CONTNOTSUPPORTED;
682 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
692 if (err != FTPRESTFAIL && !opt.server_response)
693 logputs (LOG_VERBOSE, _("done. "));
694 } /* restval && cmd & DO_RETR */
700 if (!opt.server_response)
703 logputs (LOG_VERBOSE, "\n");
704 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
707 err = ftp_retr (&con->rbuf, u->file);
708 /* FTPRERR, WRITEFAILED, FTPNSFOD */
712 logputs (LOG_VERBOSE, "\n");
713 logputs (LOG_NOTQUIET, _("\
714 Error in server response, closing control connection.\n"));
717 rbuf_uninitialize (&con->rbuf);
721 logputs (LOG_VERBOSE, "\n");
722 logputs (LOG_NOTQUIET,
723 _("Write failed, closing control connection.\n"));
726 rbuf_uninitialize (&con->rbuf);
730 logputs (LOG_VERBOSE, "\n");
731 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
743 if (!opt.server_response)
744 logputs (LOG_VERBOSE, _("done.\n"));
745 expected_bytes = ftp_expected_bytes (ftp_last_respline);
750 if (!opt.server_response)
751 logputs (LOG_VERBOSE, "==> LIST ... ");
752 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
753 without arguments is better than `LIST .'; confirmed by
755 err = ftp_list (&con->rbuf, NULL);
756 /* FTPRERR, WRITEFAILED */
760 logputs (LOG_VERBOSE, "\n");
761 logputs (LOG_NOTQUIET, _("\
762 Error in server response, closing control connection.\n"));
765 rbuf_uninitialize (&con->rbuf);
769 logputs (LOG_VERBOSE, "\n");
770 logputs (LOG_NOTQUIET,
771 _("Write failed, closing control connection.\n"));
774 rbuf_uninitialize (&con->rbuf);
778 logputs (LOG_VERBOSE, "\n");
779 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
791 if (!opt.server_response)
792 logputs (LOG_VERBOSE, _("done.\n"));
793 expected_bytes = ftp_expected_bytes (ftp_last_respline);
794 } /* cmd & DO_LIST */
796 /* Some FTP servers return the total length of file after REST
797 command, others just return the remaining size. */
798 if (*len && restval && expected_bytes
799 && (expected_bytes == *len - restval))
801 DEBUGP (("Lying FTP server found, adjusting.\n"));
802 expected_bytes = *len;
805 /* If no transmission was required, then everything is OK. */
806 if (!(cmd & (DO_LIST | DO_RETR)))
809 if (!passive_mode_open) /* we are not using pasive mode so we need
812 /* Open the data transmission socket by calling acceptport(). */
813 err = acceptport (&dtsock);
814 /* Possible errors: ACCEPTERR. */
815 if (err == ACCEPTERR)
817 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
822 /* Open the file -- if opt.dfp is set, use it instead. */
823 if (!opt.dfp || con->cmd & DO_LIST)
825 mkalldirs (con->target);
827 rotate_backups (con->target);
828 /* #### Is this correct? */
829 chmod (con->target, 0600);
831 fp = fopen (con->target, restval ? "ab" : "wb");
834 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
836 rbuf_uninitialize (&con->rbuf);
843 extern int global_download_count;
846 /* Rewind the output document if the download starts over and if
847 this is the first download. See gethttp() for a longer
849 if (!restval && global_download_count == 0)
851 /* This will silently fail for streams that don't correspond
852 to regular files, but that's OK. */
854 /* ftruncate is needed because opt.dfp is opened in append
855 mode if opt.always_rest is set. */
856 ftruncate (fileno (fp), 0);
863 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
865 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
866 logputs (LOG_VERBOSE, "\n");
867 expected_bytes = *len; /* for get_contents/show_progress */
869 else if (expected_bytes)
871 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
873 logprintf (LOG_VERBOSE, _(" [%s to go]"),
874 legible (expected_bytes - restval));
875 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
878 /* Get the contents of the document. */
879 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
881 tms = time_str (NULL);
882 tmrate = retr_rate (*len - restval, con->dltime, 0);
883 /* Close data connection socket. */
885 /* Close the local file. */
887 /* Close or flush the file. We have to be careful to check for
888 error here. Checking the result of fwrite() is not enough --
889 errors could go unnoticed! */
891 if (!opt.dfp || con->cmd & DO_LIST)
892 flush_res = fclose (fp);
894 flush_res = fflush (fp);
895 if (flush_res == EOF)
898 /* If get_contents couldn't write to fp, bail out. */
901 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
902 con->target, strerror (errno));
904 rbuf_uninitialize (&con->rbuf);
909 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
910 tms, tmrate, strerror (errno));
911 if (opt.server_response)
912 logputs (LOG_ALWAYS, "\n");
915 /* Get the server to tell us if everything is retrieved. */
916 err = ftp_response (&con->rbuf, &respline);
917 /* ...and empty the buffer. */
918 rbuf_discard (&con->rbuf);
922 /* The control connection is decidedly closed. Print the time
923 only if it hasn't already been printed. */
925 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
926 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
927 /* If there is an error on the control connection, close it, but
928 return FTPRETRINT, since there is a possibility that the
929 whole file was retrieved nevertheless (but that is for
930 ftp_loop_internal to decide). */
932 rbuf_uninitialize (&con->rbuf);
935 /* If retrieval failed for any reason, return FTPRETRINT, but do not
936 close socket, since the control connection is still alive. If
937 there is something wrong with the control connection, it will
938 become apparent later. */
939 if (*respline != '2')
943 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
944 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
951 /* What now? The data connection was erroneous, whereas the
952 response says everything is OK. We shall play it safe. */
956 if (!(cmd & LEAVE_PENDING))
958 /* I should probably send 'QUIT' and check for a reply, but this
959 is faster. #### Is it OK, though? */
961 rbuf_uninitialize (&con->rbuf);
963 /* If it was a listing, and opt.server_response is true,
965 if (opt.server_response && (con->cmd & DO_LIST))
967 mkalldirs (con->target);
968 fp = fopen (con->target, "r");
970 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
974 /* The lines are being read with read_whole_line because of
975 no-buffering on opt.lfile. */
976 while ((line = read_whole_line (fp)))
978 logprintf (LOG_ALWAYS, "%s\n", line);
983 } /* con->cmd & DO_LIST && server_response */
988 /* A one-file FTP loop. This is the part where FTP retrieval is
989 retried, and retried, and retried, and...
991 This loop either gets commands from con, or (if ON_YOUR_OWN is
992 set), makes them up to retrieve the file given by the URL. */
994 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
998 char *tms, *tmrate, *locf;
1003 con->target = url_filename (u);
1005 if (opt.noclobber && file_exists_p (con->target))
1007 logprintf (LOG_VERBOSE,
1008 _("File `%s' already there, not retrieving.\n"), con->target);
1009 /* If the file is there, we suppose it's retrieved OK. */
1013 /* Remove it if it's a link. */
1014 remove_link (con->target);
1015 if (!opt.output_document)
1018 locf = opt.output_document;
1022 if (con->st & ON_YOUR_OWN)
1023 con->st = ON_YOUR_OWN;
1025 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1030 /* Increment the pass counter. */
1032 sleep_between_retrievals (count);
1033 if (con->st & ON_YOUR_OWN)
1036 con->cmd |= (DO_RETR | LEAVE_PENDING);
1037 if (rbuf_initialized_p (&con->rbuf))
1038 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1040 con->cmd |= (DO_LOGIN | DO_CWD);
1042 else /* not on your own */
1044 if (rbuf_initialized_p (&con->rbuf))
1045 con->cmd &= ~DO_LOGIN;
1047 con->cmd |= DO_LOGIN;
1048 if (con->st & DONE_CWD)
1049 con->cmd &= ~DO_CWD;
1054 /* Assume no restarting. */
1056 if ((count > 1 || opt.always_rest)
1057 && !(con->cmd & DO_LIST)
1058 && file_exists_p (locf))
1059 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1060 restval = st.st_size;
1062 /* In `-c' is used, check whether the file we're writing to
1063 exists and is of non-zero length. If so, we'll refuse to
1064 truncate it if the server doesn't support continued
1066 if (opt.always_rest && restval > 0)
1067 con->cmd |= NO_TRUNCATE;
1069 /* Get the current time string. */
1070 tms = time_str (NULL);
1071 /* Print fetch message, if opt.verbose. */
1074 char *hurl = url_string (u, 1);
1078 sprintf (tmp, _("(try:%2d)"), count);
1079 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1080 tms, hurl, tmp, locf);
1082 ws_changetitle (hurl, 1);
1086 /* Send getftp the proper length, if fileinfo was provided. */
1091 err = getftp (u, &len, restval, con);
1093 if (!rbuf_initialized_p (&con->rbuf))
1094 con->st &= ~DONE_CWD;
1096 con->st |= DONE_CWD;
1100 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1101 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1102 /* Fatal errors, give up. */
1105 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1106 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1107 case BINDERR: case LISTENERR: case ACCEPTERR:
1108 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1109 printwhat (count, opt.ntry);
1110 /* non-fatal errors */
1114 /* If the control connection was closed, the retrieval
1115 will be considered OK if f->size == len. */
1116 if (!f || len != f->size)
1118 printwhat (count, opt.ntry);
1130 tms = time_str (NULL);
1131 tmrate = retr_rate (len - restval, con->dltime, 0);
1133 /* If we get out of the switch above without continue'ing, we've
1134 successfully downloaded a file. Remember this fact. */
1135 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1137 if (con->st & ON_YOUR_OWN)
1139 CLOSE (RBUF_FD (&con->rbuf));
1140 rbuf_uninitialize (&con->rbuf);
1142 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1143 tms, tmrate, locf, len);
1144 if (!opt.verbose && !opt.quiet)
1146 /* Need to hide the password from the URL. The `if' is here
1147 so that we don't do the needless allocation every
1149 char *hurl = url_string (u, 1);
1150 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1151 tms, hurl, len, locf, count);
1155 if ((con->cmd & DO_LIST))
1156 /* This is a directory listing file. */
1158 if (!opt.remove_listing)
1159 /* --dont-remove-listing was specified, so do count this towards the
1160 number of bytes and files downloaded. */
1162 downloaded_increase (len);
1166 /* Deletion of listing files is not controlled by --delete-after, but
1167 by the more specific option --dont-remove-listing, and the code
1168 to do this deletion is in another function. */
1171 /* This is not a directory listing file. */
1173 /* Unlike directory listing files, don't pretend normal files weren't
1174 downloaded if they're going to be deleted. People seeding proxies,
1175 for instance, may want to know how many bytes and files they've
1176 downloaded through it. */
1177 downloaded_increase (len);
1180 if (opt.delete_after)
1182 DEBUGP (("Removing file due to --delete-after in"
1183 " ftp_loop_internal():\n"));
1184 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1186 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1190 /* Restore the original leave-pendingness. */
1192 con->cmd |= LEAVE_PENDING;
1194 con->cmd &= ~LEAVE_PENDING;
1196 } while (!opt.ntry || (count < opt.ntry));
1198 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1200 CLOSE (RBUF_FD (&con->rbuf));
1201 rbuf_uninitialize (&con->rbuf);
1206 /* Return the directory listing in a reusable format. The directory
1207 is specifed in u->dir. */
1209 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1212 char *uf; /* url file name */
1213 char *lf; /* list file name */
1214 char *old_target = con->target;
1216 con->st &= ~ON_YOUR_OWN;
1217 con->cmd |= (DO_LIST | LEAVE_PENDING);
1218 con->cmd &= ~DO_RETR;
1220 /* Find the listing file name. We do it by taking the file name of
1221 the URL and replacing the last component with the listing file
1223 uf = url_filename (u);
1224 lf = file_merge (uf, LIST_FILENAME);
1226 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1229 err = ftp_loop_internal (u, NULL, con);
1230 con->target = old_target;
1233 *f = ftp_parse_ls (lf, con->rs);
1236 if (opt.remove_listing)
1239 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1241 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1244 con->cmd &= ~DO_LIST;
1248 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1250 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1251 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1252 struct fileinfo **));
1253 static void freefileinfo PARAMS ((struct fileinfo *f));
1255 /* Retrieve a list of files given in struct fileinfo linked list. If
1256 a file is a symbolic link, do not retrieve it, but rather try to
1257 set up a similar link on the local disk, if the symlinks are
1260 If opt.recursive is set, after all files have been retrieved,
1261 ftp_retrieve_dirs will be called to retrieve the directories. */
1263 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1265 static int depth = 0;
1267 struct fileinfo *orig;
1272 /* Increase the depth. */
1274 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1276 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1277 depth, opt.reclevel));
1285 con->st &= ~ON_YOUR_OWN;
1286 if (!(con->st & DONE_CWD))
1289 con->cmd &= ~DO_CWD;
1290 con->cmd |= (DO_RETR | LEAVE_PENDING);
1292 if (!rbuf_initialized_p (&con->rbuf))
1293 con->cmd |= DO_LOGIN;
1295 con->cmd &= ~DO_LOGIN;
1297 err = RETROK; /* in case it's not used */
1301 char *old_target, *ofile;
1303 if (downloaded_exceeds_quota ())
1308 old_target = con->target;
1310 ofile = xstrdup (u->file);
1311 url_set_file (u, f->name);
1313 con->target = url_filename (u);
1317 if (opt.timestamping && f->type == FT_PLAINFILE)
1320 /* If conversion of HTML files retrieved via FTP is ever implemented,
1321 we'll need to stat() <file>.orig here when -K has been specified.
1322 I'm not implementing it now since files on an FTP server are much
1323 more likely than files on an HTTP server to legitimately have a
1325 if (!stat (con->target, &st))
1329 /* Else, get it from the file. */
1330 local_size = st.st_size;
1332 /* Compare file sizes only for servers that tell us correct
1333 values. Assumme sizes being equal for servers that lie
1335 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1336 eq_size = cor_val ? (local_size == f->size) : 1 ;
1337 if (f->tstamp <= tml && eq_size)
1339 /* Remote file is older, file sizes can be compared and
1341 logprintf (LOG_VERBOSE, _("\
1342 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1347 /* Remote file is newer or sizes cannot be matched */
1348 logprintf (LOG_VERBOSE, _("\
1349 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1354 /* Sizes do not match */
1355 logprintf (LOG_VERBOSE, _("\
1356 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1359 } /* opt.timestamping && f->type == FT_PLAINFILE */
1363 /* If opt.retr_symlinks is defined, we treat symlinks as
1364 if they were normal files. There is currently no way
1365 to distinguish whether they might be directories, and
1367 if (!opt.retr_symlinks)
1371 logputs (LOG_NOTQUIET,
1372 _("Invalid name of the symlink, skipping.\n"));
1376 /* Check whether we already have the correct
1378 int rc = lstat (con->target, &st);
1381 size_t len = strlen (f->linkto) + 1;
1382 if (S_ISLNK (st.st_mode))
1384 char *link_target = (char *)alloca (len);
1385 size_t n = readlink (con->target, link_target, len);
1387 && (memcmp (link_target, f->linkto, n) == 0))
1389 logprintf (LOG_VERBOSE, _("\
1390 Already have correct symlink %s -> %s\n\n"),
1391 con->target, f->linkto);
1397 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1398 con->target, f->linkto);
1399 /* Unlink before creating symlink! */
1400 unlink (con->target);
1401 if (symlink (f->linkto, con->target) == -1)
1402 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1404 logputs (LOG_VERBOSE, "\n");
1405 } /* have f->linkto */
1406 #else /* not HAVE_SYMLINK */
1407 logprintf (LOG_NOTQUIET,
1408 _("Symlinks not supported, skipping symlink `%s'.\n"),
1410 #endif /* not HAVE_SYMLINK */
1412 else /* opt.retr_symlinks */
1415 err = ftp_loop_internal (u, f, con);
1416 } /* opt.retr_symlinks */
1420 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1424 /* Call the retrieve loop. */
1426 err = ftp_loop_internal (u, f, con);
1429 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1434 /* Set the time-stamp information to the local file. Symlinks
1435 are not to be stamped because it sets the stamp on the
1437 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1440 && file_exists_p (con->target))
1442 /* #### This code repeats in http.c and ftp.c. Move it to a
1444 const char *fl = NULL;
1445 if (opt.output_document)
1447 if (opt.od_known_regular)
1448 fl = opt.output_document;
1453 touch (fl, f->tstamp);
1455 else if (f->tstamp == -1)
1456 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1458 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1459 chmod (con->target, f->perms);
1461 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1463 xfree (con->target);
1464 con->target = old_target;
1466 url_set_file (u, ofile);
1469 /* Break on fatals. */
1470 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1472 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1476 /* We do not want to call ftp_retrieve_dirs here */
1477 if (opt.recursive &&
1478 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1479 err = ftp_retrieve_dirs (u, orig, con);
1480 else if (opt.recursive)
1481 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1482 depth, opt.reclevel));
1487 /* Retrieve the directories given in a file list. This function works
1488 by simply going through the linked list and calling
1489 ftp_retrieve_glob on each directory entry. The function knows
1490 about excluded directories. */
1492 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1494 char *container = NULL;
1495 int container_size = 0;
1497 for (; f; f = f->next)
1500 char *odir, *newdir;
1502 if (downloaded_exceeds_quota ())
1504 if (f->type != FT_DIRECTORY)
1507 /* Allocate u->dir off stack, but reallocate only if a larger
1508 string is needed. It's a pity there's no "realloca" for an
1509 item on the bottom of the stack. */
1510 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1511 if (size > container_size)
1512 container = (char *)alloca (size);
1517 || (*odir == '/' && *(odir + 1) == '\0'))
1518 /* If ODIR is empty or just "/", simply append f->name to
1519 ODIR. (In the former case, to preserve u->dir being
1520 relative; in the latter case, to avoid double slash.) */
1521 sprintf (newdir, "%s%s", odir, f->name);
1523 /* Else, use a separator. */
1524 sprintf (newdir, "%s/%s", odir, f->name);
1526 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1527 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1528 odir, f->name, newdir));
1529 if (!accdir (newdir, ALLABS))
1531 logprintf (LOG_VERBOSE, _("\
1532 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1536 con->st &= ~DONE_CWD;
1538 odir = xstrdup (u->dir); /* because url_set_dir will free
1540 url_set_dir (u, newdir);
1541 ftp_retrieve_glob (u, con, GETALL);
1542 url_set_dir (u, odir);
1545 /* Set the time-stamp? */
1548 if (opt.quota && opt.downloaded > opt.quota)
1555 /* A near-top-level function to retrieve the files in a directory.
1556 The function calls ftp_get_listing, to get a linked list of files.
1557 Then it weeds out the file names that do not match the pattern.
1558 ftp_retrieve_list is called with this updated list as an argument.
1560 If the argument ACTION is GETONE, just download the file (but first
1561 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1562 use globbing; if it's GETALL, download the whole directory. */
1564 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1566 struct fileinfo *orig, *start;
1569 con->cmd |= LEAVE_PENDING;
1571 res = ftp_get_listing (u, con, &orig);
1575 /* First: weed out that do not conform the global rules given in
1576 opt.accepts and opt.rejects. */
1577 if (opt.accepts || opt.rejects)
1579 struct fileinfo *f = orig;
1583 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1585 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1586 f = delelement (f, &start);
1592 /* Now weed out the files that do not match our globbing pattern.
1593 If we are dealing with a globbing pattern, that is. */
1594 if (*u->file && (action == GLOBALL || action == GETONE))
1597 struct fileinfo *f = start;
1601 matchres = fnmatch (u->file, f->name, 0);
1604 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1608 if (matchres == FNM_NOMATCH)
1609 f = delelement (f, &start); /* delete the element from the list */
1611 f = f->next; /* leave the element in the list */
1615 freefileinfo (start);
1616 return RETRBADPATTERN;
1622 /* Just get everything. */
1623 ftp_retrieve_list (u, start, con);
1627 if (action == GLOBALL)
1630 /* #### This message SUCKS. We should see what was the
1631 reason that nothing was retrieved. */
1632 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1634 else /* GETONE or GETALL */
1636 /* Let's try retrieving it anyway. */
1637 con->st |= ON_YOUR_OWN;
1638 res = ftp_loop_internal (u, NULL, con);
1642 freefileinfo (start);
1643 if (downloaded_exceeds_quota ())
1646 /* #### Should we return `res' here? */
1650 /* The wrapper that calls an appropriate routine according to contents
1651 of URL. Inherently, its capabilities are limited on what can be
1652 encoded into a URL. */
1654 ftp_loop (struct url *u, int *dt)
1656 ccon con; /* FTP connection */
1661 memset (&con, 0, sizeof (con));
1663 rbuf_uninitialize (&con.rbuf);
1664 con.st = ON_YOUR_OWN;
1667 res = RETROK; /* in case it's not used */
1669 /* If the file name is empty, the user probably wants a directory
1670 index. We'll provide one, properly HTML-ized. Unless
1671 opt.htmlify is 0, of course. :-) */
1672 if (!*u->file && !opt.recursive)
1675 res = ftp_get_listing (u, &con, &f);
1681 char *filename = (opt.output_document
1682 ? xstrdup (opt.output_document)
1683 : (con.target ? xstrdup (con.target)
1684 : url_filename (u)));
1685 res = ftp_index (filename, u, f);
1686 if (res == FTPOK && opt.verbose)
1688 if (!opt.output_document)
1692 if (stat (filename, &st) == 0)
1696 logprintf (LOG_NOTQUIET,
1697 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1701 logprintf (LOG_NOTQUIET,
1702 _("Wrote HTML-ized index to `%s'.\n"),
1712 int wild = has_wildcards_p (u->file);
1713 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1715 /* ftp_retrieve_glob is a catch-all function that gets called
1716 if we need globbing, time-stamping or recursion. Its
1717 third argument is just what we really need. */
1718 ftp_retrieve_glob (u, &con,
1719 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1722 res = ftp_loop_internal (u, NULL, &con);
1728 /* If a connection was left, quench it. */
1729 if (rbuf_initialized_p (&con.rbuf))
1730 CLOSE (RBUF_FD (&con.rbuf));
1731 FREE_MAYBE (con.id);
1733 FREE_MAYBE (con.target);
1738 /* Delete an element from the fileinfo linked list. Returns the
1739 address of the next element, or NULL if the list is exhausted. It
1740 can modify the start of the list. */
1741 static struct fileinfo *
1742 delelement (struct fileinfo *f, struct fileinfo **start)
1744 struct fileinfo *prev = f->prev;
1745 struct fileinfo *next = f->next;
1748 FREE_MAYBE (f->linkto);
1760 /* Free the fileinfo linked list of files. */
1762 freefileinfo (struct fileinfo *f)
1766 struct fileinfo *next = f->next;