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 struct wget_timer *timer;
131 unsigned char pasv_addr[6];
133 int passive_mode_open = 0;
134 long expected_bytes = 0L;
136 assert (con != NULL);
137 assert (con->target != NULL);
139 /* Debug-check of the sanity of the request by making sure that LIST
140 and RETR are never both requested (since we can handle only one
142 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
143 /* Make sure that at least *something* is requested. */
144 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
148 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
149 user = user ? user : opt.ftp_acc;
150 passwd = passwd ? passwd : opt.ftp_pass;
151 assert (user && passwd);
156 if (!(cmd & DO_LOGIN))
157 csock = RBUF_FD (&con->rbuf);
158 else /* cmd & DO_LOGIN */
161 struct address_list *al;
163 /* Login to the server: */
165 /* First: Establish the control connection. */
167 al = lookup_host (u->host, 0);
170 set_connection_host_name (u->host);
171 csock = connect_to_many (al, u->port, 0);
172 set_connection_host_name (NULL);
173 address_list_release (al);
176 return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
178 if (cmd & LEAVE_PENDING)
179 rbuf_initialize (&con->rbuf, csock);
181 rbuf_uninitialize (&con->rbuf);
183 /* Since this is a new connection, we may safely discard
184 anything left in the buffer. */
185 rbuf_discard (&con->rbuf);
187 /* Second: Login with proper USER/PASS sequence. */
188 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
189 if (opt.server_response)
190 logputs (LOG_ALWAYS, "\n");
191 err = ftp_login (&con->rbuf, user, passwd);
192 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
196 logputs (LOG_VERBOSE, "\n");
197 logputs (LOG_NOTQUIET, _("\
198 Error in server response, closing control connection.\n"));
200 rbuf_uninitialize (&con->rbuf);
204 logputs (LOG_VERBOSE, "\n");
205 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
207 rbuf_uninitialize (&con->rbuf);
211 logputs (LOG_VERBOSE, "\n");
212 logputs (LOG_NOTQUIET,
213 _("Write failed, closing control connection.\n"));
215 rbuf_uninitialize (&con->rbuf);
219 logputs (LOG_VERBOSE, "\n");
220 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
222 rbuf_uninitialize (&con->rbuf);
223 return FTPLOGREFUSED;
226 logputs (LOG_VERBOSE, "\n");
227 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
229 rbuf_uninitialize (&con->rbuf);
233 if (!opt.server_response)
234 logputs (LOG_VERBOSE, _("Logged in!\n"));
241 /* Third: Get the system type */
242 if (!opt.server_response)
243 logprintf (LOG_VERBOSE, "==> SYST ... ");
244 err = ftp_syst (&con->rbuf, &con->rs);
249 logputs (LOG_VERBOSE, "\n");
250 logputs (LOG_NOTQUIET, _("\
251 Error in server response, closing control connection.\n"));
253 rbuf_uninitialize (&con->rbuf);
257 logputs (LOG_VERBOSE, "\n");
258 logputs (LOG_NOTQUIET,
259 _("Server error, can't determine system type.\n"));
262 /* Everything is OK. */
268 if (!opt.server_response)
269 logputs (LOG_VERBOSE, _("done. "));
271 /* Fourth: Find the initial ftp directory */
273 if (!opt.server_response)
274 logprintf (LOG_VERBOSE, "==> PWD ... ");
275 err = ftp_pwd(&con->rbuf, &con->id);
281 logputs (LOG_VERBOSE, "\n");
282 logputs (LOG_NOTQUIET, _("\
283 Error in server response, closing control connection.\n"));
285 rbuf_uninitialize (&con->rbuf);
289 /* Everything is OK. */
295 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
296 Convert it to "/INITIAL/FOLDER" */
297 if (con->rs == ST_VMS)
299 char *path = strchr (con->id, '[');
300 char *pathend = path ? strchr (path + 1, ']') : NULL;
301 if (!path || !pathend)
302 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
305 char *idir = con->id;
306 DEBUGP (("Preprocessing the initial VMS directory\n"));
307 DEBUGP ((" old = '%s'\n", con->id));
308 /* We do the conversion in-place by copying the stuff
309 between [ and ] to the beginning, and changing dots
310 to slashes at the same time. */
312 for (++path; path < pathend; path++, idir++)
313 *idir = *path == '.' ? '/' : *path;
315 DEBUGP ((" new = '%s'\n\n", con->id));
318 if (!opt.server_response)
319 logputs (LOG_VERBOSE, _("done.\n"));
321 /* Fifth: Set the FTP type. */
322 type_char = ftp_process_type (u->params);
323 if (!opt.server_response)
324 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
325 err = ftp_type (&con->rbuf, type_char);
326 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
330 logputs (LOG_VERBOSE, "\n");
331 logputs (LOG_NOTQUIET, _("\
332 Error in server response, closing control connection.\n"));
334 rbuf_uninitialize (&con->rbuf);
338 logputs (LOG_VERBOSE, "\n");
339 logputs (LOG_NOTQUIET,
340 _("Write failed, closing control connection.\n"));
342 rbuf_uninitialize (&con->rbuf);
346 logputs (LOG_VERBOSE, "\n");
347 logprintf (LOG_NOTQUIET,
348 _("Unknown type `%c', closing control connection.\n"),
351 rbuf_uninitialize (&con->rbuf);
354 /* Everything is OK. */
360 if (!opt.server_response)
361 logputs (LOG_VERBOSE, _("done. "));
367 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
370 char *target = u->dir;
372 DEBUGP (("changing working directory\n"));
374 /* Change working directory. To change to a non-absolute
375 Unix directory, we need to prepend initial directory
376 (con->id) to it. Absolute directories "just work". */
380 int idlen = strlen (con->id);
381 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
382 /* idlen == 1 means con->id = "/" */
383 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
385 DEBUGP (("Prepended initial PWD to relative path:\n"));
386 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
390 /* If the FTP host runs VMS, we will have to convert the absolute
391 directory path in UNIX notation to absolute directory path in
392 VMS notation as VMS FTP servers do not like UNIX notation of
393 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
395 if (con->rs == ST_VMS)
398 char *ntarget = (char *)alloca (strlen (target) + 2);
399 /* We use a converted initial dir, so directories in
400 TARGET will be separated with slashes, something like
401 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
402 "[INITIAL.FOLDER.DIR.SUBDIR]". */
403 strcpy (ntarget, target);
404 assert (*ntarget == '/');
406 for (tmpp = ntarget + 1; *tmpp; tmpp++)
411 DEBUGP (("Changed file name to VMS syntax:\n"));
412 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
416 if (!opt.server_response)
417 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
418 err = ftp_cwd (&con->rbuf, target);
419 /* FTPRERR, WRITEFAILED, FTPNSFOD */
423 logputs (LOG_VERBOSE, "\n");
424 logputs (LOG_NOTQUIET, _("\
425 Error in server response, closing control connection.\n"));
427 rbuf_uninitialize (&con->rbuf);
431 logputs (LOG_VERBOSE, "\n");
432 logputs (LOG_NOTQUIET,
433 _("Write failed, closing control connection.\n"));
435 rbuf_uninitialize (&con->rbuf);
439 logputs (LOG_VERBOSE, "\n");
440 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
443 rbuf_uninitialize (&con->rbuf);
453 if (!opt.server_response)
454 logputs (LOG_VERBOSE, _("done.\n"));
457 else /* do not CWD */
458 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
460 if ((cmd & DO_RETR) && restval && *len == 0)
464 if (!opt.server_response)
465 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
468 err = ftp_size(&con->rbuf, u->file, len);
474 logputs (LOG_VERBOSE, "\n");
475 logputs (LOG_NOTQUIET, _("\
476 Error in server response, closing control connection.\n"));
478 rbuf_uninitialize (&con->rbuf);
482 /* Everything is OK. */
488 if (!opt.server_response)
489 logputs (LOG_VERBOSE, _("done.\n"));
492 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
493 if (cmd & (DO_LIST | DO_RETR))
495 if (opt.ftp_pasv > 0)
498 unsigned short tport;
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 struct address_list *al;
541 sprintf (thost, "%d.%d.%d.%d",
542 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
543 tport = (pasv_addr[4] << 8) + pasv_addr[5];
545 al = lookup_host (thost, 0);
549 rbuf_uninitialize (&con->rbuf);
552 dtsock = connect_to_many (al, tport, 0);
553 address_list_release (al);
557 int save_errno = errno;
559 rbuf_uninitialize (&con->rbuf);
560 return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
563 passive_mode_open= 1; /* Flag to avoid accept port */
564 if (!opt.server_response)
565 logputs (LOG_VERBOSE, _("done. "));
569 if (!passive_mode_open) /* Try to use a port command if PASV failed */
571 if (!opt.server_response)
572 logputs (LOG_VERBOSE, "==> PORT ... ");
573 err = ftp_port (&con->rbuf);
574 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
575 LISTENERR), HOSTERR, FTPPORTERR */
579 logputs (LOG_VERBOSE, "\n");
580 logputs (LOG_NOTQUIET, _("\
581 Error in server response, closing control connection.\n"));
584 rbuf_uninitialize (&con->rbuf);
588 logputs (LOG_VERBOSE, "\n");
589 logputs (LOG_NOTQUIET,
590 _("Write failed, closing control connection.\n"));
593 rbuf_uninitialize (&con->rbuf);
597 logputs (LOG_VERBOSE, "\n");
598 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
601 rbuf_uninitialize (&con->rbuf);
604 case CONPORTERR: case BINDERR: case LISTENERR:
605 /* What now? These problems are local... */
606 logputs (LOG_VERBOSE, "\n");
607 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
613 logputs (LOG_VERBOSE, "\n");
614 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
618 rbuf_uninitialize (&con->rbuf);
622 logputs (LOG_VERBOSE, "\n");
623 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
626 rbuf_uninitialize (&con->rbuf);
636 if (!opt.server_response)
637 logputs (LOG_VERBOSE, _("done. "));
639 } /* cmd & (DO_LIST | DO_RETR) */
641 /* Restart if needed. */
642 if (restval && (cmd & DO_RETR))
644 if (!opt.server_response)
645 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
646 err = ftp_rest (&con->rbuf, restval);
648 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
652 logputs (LOG_VERBOSE, "\n");
653 logputs (LOG_NOTQUIET, _("\
654 Error in server response, closing control connection.\n"));
657 rbuf_uninitialize (&con->rbuf);
661 logputs (LOG_VERBOSE, "\n");
662 logputs (LOG_NOTQUIET,
663 _("Write failed, closing control connection.\n"));
666 rbuf_uninitialize (&con->rbuf);
670 /* If `-c' is specified and the file already existed when
671 Wget was started, it would be a bad idea for us to start
672 downloading it from scratch, effectively truncating it. */
673 if (opt.always_rest && (cmd & NO_TRUNCATE))
675 logprintf (LOG_NOTQUIET,
676 _("\nREST failed; will not truncate `%s'.\n"),
680 rbuf_uninitialize (&con->rbuf);
681 return CONTNOTSUPPORTED;
683 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
693 if (err != FTPRESTFAIL && !opt.server_response)
694 logputs (LOG_VERBOSE, _("done. "));
695 } /* restval && cmd & DO_RETR */
701 if (!opt.server_response)
704 logputs (LOG_VERBOSE, "\n");
705 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
708 err = ftp_retr (&con->rbuf, u->file);
709 /* FTPRERR, WRITEFAILED, FTPNSFOD */
713 logputs (LOG_VERBOSE, "\n");
714 logputs (LOG_NOTQUIET, _("\
715 Error in server response, closing control connection.\n"));
718 rbuf_uninitialize (&con->rbuf);
722 logputs (LOG_VERBOSE, "\n");
723 logputs (LOG_NOTQUIET,
724 _("Write failed, closing control connection.\n"));
727 rbuf_uninitialize (&con->rbuf);
731 logputs (LOG_VERBOSE, "\n");
732 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
744 if (!opt.server_response)
745 logputs (LOG_VERBOSE, _("done.\n"));
746 expected_bytes = ftp_expected_bytes (ftp_last_respline);
751 if (!opt.server_response)
752 logputs (LOG_VERBOSE, "==> LIST ... ");
753 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
754 without arguments is better than `LIST .'; confirmed by
756 err = ftp_list (&con->rbuf, NULL);
757 /* FTPRERR, WRITEFAILED */
761 logputs (LOG_VERBOSE, "\n");
762 logputs (LOG_NOTQUIET, _("\
763 Error in server response, closing control connection.\n"));
766 rbuf_uninitialize (&con->rbuf);
770 logputs (LOG_VERBOSE, "\n");
771 logputs (LOG_NOTQUIET,
772 _("Write failed, closing control connection.\n"));
775 rbuf_uninitialize (&con->rbuf);
779 logputs (LOG_VERBOSE, "\n");
780 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
792 if (!opt.server_response)
793 logputs (LOG_VERBOSE, _("done.\n"));
794 expected_bytes = ftp_expected_bytes (ftp_last_respline);
795 } /* cmd & DO_LIST */
797 /* Some FTP servers return the total length of file after REST
798 command, others just return the remaining size. */
799 if (*len && restval && expected_bytes
800 && (expected_bytes == *len - restval))
802 DEBUGP (("Lying FTP server found, adjusting.\n"));
803 expected_bytes = *len;
806 /* If no transmission was required, then everything is OK. */
807 if (!(cmd & (DO_LIST | DO_RETR)))
810 if (!passive_mode_open) /* we are not using pasive mode so we need
813 /* Open the data transmission socket by calling acceptport(). */
814 err = acceptport (&dtsock);
815 /* Possible errors: ACCEPTERR. */
816 if (err == ACCEPTERR)
818 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
823 /* Open the file -- if opt.dfp is set, use it instead. */
824 if (!opt.dfp || con->cmd & DO_LIST)
826 mkalldirs (con->target);
828 rotate_backups (con->target);
829 /* #### Is this correct? */
830 chmod (con->target, 0600);
832 fp = fopen (con->target, restval ? "ab" : "wb");
835 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
837 rbuf_uninitialize (&con->rbuf);
844 extern int global_download_count;
847 /* Rewind the output document if the download starts over and if
848 this is the first download. See gethttp() for a longer
850 if (!restval && global_download_count == 0)
852 /* This will silently fail for streams that don't correspond
853 to regular files, but that's OK. */
855 /* ftruncate is needed because opt.dfp is opened in append
856 mode if opt.always_rest is set. */
857 ftruncate (fileno (fp), 0);
864 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
866 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
867 logputs (LOG_VERBOSE, "\n");
868 expected_bytes = *len; /* for get_contents/show_progress */
870 else if (expected_bytes)
872 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
874 logprintf (LOG_VERBOSE, _(" [%s to go]"),
875 legible (expected_bytes - restval));
876 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
878 timer = wtimer_new ();
879 /* Get the contents of the document. */
880 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
881 con->dltime = wtimer_elapsed (timer);
882 wtimer_delete (timer);
883 tms = time_str (NULL);
884 tmrate = retr_rate (*len - restval, con->dltime, 0);
885 /* Close data connection socket. */
887 /* Close the local file. */
889 /* Close or flush the file. We have to be careful to check for
890 error here. Checking the result of fwrite() is not enough --
891 errors could go unnoticed! */
893 if (!opt.dfp || con->cmd & DO_LIST)
894 flush_res = fclose (fp);
896 flush_res = fflush (fp);
897 if (flush_res == EOF)
900 /* If get_contents couldn't write to fp, bail out. */
903 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
904 con->target, strerror (errno));
906 rbuf_uninitialize (&con->rbuf);
911 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
912 tms, tmrate, strerror (errno));
913 if (opt.server_response)
914 logputs (LOG_ALWAYS, "\n");
917 /* Get the server to tell us if everything is retrieved. */
918 err = ftp_response (&con->rbuf, &respline);
919 /* ...and empty the buffer. */
920 rbuf_discard (&con->rbuf);
924 /* The control connection is decidedly closed. Print the time
925 only if it hasn't already been printed. */
927 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
928 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
929 /* If there is an error on the control connection, close it, but
930 return FTPRETRINT, since there is a possibility that the
931 whole file was retrieved nevertheless (but that is for
932 ftp_loop_internal to decide). */
934 rbuf_uninitialize (&con->rbuf);
937 /* If retrieval failed for any reason, return FTPRETRINT, but do not
938 close socket, since the control connection is still alive. If
939 there is something wrong with the control connection, it will
940 become apparent later. */
941 if (*respline != '2')
945 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
946 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
953 /* What now? The data connection was erroneous, whereas the
954 response says everything is OK. We shall play it safe. */
958 if (!(cmd & LEAVE_PENDING))
960 /* I should probably send 'QUIT' and check for a reply, but this
961 is faster. #### Is it OK, though? */
963 rbuf_uninitialize (&con->rbuf);
965 /* If it was a listing, and opt.server_response is true,
967 if (opt.server_response && (con->cmd & DO_LIST))
969 mkalldirs (con->target);
970 fp = fopen (con->target, "r");
972 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
976 /* The lines are being read with read_whole_line because of
977 no-buffering on opt.lfile. */
978 while ((line = read_whole_line (fp)))
980 logprintf (LOG_ALWAYS, "%s\n", line);
985 } /* con->cmd & DO_LIST && server_response */
990 /* A one-file FTP loop. This is the part where FTP retrieval is
991 retried, and retried, and retried, and...
993 This loop either gets commands from con, or (if ON_YOUR_OWN is
994 set), makes them up to retrieve the file given by the URL. */
996 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1000 char *tms, *tmrate, *locf;
1005 con->target = url_filename (u);
1007 if (opt.noclobber && file_exists_p (con->target))
1009 logprintf (LOG_VERBOSE,
1010 _("File `%s' already there, not retrieving.\n"), con->target);
1011 /* If the file is there, we suppose it's retrieved OK. */
1015 /* Remove it if it's a link. */
1016 remove_link (con->target);
1017 if (!opt.output_document)
1020 locf = opt.output_document;
1024 if (con->st & ON_YOUR_OWN)
1025 con->st = ON_YOUR_OWN;
1027 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1032 /* Increment the pass counter. */
1034 sleep_between_retrievals (count);
1035 if (con->st & ON_YOUR_OWN)
1038 con->cmd |= (DO_RETR | LEAVE_PENDING);
1039 if (rbuf_initialized_p (&con->rbuf))
1040 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1042 con->cmd |= (DO_LOGIN | DO_CWD);
1044 else /* not on your own */
1046 if (rbuf_initialized_p (&con->rbuf))
1047 con->cmd &= ~DO_LOGIN;
1049 con->cmd |= DO_LOGIN;
1050 if (con->st & DONE_CWD)
1051 con->cmd &= ~DO_CWD;
1056 /* Assume no restarting. */
1058 if ((count > 1 || opt.always_rest)
1059 && !(con->cmd & DO_LIST)
1060 && file_exists_p (locf))
1061 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1062 restval = st.st_size;
1064 /* In `-c' is used, check whether the file we're writing to
1065 exists and is of non-zero length. If so, we'll refuse to
1066 truncate it if the server doesn't support continued
1068 if (opt.always_rest && restval > 0)
1069 con->cmd |= NO_TRUNCATE;
1071 /* Get the current time string. */
1072 tms = time_str (NULL);
1073 /* Print fetch message, if opt.verbose. */
1076 char *hurl = url_string (u, 1);
1080 sprintf (tmp, _("(try:%2d)"), count);
1081 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1082 tms, hurl, tmp, locf);
1084 ws_changetitle (hurl, 1);
1088 /* Send getftp the proper length, if fileinfo was provided. */
1093 err = getftp (u, &len, restval, con);
1095 if (!rbuf_initialized_p (&con->rbuf))
1096 con->st &= ~DONE_CWD;
1098 con->st |= DONE_CWD;
1102 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1103 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1104 /* Fatal errors, give up. */
1107 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1108 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1109 case BINDERR: case LISTENERR: case ACCEPTERR:
1110 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1111 printwhat (count, opt.ntry);
1112 /* non-fatal errors */
1116 /* If the control connection was closed, the retrieval
1117 will be considered OK if f->size == len. */
1118 if (!f || len != f->size)
1120 printwhat (count, opt.ntry);
1132 tms = time_str (NULL);
1133 tmrate = retr_rate (len - restval, con->dltime, 0);
1135 /* If we get out of the switch above without continue'ing, we've
1136 successfully downloaded a file. Remember this fact. */
1137 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1139 if (con->st & ON_YOUR_OWN)
1141 CLOSE (RBUF_FD (&con->rbuf));
1142 rbuf_uninitialize (&con->rbuf);
1144 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1145 tms, tmrate, locf, len);
1146 if (!opt.verbose && !opt.quiet)
1148 /* Need to hide the password from the URL. The `if' is here
1149 so that we don't do the needless allocation every
1151 char *hurl = url_string (u, 1);
1152 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1153 tms, hurl, len, locf, count);
1157 if ((con->cmd & DO_LIST))
1158 /* This is a directory listing file. */
1160 if (!opt.remove_listing)
1161 /* --dont-remove-listing was specified, so do count this towards the
1162 number of bytes and files downloaded. */
1164 downloaded_increase (len);
1168 /* Deletion of listing files is not controlled by --delete-after, but
1169 by the more specific option --dont-remove-listing, and the code
1170 to do this deletion is in another function. */
1173 /* This is not a directory listing file. */
1175 /* Unlike directory listing files, don't pretend normal files weren't
1176 downloaded if they're going to be deleted. People seeding proxies,
1177 for instance, may want to know how many bytes and files they've
1178 downloaded through it. */
1179 downloaded_increase (len);
1182 if (opt.delete_after)
1184 DEBUGP (("Removing file due to --delete-after in"
1185 " ftp_loop_internal():\n"));
1186 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1188 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1192 /* Restore the original leave-pendingness. */
1194 con->cmd |= LEAVE_PENDING;
1196 con->cmd &= ~LEAVE_PENDING;
1198 } while (!opt.ntry || (count < opt.ntry));
1200 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1202 CLOSE (RBUF_FD (&con->rbuf));
1203 rbuf_uninitialize (&con->rbuf);
1208 /* Return the directory listing in a reusable format. The directory
1209 is specifed in u->dir. */
1211 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1214 char *uf; /* url file name */
1215 char *lf; /* list file name */
1216 char *old_target = con->target;
1218 con->st &= ~ON_YOUR_OWN;
1219 con->cmd |= (DO_LIST | LEAVE_PENDING);
1220 con->cmd &= ~DO_RETR;
1222 /* Find the listing file name. We do it by taking the file name of
1223 the URL and replacing the last component with the listing file
1225 uf = url_filename (u);
1226 lf = file_merge (uf, LIST_FILENAME);
1228 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1231 err = ftp_loop_internal (u, NULL, con);
1232 con->target = old_target;
1235 *f = ftp_parse_ls (lf, con->rs);
1238 if (opt.remove_listing)
1241 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1243 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1246 con->cmd &= ~DO_LIST;
1250 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1252 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1253 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1254 struct fileinfo **));
1255 static void freefileinfo PARAMS ((struct fileinfo *f));
1257 /* Retrieve a list of files given in struct fileinfo linked list. If
1258 a file is a symbolic link, do not retrieve it, but rather try to
1259 set up a similar link on the local disk, if the symlinks are
1262 If opt.recursive is set, after all files have been retrieved,
1263 ftp_retrieve_dirs will be called to retrieve the directories. */
1265 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1267 static int depth = 0;
1269 struct fileinfo *orig;
1274 /* Increase the depth. */
1276 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1278 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1279 depth, opt.reclevel));
1287 con->st &= ~ON_YOUR_OWN;
1288 if (!(con->st & DONE_CWD))
1291 con->cmd &= ~DO_CWD;
1292 con->cmd |= (DO_RETR | LEAVE_PENDING);
1294 if (!rbuf_initialized_p (&con->rbuf))
1295 con->cmd |= DO_LOGIN;
1297 con->cmd &= ~DO_LOGIN;
1299 err = RETROK; /* in case it's not used */
1303 char *old_target, *ofile;
1305 if (downloaded_exceeds_quota ())
1310 old_target = con->target;
1312 ofile = xstrdup (u->file);
1313 url_set_file (u, f->name);
1315 con->target = url_filename (u);
1319 if (opt.timestamping && f->type == FT_PLAINFILE)
1322 /* If conversion of HTML files retrieved via FTP is ever implemented,
1323 we'll need to stat() <file>.orig here when -K has been specified.
1324 I'm not implementing it now since files on an FTP server are much
1325 more likely than files on an HTTP server to legitimately have a
1327 if (!stat (con->target, &st))
1331 /* Else, get it from the file. */
1332 local_size = st.st_size;
1334 /* Compare file sizes only for servers that tell us correct
1335 values. Assumme sizes being equal for servers that lie
1337 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1338 eq_size = cor_val ? (local_size == f->size) : 1 ;
1339 if (f->tstamp <= tml && eq_size)
1341 /* Remote file is older, file sizes can be compared and
1343 logprintf (LOG_VERBOSE, _("\
1344 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1349 /* Remote file is newer or sizes cannot be matched */
1350 logprintf (LOG_VERBOSE, _("\
1351 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1356 /* Sizes do not match */
1357 logprintf (LOG_VERBOSE, _("\
1358 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1361 } /* opt.timestamping && f->type == FT_PLAINFILE */
1365 /* If opt.retr_symlinks is defined, we treat symlinks as
1366 if they were normal files. There is currently no way
1367 to distinguish whether they might be directories, and
1369 if (!opt.retr_symlinks)
1373 logputs (LOG_NOTQUIET,
1374 _("Invalid name of the symlink, skipping.\n"));
1378 /* Check whether we already have the correct
1380 int rc = lstat (con->target, &st);
1383 size_t len = strlen (f->linkto) + 1;
1384 if (S_ISLNK (st.st_mode))
1386 char *link_target = (char *)alloca (len);
1387 size_t n = readlink (con->target, link_target, len);
1389 && (memcmp (link_target, f->linkto, n) == 0))
1391 logprintf (LOG_VERBOSE, _("\
1392 Already have correct symlink %s -> %s\n\n"),
1393 con->target, f->linkto);
1399 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1400 con->target, f->linkto);
1401 /* Unlink before creating symlink! */
1402 unlink (con->target);
1403 if (symlink (f->linkto, con->target) == -1)
1404 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1406 logputs (LOG_VERBOSE, "\n");
1407 } /* have f->linkto */
1408 #else /* not HAVE_SYMLINK */
1409 logprintf (LOG_NOTQUIET,
1410 _("Symlinks not supported, skipping symlink `%s'.\n"),
1412 #endif /* not HAVE_SYMLINK */
1414 else /* opt.retr_symlinks */
1417 err = ftp_loop_internal (u, f, con);
1418 } /* opt.retr_symlinks */
1422 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1426 /* Call the retrieve loop. */
1428 err = ftp_loop_internal (u, f, con);
1431 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1436 /* Set the time-stamp information to the local file. Symlinks
1437 are not to be stamped because it sets the stamp on the
1439 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1442 && file_exists_p (con->target))
1444 /* #### This code repeats in http.c and ftp.c. Move it to a
1446 const char *fl = NULL;
1447 if (opt.output_document)
1449 if (opt.od_known_regular)
1450 fl = opt.output_document;
1455 touch (fl, f->tstamp);
1457 else if (f->tstamp == -1)
1458 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1460 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1461 chmod (con->target, f->perms);
1463 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1465 xfree (con->target);
1466 con->target = old_target;
1468 url_set_file (u, ofile);
1471 /* Break on fatals. */
1472 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1474 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1478 /* We do not want to call ftp_retrieve_dirs here */
1479 if (opt.recursive &&
1480 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1481 err = ftp_retrieve_dirs (u, orig, con);
1482 else if (opt.recursive)
1483 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1484 depth, opt.reclevel));
1489 /* Retrieve the directories given in a file list. This function works
1490 by simply going through the linked list and calling
1491 ftp_retrieve_glob on each directory entry. The function knows
1492 about excluded directories. */
1494 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1496 char *container = NULL;
1497 int container_size = 0;
1499 for (; f; f = f->next)
1502 char *odir, *newdir;
1504 if (downloaded_exceeds_quota ())
1506 if (f->type != FT_DIRECTORY)
1509 /* Allocate u->dir off stack, but reallocate only if a larger
1510 string is needed. It's a pity there's no "realloca" for an
1511 item on the bottom of the stack. */
1512 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1513 if (size > container_size)
1514 container = (char *)alloca (size);
1519 || (*odir == '/' && *(odir + 1) == '\0'))
1520 /* If ODIR is empty or just "/", simply append f->name to
1521 ODIR. (In the former case, to preserve u->dir being
1522 relative; in the latter case, to avoid double slash.) */
1523 sprintf (newdir, "%s%s", odir, f->name);
1525 /* Else, use a separator. */
1526 sprintf (newdir, "%s/%s", odir, f->name);
1528 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1529 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1530 odir, f->name, newdir));
1531 if (!accdir (newdir, ALLABS))
1533 logprintf (LOG_VERBOSE, _("\
1534 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1538 con->st &= ~DONE_CWD;
1540 odir = xstrdup (u->dir); /* because url_set_dir will free
1542 url_set_dir (u, newdir);
1543 ftp_retrieve_glob (u, con, GETALL);
1544 url_set_dir (u, odir);
1547 /* Set the time-stamp? */
1550 if (opt.quota && opt.downloaded > opt.quota)
1557 /* A near-top-level function to retrieve the files in a directory.
1558 The function calls ftp_get_listing, to get a linked list of files.
1559 Then it weeds out the file names that do not match the pattern.
1560 ftp_retrieve_list is called with this updated list as an argument.
1562 If the argument ACTION is GETONE, just download the file (but first
1563 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1564 use globbing; if it's GETALL, download the whole directory. */
1566 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1568 struct fileinfo *orig, *start;
1571 con->cmd |= LEAVE_PENDING;
1573 res = ftp_get_listing (u, con, &orig);
1577 /* First: weed out that do not conform the global rules given in
1578 opt.accepts and opt.rejects. */
1579 if (opt.accepts || opt.rejects)
1581 struct fileinfo *f = orig;
1585 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1587 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1588 f = delelement (f, &start);
1594 /* Now weed out the files that do not match our globbing pattern.
1595 If we are dealing with a globbing pattern, that is. */
1596 if (*u->file && (action == GLOBALL || action == GETONE))
1599 struct fileinfo *f = start;
1603 matchres = fnmatch (u->file, f->name, 0);
1606 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1610 if (matchres == FNM_NOMATCH)
1611 f = delelement (f, &start); /* delete the element from the list */
1613 f = f->next; /* leave the element in the list */
1617 freefileinfo (start);
1618 return RETRBADPATTERN;
1624 /* Just get everything. */
1625 ftp_retrieve_list (u, start, con);
1629 if (action == GLOBALL)
1632 /* #### This message SUCKS. We should see what was the
1633 reason that nothing was retrieved. */
1634 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1636 else /* GETONE or GETALL */
1638 /* Let's try retrieving it anyway. */
1639 con->st |= ON_YOUR_OWN;
1640 res = ftp_loop_internal (u, NULL, con);
1644 freefileinfo (start);
1645 if (downloaded_exceeds_quota ())
1648 /* #### Should we return `res' here? */
1652 /* The wrapper that calls an appropriate routine according to contents
1653 of URL. Inherently, its capabilities are limited on what can be
1654 encoded into a URL. */
1656 ftp_loop (struct url *u, int *dt)
1658 ccon con; /* FTP connection */
1663 memset (&con, 0, sizeof (con));
1665 rbuf_uninitialize (&con.rbuf);
1666 con.st = ON_YOUR_OWN;
1669 res = RETROK; /* in case it's not used */
1671 /* If the file name is empty, the user probably wants a directory
1672 index. We'll provide one, properly HTML-ized. Unless
1673 opt.htmlify is 0, of course. :-) */
1674 if (!*u->file && !opt.recursive)
1677 res = ftp_get_listing (u, &con, &f);
1683 char *filename = (opt.output_document
1684 ? xstrdup (opt.output_document)
1685 : (con.target ? xstrdup (con.target)
1686 : url_filename (u)));
1687 res = ftp_index (filename, u, f);
1688 if (res == FTPOK && opt.verbose)
1690 if (!opt.output_document)
1694 if (stat (filename, &st) == 0)
1698 logprintf (LOG_NOTQUIET,
1699 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1703 logprintf (LOG_NOTQUIET,
1704 _("Wrote HTML-ized index to `%s'.\n"),
1714 int wild = has_wildcards_p (u->file);
1715 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1717 /* ftp_retrieve_glob is a catch-all function that gets called
1718 if we need globbing, time-stamping or recursion. Its
1719 third argument is just what we really need. */
1720 ftp_retrieve_glob (u, &con,
1721 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1724 res = ftp_loop_internal (u, NULL, &con);
1730 /* If a connection was left, quench it. */
1731 if (rbuf_initialized_p (&con.rbuf))
1732 CLOSE (RBUF_FD (&con.rbuf));
1733 FREE_MAYBE (con.id);
1735 FREE_MAYBE (con.target);
1740 /* Delete an element from the fileinfo linked list. Returns the
1741 address of the next element, or NULL if the list is exhausted. It
1742 can modify the start of the list. */
1743 static struct fileinfo *
1744 delelement (struct fileinfo *f, struct fileinfo **start)
1746 struct fileinfo *prev = f->prev;
1747 struct fileinfo *next = f->next;
1750 FREE_MAYBE (f->linkto);
1762 /* Free the fileinfo linked list of files. */
1764 freefileinfo (struct fileinfo *f)
1768 struct fileinfo *next = f->next;