📄 ftp.c
字号:
logprintf (LOG_VERBOSE, "==> CWD %s ... ", target); err = ftp_cwd (&con->rbuf, target); /* FTPRERR, WRITEFAILED, FTPNSFOD */ 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 WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"), u->dir); CLOSE (csock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); } } else /* do not CWD */ logputs (LOG_VERBOSE, _("==> CWD not required.\n")); if ((cmd & DO_RETR) && restval && *len == 0) { if (opt.verbose) { if (!opt.server_response) logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file); } err = ftp_size(&con->rbuf, u->file, len); /* FTPRERR */ switch (err) { case FTPRERR: case 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")); } /* If anything is to be retrieved, PORT (or PASV) must be sent. */ if (cmd & (DO_LIST | DO_RETR)) { if (opt.ftp_pasv > 0) { ip_address passive_addr; unsigned short passive_port; if (!opt.server_response) logputs (LOG_VERBOSE, "==> PASV ... "); err = ftp_pasv (&con->rbuf, &passive_addr, &passive_port); /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */ 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 WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPNOPASV: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n")); break; case FTPINVPASV: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n")); break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } /* switch(err) */ if (err==FTPOK) { dtsock = connect_to_one (&passive_addr, passive_port, 1); if (dtsock < 0) { int save_errno = errno; CLOSE (csock); rbuf_uninitialize (&con->rbuf); logprintf (LOG_VERBOSE, _("couldn't connect to %s:%hu: %s\n"), pretty_print_address (&passive_addr), passive_port, strerror (save_errno)); return CONNECT_ERROR (save_errno); } pasv_mode_open = 1; /* Flag to avoid accept port */ if (!opt.server_response) logputs (LOG_VERBOSE, _("done. ")); } /* err==FTP_OK */ } if (!pasv_mode_open) /* Try to use a port command if PASV failed */ { if (!opt.server_response) logputs (LOG_VERBOSE, "==> PORT ... "); err = ftp_port (&con->rbuf); /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR, LISTENERR), HOSTERR, FTPPORTERR */ switch (err) { case FTPRERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case CONSOCKERR: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno)); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case CONPORTERR: case BINDERR: case LISTENERR: /* What now? These problems are local... */ logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"), strerror (errno)); closeport (dtsock); return err; break; case FTPPORTERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Invalid PORT.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } /* port switch */ if (!opt.server_response) logputs (LOG_VERBOSE, _("done. ")); } /* dtsock == -1 */ } /* cmd & (DO_LIST | DO_RETR) */ /* Restart if needed. */ if (restval && (cmd & DO_RETR)) { if (!opt.server_response) logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval); err = ftp_rest (&con->rbuf, restval); /* FTPRERR, WRITEFAILED, FTPRESTFAIL */ switch (err) { case FTPRERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPRESTFAIL: /* If `-c' is specified and the file already existed when Wget was started, it would be a bad idea for us to start downloading it from scratch, effectively truncating it. */ if (opt.always_rest && (cmd & NO_TRUNCATE)) { logprintf (LOG_NOTQUIET, _("\nREST failed; will not truncate `%s'.\n"), con->target); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return CONTNOTSUPPORTED; } logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n")); restval = 0L; break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } if (err != FTPRESTFAIL && !opt.server_response) logputs (LOG_VERBOSE, _("done. ")); } /* restval && cmd & DO_RETR */ if (cmd & DO_RETR) { /* If we're in spider mode, don't really retrieve anything. The fact that we got to this point should be proof enough that the file exists, vaguely akin to HTTP's concept of a "HEAD" request. */ if (opt.spider) { CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return RETRFINISHED; } if (opt.verbose) { if (!opt.server_response) { if (restval) logputs (LOG_VERBOSE, "\n"); logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file); } } err = ftp_retr (&con->rbuf, u->file); /* FTPRERR, WRITEFAILED, FTPNSFOD */ switch (err) { case FTPRERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file); closeport (dtsock); return err; break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); expected_bytes = ftp_expected_bytes (ftp_last_respline); } /* do retrieve */ if (cmd & DO_LIST) { if (!opt.server_response) logputs (LOG_VERBOSE, "==> LIST ... "); /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST' without arguments is better than `LIST .'; confirmed by RFC959. */ err = ftp_list (&con->rbuf, NULL); /* FTPRERR, WRITEFAILED */ switch (err) { case FTPRERR: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("\Error in server response, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case WRITEFAILED: logputs (LOG_VERBOSE, "\n"); logputs (LOG_NOTQUIET, _("Write failed, closing control connection.\n")); CLOSE (csock); closeport (dtsock); rbuf_uninitialize (&con->rbuf); return err; break; case FTPNSFOD: logputs (LOG_VERBOSE, "\n"); logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"), "."); closeport (dtsock); return err; break; case FTPOK: /* fine and dandy */ break; default: abort (); break; } if (!opt.server_response) logputs (LOG_VERBOSE, _("done.\n")); expected_bytes = ftp_expected_bytes (ftp_last_respline); } /* cmd & DO_LIST */ if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST))) return RETRFINISHED; /* 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 (!pasv_mode_open) /* we are not using pasive mode so we need to accept */ { /* Open the data transmission socket by calling acceptport(). */ err = acceptport (&dtsock); /* Possible errors: ACCEPTERR. */ if (err == ACCEPTERR) { logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno)); return err; } } /* Open the file -- if opt.dfp is set, use it instead. */ if (!opt.dfp || con->cmd & DO_LIST) { mkalldirs (con->target); if (opt.backups) rotate_backups (con->target); /* #### Is this correct? */ chmod (con->target, 0600); fp = fopen (con->target, restval ? "ab" : "wb"); if (!fp) { logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno)); CLOSE (csock); rbuf_uninitialize (&con->rbuf); closeport (dtsock); return FOPENERR; } } else { extern int global_download_count; fp = opt.dfp; /* Rewind the output document if the download starts over and if this is the first download. See gethttp() for a longer explanation. */ if (!restval && global_download_count == 0 && opt.dfp != stdout) { /* This will silently fail for streams that don't correspond to regular files, but that's OK. */ rewind (fp); /* ftruncate is needed because opt.dfp is opened in append mode if opt.always_rest is set. */ ftruncate (fileno (fp), 0); clearerr (fp); } } if (*len) { logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len)); if (restval) logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval)); logputs (LOG_VERBOSE, "\n"); expected_bytes = *len; /* for get_contents/show_progress */ } else if (expected_bytes) { logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes)); if (restval) logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (expected_bytes - restval)); logputs (LOG_VERBOSE, _(" (unauthoritative)\n")); } /* Get the contents of the document. */ res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0, &con->dltime); tms = time_str (NULL); tmrate = retr_rate (*len - restval, con->dltime, 0); /* Close data connection socket. */ closeport (dtsock); /* Close the local file. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -