X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/5abee4863220c2d9b135dc832b33c8680e5ba12e..91414dd77ec7efe1d3fc053e32cbe4d82263e015:/methods/ftp.cc?ds=sidebyside diff --git a/methods/ftp.cc b/methods/ftp.cc index ad8a7b828..a8bc95938 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -3,7 +3,7 @@ // $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 @@ -23,10 +23,13 @@ #include #include #include +#include +#include +#include +#include #include #include -#include #include #include #include @@ -36,13 +39,13 @@ // Internet stuff #include -#include #include #include #include "rfc2553emu.h" #include "connect.h" #include "ftp.h" + #include /*}}}*/ @@ -57,9 +60,9 @@ struct AFMap }; #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; @@ -71,12 +74,14 @@ time_t FtpMethod::FailTime = 0; // 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 /*{{{*/ @@ -253,19 +258,21 @@ bool FTPConn::Login() { 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 @@ -435,6 +442,7 @@ bool FTPConn::WriteMsg(unsigned int &Ret,string &Text,const char *Fmt,...) char S[400]; vsnprintf(S,sizeof(S) - 4,Fmt,args); strcat(S,"\r\n"); + va_end(args); if (Debug == true) cerr << "-> '" << QuoteString(S,"") << "'" << endl; @@ -621,8 +629,7 @@ bool FTPConn::ExtGoPasv() } // 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; @@ -720,14 +727,13 @@ bool FTPConn::CreateDataFd() 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 @@ -739,7 +745,7 @@ bool FTPConn::CreateDataFd() } // 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")); @@ -844,7 +850,8 @@ bool FTPConn::Finalize() /* 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) @@ -917,7 +924,14 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume, { 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 @@ -936,7 +950,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume, // FtpMethod::FtpMethod - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -FtpMethod::FtpMethod() : pkgAcqMethod("1.0",SendConfig) +FtpMethod::FtpMethod() : aptMethod("ftp","1.0",SendConfig) { signal(SIGTERM,SigTerm); signal(SIGINT,SigTerm); @@ -947,20 +961,22 @@ FtpMethod::FtpMethod() : pkgAcqMethod("1.0",SendConfig) /*}}}*/ // 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); } /*}}}*/ @@ -969,10 +985,11 @@ void FtpMethod::SigTerm(int) /* We stash the desired pipeline depth */ bool FtpMethod::Configuration(string Message) { - if (pkgAcqMethod::Configuration(Message) == false) + if (aptMethod::Configuration(Message) == false) return false; - + TimeOut = _config->FindI("Acquire::Ftp::Timeout",TimeOut); + return true; } /*}}}*/ @@ -1043,7 +1060,7 @@ bool FtpMethod::Fetch(FetchItem *Itm) } // Open the file - Hashes Hash; + Hashes Hash(Itm->ExpectedHashes); { FileFd Fd(Itm->DestFile,FileFd::WriteAny); if (_error->PendingError() == true) @@ -1052,24 +1069,25 @@ bool FtpMethod::Fetch(FetchItem *Itm) 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) { - unlink(FailFile.c_str()); + RemoveFile("ftp", FailFile); return false; } Fail(true); @@ -1077,25 +1095,26 @@ bool FtpMethod::Fetch(FetchItem *Itm) } 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, ""); @@ -1123,6 +1142,6 @@ int main(int argc,const char *argv[]) } FtpMethod Mth; - + return Mth.Run(); }