]> git.saurik.com Git - apt.git/blobdiff - methods/ftp.cc
Fixed back pthread check
[apt.git] / methods / ftp.cc
index ace70cc7990adcc75cce9abb83c49d59dd4a6d11..7bd0a3e18cc290dddbac91c36a76baaa05f71d95 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: ftp.cc,v 1.3 1999/03/15 08:10:26 jgg Exp $
+// $Id: ftp.cc,v 1.13 1999/05/29 03:25:03 jgg Exp $
 /* ######################################################################
 
    HTTP Aquire Method - This is the FTP aquire method for APT.
 /* ######################################################################
 
    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.
    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                                                       /*{{{*/
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
@@ -33,9 +35,9 @@
 #include <arpa/inet.h>
 #include <netdb.h>
 
 #include <arpa/inet.h>
 #include <netdb.h>
 
+#include "rfc2553emu.h"
+#include "connect.h"
 #include "ftp.h"
 #include "ftp.h"
-
-
                                                                        /*}}}*/
 
 unsigned long TimeOut = 120;
                                                                        /*}}}*/
 
 unsigned long TimeOut = 120;
@@ -80,8 +82,6 @@ void FTPConn::Close()
 // ---------------------------------------------------------------------
 /* Connect to the server using a non-blocking connection and perform a 
    login. */
 // ---------------------------------------------------------------------
 /* 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.
 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
       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)
    {
    string Host;   
    if (Proxy.empty() == true)
    {
@@ -123,50 +123,14 @@ bool FTPConn::Open(pkgAcqMethod *Owner)
         Port = Proxy.Port;
       Host = Proxy.Host;
    }
         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",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();
 }
    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)
 {
 /* 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))
    {
    // Suck in a line
    while (Len < sizeof(Buffer))
    {
@@ -315,7 +282,7 @@ bool FTPConn::ReadLine(string &Text)
       }
       
       // Suck it back
       }
       
       // Suck it back
-      int Res = read(ServerFd,Buffer,sizeof(Buffer) - Len);
+      int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len);
       if (Res <= 0)
       {
         Close();
       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
         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;
       if (WaitFd(ServerFd,true,TimeOut) == false)
         return _error->Error("Could not connect data socket, connection timed out");
       unsigned int Err;
@@ -591,24 +558,23 @@ bool FTPConn::CreateDataFd()
    }
    
    // Port mode :<
    }
    
    // Port mode :<
-   if (DataListenFd == -1)
-   {
-      // Get a socket
-      if ((DataListenFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
-        return _error->Errno("socket","Could not create a socket");
-      
-      // Bind and listen
-      sockaddr_in Addr;
-      memset(&Addr,0,sizeof(Addr));
-      if (bind(DataListenFd,(sockaddr *)&Addr,sizeof(Addr)) < 0)
-        return _error->Errno("bind","Could not bind a socket");
-      if (listen(DataListenFd,1) < 0)
-        return _error->Errno("listen","Could not listen on the socket");
-      SetNonBlock(DataListenFd,true);
-   }
+   close(DataListenFd);
+   DataListenFd = -1;
+
+   // Get a socket
+   if ((DataListenFd = socket(AF_INET,SOCK_STREAM,0)) < 0)
+      return _error->Errno("socket","Could not create a socket");
    
    
-   // Determine the name to send to the remote
+   // Bind and listen
    sockaddr_in Addr;
    sockaddr_in Addr;
+   memset(&Addr,0,sizeof(Addr));
+   if (bind(DataListenFd,(sockaddr *)&Addr,sizeof(Addr)) < 0)
+      return _error->Errno("bind","Could not bind a socket");
+   if (listen(DataListenFd,1) < 0)
+      return _error->Errno("listen","Could not listen on the socket");
+   SetNonBlock(DataListenFd,true);
+   
+   // Determine the name to send to the remote
    sockaddr_in Addr2;
    socklen_t Jnk = sizeof(Addr);
    if (getsockname(DataListenFd,(sockaddr *)&Addr,&Jnk) < 0)
    sockaddr_in Addr2;
    socklen_t Jnk = sizeof(Addr);
    if (getsockname(DataListenFd,(sockaddr *)&Addr,&Jnk) < 0)
@@ -660,6 +626,9 @@ bool FTPConn::Finalize()
    if (DataFd < 0)
       return _error->Errno("accept","Unable to accept connection");
 
    if (DataFd < 0)
       return _error->Errno("accept","Unable to accept connection");
 
+   close(DataListenFd);
+   DataListenFd = -1;
+   
    return true;
 }
                                                                        /*}}}*/
    return true;
 }
                                                                        /*}}}*/
@@ -720,8 +689,11 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume,
    {
       // Wait for some data..
       if (WaitFd(DataFd,false,TimeOut) == false)
    {
       // 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)
       // Read the data..
       int Res = read(DataFd,Buffer,sizeof(Buffer));
       if (Res == 0)
@@ -735,7 +707,10 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long Resume,
    
       MD5.Add(Buffer,Res);
       if (To.Write(Buffer,Res) == false)
    
       MD5.Add(Buffer,Res);
       if (To.Write(Buffer,Res) == false)
+      {
+        Close();
         return false;
         return false;
+      }      
    }
 
    // All done
    }
 
    // All done
@@ -815,11 +790,13 @@ bool FtpMethod::Fetch(FetchItem *Itm)
    // Could not connect is a transient error..
    if (Server->Open(this) == false)
    {
    // Could not connect is a transient error..
    if (Server->Open(this) == false)
    {
+      Server->Close();
       Fail(true);
       return true;
    }
    
    // Get the files information
       Fail(true);
       return true;
    }
    
    // Get the files information
+   Status("Query");
    unsigned long Size;
    if (Server->Size(File,Size) == false ||
        Server->ModTime(File,FailTime) == false)
    unsigned long Size;
    if (Server->Size(File,Size) == false ||
        Server->ModTime(File,FailTime) == false)
@@ -898,8 +875,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();
    FtpMethod Mth;
    
    return Mth.Run();