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>
52 /* File where the "ls -al" listing will be saved. */
53 #define LIST_FILENAME ".listing"
55 extern char ftp_last_respline[];
59 int st; /* connection status */
60 int cmd; /* command code */
61 struct rbuf rbuf; /* control connection buffer */
62 long dltime; /* time of the download */
63 enum stype rs; /* remote system reported by ftp server */
64 char *id; /* initial directory */
65 char *target; /* target file name */
66 struct url *proxy; /* FTWK-style proxy */
70 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
71 the string S, and return the number converted to long, if found, 0
74 ftp_expected_bytes (const char *s)
80 while (*s && *s != '(')
84 for (++s; *s && ISSPACE (*s); s++);
92 res = (*s - '0') + 10 * res;
95 while (*s && ISDIGIT (*s));
98 while (*s && ISSPACE (*s))
102 if (TOLOWER (*s) != 'b')
104 if (strncasecmp (s, "byte", 4))
112 /* Retrieves a file with denoted parameters through opening an FTP
113 connection to the server. It always closes the data connection,
114 and closes the control connection in case of error. */
116 getftp (struct url *u, long *len, long restval, ccon *con)
118 int csock, dtsock, res;
121 char *user, *passwd, *respline;
124 int pasv_mode_open = 0;
125 long expected_bytes = 0L;
127 assert (con != NULL);
128 assert (con->target != NULL);
130 /* Debug-check of the sanity of the request by making sure that LIST
131 and RETR are never both requested (since we can handle only one
133 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
134 /* Make sure that at least *something* is requested. */
135 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
139 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
140 user = user ? user : opt.ftp_acc;
141 passwd = passwd ? passwd : opt.ftp_pass;
142 assert (user && passwd);
147 if (!(cmd & DO_LOGIN))
148 csock = RBUF_FD (&con->rbuf);
149 else /* cmd & DO_LOGIN */
152 struct address_list *al;
154 char *host = con->proxy ? con->proxy->host : u->host;
155 int port = con->proxy ? con->proxy->port : u->port;
156 char *logname = user;
160 /* If proxy is in use, log in as username@target-site. */
161 logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
162 sprintf (logname, "%s@%s", user, u->host);
165 /* Login to the server: */
167 /* First: Establish the control connection. */
169 al = lookup_host (host, 0);
172 set_connection_host_name (host);
173 csock = connect_to_many (al, port, 0);
174 set_connection_host_name (NULL);
175 address_list_release (al);
178 return errno == ECONNREFUSED ? CONREFUSED : CONERROR;
180 if (cmd & LEAVE_PENDING)
181 rbuf_initialize (&con->rbuf, csock);
183 rbuf_uninitialize (&con->rbuf);
185 /* Since this is a new connection, we may safely discard
186 anything left in the buffer. */
187 rbuf_discard (&con->rbuf);
189 /* Second: Login with proper USER/PASS sequence. */
190 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
191 if (opt.server_response)
192 logputs (LOG_ALWAYS, "\n");
193 err = ftp_login (&con->rbuf, logname, passwd);
198 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
202 logputs (LOG_VERBOSE, "\n");
203 logputs (LOG_NOTQUIET, _("\
204 Error in server response, closing control connection.\n"));
206 rbuf_uninitialize (&con->rbuf);
210 logputs (LOG_VERBOSE, "\n");
211 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
213 rbuf_uninitialize (&con->rbuf);
217 logputs (LOG_VERBOSE, "\n");
218 logputs (LOG_NOTQUIET,
219 _("Write failed, closing control connection.\n"));
221 rbuf_uninitialize (&con->rbuf);
225 logputs (LOG_VERBOSE, "\n");
226 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
228 rbuf_uninitialize (&con->rbuf);
229 return FTPLOGREFUSED;
232 logputs (LOG_VERBOSE, "\n");
233 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
235 rbuf_uninitialize (&con->rbuf);
239 if (!opt.server_response)
240 logputs (LOG_VERBOSE, _("Logged in!\n"));
247 /* Third: Get the system type */
248 if (!opt.server_response)
249 logprintf (LOG_VERBOSE, "==> SYST ... ");
250 err = ftp_syst (&con->rbuf, &con->rs);
255 logputs (LOG_VERBOSE, "\n");
256 logputs (LOG_NOTQUIET, _("\
257 Error in server response, closing control connection.\n"));
259 rbuf_uninitialize (&con->rbuf);
263 logputs (LOG_VERBOSE, "\n");
264 logputs (LOG_NOTQUIET,
265 _("Server error, can't determine system type.\n"));
268 /* Everything is OK. */
274 if (!opt.server_response && err != FTPSRVERR)
275 logputs (LOG_VERBOSE, _("done. "));
277 /* Fourth: Find the initial ftp directory */
279 if (!opt.server_response)
280 logprintf (LOG_VERBOSE, "==> PWD ... ");
281 err = ftp_pwd(&con->rbuf, &con->id);
286 logputs (LOG_VERBOSE, "\n");
287 logputs (LOG_NOTQUIET, _("\
288 Error in server response, closing control connection.\n"));
290 rbuf_uninitialize (&con->rbuf);
294 /* PWD unsupported -- assume "/". */
295 FREE_MAYBE (con->id);
296 con->id = xstrdup ("/");
299 /* Everything is OK. */
305 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
306 Convert it to "/INITIAL/FOLDER" */
307 if (con->rs == ST_VMS)
309 char *path = strchr (con->id, '[');
310 char *pathend = path ? strchr (path + 1, ']') : NULL;
311 if (!path || !pathend)
312 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
315 char *idir = con->id;
316 DEBUGP (("Preprocessing the initial VMS directory\n"));
317 DEBUGP ((" old = '%s'\n", con->id));
318 /* We do the conversion in-place by copying the stuff
319 between [ and ] to the beginning, and changing dots
320 to slashes at the same time. */
322 for (++path; path < pathend; path++, idir++)
323 *idir = *path == '.' ? '/' : *path;
325 DEBUGP ((" new = '%s'\n\n", con->id));
328 if (!opt.server_response)
329 logputs (LOG_VERBOSE, _("done.\n"));
331 /* Fifth: Set the FTP type. */
332 type_char = ftp_process_type (u->params);
333 if (!opt.server_response)
334 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
335 err = ftp_type (&con->rbuf, type_char);
336 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
340 logputs (LOG_VERBOSE, "\n");
341 logputs (LOG_NOTQUIET, _("\
342 Error in server response, closing control connection.\n"));
344 rbuf_uninitialize (&con->rbuf);
348 logputs (LOG_VERBOSE, "\n");
349 logputs (LOG_NOTQUIET,
350 _("Write failed, closing control connection.\n"));
352 rbuf_uninitialize (&con->rbuf);
356 logputs (LOG_VERBOSE, "\n");
357 logprintf (LOG_NOTQUIET,
358 _("Unknown type `%c', closing control connection.\n"),
361 rbuf_uninitialize (&con->rbuf);
364 /* Everything is OK. */
370 if (!opt.server_response)
371 logputs (LOG_VERBOSE, _("done. "));
377 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
380 char *target = u->dir;
382 DEBUGP (("changing working directory\n"));
384 /* Change working directory. To change to a non-absolute
385 Unix directory, we need to prepend initial directory
386 (con->id) to it. Absolute directories "just work".
388 A relative directory is one that does not begin with '/'
389 and, on non-Unix OS'es, one that doesn't begin with
393 && !(con->rs != ST_UNIX
394 && ISALPHA (target[0]) && target[1] == ':'))
396 int idlen = strlen (con->id);
399 /* Strip trailing slash(es) from con->id. */
400 while (idlen > 0 && con->id[idlen - 1] == '/')
402 p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
403 memcpy (p, con->id, idlen);
408 DEBUGP (("Prepended initial PWD to relative path:\n"));
409 DEBUGP ((" pwd: '%s'\n old: '%s'\n new: '%s'\n",
410 con->id, target, ntarget));
414 /* If the FTP host runs VMS, we will have to convert the absolute
415 directory path in UNIX notation to absolute directory path in
416 VMS notation as VMS FTP servers do not like UNIX notation of
417 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
419 if (con->rs == ST_VMS)
422 char *ntarget = (char *)alloca (strlen (target) + 2);
423 /* We use a converted initial dir, so directories in
424 TARGET will be separated with slashes, something like
425 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
426 "[INITIAL.FOLDER.DIR.SUBDIR]". */
427 strcpy (ntarget, target);
428 assert (*ntarget == '/');
430 for (tmpp = ntarget + 1; *tmpp; tmpp++)
435 DEBUGP (("Changed file name to VMS syntax:\n"));
436 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
440 if (!opt.server_response)
441 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
442 err = ftp_cwd (&con->rbuf, target);
443 /* FTPRERR, WRITEFAILED, FTPNSFOD */
447 logputs (LOG_VERBOSE, "\n");
448 logputs (LOG_NOTQUIET, _("\
449 Error in server response, closing control connection.\n"));
451 rbuf_uninitialize (&con->rbuf);
455 logputs (LOG_VERBOSE, "\n");
456 logputs (LOG_NOTQUIET,
457 _("Write failed, closing control connection.\n"));
459 rbuf_uninitialize (&con->rbuf);
463 logputs (LOG_VERBOSE, "\n");
464 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
467 rbuf_uninitialize (&con->rbuf);
477 if (!opt.server_response)
478 logputs (LOG_VERBOSE, _("done.\n"));
481 else /* do not CWD */
482 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
484 if ((cmd & DO_RETR) && restval && *len == 0)
488 if (!opt.server_response)
489 logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
492 err = ftp_size(&con->rbuf, u->file, len);
498 logputs (LOG_VERBOSE, "\n");
499 logputs (LOG_NOTQUIET, _("\
500 Error in server response, closing control connection.\n"));
502 rbuf_uninitialize (&con->rbuf);
506 /* Everything is OK. */
512 if (!opt.server_response)
513 logputs (LOG_VERBOSE, _("done.\n"));
516 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
517 if (cmd & (DO_LIST | DO_RETR))
519 if (opt.ftp_pasv > 0)
521 ip_address passive_addr;
522 unsigned short passive_port;
523 if (!opt.server_response)
524 logputs (LOG_VERBOSE, "==> PASV ... ");
525 err = ftp_pasv (&con->rbuf, &passive_addr, &passive_port);
526 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
530 logputs (LOG_VERBOSE, "\n");
531 logputs (LOG_NOTQUIET, _("\
532 Error in server response, closing control connection.\n"));
534 rbuf_uninitialize (&con->rbuf);
538 logputs (LOG_VERBOSE, "\n");
539 logputs (LOG_NOTQUIET,
540 _("Write failed, closing control connection.\n"));
542 rbuf_uninitialize (&con->rbuf);
546 logputs (LOG_VERBOSE, "\n");
547 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
550 logputs (LOG_VERBOSE, "\n");
551 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
562 dtsock = connect_to_one (&passive_addr, passive_port, 1);
565 int save_errno = errno;
567 rbuf_uninitialize (&con->rbuf);
568 logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"),
569 pretty_print_address (&passive_addr), passive_port,
570 strerror (save_errno));
571 return save_errno == ECONNREFUSED ? CONREFUSED : CONERROR;
574 pasv_mode_open = 1; /* Flag to avoid accept port */
575 if (!opt.server_response)
576 logputs (LOG_VERBOSE, _("done. "));
580 if (!pasv_mode_open) /* Try to use a port command if PASV failed */
582 if (!opt.server_response)
583 logputs (LOG_VERBOSE, "==> PORT ... ");
584 err = ftp_port (&con->rbuf);
585 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
586 LISTENERR), HOSTERR, FTPPORTERR */
590 logputs (LOG_VERBOSE, "\n");
591 logputs (LOG_NOTQUIET, _("\
592 Error in server response, closing control connection.\n"));
595 rbuf_uninitialize (&con->rbuf);
599 logputs (LOG_VERBOSE, "\n");
600 logputs (LOG_NOTQUIET,
601 _("Write failed, closing control connection.\n"));
604 rbuf_uninitialize (&con->rbuf);
608 logputs (LOG_VERBOSE, "\n");
609 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
612 rbuf_uninitialize (&con->rbuf);
615 case CONPORTERR: case BINDERR: case LISTENERR:
616 /* What now? These problems are local... */
617 logputs (LOG_VERBOSE, "\n");
618 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
624 logputs (LOG_VERBOSE, "\n");
625 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
628 rbuf_uninitialize (&con->rbuf);
638 if (!opt.server_response)
639 logputs (LOG_VERBOSE, _("done. "));
641 } /* cmd & (DO_LIST | DO_RETR) */
643 /* Restart if needed. */
644 if (restval && (cmd & DO_RETR))
646 if (!opt.server_response)
647 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
648 err = ftp_rest (&con->rbuf, restval);
650 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
654 logputs (LOG_VERBOSE, "\n");
655 logputs (LOG_NOTQUIET, _("\
656 Error in server response, closing control connection.\n"));
659 rbuf_uninitialize (&con->rbuf);
663 logputs (LOG_VERBOSE, "\n");
664 logputs (LOG_NOTQUIET,
665 _("Write failed, closing control connection.\n"));
668 rbuf_uninitialize (&con->rbuf);
672 /* If `-c' is specified and the file already existed when
673 Wget was started, it would be a bad idea for us to start
674 downloading it from scratch, effectively truncating it. */
675 if (opt.always_rest && (cmd & NO_TRUNCATE))
677 logprintf (LOG_NOTQUIET,
678 _("\nREST failed; will not truncate `%s'.\n"),
682 rbuf_uninitialize (&con->rbuf);
683 return CONTNOTSUPPORTED;
685 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
695 if (err != FTPRESTFAIL && !opt.server_response)
696 logputs (LOG_VERBOSE, _("done. "));
697 } /* restval && cmd & DO_RETR */
701 /* If we're in spider mode, don't really retrieve anything. The
702 fact that we got to this point should be proof enough that
703 the file exists, vaguely akin to HTTP's concept of a "HEAD"
709 rbuf_uninitialize (&con->rbuf);
715 if (!opt.server_response)
718 logputs (LOG_VERBOSE, "\n");
719 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
722 err = ftp_retr (&con->rbuf, u->file);
723 /* FTPRERR, WRITEFAILED, FTPNSFOD */
727 logputs (LOG_VERBOSE, "\n");
728 logputs (LOG_NOTQUIET, _("\
729 Error in server response, closing control connection.\n"));
732 rbuf_uninitialize (&con->rbuf);
736 logputs (LOG_VERBOSE, "\n");
737 logputs (LOG_NOTQUIET,
738 _("Write failed, closing control connection.\n"));
741 rbuf_uninitialize (&con->rbuf);
745 logputs (LOG_VERBOSE, "\n");
746 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
758 if (!opt.server_response)
759 logputs (LOG_VERBOSE, _("done.\n"));
760 expected_bytes = ftp_expected_bytes (ftp_last_respline);
765 if (!opt.server_response)
766 logputs (LOG_VERBOSE, "==> LIST ... ");
767 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
768 without arguments is better than `LIST .'; confirmed by
770 err = ftp_list (&con->rbuf, NULL);
771 /* FTPRERR, WRITEFAILED */
775 logputs (LOG_VERBOSE, "\n");
776 logputs (LOG_NOTQUIET, _("\
777 Error in server response, closing control connection.\n"));
780 rbuf_uninitialize (&con->rbuf);
784 logputs (LOG_VERBOSE, "\n");
785 logputs (LOG_NOTQUIET,
786 _("Write failed, closing control connection.\n"));
789 rbuf_uninitialize (&con->rbuf);
793 logputs (LOG_VERBOSE, "\n");
794 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
806 if (!opt.server_response)
807 logputs (LOG_VERBOSE, _("done.\n"));
808 expected_bytes = ftp_expected_bytes (ftp_last_respline);
809 } /* cmd & DO_LIST */
811 /* Some FTP servers return the total length of file after REST
812 command, others just return the remaining size. */
813 if (*len && restval && expected_bytes
814 && (expected_bytes == *len - restval))
816 DEBUGP (("Lying FTP server found, adjusting.\n"));
817 expected_bytes = *len;
820 /* If no transmission was required, then everything is OK. */
821 if (!(cmd & (DO_LIST | DO_RETR)))
824 if (!pasv_mode_open) /* we are not using pasive mode so we need
827 /* Open the data transmission socket by calling acceptport(). */
828 err = acceptport (&dtsock);
829 /* Possible errors: ACCEPTERR. */
830 if (err == ACCEPTERR)
832 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
837 /* Open the file -- if opt.dfp is set, use it instead. */
838 if (!opt.dfp || con->cmd & DO_LIST)
840 mkalldirs (con->target);
842 rotate_backups (con->target);
843 /* #### Is this correct? */
844 chmod (con->target, 0600);
846 fp = fopen (con->target, restval ? "ab" : "wb");
849 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
851 rbuf_uninitialize (&con->rbuf);
858 extern int global_download_count;
861 /* Rewind the output document if the download starts over and if
862 this is the first download. See gethttp() for a longer
864 if (!restval && global_download_count == 0)
866 /* This will silently fail for streams that don't correspond
867 to regular files, but that's OK. */
869 /* ftruncate is needed because opt.dfp is opened in append
870 mode if opt.always_rest is set. */
871 ftruncate (fileno (fp), 0);
878 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
880 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
881 logputs (LOG_VERBOSE, "\n");
882 expected_bytes = *len; /* for get_contents/show_progress */
884 else if (expected_bytes)
886 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
888 logprintf (LOG_VERBOSE, _(" [%s to go]"),
889 legible (expected_bytes - restval));
890 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
893 /* Get the contents of the document. */
894 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf,
896 tms = time_str (NULL);
897 tmrate = retr_rate (*len - restval, con->dltime, 0);
898 /* Close data connection socket. */
900 /* Close the local file. */
902 /* Close or flush the file. We have to be careful to check for
903 error here. Checking the result of fwrite() is not enough --
904 errors could go unnoticed! */
906 if (!opt.dfp || con->cmd & DO_LIST)
907 flush_res = fclose (fp);
909 flush_res = fflush (fp);
910 if (flush_res == EOF)
913 /* If get_contents couldn't write to fp, bail out. */
916 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
917 con->target, strerror (errno));
919 rbuf_uninitialize (&con->rbuf);
924 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
925 tms, tmrate, strerror (errno));
926 if (opt.server_response)
927 logputs (LOG_ALWAYS, "\n");
930 /* Get the server to tell us if everything is retrieved. */
931 err = ftp_response (&con->rbuf, &respline);
932 /* ...and empty the buffer. */
933 rbuf_discard (&con->rbuf);
937 /* The control connection is decidedly closed. Print the time
938 only if it hasn't already been printed. */
940 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
941 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
942 /* If there is an error on the control connection, close it, but
943 return FTPRETRINT, since there is a possibility that the
944 whole file was retrieved nevertheless (but that is for
945 ftp_loop_internal to decide). */
947 rbuf_uninitialize (&con->rbuf);
950 /* If retrieval failed for any reason, return FTPRETRINT, but do not
951 close socket, since the control connection is still alive. If
952 there is something wrong with the control connection, it will
953 become apparent later. */
954 if (*respline != '2')
958 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
959 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
966 /* What now? The data connection was erroneous, whereas the
967 response says everything is OK. We shall play it safe. */
971 if (!(cmd & LEAVE_PENDING))
973 /* I should probably send 'QUIT' and check for a reply, but this
974 is faster. #### Is it OK, though? */
976 rbuf_uninitialize (&con->rbuf);
978 /* If it was a listing, and opt.server_response is true,
980 if (opt.server_response && (con->cmd & DO_LIST))
982 mkalldirs (con->target);
983 fp = fopen (con->target, "r");
985 logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
989 /* The lines are being read with read_whole_line because of
990 no-buffering on opt.lfile. */
991 while ((line = read_whole_line (fp)))
993 logprintf (LOG_ALWAYS, "%s\n", line);
998 } /* con->cmd & DO_LIST && server_response */
1000 return RETRFINISHED;
1003 /* A one-file FTP loop. This is the part where FTP retrieval is
1004 retried, and retried, and retried, and...
1006 This loop either gets commands from con, or (if ON_YOUR_OWN is
1007 set), makes them up to retrieve the file given by the URL. */
1009 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1013 char *tms, *tmrate, *locf;
1018 con->target = url_filename (u);
1020 if (opt.noclobber && file_exists_p (con->target))
1022 logprintf (LOG_VERBOSE,
1023 _("File `%s' already there, not retrieving.\n"), con->target);
1024 /* If the file is there, we suppose it's retrieved OK. */
1028 /* Remove it if it's a link. */
1029 remove_link (con->target);
1030 if (!opt.output_document)
1033 locf = opt.output_document;
1037 if (con->st & ON_YOUR_OWN)
1038 con->st = ON_YOUR_OWN;
1040 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1045 /* Increment the pass counter. */
1047 sleep_between_retrievals (count);
1048 if (con->st & ON_YOUR_OWN)
1051 con->cmd |= (DO_RETR | LEAVE_PENDING);
1052 if (rbuf_initialized_p (&con->rbuf))
1053 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1055 con->cmd |= (DO_LOGIN | DO_CWD);
1057 else /* not on your own */
1059 if (rbuf_initialized_p (&con->rbuf))
1060 con->cmd &= ~DO_LOGIN;
1062 con->cmd |= DO_LOGIN;
1063 if (con->st & DONE_CWD)
1064 con->cmd &= ~DO_CWD;
1069 /* Assume no restarting. */
1071 if ((count > 1 || opt.always_rest)
1072 && !(con->cmd & DO_LIST)
1073 && file_exists_p (locf))
1074 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1075 restval = st.st_size;
1077 /* In `-c' is used, check whether the file we're writing to
1078 exists and is of non-zero length. If so, we'll refuse to
1079 truncate it if the server doesn't support continued
1081 if (opt.always_rest && restval > 0)
1082 con->cmd |= NO_TRUNCATE;
1084 /* Get the current time string. */
1085 tms = time_str (NULL);
1086 /* Print fetch message, if opt.verbose. */
1089 char *hurl = url_string (u, 1);
1093 sprintf (tmp, _("(try:%2d)"), count);
1094 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1095 tms, hurl, tmp, locf);
1097 ws_changetitle (hurl, 1);
1101 /* Send getftp the proper length, if fileinfo was provided. */
1106 err = getftp (u, &len, restval, con);
1108 if (!rbuf_initialized_p (&con->rbuf))
1109 con->st &= ~DONE_CWD;
1111 con->st |= DONE_CWD;
1115 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1116 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1117 /* Fatal errors, give up. */
1120 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1121 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1122 case BINDERR: case LISTENERR: case ACCEPTERR:
1123 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1124 printwhat (count, opt.ntry);
1125 /* non-fatal errors */
1129 /* If the control connection was closed, the retrieval
1130 will be considered OK if f->size == len. */
1131 if (!f || len != f->size)
1133 printwhat (count, opt.ntry);
1145 tms = time_str (NULL);
1146 tmrate = retr_rate (len - restval, con->dltime, 0);
1148 /* If we get out of the switch above without continue'ing, we've
1149 successfully downloaded a file. Remember this fact. */
1150 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1152 if (con->st & ON_YOUR_OWN)
1154 CLOSE (RBUF_FD (&con->rbuf));
1155 rbuf_uninitialize (&con->rbuf);
1157 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1158 tms, tmrate, locf, len);
1159 if (!opt.verbose && !opt.quiet)
1161 /* Need to hide the password from the URL. The `if' is here
1162 so that we don't do the needless allocation every
1164 char *hurl = url_string (u, 1);
1165 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1166 tms, hurl, len, locf, count);
1170 if ((con->cmd & DO_LIST))
1171 /* This is a directory listing file. */
1173 if (!opt.remove_listing)
1174 /* --dont-remove-listing was specified, so do count this towards the
1175 number of bytes and files downloaded. */
1177 downloaded_increase (len);
1181 /* Deletion of listing files is not controlled by --delete-after, but
1182 by the more specific option --dont-remove-listing, and the code
1183 to do this deletion is in another function. */
1186 /* This is not a directory listing file. */
1188 /* Unlike directory listing files, don't pretend normal files weren't
1189 downloaded if they're going to be deleted. People seeding proxies,
1190 for instance, may want to know how many bytes and files they've
1191 downloaded through it. */
1192 downloaded_increase (len);
1195 if (opt.delete_after)
1197 DEBUGP (("Removing file due to --delete-after in"
1198 " ftp_loop_internal():\n"));
1199 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1201 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1205 /* Restore the original leave-pendingness. */
1207 con->cmd |= LEAVE_PENDING;
1209 con->cmd &= ~LEAVE_PENDING;
1211 } while (!opt.ntry || (count < opt.ntry));
1213 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1215 CLOSE (RBUF_FD (&con->rbuf));
1216 rbuf_uninitialize (&con->rbuf);
1221 /* Return the directory listing in a reusable format. The directory
1222 is specifed in u->dir. */
1224 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1227 char *uf; /* url file name */
1228 char *lf; /* list file name */
1229 char *old_target = con->target;
1231 con->st &= ~ON_YOUR_OWN;
1232 con->cmd |= (DO_LIST | LEAVE_PENDING);
1233 con->cmd &= ~DO_RETR;
1235 /* Find the listing file name. We do it by taking the file name of
1236 the URL and replacing the last component with the listing file
1238 uf = url_filename (u);
1239 lf = file_merge (uf, LIST_FILENAME);
1241 DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1244 err = ftp_loop_internal (u, NULL, con);
1245 con->target = old_target;
1248 *f = ftp_parse_ls (lf, con->rs);
1251 if (opt.remove_listing)
1254 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1256 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1259 con->cmd &= ~DO_LIST;
1263 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1265 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1266 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1267 struct fileinfo **));
1268 static void freefileinfo PARAMS ((struct fileinfo *f));
1270 /* Retrieve a list of files given in struct fileinfo linked list. If
1271 a file is a symbolic link, do not retrieve it, but rather try to
1272 set up a similar link on the local disk, if the symlinks are
1275 If opt.recursive is set, after all files have been retrieved,
1276 ftp_retrieve_dirs will be called to retrieve the directories. */
1278 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1280 static int depth = 0;
1282 struct fileinfo *orig;
1287 /* Increase the depth. */
1289 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1291 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1292 depth, opt.reclevel));
1300 con->st &= ~ON_YOUR_OWN;
1301 if (!(con->st & DONE_CWD))
1304 con->cmd &= ~DO_CWD;
1305 con->cmd |= (DO_RETR | LEAVE_PENDING);
1307 if (!rbuf_initialized_p (&con->rbuf))
1308 con->cmd |= DO_LOGIN;
1310 con->cmd &= ~DO_LOGIN;
1312 err = RETROK; /* in case it's not used */
1316 char *old_target, *ofile;
1318 if (downloaded_exceeds_quota ())
1323 old_target = con->target;
1325 ofile = xstrdup (u->file);
1326 url_set_file (u, f->name);
1328 con->target = url_filename (u);
1332 if (opt.timestamping && f->type == FT_PLAINFILE)
1335 /* If conversion of HTML files retrieved via FTP is ever implemented,
1336 we'll need to stat() <file>.orig here when -K has been specified.
1337 I'm not implementing it now since files on an FTP server are much
1338 more likely than files on an HTTP server to legitimately have a
1340 if (!stat (con->target, &st))
1344 /* Else, get it from the file. */
1345 local_size = st.st_size;
1348 /* Modification time granularity is 2 seconds for Windows, so
1349 increase local time by 1 second for later comparison. */
1352 /* Compare file sizes only for servers that tell us correct
1353 values. Assumme sizes being equal for servers that lie
1355 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1356 eq_size = cor_val ? (local_size == f->size) : 1 ;
1357 if (f->tstamp <= tml && eq_size)
1359 /* Remote file is older, file sizes can be compared and
1361 logprintf (LOG_VERBOSE, _("\
1362 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1367 /* Remote file is newer or sizes cannot be matched */
1368 logprintf (LOG_VERBOSE, _("\
1369 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1374 /* Sizes do not match */
1375 logprintf (LOG_VERBOSE, _("\
1376 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1379 } /* opt.timestamping && f->type == FT_PLAINFILE */
1383 /* If opt.retr_symlinks is defined, we treat symlinks as
1384 if they were normal files. There is currently no way
1385 to distinguish whether they might be directories, and
1387 if (!opt.retr_symlinks)
1391 logputs (LOG_NOTQUIET,
1392 _("Invalid name of the symlink, skipping.\n"));
1396 /* Check whether we already have the correct
1398 int rc = lstat (con->target, &st);
1401 size_t len = strlen (f->linkto) + 1;
1402 if (S_ISLNK (st.st_mode))
1404 char *link_target = (char *)alloca (len);
1405 size_t n = readlink (con->target, link_target, len);
1407 && (memcmp (link_target, f->linkto, n) == 0))
1409 logprintf (LOG_VERBOSE, _("\
1410 Already have correct symlink %s -> %s\n\n"),
1411 con->target, f->linkto);
1417 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1418 con->target, f->linkto);
1419 /* Unlink before creating symlink! */
1420 unlink (con->target);
1421 if (symlink (f->linkto, con->target) == -1)
1422 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1424 logputs (LOG_VERBOSE, "\n");
1425 } /* have f->linkto */
1426 #else /* not HAVE_SYMLINK */
1427 logprintf (LOG_NOTQUIET,
1428 _("Symlinks not supported, skipping symlink `%s'.\n"),
1430 #endif /* not HAVE_SYMLINK */
1432 else /* opt.retr_symlinks */
1435 err = ftp_loop_internal (u, f, con);
1436 } /* opt.retr_symlinks */
1440 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1444 /* Call the retrieve loop. */
1446 err = ftp_loop_internal (u, f, con);
1449 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1454 /* Set the time-stamp information to the local file. Symlinks
1455 are not to be stamped because it sets the stamp on the
1457 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1460 && file_exists_p (con->target))
1462 /* #### This code repeats in http.c and ftp.c. Move it to a
1464 const char *fl = NULL;
1465 if (opt.output_document)
1467 if (opt.od_known_regular)
1468 fl = opt.output_document;
1473 touch (fl, f->tstamp);
1475 else if (f->tstamp == -1)
1476 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1478 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1479 chmod (con->target, f->perms);
1481 DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1483 xfree (con->target);
1484 con->target = old_target;
1486 url_set_file (u, ofile);
1489 /* Break on fatals. */
1490 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1492 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1496 /* We do not want to call ftp_retrieve_dirs here */
1497 if (opt.recursive &&
1498 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1499 err = ftp_retrieve_dirs (u, orig, con);
1500 else if (opt.recursive)
1501 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1502 depth, opt.reclevel));
1507 /* Retrieve the directories given in a file list. This function works
1508 by simply going through the linked list and calling
1509 ftp_retrieve_glob on each directory entry. The function knows
1510 about excluded directories. */
1512 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1514 char *container = NULL;
1515 int container_size = 0;
1517 for (; f; f = f->next)
1520 char *odir, *newdir;
1522 if (downloaded_exceeds_quota ())
1524 if (f->type != FT_DIRECTORY)
1527 /* Allocate u->dir off stack, but reallocate only if a larger
1528 string is needed. It's a pity there's no "realloca" for an
1529 item on the bottom of the stack. */
1530 size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1531 if (size > container_size)
1532 container = (char *)alloca (size);
1537 || (*odir == '/' && *(odir + 1) == '\0'))
1538 /* If ODIR is empty or just "/", simply append f->name to
1539 ODIR. (In the former case, to preserve u->dir being
1540 relative; in the latter case, to avoid double slash.) */
1541 sprintf (newdir, "%s%s", odir, f->name);
1543 /* Else, use a separator. */
1544 sprintf (newdir, "%s/%s", odir, f->name);
1546 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1547 DEBUGP ((" odir = '%s'\n f->name = '%s'\n newdir = '%s'\n\n",
1548 odir, f->name, newdir));
1549 if (!accdir (newdir, ALLABS))
1551 logprintf (LOG_VERBOSE, _("\
1552 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1556 con->st &= ~DONE_CWD;
1558 odir = xstrdup (u->dir); /* because url_set_dir will free
1560 url_set_dir (u, newdir);
1561 ftp_retrieve_glob (u, con, GETALL);
1562 url_set_dir (u, odir);
1565 /* Set the time-stamp? */
1568 if (opt.quota && opt.downloaded > opt.quota)
1575 /* A near-top-level function to retrieve the files in a directory.
1576 The function calls ftp_get_listing, to get a linked list of files.
1577 Then it weeds out the file names that do not match the pattern.
1578 ftp_retrieve_list is called with this updated list as an argument.
1580 If the argument ACTION is GETONE, just download the file (but first
1581 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1582 use globbing; if it's GETALL, download the whole directory. */
1584 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1586 struct fileinfo *orig, *start;
1589 con->cmd |= LEAVE_PENDING;
1591 res = ftp_get_listing (u, con, &orig);
1595 /* First: weed out that do not conform the global rules given in
1596 opt.accepts and opt.rejects. */
1597 if (opt.accepts || opt.rejects)
1599 struct fileinfo *f = orig;
1603 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1605 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1606 f = delelement (f, &start);
1612 /* Now weed out the files that do not match our globbing pattern.
1613 If we are dealing with a globbing pattern, that is. */
1614 if (*u->file && (action == GLOBALL || action == GETONE))
1617 struct fileinfo *f = start;
1621 matchres = fnmatch (u->file, f->name, 0);
1624 logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1628 if (matchres == FNM_NOMATCH)
1629 f = delelement (f, &start); /* delete the element from the list */
1631 f = f->next; /* leave the element in the list */
1635 freefileinfo (start);
1636 return RETRBADPATTERN;
1642 /* Just get everything. */
1643 ftp_retrieve_list (u, start, con);
1647 if (action == GLOBALL)
1650 /* #### This message SUCKS. We should see what was the
1651 reason that nothing was retrieved. */
1652 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1654 else /* GETONE or GETALL */
1656 /* Let's try retrieving it anyway. */
1657 con->st |= ON_YOUR_OWN;
1658 res = ftp_loop_internal (u, NULL, con);
1662 freefileinfo (start);
1663 if (downloaded_exceeds_quota ())
1666 /* #### Should we return `res' here? */
1670 /* The wrapper that calls an appropriate routine according to contents
1671 of URL. Inherently, its capabilities are limited on what can be
1672 encoded into a URL. */
1674 ftp_loop (struct url *u, int *dt, struct url *proxy)
1676 ccon con; /* FTP connection */
1681 memset (&con, 0, sizeof (con));
1683 rbuf_uninitialize (&con.rbuf);
1684 con.st = ON_YOUR_OWN;
1688 res = RETROK; /* in case it's not used */
1690 /* If the file name is empty, the user probably wants a directory
1691 index. We'll provide one, properly HTML-ized. Unless
1692 opt.htmlify is 0, of course. :-) */
1693 if (!*u->file && !opt.recursive)
1696 res = ftp_get_listing (u, &con, &f);
1702 char *filename = (opt.output_document
1703 ? xstrdup (opt.output_document)
1704 : (con.target ? xstrdup (con.target)
1705 : url_filename (u)));
1706 res = ftp_index (filename, u, f);
1707 if (res == FTPOK && opt.verbose)
1709 if (!opt.output_document)
1713 if (stat (filename, &st) == 0)
1717 logprintf (LOG_NOTQUIET,
1718 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1722 logprintf (LOG_NOTQUIET,
1723 _("Wrote HTML-ized index to `%s'.\n"),
1733 int wild = has_wildcards_p (u->file);
1734 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1736 /* ftp_retrieve_glob is a catch-all function that gets called
1737 if we need globbing, time-stamping or recursion. Its
1738 third argument is just what we really need. */
1739 res = ftp_retrieve_glob (u, &con,
1740 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1743 res = ftp_loop_internal (u, NULL, &con);
1749 /* If a connection was left, quench it. */
1750 if (rbuf_initialized_p (&con.rbuf))
1751 CLOSE (RBUF_FD (&con.rbuf));
1752 FREE_MAYBE (con.id);
1754 FREE_MAYBE (con.target);
1759 /* Delete an element from the fileinfo linked list. Returns the
1760 address of the next element, or NULL if the list is exhausted. It
1761 can modify the start of the list. */
1762 static struct fileinfo *
1763 delelement (struct fileinfo *f, struct fileinfo **start)
1765 struct fileinfo *prev = f->prev;
1766 struct fileinfo *next = f->next;
1769 FREE_MAYBE (f->linkto);
1781 /* Free the fileinfo linked list of files. */
1783 freefileinfo (struct fileinfo *f)
1787 struct fileinfo *next = f->next;