X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fftp.c;h=8ce71fd66b89bdf340d882ce118afc4abbba6d68;hp=ab70114b33220b00005bc22e428d730bbeed8005;hb=7b5ad90acfc8c101a6cf919cd2a00217f0194e93;hpb=f4673bcdaf77ce854e8c8c999ab1ae6c9178ff99 diff --git a/src/ftp.c b/src/ftp.c index ab70114b..8ce71fd6 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -1,5 +1,5 @@ /* File Transfer Protocol support. - Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. This file is part of Wget. @@ -40,7 +40,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "rbuf.h" #include "retr.h" #include "ftp.h" -#include "html.h" #include "connect.h" #include "host.h" #include "fnmatch.h" @@ -58,6 +57,12 @@ extern int h_errno; extern char ftp_last_respline[]; +/* #### Global variables?? These two should be members of struct + ccon! */ + +static enum stype host_type=ST_UNIX; +static char *pwd; + /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in the string S, and return the number converted to long, if found, 0 otherwise. */ @@ -130,7 +135,7 @@ getftp (const struct urlinfo *u, long *len, long restval, ccon *con) search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1); user = user ? user : opt.ftp_acc; if (!opt.ftp_pass) - opt.ftp_pass = xstrdup (ftp_getaddress ()); + opt.ftp_pass = ftp_getaddress (); passwd = passwd ? passwd : opt.ftp_pass; assert (user && passwd); @@ -241,7 +246,63 @@ Error in server response, closing control connection.\n")); exit (1); break; } - /* Third: Set type to Image (binary). */ + /* Third: Get the system type */ + if (!opt.server_response) + logprintf (LOG_VERBOSE, "==> SYST ... "); + err = ftp_syst (&con->rbuf, &host_type); + /* FTPRERR */ + switch (err) + { + case FTPRERR: + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_NOTQUIET, _("\ +Error in server response, closing control connection.\n")); + CLOSE (csock); + rbuf_uninitialize (&con->rbuf); + return err; + break; + case FTPSRVERR: + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_NOTQUIET, + _("Server error, can't determine system type.\n")); + break; + case FTPOK: + /* Everything is OK. */ + break; + default: + abort (); + break; + } + if (!opt.server_response) + logputs (LOG_VERBOSE, _("done. ")); + + /* Fourth: Find the initial ftp directory */ + + if (!opt.server_response) + logprintf (LOG_VERBOSE, "==> PWD ... "); + err = ftp_pwd(&con->rbuf, &pwd); + /* FTPRERR */ + switch (err) + { + case FTPRERR || FTPSRVERR : + logputs (LOG_VERBOSE, "\n"); + logputs (LOG_NOTQUIET, _("\ +Error in server response, closing control connection.\n")); + CLOSE (csock); + rbuf_uninitialize (&con->rbuf); + return err; + break; + case FTPOK: + /* Everything is OK. */ + break; + default: + abort (); + break; + } + if (!opt.server_response) + logputs (LOG_VERBOSE, _("done.\n")); + + /* Fifth: Set the FTP type. */ if (!opt.server_response) logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type)); err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type)); @@ -289,10 +350,58 @@ Error in server response, closing control connection.\n")); logputs (LOG_VERBOSE, _("==> CWD not needed.\n")); else { - /* Change working directory. */ - if (!opt.server_response) - logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir); - err = ftp_cwd (&con->rbuf, u->dir); + /* Change working directory. If the FTP host runs VMS and + the path specified is absolute, we will have to convert + it to VMS style as VMS does not like leading slashes */ + DEBUGP (("changing working directory\n")); + if (*(u->dir) == '/') + { + int pwd_len = strlen (pwd); + char *result = (char *)alloca (strlen (u->dir) + pwd_len + 10); + *result = '\0'; + switch (host_type) + { + case ST_VMS: + { + char *tmp_dir, *tmpp; + STRDUP_ALLOCA (tmp_dir, u->dir); + for (tmpp = tmp_dir; *tmpp; tmpp++) + if (*tmpp=='/') + *tmpp = '.'; + strcpy (result, pwd); + /* pwd ends with ']', we have to get rid of it */ + result[pwd_len - 1]= '\0'; + strcat (result, tmp_dir); + strcat (result, "]"); + } + break; + case ST_UNIX: + case ST_WINNT: + /* pwd_len == 1 means pwd = "/", but u->dir begins with '/' + already */ + if (pwd_len > 1) + strcpy (result, pwd); + strcat (result, u->dir); + /* These look like debugging messages to me. */ +#if 0 + logprintf (LOG_VERBOSE, "\npwd=\"%s\"", pwd); + logprintf (LOG_VERBOSE, "\nu->dir=\"%s\"", u->dir); +#endif + break; + default: + abort (); + break; + } + if (!opt.server_response) + logprintf (LOG_VERBOSE, "==> CWD %s ... ", result); + err = ftp_cwd (&con->rbuf, result); + } + else + { + if (!opt.server_response) + logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir); + err = ftp_cwd (&con->rbuf, u->dir); + } /* FTPRERR, WRITEFAILED, FTPNSFOD */ switch (err) { @@ -648,6 +757,15 @@ Error in server response, closing control connection.\n")); expected_bytes = ftp_expected_bytes (ftp_last_respline); } /* cmd & DO_LIST */ + /* Some FTP servers return the total length of file after REST + command, others just return the remaining size. */ + if (*len && restval && expected_bytes + && (expected_bytes == *len - restval)) + { + DEBUGP (("Lying FTP server found, adjusting.\n")); + expected_bytes = *len; + } + /* If no transmission was required, then everything is OK. */ if (!(cmd & (DO_LIST | DO_RETR))) return RETRFINISHED; @@ -685,16 +803,16 @@ Error in server response, closing control connection.\n")); } } else - fp = opt.dfp; - - /* Some FTP servers return the total length of file after REST command, - others just return the remaining size. */ - if (*len && restval && expected_bytes - && (expected_bytes == *len - restval)) - { - DEBUGP (("Lying FTP server found, adjusting.\n")); - expected_bytes = *len; - } + { + fp = opt.dfp; + if (!restval) + { + /* This will silently fail for streams that don't correspond + to regular files, but that's OK. */ + rewind (fp); + clearerr (fp); + } + } if (*len) { @@ -713,7 +831,7 @@ Error in server response, closing control connection.\n")); } reset_timer (); /* Get the contents of the document. */ - res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf); + res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0); con->dltime = elapsed_time (); tms = time_str (NULL); tmrate = rate (*len - restval, con->dltime); @@ -755,7 +873,7 @@ Error in server response, closing control connection.\n")); rbuf_discard (&con->rbuf); if (err != FTPOK) { - free (respline); + xfree (respline); /* The control connection is decidedly closed. Print the time only if it hasn't already been printed. */ if (res != -1) @@ -775,13 +893,13 @@ Error in server response, closing control connection.\n")); become apparent later. */ if (*respline != '2') { - free (respline); + xfree (respline); if (res != -1) logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate); logputs (LOG_NOTQUIET, _("Data transfer aborted.\n")); return FTPRETRINT; } - free (respline); + xfree (respline); if (res == -1) { @@ -813,7 +931,7 @@ Error in server response, closing control connection.\n")); while ((line = read_whole_line (fp))) { logprintf (LOG_ALWAYS, "%s\n", line); - free (line); + xfree (line); } fclose (fp); } @@ -927,7 +1045,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) #ifdef WINDOWS ws_changetitle (hurl, 1); #endif - free (hurl); + xfree (hurl); } /* Send getftp the proper length, if fileinfo was provided. */ if (f) @@ -987,8 +1105,16 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) } logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"), tms, tmrate, locf, len); - logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n", - tms, u->url, len, locf, count); + if (!opt.verbose && !opt.quiet) + { + /* Need to hide the password from the URL. The `if' is here + so that we don't do the needless allocation every + time. */ + char *hurl = str_url (u->proxy ? u->proxy : u, 1); + logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n", + tms, hurl, len, locf, count); + xfree (hurl); + } if ((con->cmd & DO_LIST)) /* This is a directory listing file. */ @@ -997,7 +1123,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) /* --dont-remove-listing was specified, so do count this towards the number of bytes and files downloaded. */ { - opt.downloaded += len; + downloaded_increase (len); opt.numurls++; } @@ -1012,7 +1138,7 @@ ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con) downloaded if they're going to be deleted. People seeding proxies, for instance, may want to know how many bytes and files they've downloaded through it. */ - opt.downloaded += len; + downloaded_increase (len); opt.numurls++; if (opt.delete_after) @@ -1064,7 +1190,7 @@ ftp_get_listing (struct urlinfo *u, ccon *con) err = ftp_loop_internal (u, NULL, con); u->local = olocal; if (err == RETROK) - f = ftp_parse_ls (list_filename); + f = ftp_parse_ls (list_filename, host_type); else f = NULL; if (opt.remove_listing) @@ -1074,7 +1200,7 @@ ftp_get_listing (struct urlinfo *u, ccon *con) else logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename); } - free (list_filename); + xfree (list_filename); con->cmd &= ~DO_LIST; return f; } @@ -1133,7 +1259,7 @@ ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con) while (f) { - if (opt.quota && opt.downloaded > opt.quota) + if (downloaded_exceeds_quota ()) { --depth; return QUOTEXC; @@ -1166,8 +1292,17 @@ Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local); } else if (local_size != f->size) { - logprintf (LOG_VERBOSE, _("\ + if (host_type == ST_VMS) + { + logprintf (LOG_VERBOSE, _("\ +Cannot compare sizes, remote system is VMS.\n")); + dlthis = 0; + } + else + { + logprintf (LOG_VERBOSE, _("\ The sizes do not match (local %ld) -- retrieving.\n"), local_size); + } } } } /* opt.timestamping && f->type == FT_PLAINFILE */ @@ -1264,7 +1399,7 @@ Already have correct symlink %s -> %s\n\n"), else DEBUGP (("Unrecognized permissions for %s.\n", u->local)); - free (u->local); + xfree (u->local); u->local = olocal; u->file = ofile; /* Break on fatals. */ @@ -1299,7 +1434,7 @@ ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con) { int len; - if (opt.quota && opt.downloaded > opt.quota) + if (downloaded_exceeds_quota ()) break; if (f->type != FT_DIRECTORY) continue; @@ -1420,7 +1555,7 @@ ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action) } } freefileinfo (start); - if (opt.quota && opt.downloaded > opt.quota) + if (downloaded_exceeds_quota ()) return QUOTEXC; else /* #### Should we return `res' here? */ @@ -1477,7 +1612,7 @@ ftp_loop (struct urlinfo *u, int *dt) _("Wrote HTML-ized index to `%s'.\n"), filename); } - free (filename); + xfree (filename); } freefileinfo (f); } @@ -1503,6 +1638,8 @@ ftp_loop (struct urlinfo *u, int *dt) /* If a connection was left, quench it. */ if (rbuf_initialized_p (&con.rbuf)) CLOSE (RBUF_FD (&con.rbuf)); + FREE_MAYBE (pwd); + pwd = NULL; return res; } @@ -1515,9 +1652,9 @@ delelement (struct fileinfo *f, struct fileinfo **start) struct fileinfo *prev = f->prev; struct fileinfo *next = f->next; - free (f->name); + xfree (f->name); FREE_MAYBE (f->linkto); - free (f); + xfree (f); if (next) next->prev = prev; @@ -1535,10 +1672,10 @@ freefileinfo (struct fileinfo *f) while (f) { struct fileinfo *next = f->next; - free (f->name); + xfree (f->name); if (f->linkto) - free (f->linkto); - free (f); + xfree (f->linkto); + xfree (f); f = next; } }