]> git.saurik.com Git - apt.git/blobdiff - methods/ftp.cc
CD swapping support
[apt.git] / methods / ftp.cc
index 145858f1f6c2e6c66fcb63391d97e2a70665b457..7bd0a3e18cc290dddbac91c36a76baaa05f71d95 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: ftp.cc,v 1.6 1999/04/11 21:23:10 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.
@@ -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 <arpa/inet.h>
 #include <netdb.h>
 
+#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",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();
 }
@@ -580,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;
@@ -725,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)
@@ -740,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
@@ -820,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;
    }
@@ -904,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();