X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/f26f6d3820f47ea4f072a0804636c2871a02bf61..17c0e8e1f979c0638c354614b29a8ec484e8f44e:/methods/ftp.cc diff --git a/methods/ftp.cc b/methods/ftp.cc index 09fbaeb7f..6f4b00307 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: ftp.cc,v 1.5 1999/03/15 19:51:27 jgg Exp $ +// $Id: ftp.cc,v 1.15 1999/09/05 05:41:41 jgg Exp $ /* ###################################################################### HTTP Aquire Method - This is the FTP aquire method for APT. @@ -9,7 +9,9 @@ at all. Commands are sent syncronously with the FTP server (as the rfc recommends, but it is not really necessary..) and no tricks are done to speed things along. - + + RFC 2428 describes the IPv6 FTP behavior + ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ @@ -33,9 +35,9 @@ #include #include +#include "rfc2553emu.h" +#include "connect.h" #include "ftp.h" - - /*}}}*/ unsigned long TimeOut = 120; @@ -80,8 +82,6 @@ void FTPConn::Close() // --------------------------------------------------------------------- /* Connect to the server using a non-blocking connection and perform a login. */ -string LastHost; -in_addr LastHostA; bool FTPConn::Open(pkgAcqMethod *Owner) { // Use the already open connection if possible. @@ -109,7 +109,7 @@ bool FTPConn::Open(pkgAcqMethod *Owner) Proxy = getenv("ftp_proxy"); // Determine what host and port to use based on the proxy settings - int Port = 21; + int Port = 0; string Host; if (Proxy.empty() == true) { @@ -123,50 +123,14 @@ bool FTPConn::Open(pkgAcqMethod *Owner) Port = Proxy.Port; Host = Proxy.Host; } - - /* We used a cached address record.. Yes this is against the spec but - the way we have setup our rotating dns suggests that this is more - sensible */ - if (LastHost != Host) - { - Owner->Status("Connecting to %s",Host.c_str()); - - // Lookup the host - hostent *Addr = gethostbyname(Host.c_str()); - if (Addr == 0 || Addr->h_addr_list[0] == 0) - return _error->Error("Could not resolve '%s'",Host.c_str()); - LastHost = Host; - LastHostA = *(in_addr *)(Addr->h_addr_list[0]); - } - - Owner->Status("Connecting to %s (%s)",Host.c_str(),inet_ntoa(LastHostA)); - - // Get a socket - if ((ServerFd = socket(AF_INET,SOCK_STREAM,0)) < 0) - return _error->Errno("socket","Could not create a socket"); - - // Connect to the server - struct sockaddr_in server; - server.sin_family = AF_INET; - server.sin_port = htons(Port); - server.sin_addr = LastHostA; - SetNonBlock(ServerFd,true); - if (connect(ServerFd,(sockaddr *)&server,sizeof(server)) < 0 && - errno != EINPROGRESS) - return _error->Errno("socket","Could not create a socket"); - Peer = server; - - /* This implements a timeout for connect by opening the connection - nonblocking */ - if (WaitFd(ServerFd,true,TimeOut) == false) - return _error->Error("Could not connect, connection timed out"); - unsigned int Err; - unsigned int Len = sizeof(Err); - if (getsockopt(ServerFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0) - return _error->Errno("getsockopt","Failed"); - if (Err != 0) - return _error->Error("Could not connect."); + // Connect to the remote server + if (Connect(Host,Port,"ftp",21,ServerFd,TimeOut,Owner) == false) + return false; + socklen_t Len = sizeof(Peer); + if (getpeername(ServerFd,(sockaddr *)&Peer,&Len) != 0) + return _error->Errno("getpeername","Unable to determine the peer name"); + Owner->Status("Logging in"); return Login(); } @@ -286,6 +250,9 @@ bool FTPConn::Login() /* This performs a very simple buffered read. */ bool FTPConn::ReadLine(string &Text) { + if (ServerFd == -1) + return false; + // Suck in a line while (Len < sizeof(Buffer)) { @@ -315,7 +282,7 @@ bool FTPConn::ReadLine(string &Text) } // Suck it back - int Res = read(ServerFd,Buffer,sizeof(Buffer) - Len); + int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len); if (Res <= 0) { Close(); @@ -577,7 +544,7 @@ bool FTPConn::CreateDataFd() return _error->Errno("socket","Could not create a socket"); /* This implements a timeout for connect by opening the connection - nonblocking */ + nonblocking */ if (WaitFd(ServerFd,true,TimeOut) == false) return _error->Error("Could not connect data socket, connection timed out"); unsigned int Err; @@ -722,8 +689,11 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, { // Wait for some data.. if (WaitFd(DataFd,false,TimeOut) == false) - return _error->Error("Data socket connect timed out"); - + { + Close(); + return _error->Error("Data socket timed out"); + } + // Read the data.. int Res = read(DataFd,Buffer,sizeof(Buffer)); if (Res == 0) @@ -737,7 +707,10 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume, MD5.Add(Buffer,Res); if (To.Write(Buffer,Res) == false) + { + Close(); return false; + } } // All done @@ -817,6 +790,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) // Could not connect is a transient error.. if (Server->Open(this) == false) { + Server->Close(); Fail(true); return true; } @@ -874,6 +848,15 @@ bool FtpMethod::Fetch(FetchItem *Itm) bool Missing; if (Server->Get(File,Fd,Res.ResumePoint,MD5,Missing) == false) { + Fd.Close(); + + // Timestamp + struct utimbuf UBuf; + time(&UBuf.actime); + UBuf.actime = FailTime; + UBuf.modtime = FailTime; + utime(FailFile.c_str(),&UBuf); + // If the file is missing we hard fail otherwise transient fail if (Missing == true) return false; @@ -901,8 +884,28 @@ bool FtpMethod::Fetch(FetchItem *Itm) } /*}}}*/ -int main() +int main(int argc,const char *argv[]) { + /* See if we should be come the http client - we do this for http + proxy urls */ + if (getenv("ftp_proxy") != 0) + { + URI Proxy = string(getenv("ftp_proxy")); + if (Proxy.Access == "http") + { + // Copy over the environment setting + char S[300]; + snprintf(S,sizeof(S),"http_proxy=%s",getenv("ftp_proxy")); + putenv(S); + + // Run the http method + string Path = flNotFile(argv[0]) + "/http"; + execl(Path.c_str(),Path.c_str(),0); + cerr << "Unable to invoke " << Path << endl; + exit(100); + } + } + FtpMethod Mth; return Mth.Run();