// $Id: ftp.cc,v 1.31.2.1 2004/01/16 18:58:50 mdz Exp $
/* ######################################################################
- FTP Aquire Method - This is the FTP aquire method for APT.
+ FTP Acquire Method - This is the FTP acquire method for APT.
This is a very simple implementation that does not try to optimize
at all. Commands are sent syncronously with the FTP server (as the
#include <apt-pkg/error.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/netrc.h>
+#include <apt-pkg/configuration.h>
+#include <apt-pkg/strutl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
-#include <utime.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
// Internet stuff
#include <netinet/in.h>
-#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "rfc2553emu.h"
#include "connect.h"
#include "ftp.h"
+
#include <apti18n.h>
/*}}}*/
};
#ifndef AF_INET6
-struct AFMap AFMap[] = {{AF_INET,1},{}};
+struct AFMap AFMap[] = {{AF_INET,1},{0, 0}};
#else
-struct AFMap AFMap[] = {{AF_INET,1},{AF_INET6,2},{}};
+struct AFMap AFMap[] = {{AF_INET,1},{AF_INET6,2},{0, 0}};
#endif
unsigned long TimeOut = 120;
// FTPConn::FTPConn - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-FTPConn::FTPConn(URI Srv) : Len(0), ServerFd(-1), DataFd(-1),
+FTPConn::FTPConn(URI Srv) : Len(0), ServerFd(-1), DataFd(-1),
DataListenFd(-1), ServerName(Srv),
- ForceExtended(false), TryPassive(true)
+ ForceExtended(false), TryPassive(true),
+ PeerAddrLen(0), ServerAddrLen(0)
{
Debug = _config->FindB("Debug::Acquire::Ftp",false);
PasvAddr = 0;
+ Buffer[0] = '\0';
}
/*}}}*/
// FTPConn::~FTPConn - Destructor /*{{{*/
{
if (Opts->Value.empty() == true)
continue;
-
+
// Substitute the variables into the command
- char SitePort[20];
- if (ServerName.Port != 0)
- sprintf(SitePort,"%u",ServerName.Port);
- else
- strcpy(SitePort,"21");
string Tmp = Opts->Value;
Tmp = SubstVar(Tmp,"$(PROXY_USER)",Proxy.User);
Tmp = SubstVar(Tmp,"$(PROXY_PASS)",Proxy.Password);
Tmp = SubstVar(Tmp,"$(SITE_USER)",User);
Tmp = SubstVar(Tmp,"$(SITE_PASS)",Pass);
- Tmp = SubstVar(Tmp,"$(SITE_PORT)",SitePort);
+ if (ServerName.Port != 0)
+ {
+ std::string SitePort;
+ strprintf(SitePort, "%u", ServerName.Port);
+ Tmp = SubstVar(Tmp,"$(SITE_PORT)", SitePort);
+ }
+ else
+ Tmp = SubstVar(Tmp,"$(SITE_PORT)", "21");
Tmp = SubstVar(Tmp,"$(SITE)",ServerName.Host);
// Send the command
char S[400];
vsnprintf(S,sizeof(S) - 4,Fmt,args);
strcat(S,"\r\n");
+ va_end(args);
if (Debug == true)
cerr << "-> '" << QuoteString(S,"") << "'" << endl;
}
// Get a new passive address.
- int Res;
- if ((Res = getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr)) != 0)
+ if (getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr) != 0)
return true;
return true;
DataListenFd = -1;
// Get the information for a listening socket.
- struct addrinfo *BindAddr = 0;
+ struct addrinfo *BindAddr = NULL;
struct addrinfo Hints;
memset(&Hints,0,sizeof(Hints));
Hints.ai_socktype = SOCK_STREAM;
Hints.ai_flags |= AI_PASSIVE;
Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
- int Res;
- if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
+ if (getaddrinfo(0,"0",&Hints,&BindAddr) != 0 || BindAddr == NULL)
return _error->Error(_("getaddrinfo was unable to get a listening socket"));
// Construct the socket
}
// Bind and listen
- if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
+ if (::bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
{
freeaddrinfo(BindAddr);
return _error->Errno("bind",_("Could not bind a socket"));
/* This opens a data connection, sends REST and RETR and then
transfers the file over. */
bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume,
- Hashes &Hash,bool &Missing)
+ Hashes &Hash,bool &Missing, unsigned long long MaximumSize,
+ pkgAcqMethod *Owner)
{
Missing = false;
if (CreateDataFd() == false)
if (Resume != 0)
{
- if (Hash.AddFD(To.Fd(),Resume) == false)
+ if (Hash.AddFD(To,Resume) == false)
{
_error->Errno("read",_("Problem hashing file"));
return false;
{
Close();
return false;
- }
+ }
+
+ if (MaximumSize > 0 && To.Tell() > MaximumSize)
+ {
+ Owner->SetFailReason("MaximumSizeExceeded");
+ return _error->Error("Writing more data than expected (%llu > %llu)",
+ To.Tell(), MaximumSize);
+ }
}
// All done
/*}}}*/
// FtpMethod::SigTerm - Handle a fatal signal /*{{{*/
// ---------------------------------------------------------------------
-/* This closes and timestamps the open file. This is neccessary to get
+/* This closes and timestamps the open file. This is necessary to get
resume behavoir on user abort */
void FtpMethod::SigTerm(int)
{
if (FailFd == -1)
_exit(100);
- close(FailFd);
-
+
// Timestamp
- struct utimbuf UBuf;
- UBuf.actime = FailTime;
- UBuf.modtime = FailTime;
- utime(FailFile.c_str(),&UBuf);
-
+ struct timeval times[2];
+ times[0].tv_sec = FailTime;
+ times[1].tv_sec = FailTime;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ utimes(FailFile.c_str(), times);
+
+ close(FailFd);
+
_exit(100);
}
/*}}}*/
return false;
TimeOut = _config->FindI("Acquire::Ftp::Timeout",TimeOut);
+
+ // no more active ftp, sorry
+ DropPrivsOrDie();
+
return true;
}
/*}}}*/
}
// Open the file
- Hashes Hash;
+ Hashes Hash(Itm->ExpectedHashes);
{
FileFd Fd(Itm->DestFile,FileFd::WriteAny);
if (_error->PendingError() == true)
URIStart(Res);
FailFile = Itm->DestFile;
- FailFile.c_str(); // Make sure we dont do a malloc in the signal handler
+ FailFile.c_str(); // Make sure we don't do a malloc in the signal handler
FailFd = Fd.Fd();
bool Missing;
- if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing) == false)
+ if (Server->Get(File,Fd,Res.ResumePoint,Hash,Missing,Itm->MaximumSize,this) == false)
{
Fd.Close();
-
+
// Timestamp
- struct utimbuf UBuf;
- UBuf.actime = FailTime;
- UBuf.modtime = FailTime;
- utime(FailFile.c_str(),&UBuf);
-
+ struct timeval times[2];
+ times[0].tv_sec = FailTime;
+ times[1].tv_sec = FailTime;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ utimes(FailFile.c_str(), times);
+
// If the file is missing we hard fail and delete the destfile
// otherwise transient fail
if (Missing == true) {
}
Res.Size = Fd.Size();
+
+ // Timestamp
+ struct timeval times[2];
+ times[0].tv_sec = FailTime;
+ times[1].tv_sec = FailTime;
+ times[0].tv_usec = times[1].tv_usec = 0;
+ utimes(Fd.Name().c_str(), times);
+ FailFd = -1;
}
-
+
Res.LastModified = FailTime;
Res.TakeHashes(Hash);
-
- // Timestamp
- struct utimbuf UBuf;
- UBuf.actime = FailTime;
- UBuf.modtime = FailTime;
- utime(Queue->DestFile.c_str(),&UBuf);
- FailFd = -1;
URIDone(Res);
-
+
return true;
}
/*}}}*/
-int main(int argc,const char *argv[])
+int main(int, const char *argv[])
{
setlocale(LC_ALL, "");
}
FtpMethod Mth;
-
+
return Mth.Run();
}