1 /* File Transfer Protocol support.
2 Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
4 This file is part of Wget.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
32 #include <sys/types.h>
36 # include <netdb.h> /* for h_errno */
59 /* File where the "ls -al" listing will be saved. */
60 #define LIST_FILENAME ".listing"
62 extern char ftp_last_respline[];
64 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
65 the string S, and return the number converted to long, if found, 0
68 ftp_expected_bytes (const char *s)
74 while (*s && *s != '(')
78 for (++s; *s && ISSPACE (*s); s++);
86 res = (*s - '0') + 10 * res;
89 while (*s && ISDIGIT (*s));
92 while (*s && ISSPACE (*s))
96 if (TOLOWER (*s) != 'b')
98 if (strncasecmp (s, "byte", 4))
106 /* Retrieves a file with denoted parameters through opening an FTP
107 connection to the server. It always closes the data connection,
108 and closes the control connection in case of error. */
110 getftp (struct urlinfo *u, long *len, long restval, ccon *con)
112 int csock, dtsock, res;
115 char *user, *passwd, *respline;
117 struct wget_timer *timer;
118 unsigned char pasv_addr[6];
120 int passive_mode_open = 0;
121 long expected_bytes = 0L;
123 assert (con != NULL);
124 assert (u->local != NULL);
125 /* Debug-check of the sanity of the request by making sure that LIST
126 and RETR are never both requested (since we can handle only one
128 assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
129 /* Make sure that at least *something* is requested. */
130 assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
134 search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
135 user = user ? user : opt.ftp_acc;
137 opt.ftp_pass = ftp_getaddress ();
138 passwd = passwd ? passwd : opt.ftp_pass;
139 assert (user && passwd);
144 if (!(cmd & DO_LOGIN))
145 csock = RBUF_FD (&con->rbuf);
146 else /* cmd & DO_LOGIN */
148 /* Login to the server: */
150 /* First: Establish the control connection. */
151 logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
152 err = make_connection (&csock, u->host, u->port);
153 if (cmd & LEAVE_PENDING)
154 rbuf_initialize (&con->rbuf, csock);
156 rbuf_uninitialize (&con->rbuf);
159 /* Do not close the socket in first several cases, since it
160 wasn't created at all. */
162 logputs (LOG_VERBOSE, "\n");
163 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
167 logputs (LOG_VERBOSE, "\n");
168 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
172 logputs (LOG_VERBOSE, "\n");
173 logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
176 rbuf_uninitialize (&con->rbuf);
179 logputs (LOG_VERBOSE, "\n");
180 logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
182 rbuf_uninitialize (&con->rbuf);
189 /* Since this is a new connection, we may safely discard
190 anything left in the buffer. */
191 rbuf_discard (&con->rbuf);
193 /* Second: Login with proper USER/PASS sequence. */
194 logputs (LOG_VERBOSE, _("connected!\n"));
195 logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
196 if (opt.server_response)
197 logputs (LOG_ALWAYS, "\n");
198 err = ftp_login (&con->rbuf, user, passwd);
199 /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
203 logputs (LOG_VERBOSE, "\n");
204 logputs (LOG_NOTQUIET, _("\
205 Error in server response, closing control connection.\n"));
207 rbuf_uninitialize (&con->rbuf);
211 logputs (LOG_VERBOSE, "\n");
212 logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
214 rbuf_uninitialize (&con->rbuf);
218 logputs (LOG_VERBOSE, "\n");
219 logputs (LOG_NOTQUIET,
220 _("Write failed, closing control connection.\n"));
222 rbuf_uninitialize (&con->rbuf);
226 logputs (LOG_VERBOSE, "\n");
227 logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
229 rbuf_uninitialize (&con->rbuf);
230 return FTPLOGREFUSED;
233 logputs (LOG_VERBOSE, "\n");
234 logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
236 rbuf_uninitialize (&con->rbuf);
240 if (!opt.server_response)
241 logputs (LOG_VERBOSE, _("Logged in!\n"));
248 /* Third: Get the system type */
249 if (!opt.server_response)
250 logprintf (LOG_VERBOSE, "==> SYST ... ");
251 err = ftp_syst (&con->rbuf, &con->rs);
256 logputs (LOG_VERBOSE, "\n");
257 logputs (LOG_NOTQUIET, _("\
258 Error in server response, closing control connection.\n"));
260 rbuf_uninitialize (&con->rbuf);
264 logputs (LOG_VERBOSE, "\n");
265 logputs (LOG_NOTQUIET,
266 _("Server error, can't determine system type.\n"));
269 /* Everything is OK. */
275 if (!opt.server_response)
276 logputs (LOG_VERBOSE, _("done. "));
278 /* Fourth: Find the initial ftp directory */
280 if (!opt.server_response)
281 logprintf (LOG_VERBOSE, "==> PWD ... ");
282 err = ftp_pwd(&con->rbuf, &con->id);
288 logputs (LOG_VERBOSE, "\n");
289 logputs (LOG_NOTQUIET, _("\
290 Error in server response, closing control connection.\n"));
292 rbuf_uninitialize (&con->rbuf);
296 /* Everything is OK. */
302 /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
303 Convert it to "/INITIAL/FOLDER" */
304 if (con->rs == ST_VMS)
306 char *path = strchr (con->id, '[');
307 char *pathend = path ? strchr (path + 1, ']') : NULL;
308 if (!path || !pathend)
309 DEBUGP (("Initial VMS directory not in the form [...]!\n"));
312 char *idir = con->id;
313 DEBUGP (("Preprocessing the initial VMS directory\n"));
314 DEBUGP ((" old = '%s'\n", con->id));
315 /* We do the conversion in-place by copying the stuff
316 between [ and ] to the beginning, and changing dots
317 to slashes at the same time. */
319 for (++path; path < pathend; path++, idir++)
320 *idir = *path == '.' ? '/' : *path;
322 DEBUGP ((" new = '%s'\n\n", con->id));
325 if (!opt.server_response)
326 logputs (LOG_VERBOSE, _("done.\n"));
328 /* Fifth: Set the FTP type. */
329 if (!opt.server_response)
330 logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
331 err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
332 /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
336 logputs (LOG_VERBOSE, "\n");
337 logputs (LOG_NOTQUIET, _("\
338 Error in server response, closing control connection.\n"));
340 rbuf_uninitialize (&con->rbuf);
344 logputs (LOG_VERBOSE, "\n");
345 logputs (LOG_NOTQUIET,
346 _("Write failed, closing control connection.\n"));
348 rbuf_uninitialize (&con->rbuf);
352 logputs (LOG_VERBOSE, "\n");
353 logprintf (LOG_NOTQUIET,
354 _("Unknown type `%c', closing control connection.\n"),
355 TOUPPER (u->ftp_type));
357 rbuf_uninitialize (&con->rbuf);
360 /* Everything is OK. */
366 if (!opt.server_response)
367 logputs (LOG_VERBOSE, _("done. "));
373 logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
376 char *target = u->dir;
378 DEBUGP (("changing working directory\n"));
380 /* Change working directory. To change to a non-absolute
381 Unix directory, we need to prepend initial directory
382 (con->id) to it. Absolute directories "just work". */
386 int idlen = strlen (con->id);
387 char *ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
388 /* idlen == 1 means con->id = "/" */
389 sprintf (ntarget, "%s%s%s", con->id, idlen == 1 ? "" : "/",
391 DEBUGP (("Prepended initial PWD to relative path:\n"));
392 DEBUGP ((" old: '%s'\n new: '%s'\n", target, ntarget));
396 /* If the FTP host runs VMS, we will have to convert the absolute
397 directory path in UNIX notation to absolute directory path in
398 VMS notation as VMS FTP servers do not like UNIX notation of
399 absolute paths. "VMS notation" is [dir.subdir.subsubdir]. */
401 if (con->rs == ST_VMS)
404 char *ntarget = (char *)alloca (strlen (target) + 2);
405 /* We use a converted initial dir, so directories in
406 TARGET will be separated with slashes, something like
407 "/INITIAL/FOLDER/DIR/SUBDIR". Convert that to
408 "[INITIAL.FOLDER.DIR.SUBDIR]". */
409 strcpy (ntarget, target);
410 assert (*ntarget == '/');
412 for (tmpp = ntarget + 1; *tmpp; tmpp++)
417 DEBUGP (("Changed file name to VMS syntax:\n"));
418 DEBUGP ((" Unix: '%s'\n VMS: '%s'\n", target, ntarget));
422 if (!opt.server_response)
423 logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
424 err = ftp_cwd (&con->rbuf, target);
425 /* FTPRERR, WRITEFAILED, FTPNSFOD */
429 logputs (LOG_VERBOSE, "\n");
430 logputs (LOG_NOTQUIET, _("\
431 Error in server response, closing control connection.\n"));
433 rbuf_uninitialize (&con->rbuf);
437 logputs (LOG_VERBOSE, "\n");
438 logputs (LOG_NOTQUIET,
439 _("Write failed, closing control connection.\n"));
441 rbuf_uninitialize (&con->rbuf);
445 logputs (LOG_VERBOSE, "\n");
446 logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
449 rbuf_uninitialize (&con->rbuf);
459 if (!opt.server_response)
460 logputs (LOG_VERBOSE, _("done.\n"));
463 else /* do not CWD */
464 logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
466 /* If anything is to be retrieved, PORT (or PASV) must be sent. */
467 if (cmd & (DO_LIST | DO_RETR))
469 if (opt.ftp_pasv > 0)
472 unsigned short tport;
474 if (!opt.server_response)
475 logputs (LOG_VERBOSE, "==> PASV ... ");
476 err = ftp_pasv (&con->rbuf, pasv_addr);
477 /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
481 logputs (LOG_VERBOSE, "\n");
482 logputs (LOG_NOTQUIET, _("\
483 Error in server response, closing control connection.\n"));
485 rbuf_uninitialize (&con->rbuf);
489 logputs (LOG_VERBOSE, "\n");
490 logputs (LOG_NOTQUIET,
491 _("Write failed, closing control connection.\n"));
493 rbuf_uninitialize (&con->rbuf);
497 logputs (LOG_VERBOSE, "\n");
498 logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
501 logputs (LOG_VERBOSE, "\n");
502 logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
513 sprintf (thost, "%d.%d.%d.%d",
514 pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
515 tport = (pasv_addr[4] << 8) + pasv_addr[5];
516 DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
517 err = make_connection (&dtsock, thost, tport);
520 /* Do not close the socket in first several cases,
521 since it wasn't created at all. */
523 logputs (LOG_VERBOSE, "\n");
524 logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
527 rbuf_uninitialize (&con->rbuf);
531 logputs (LOG_VERBOSE, "\n");
532 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
534 rbuf_uninitialize (&con->rbuf);
538 logputs (LOG_VERBOSE, "\n");
539 logprintf (LOG_NOTQUIET,
540 _("Connection to %s:%hu refused.\n"),
543 rbuf_uninitialize (&con->rbuf);
547 logputs (LOG_VERBOSE, "\n");
548 logprintf (LOG_NOTQUIET, "connect: %s\n",
551 rbuf_uninitialize (&con->rbuf);
559 passive_mode_open= 1; /* Flag to avoid accept port */
560 if (!opt.server_response)
561 logputs (LOG_VERBOSE, _("done. "));
565 if (!passive_mode_open) /* Try to use a port command if PASV failed */
567 if (!opt.server_response)
568 logputs (LOG_VERBOSE, "==> PORT ... ");
569 err = ftp_port (&con->rbuf);
570 /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
571 LISTENERR), HOSTERR, FTPPORTERR */
575 logputs (LOG_VERBOSE, "\n");
576 logputs (LOG_NOTQUIET, _("\
577 Error in server response, closing control connection.\n"));
580 rbuf_uninitialize (&con->rbuf);
584 logputs (LOG_VERBOSE, "\n");
585 logputs (LOG_NOTQUIET,
586 _("Write failed, closing control connection.\n"));
589 rbuf_uninitialize (&con->rbuf);
593 logputs (LOG_VERBOSE, "\n");
594 logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
597 rbuf_uninitialize (&con->rbuf);
600 case CONPORTERR: case BINDERR: case LISTENERR:
601 /* What now? These problems are local... */
602 logputs (LOG_VERBOSE, "\n");
603 logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
609 logputs (LOG_VERBOSE, "\n");
610 logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
614 rbuf_uninitialize (&con->rbuf);
618 logputs (LOG_VERBOSE, "\n");
619 logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
622 rbuf_uninitialize (&con->rbuf);
632 if (!opt.server_response)
633 logputs (LOG_VERBOSE, _("done. "));
635 } /* cmd & (DO_LIST | DO_RETR) */
637 /* Restart if needed. */
638 if (restval && (cmd & DO_RETR))
640 if (!opt.server_response)
641 logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
642 err = ftp_rest (&con->rbuf, restval);
644 /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
648 logputs (LOG_VERBOSE, "\n");
649 logputs (LOG_NOTQUIET, _("\
650 Error in server response, closing control connection.\n"));
653 rbuf_uninitialize (&con->rbuf);
657 logputs (LOG_VERBOSE, "\n");
658 logputs (LOG_NOTQUIET,
659 _("Write failed, closing control connection.\n"));
662 rbuf_uninitialize (&con->rbuf);
666 /* If `-c' is specified and the file already existed when
667 Wget was started, it would be a bad idea for us to start
668 downloading it from scratch, effectively truncating it. */
669 if (opt.always_rest && (cmd & NO_TRUNCATE))
671 logprintf (LOG_NOTQUIET,
672 _("\nREST failed; will not truncate `%s'.\n"),
676 rbuf_uninitialize (&con->rbuf);
677 return CONTNOTSUPPORTED;
679 logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
689 if (err != FTPRESTFAIL && !opt.server_response)
690 logputs (LOG_VERBOSE, _("done. "));
691 } /* restval && cmd & DO_RETR */
697 if (!opt.server_response)
700 logputs (LOG_VERBOSE, "\n");
701 logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
704 err = ftp_retr (&con->rbuf, u->file);
705 /* FTPRERR, WRITEFAILED, FTPNSFOD */
709 logputs (LOG_VERBOSE, "\n");
710 logputs (LOG_NOTQUIET, _("\
711 Error in server response, closing control connection.\n"));
714 rbuf_uninitialize (&con->rbuf);
718 logputs (LOG_VERBOSE, "\n");
719 logputs (LOG_NOTQUIET,
720 _("Write failed, closing control connection.\n"));
723 rbuf_uninitialize (&con->rbuf);
727 logputs (LOG_VERBOSE, "\n");
728 logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
740 if (!opt.server_response)
741 logputs (LOG_VERBOSE, _("done.\n"));
742 expected_bytes = ftp_expected_bytes (ftp_last_respline);
747 if (!opt.server_response)
748 logputs (LOG_VERBOSE, "==> LIST ... ");
749 /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
750 without arguments is better than `LIST .'; confirmed by
752 err = ftp_list (&con->rbuf, NULL);
753 /* FTPRERR, WRITEFAILED */
757 logputs (LOG_VERBOSE, "\n");
758 logputs (LOG_NOTQUIET, _("\
759 Error in server response, closing control connection.\n"));
762 rbuf_uninitialize (&con->rbuf);
766 logputs (LOG_VERBOSE, "\n");
767 logputs (LOG_NOTQUIET,
768 _("Write failed, closing control connection.\n"));
771 rbuf_uninitialize (&con->rbuf);
775 logputs (LOG_VERBOSE, "\n");
776 logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
788 if (!opt.server_response)
789 logputs (LOG_VERBOSE, _("done.\n"));
790 expected_bytes = ftp_expected_bytes (ftp_last_respline);
791 } /* cmd & DO_LIST */
793 /* Some FTP servers return the total length of file after REST
794 command, others just return the remaining size. */
795 if (*len && restval && expected_bytes
796 && (expected_bytes == *len - restval))
798 DEBUGP (("Lying FTP server found, adjusting.\n"));
799 expected_bytes = *len;
802 /* If no transmission was required, then everything is OK. */
803 if (!(cmd & (DO_LIST | DO_RETR)))
806 if (!passive_mode_open) /* we are not using pasive mode so we need
809 /* Open the data transmission socket by calling acceptport(). */
810 err = acceptport (&dtsock);
811 /* Possible errors: ACCEPTERR. */
812 if (err == ACCEPTERR)
814 logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
819 /* Open the file -- if opt.dfp is set, use it instead. */
820 if (!opt.dfp || con->cmd & DO_LIST)
822 mkalldirs (u->local);
824 rotate_backups (u->local);
825 /* #### Is this correct? */
826 chmod (u->local, 0600);
828 fp = fopen (u->local, restval ? "ab" : "wb");
831 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
833 rbuf_uninitialize (&con->rbuf);
840 extern int global_download_count;
843 /* Rewind the output document if the download starts over and if
844 this is the first download. See gethttp() for a longer
846 if (!restval && global_download_count == 0)
848 /* This will silently fail for streams that don't correspond
849 to regular files, but that's OK. */
851 /* ftruncate is needed because opt.dfp is opened in append
852 mode if opt.always_rest is set. */
853 ftruncate (fileno (fp), 0);
860 logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
862 logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
863 logputs (LOG_VERBOSE, "\n");
864 expected_bytes = *len; /* for get_contents/show_progress */
866 else if (expected_bytes)
868 logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
870 logprintf (LOG_VERBOSE, _(" [%s to go]"),
871 legible (expected_bytes - restval));
872 logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
874 timer = wtimer_new ();
875 /* Get the contents of the document. */
876 res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
877 con->dltime = wtimer_elapsed (timer);
878 wtimer_delete (timer);
879 tms = time_str (NULL);
880 tmrate = rate (*len - restval, con->dltime, 0);
881 /* Close data connection socket. */
883 /* Close the local file. */
885 /* Close or flush the file. We have to be careful to check for
886 error here. Checking the result of fwrite() is not enough --
887 errors could go unnoticed! */
889 if (!opt.dfp || con->cmd & DO_LIST)
890 flush_res = fclose (fp);
892 flush_res = fflush (fp);
893 if (flush_res == EOF)
896 /* If get_contents couldn't write to fp, bail out. */
899 logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
900 u->local, strerror (errno));
902 rbuf_uninitialize (&con->rbuf);
907 logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
908 tms, tmrate, strerror (errno));
909 if (opt.server_response)
910 logputs (LOG_ALWAYS, "\n");
913 /* Get the server to tell us if everything is retrieved. */
914 err = ftp_response (&con->rbuf, &respline);
915 /* ...and empty the buffer. */
916 rbuf_discard (&con->rbuf);
920 /* The control connection is decidedly closed. Print the time
921 only if it hasn't already been printed. */
923 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
924 logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
925 /* If there is an error on the control connection, close it, but
926 return FTPRETRINT, since there is a possibility that the
927 whole file was retrieved nevertheless (but that is for
928 ftp_loop_internal to decide). */
930 rbuf_uninitialize (&con->rbuf);
933 /* If retrieval failed for any reason, return FTPRETRINT, but do not
934 close socket, since the control connection is still alive. If
935 there is something wrong with the control connection, it will
936 become apparent later. */
937 if (*respline != '2')
941 logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
942 logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
949 /* What now? The data connection was erroneous, whereas the
950 response says everything is OK. We shall play it safe. */
954 if (!(cmd & LEAVE_PENDING))
956 /* I should probably send 'QUIT' and check for a reply, but this
957 is faster. #### Is it OK, though? */
959 rbuf_uninitialize (&con->rbuf);
961 /* If it was a listing, and opt.server_response is true,
963 if (opt.server_response && (con->cmd & DO_LIST))
965 mkalldirs (u->local);
966 fp = fopen (u->local, "r");
968 logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
972 /* The lines are being read with read_whole_line because of
973 no-buffering on opt.lfile. */
974 while ((line = read_whole_line (fp)))
976 logprintf (LOG_ALWAYS, "%s\n", line);
981 } /* con->cmd & DO_LIST && server_response */
986 /* A one-file FTP loop. This is the part where FTP retrieval is
987 retried, and retried, and retried, and...
989 This loop either gets commands from con, or (if ON_YOUR_OWN is
990 set), makes them up to retrieve the file given by the URL. */
992 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
994 int count, orig_lp, no_truncate;
996 char *tms, *tmrate, *locf;
1001 u->local = url_filename (u);
1003 if (opt.noclobber && file_exists_p (u->local))
1005 logprintf (LOG_VERBOSE,
1006 _("File `%s' already there, not retrieving.\n"), u->local);
1007 /* If the file is there, we suppose it's retrieved OK. */
1011 /* Remove it if it's a link. */
1012 remove_link (u->local);
1013 if (!opt.output_document)
1016 locf = opt.output_document;
1020 if (con->st & ON_YOUR_OWN)
1021 con->st = ON_YOUR_OWN;
1023 orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1025 /* In `-c' is used, check whether the file we're writing to exists
1026 before we've done anything. If so, we'll refuse to truncate it
1027 if the server doesn't support continued downloads. */
1029 if (opt.always_rest)
1030 no_truncate = file_exists_p (locf);
1035 /* Increment the pass counter. */
1037 sleep_between_retrievals (count);
1038 if (con->st & ON_YOUR_OWN)
1041 con->cmd |= (DO_RETR | LEAVE_PENDING);
1042 if (rbuf_initialized_p (&con->rbuf))
1043 con->cmd &= ~ (DO_LOGIN | DO_CWD);
1045 con->cmd |= (DO_LOGIN | DO_CWD);
1047 else /* not on your own */
1049 if (rbuf_initialized_p (&con->rbuf))
1050 con->cmd &= ~DO_LOGIN;
1052 con->cmd |= DO_LOGIN;
1053 if (con->st & DONE_CWD)
1054 con->cmd &= ~DO_CWD;
1059 con->cmd |= NO_TRUNCATE;
1060 /* Assume no restarting. */
1062 if ((count > 1 || opt.always_rest)
1063 && !(con->cmd & DO_LIST)
1064 && file_exists_p (locf))
1065 if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1066 restval = st.st_size;
1067 /* Get the current time string. */
1068 tms = time_str (NULL);
1069 /* Print fetch message, if opt.verbose. */
1072 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1076 sprintf (tmp, _("(try:%2d)"), count);
1077 logprintf (LOG_VERBOSE, "--%s-- %s\n %s => `%s'\n",
1078 tms, hurl, tmp, locf);
1080 ws_changetitle (hurl, 1);
1084 /* Send getftp the proper length, if fileinfo was provided. */
1089 err = getftp (u, &len, restval, con);
1091 tms = time_str (NULL);
1092 tmrate = rate (len - restval, con->dltime, 0);
1094 if (!rbuf_initialized_p (&con->rbuf))
1095 con->st &= ~DONE_CWD;
1097 con->st |= DONE_CWD;
1101 case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1102 case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1103 /* Fatal errors, give up. */
1106 case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1107 case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1108 case BINDERR: case LISTENERR: case ACCEPTERR:
1109 case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1110 printwhat (count, opt.ntry);
1111 /* non-fatal errors */
1115 /* If the control connection was closed, the retrieval
1116 will be considered OK if f->size == len. */
1117 if (!f || len != f->size)
1119 printwhat (count, opt.ntry);
1131 /* If we get out of the switch above without continue'ing, we've
1132 successfully downloaded a file. Remember this fact. */
1133 downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1135 if (con->st & ON_YOUR_OWN)
1137 CLOSE (RBUF_FD (&con->rbuf));
1138 rbuf_uninitialize (&con->rbuf);
1140 logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1141 tms, tmrate, locf, len);
1142 if (!opt.verbose && !opt.quiet)
1144 /* Need to hide the password from the URL. The `if' is here
1145 so that we don't do the needless allocation every
1147 char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1148 logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1149 tms, hurl, len, locf, count);
1153 if ((con->cmd & DO_LIST))
1154 /* This is a directory listing file. */
1156 if (!opt.remove_listing)
1157 /* --dont-remove-listing was specified, so do count this towards the
1158 number of bytes and files downloaded. */
1160 downloaded_increase (len);
1164 /* Deletion of listing files is not controlled by --delete-after, but
1165 by the more specific option --dont-remove-listing, and the code
1166 to do this deletion is in another function. */
1169 /* This is not a directory listing file. */
1171 /* Unlike directory listing files, don't pretend normal files weren't
1172 downloaded if they're going to be deleted. People seeding proxies,
1173 for instance, may want to know how many bytes and files they've
1174 downloaded through it. */
1175 downloaded_increase (len);
1178 if (opt.delete_after)
1180 DEBUGP (("Removing file due to --delete-after in"
1181 " ftp_loop_internal():\n"));
1182 logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1184 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1188 /* Restore the original leave-pendingness. */
1190 con->cmd |= LEAVE_PENDING;
1192 con->cmd &= ~LEAVE_PENDING;
1194 } while (!opt.ntry || (count < opt.ntry));
1196 if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1198 CLOSE (RBUF_FD (&con->rbuf));
1199 rbuf_uninitialize (&con->rbuf);
1204 /* Return the directory listing in a reusable format. The directory
1205 is specifed in u->dir. */
1207 ftp_get_listing (struct urlinfo *u, ccon *con, struct fileinfo **f)
1210 char *olocal = u->local;
1211 char *list_filename, *ofile;
1213 con->st &= ~ON_YOUR_OWN;
1214 con->cmd |= (DO_LIST | LEAVE_PENDING);
1215 con->cmd &= ~DO_RETR;
1216 /* Get the listing filename. */
1218 u->file = LIST_FILENAME;
1219 list_filename = url_filename (u);
1221 u->local = list_filename;
1222 DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1223 err = ftp_loop_internal (u, NULL, con);
1226 *f = ftp_parse_ls (list_filename, con->rs);
1229 if (opt.remove_listing)
1231 if (unlink (list_filename))
1232 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1234 logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1236 xfree (list_filename);
1237 con->cmd &= ~DO_LIST;
1241 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1243 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1244 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1245 struct fileinfo **));
1246 static void freefileinfo PARAMS ((struct fileinfo *f));
1248 /* Retrieve a list of files given in struct fileinfo linked list. If
1249 a file is a symbolic link, do not retrieve it, but rather try to
1250 set up a similar link on the local disk, if the symlinks are
1253 If opt.recursive is set, after all files have been retrieved,
1254 ftp_retrieve_dirs will be called to retrieve the directories. */
1256 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1258 static int depth = 0;
1260 char *olocal, *ofile;
1261 struct fileinfo *orig;
1266 /* Increase the depth. */
1268 if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1270 DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1271 depth, opt.reclevel));
1279 con->st &= ~ON_YOUR_OWN;
1280 if (!(con->st & DONE_CWD))
1283 con->cmd &= ~DO_CWD;
1284 con->cmd |= (DO_RETR | LEAVE_PENDING);
1286 if (!rbuf_initialized_p (&con->rbuf))
1287 con->cmd |= DO_LOGIN;
1289 con->cmd &= ~DO_LOGIN;
1291 err = RETROK; /* in case it's not used */
1295 if (downloaded_exceeds_quota ())
1303 u->local = url_filename (u);
1307 if (opt.timestamping && f->type == FT_PLAINFILE)
1310 /* If conversion of HTML files retrieved via FTP is ever implemented,
1311 we'll need to stat() <file>.orig here when -K has been specified.
1312 I'm not implementing it now since files on an FTP server are much
1313 more likely than files on an HTTP server to legitimately have a
1315 if (!stat (u->local, &st))
1319 /* Else, get it from the file. */
1320 local_size = st.st_size;
1322 /* Compare file sizes only for servers that tell us correct
1323 values. Assumme sizes being equal for servers that lie
1325 cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1326 eq_size = cor_val ? (local_size == f->size) : 1 ;
1327 if (f->tstamp <= tml && eq_size)
1329 /* Remote file is older, file sizes can be compared and
1331 logprintf (LOG_VERBOSE, _("\
1332 Remote file no newer than local file `%s' -- not retrieving.\n"), u->local);
1337 /* Remote file is newer or sizes cannot be matched */
1338 logprintf (LOG_VERBOSE, _("\
1339 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1344 /* Sizes do not match */
1345 logprintf (LOG_VERBOSE, _("\
1346 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1349 } /* opt.timestamping && f->type == FT_PLAINFILE */
1353 /* If opt.retr_symlinks is defined, we treat symlinks as
1354 if they were normal files. There is currently no way
1355 to distinguish whether they might be directories, and
1357 if (!opt.retr_symlinks)
1361 logputs (LOG_NOTQUIET,
1362 _("Invalid name of the symlink, skipping.\n"));
1366 /* Check whether we already have the correct
1368 int rc = lstat (u->local, &st);
1371 size_t len = strlen (f->linkto) + 1;
1372 if (S_ISLNK (st.st_mode))
1374 char *link_target = (char *)alloca (len);
1375 size_t n = readlink (u->local, link_target, len);
1377 && (memcmp (link_target, f->linkto, n) == 0))
1379 logprintf (LOG_VERBOSE, _("\
1380 Already have correct symlink %s -> %s\n\n"),
1381 u->local, f->linkto);
1387 logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1388 u->local, f->linkto);
1389 /* Unlink before creating symlink! */
1391 if (symlink (f->linkto, u->local) == -1)
1392 logprintf (LOG_NOTQUIET, "symlink: %s\n",
1394 logputs (LOG_VERBOSE, "\n");
1395 } /* have f->linkto */
1396 #else /* not HAVE_SYMLINK */
1397 logprintf (LOG_NOTQUIET,
1398 _("Symlinks not supported, skipping symlink `%s'.\n"),
1400 #endif /* not HAVE_SYMLINK */
1402 else /* opt.retr_symlinks */
1405 err = ftp_loop_internal (u, f, con);
1406 } /* opt.retr_symlinks */
1410 logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1414 /* Call the retrieve loop. */
1416 err = ftp_loop_internal (u, f, con);
1419 logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1424 /* Set the time-stamp information to the local file. Symlinks
1425 are not to be stamped because it sets the stamp on the
1427 if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1430 && file_exists_p (u->local))
1432 /* #### This code repeats in http.c and ftp.c. Move it to a
1434 const char *fl = NULL;
1435 if (opt.output_document)
1437 if (opt.od_known_regular)
1438 fl = opt.output_document;
1443 touch (fl, f->tstamp);
1445 else if (f->tstamp == -1)
1446 logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1448 if (f->perms && f->type == FT_PLAINFILE && dlthis)
1449 chmod (u->local, f->perms);
1451 DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1456 /* Break on fatals. */
1457 if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1459 con->cmd &= ~ (DO_CWD | DO_LOGIN);
1462 /* We do not want to call ftp_retrieve_dirs here */
1463 if (opt.recursive &&
1464 !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1465 err = ftp_retrieve_dirs (u, orig, con);
1466 else if (opt.recursive)
1467 DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1468 depth, opt.reclevel));
1473 /* Retrieve the directories given in a file list. This function works
1474 by simply going through the linked list and calling
1475 ftp_retrieve_glob on each directory entry. The function knows
1476 about excluded directories. */
1478 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1481 char *current_container = NULL;
1482 int current_length = 0;
1484 for (; f; f = f->next)
1488 if (downloaded_exceeds_quota ())
1490 if (f->type != FT_DIRECTORY)
1493 len = strlen (u->dir) + 1 + strlen (f->name) + 1;
1494 /* Allocate u->dir off stack, but reallocate only if a larger
1495 string is needed. */
1496 if (len > current_length)
1497 current_container = (char *)alloca (len);
1498 u->dir = current_container;
1500 || (*odir == '/' && *(odir + 1) == '\0'))
1501 /* If ODIR is empty or just "/", simply append f->name to
1502 ODIR. (In the former case, to preserve u->dir being
1503 relative; in the latter case, to avoid double slash.) */
1504 sprintf (u->dir, "%s%s", odir, f->name);
1506 /* Else, use a separator. */
1507 sprintf (u->dir, "%s/%s", odir, f->name);
1508 DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1509 DEBUGP ((" odir = '%s'\n f->name = '%s'\n u->dir = '%s'\n\n",
1510 odir, f->name, u->dir));
1511 if (!accdir (u->dir, ALLABS))
1513 logprintf (LOG_VERBOSE, _("\
1514 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1518 con->st &= ~DONE_CWD;
1519 ftp_retrieve_glob (u, con, GETALL);
1520 /* Set the time-stamp? */
1523 if (opt.quota && opt.downloaded > opt.quota)
1530 /* A near-top-level function to retrieve the files in a directory.
1531 The function calls ftp_get_listing, to get a linked list of files.
1532 Then it weeds out the file names that do not match the pattern.
1533 ftp_retrieve_list is called with this updated list as an argument.
1535 If the argument ACTION is GETONE, just download the file (but first
1536 get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1537 use globbing; if it's GETALL, download the whole directory. */
1539 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1541 struct fileinfo *orig, *start;
1544 con->cmd |= LEAVE_PENDING;
1546 res = ftp_get_listing (u, con, &orig);
1550 /* First: weed out that do not conform the global rules given in
1551 opt.accepts and opt.rejects. */
1552 if (opt.accepts || opt.rejects)
1554 struct fileinfo *f = orig;
1558 if (f->type != FT_DIRECTORY && !acceptable (f->name))
1560 logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1561 f = delelement (f, &start);
1567 /* Now weed out the files that do not match our globbing pattern.
1568 If we are dealing with a globbing pattern, that is. */
1569 if (*u->file && (action == GLOBALL || action == GETONE))
1572 struct fileinfo *f = start;
1576 matchres = fnmatch (u->file, f->name, 0);
1579 logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1583 if (matchres == FNM_NOMATCH)
1584 f = delelement (f, &start); /* delete the element from the list */
1586 f = f->next; /* leave the element in the list */
1590 freefileinfo (start);
1591 return RETRBADPATTERN;
1597 /* Just get everything. */
1598 ftp_retrieve_list (u, start, con);
1602 if (action == GLOBALL)
1605 /* #### This message SUCKS. We should see what was the
1606 reason that nothing was retrieved. */
1607 logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1609 else /* GETONE or GETALL */
1611 /* Let's try retrieving it anyway. */
1612 con->st |= ON_YOUR_OWN;
1613 res = ftp_loop_internal (u, NULL, con);
1617 freefileinfo (start);
1618 if (downloaded_exceeds_quota ())
1621 /* #### Should we return `res' here? */
1625 /* The wrapper that calls an appropriate routine according to contents
1626 of URL. Inherently, its capabilities are limited on what can be
1627 encoded into a URL. */
1629 ftp_loop (struct urlinfo *u, int *dt)
1631 ccon con; /* FTP connection */
1636 memset (&con, 0, sizeof (con));
1638 rbuf_uninitialize (&con.rbuf);
1639 con.st = ON_YOUR_OWN;
1642 res = RETROK; /* in case it's not used */
1644 /* If the file name is empty, the user probably wants a directory
1645 index. We'll provide one, properly HTML-ized. Unless
1646 opt.htmlify is 0, of course. :-) */
1647 if (!*u->file && !opt.recursive)
1650 res = ftp_get_listing (u, &con, &f);
1656 char *filename = (opt.output_document
1657 ? xstrdup (opt.output_document)
1658 : (u->local ? xstrdup (u->local)
1659 : url_filename (u)));
1660 res = ftp_index (filename, u, f);
1661 if (res == FTPOK && opt.verbose)
1663 if (!opt.output_document)
1667 if (stat (filename, &st) == 0)
1671 logprintf (LOG_NOTQUIET,
1672 _("Wrote HTML-ized index to `%s' [%ld].\n"),
1676 logprintf (LOG_NOTQUIET,
1677 _("Wrote HTML-ized index to `%s'.\n"),
1687 int wild = has_wildcards_p (u->file);
1688 if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1690 /* ftp_retrieve_glob is a catch-all function that gets called
1691 if we need globbing, time-stamping or recursion. Its
1692 third argument is just what we really need. */
1693 ftp_retrieve_glob (u, &con,
1694 (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1697 res = ftp_loop_internal (u, NULL, &con);
1703 /* If a connection was left, quench it. */
1704 if (rbuf_initialized_p (&con.rbuf))
1705 CLOSE (RBUF_FD (&con.rbuf));
1706 FREE_MAYBE (con.id);
1711 /* Delete an element from the fileinfo linked list. Returns the
1712 address of the next element, or NULL if the list is exhausted. It
1713 can modify the start of the list. */
1714 static struct fileinfo *
1715 delelement (struct fileinfo *f, struct fileinfo **start)
1717 struct fileinfo *prev = f->prev;
1718 struct fileinfo *next = f->next;
1721 FREE_MAYBE (f->linkto);
1733 /* Free the fileinfo linked list of files. */
1735 freefileinfo (struct fileinfo *f)
1739 struct fileinfo *next = f->next;