// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: ftp.cc,v 1.9 1999/05/23 23:30:09 jgg Exp $
+// $Id: ftp.cc,v 1.19 2000/01/10 03:44:54 jgg Exp $
/* ######################################################################
HTTP Aquire Method - This is the FTP aquire method for APT.
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 <arpa/inet.h>
#include <netdb.h>
+#include "rfc2553emu.h"
+#include "connect.h"
#include "ftp.h"
-
-
/*}}}*/
unsigned long TimeOut = 120;
// ---------------------------------------------------------------------
/* 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.
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)
{
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();
}
int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len);
if (Res <= 0)
{
+ _error->Errno("read","Read error");
Close();
- return _error->Errno("read","Read error");
+ return false;
}
Len += Res;
}
int Res = write(ServerFd,S + Start,Len);
if (Res <= 0)
{
+ _error->Errno("write","Write Error");
Close();
- return _error->Errno("write","Write Error");
+ return false;
}
Len -= Res;
return true;
// Parse it
- struct tm tm;
- memset(&tm,0,sizeof(tm));
- if (sscanf(Msg.c_str(),"%4d%2d%2d%2d%2d%2d",&tm.tm_year,&tm.tm_mon,
- &tm.tm_mday,&tm.tm_hour,&tm.tm_min,&tm.tm_sec) != 6)
- return true;
-
- tm.tm_year -= 1900;
- tm.tm_mon--;
-
- /* We use timegm from the GNU C library, libapt-pkg will provide this
- symbol if it does not exist */
- Time = timegm(&tm);
+ StrToTime(Msg,Time);
return true;
}
/*}}}*/
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;
void FtpMethod::SigTerm(int)
{
if (FailFd == -1)
- exit(100);
+ _exit(100);
close(FailFd);
// Timestamp
UBuf.modtime = FailTime;
utime(FailFile.c_str(),&UBuf);
- exit(100);
+ _exit(100);
}
/*}}}*/
// FtpMethod::Configuration - Handle a configuration message /*{{{*/
// Could not connect is a transient error..
if (Server->Open(this) == false)
{
+ Server->Close();
Fail(true);
return true;
}
{
Res.Size = Buf.st_size;
Res.LastModified = Buf.st_mtime;
+ Res.ResumePoint = Buf.st_size;
URIDone(Res);
return true;
}
bool Missing;
if (Server->Get(File,Fd,Res.ResumePoint,MD5,Missing) == false)
{
+ Fd.Close();
+
+ // Timestamp
+ struct utimbuf UBuf;
+ 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;
// Timestamp
struct utimbuf UBuf;
- time(&UBuf.actime);
UBuf.actime = FailTime;
UBuf.modtime = FailTime;
utime(Queue->DestFile.c_str(),&UBuf);