X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/6cb30d01f8e247e85966ba8ad657453d73598527..d4a6c3bbb1a57494256ad09c08cc21c9d4f2182a:/apt-pkg/acquire-item.cc?ds=inline diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 5d741af6f..b48972c22 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -103,7 +103,8 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string, { // We just downloaded something.. string FileName = LookupTag(Message,"Filename"); - if (Complete == false && FileName == DestFile) + // we only inform the Log class if it was actually not a local thing + if (Complete == false && !Local && FileName == DestFile) { if (Owner->Log != 0) Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str())); @@ -134,70 +135,63 @@ void pkgAcquire::Item::Rename(string From,string To) } /*}}}*/ -// AcqIndexDiffs::AcqIndexDiffs - Constructor + +// AcqDiffIndex::AcqDiffIndex - Constructor // --------------------------------------------------------------------- -/* The package diff is added to the queue. one object is constructed - * for each diff and the index +/* Get the DiffIndex file first and see if there are patches availabe + * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the + * patches. If anything goes wrong in that process, it will fall back to + * the original packages file */ -pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, - string URI,string URIDesc,string ShortDesc, - string ExpectedMD5, vector diffs) - : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), needed_files(diffs) +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, + string URI,string URIDesc,string ShortDesc, + string ExpectedMD5) + : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc) { - DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(URI); - Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - Desc.Description = URIDesc; + Desc.Description = URIDesc + "/DiffIndex"; Desc.Owner = this; Desc.ShortDesc = ShortDesc; + Desc.URI = URI + ".diff/Index"; + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(URI) + string(".DiffIndex"); + + if(Debug) + std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; + + // look for the current package file CurrentPackagesFile = _config->FindDir("Dir::State::lists"); CurrentPackagesFile += URItoFileName(RealURI); - if(Debug) { - std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " - << CurrentPackagesFile << std::endl; - } - + // FIXME: this file:/ check is a hack to prevent fetching + // from local sources. this is really silly, and + // should be fixed cleanly as soon as possible if(!FileExists(CurrentPackagesFile) || - !_config->FindB("Acquire::Diffs",true)) { + Desc.URI.substr(0,strlen("file:/")) == "file:/") + { // we don't have a pkg file or we don't want to queue if(Debug) - std::clog << "No index file or canceld by user" << std::endl; + std::clog << "No index file, local or canceld by user" << std::endl; Failed("", NULL); return; } - if(needed_files.size() == 0) - QueueDiffIndex(URI); - else - QueueNextDiff(); -} - -void pkgAcqIndexDiffs::QueueDiffIndex(string URI) -{ - Desc.URI = URI + ".diff/Index"; - Desc.Description = Description + "IndexDiff"; - DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(URI) + string(".IndexDiff"); - - if(Debug) - std::clog << "QueueDiffIndex: " << Desc.URI << std::endl; - + if(Debug) + std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " + << CurrentPackagesFile << std::endl; + QueueURI(Desc); + } // AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ // --------------------------------------------------------------------- /* The only header we use is the last-modified header. */ -string pkgAcqIndexDiffs::Custom600Headers() +string pkgAcqDiffIndex::Custom600Headers() { - if(DestFile.rfind(".IndexDiff") == string::npos) - return string(""); - string Final = _config->FindDir("Dir::State::lists"); Final += URItoFileName(RealURI) + string(".IndexDiff"); @@ -211,12 +205,181 @@ string pkgAcqIndexDiffs::Custom600Headers() return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); } + +bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile + << std::endl; + + pkgTagSection Tags; + string ServerSha1; + vector available_patches; + + FileFd Fd(IndexDiffFile,FileFd::ReadOnly); + pkgTagFile TF(&Fd); + if (_error->PendingError() == true) + return false; + + if(TF.Step(Tags) == true) + { + string local_sha1; + bool found = false; + DiffInfo d; + string size; + + string tmp = Tags.FindS("SHA1-Current"); + std::stringstream ss(tmp); + ss >> ServerSha1; + + FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + SHA1Summation SHA1; + SHA1.AddFD(fd.Fd(), fd.Size()); + local_sha1 = string(SHA1.Result()); + + if(local_sha1 == ServerSha1) + { + // we have the same sha1 as the server + if(Debug) + std::clog << "Package file is up-to-date" << std::endl; + // set found to true, this will queue a pkgAcqIndexDiffs with + // a empty availabe_patches + found = true; + } + else + { + if(Debug) + std::clog << "SHA1-Current: " << ServerSha1 << std::endl; + + // check the historie and see what patches we need + string history = Tags.FindS("SHA1-History"); + std::stringstream hist(history); + while(hist >> d.sha1 >> size >> d.file) + { + d.size = atoi(size.c_str()); + // read until the first match is found + if(d.sha1 == local_sha1) + found=true; + // from that point on, we probably need all diffs + if(found) + { + if(Debug) + std::clog << "Need to get diff: " << d.file << std::endl; + available_patches.push_back(d); + } + } + } + + // no information how to get the patches, bail out + if(!found) + { + if(Debug) + std::clog << "Can't find a patch in the index file" << std::endl; + // Failed will queue a big package file + Failed("", NULL); + } + else + { + // queue the diffs + new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, + ExpectedMD5, available_patches); + Complete = false; + Status = StatDone; + Dequeue(); + return true; + } + } + + return false; +} + +void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +{ + if(Debug) + std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl + << "Falling back to normal index file aquire" << std::endl; + + new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, + ExpectedMD5); + + Complete = false; + Status = StatDone; + Dequeue(); +} + +void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf) +{ + if(Debug) + std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; + + Item::Done(Message,Size,Md5Hash,Cnf); + + string FinalFile; + FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); + + // sucess in downloading the index + // rename the index + FinalFile += string(".IndexDiff"); + if(Debug) + std::clog << "Renaming: " << DestFile << " -> " << FinalFile + << std::endl; + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); + DestFile = FinalFile; + + if(!ParseDiffIndex(DestFile)) + return Failed("", NULL); + + Complete = true; + Status = StatDone; + Dequeue(); + return; +} + + + +// AcqIndexDiffs::AcqIndexDiffs - Constructor +// --------------------------------------------------------------------- +/* The package diff is added to the queue. one object is constructed + * for each diff and the index + */ +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, + string URI,string URIDesc,string ShortDesc, + string ExpectedMD5, vector diffs) + : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), + available_patches(diffs) +{ + + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(URI); + + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + + Desc.Description = URIDesc; + Desc.Owner = this; + Desc.ShortDesc = ShortDesc; + + if(available_patches.size() == 0) + { + // we are done (yeah!) + Finish(true); + } + else + { + // get the next diff + State = StateFetchDiff; + QueueNextDiff(); + } +} + + void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf) { if(Debug) - std::clog << "Failed(): " << Desc.URI << std::endl - << "Falling back to big package file" << std::endl; - new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc, + std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl + << "Falling back to normal index file aquire" << std::endl; + new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, ExpectedMD5); Finish(); } @@ -227,16 +390,34 @@ void pkgAcqIndexDiffs::Finish(bool allDone) { // we restore the original name, this is required, otherwise // the file will be cleaned - if(allDone) { - // this is for the "real" finish + if(allDone) + { DestFile = _config->FindDir("Dir::State::lists"); DestFile += URItoFileName(RealURI); + + // do the final md5sum checking + MD5Summation sum; + FileFd Fd(DestFile, FileFd::ReadOnly); + sum.AddFD(Fd.Fd(), Fd.Size()); + Fd.Close(); + string MD5 = (string)sum.Result(); + + if (!ExpectedMD5.empty() && MD5 != ExpectedMD5) + { + Status = StatAuthError; + ErrorText = _("MD5Sum mismatch"); + Rename(DestFile,DestFile + ".FAILED"); + Dequeue(); + return; + } + + // this is for the "real" finish Complete = true; + Status = StatDone; Dequeue(); if(Debug) std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; return; - } if(Debug) @@ -248,45 +429,46 @@ void pkgAcqIndexDiffs::Finish(bool allDone) } -// this needs to be rewriten to not depend on the external ed -bool pkgAcqIndexDiffs::ApplyDiff(string PatchFile) + +bool pkgAcqIndexDiffs::QueueNextDiff() { - char *error; - int res=0; + // calc sha1 of the just patched file string FinalFile = _config->FindDir("Dir::State::lists"); FinalFile += URItoFileName(RealURI); - int Process = ExecFork(); - if (Process == 0) + FileFd fd(FinalFile, FileFd::ReadOnly); + SHA1Summation SHA1; + SHA1.AddFD(fd.Fd(), fd.Size()); + string local_sha1 = string(SHA1.Result()); + if(Debug) + std::clog << "QueueNextDiff: " + << FinalFile << " (" << local_sha1 << ")"<::iterator I=available_patches.begin(); + available_patches.size() > 0 && + I != available_patches.end() && + (*I).sha1 != local_sha1; + I++) { - chdir(_config->FindDir("Dir::State::lists").c_str()); - string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | red " + FinalFile + " >/dev/null 2>/dev/null"; - if(Debug) - std::clog << "Runing: " << cmd << std::endl; - res = system(cmd.c_str()); - _exit(WEXITSTATUS(res)); + available_patches.erase(I); } - if(!ExecWait(Process, error, true)) { - //_error->Error("Patch failed: %s ", error); + + // error checking and falling back if no patch was found + if(available_patches.size() == 0) + { + Failed("", NULL); return false; } - return true; -} - -bool pkgAcqIndexDiffs::QueueNextDiff() -{ - // FIXME: don't use the needed_files[0] but check sha1 and search - // for the right patch in needed_files - // -> and rename needed_files to "available_patches" - - // queue diff - Desc.URI = string(RealURI) + string(".diff/") + needed_files[0].file + string(".gz"); - Desc.Description = needed_files[0].file + string(".pdiff"); + // queue the right diff + Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz"; + Desc.Description = available_patches[0].file + string(".pdiff"); DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(RealURI + string(".diff/") + needed_files[0].file); + DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file); if(Debug) std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; @@ -296,71 +478,6 @@ bool pkgAcqIndexDiffs::QueueNextDiff() return true; } -bool pkgAcqIndexDiffs::ParseIndexDiff(string IndexDiffFile) -{ - if(Debug) - std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile - << std::endl; - - FileFd Fd(IndexDiffFile,FileFd::ReadOnly); - pkgTagFile TF(&Fd); - if (_error->PendingError() == true) - return false; - pkgTagSection Tags; - if(TF.Step(Tags) == true) - { - string local_sha1; - string tmp = Tags.FindS("SHA1-Current"); - std::stringstream ss(tmp); - ss >> ServerSha1; - - FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); - SHA1Summation SHA1; - SHA1.AddFD(fd.Fd(), fd.Size()); - local_sha1 = string(SHA1.Result()); - - if(local_sha1 == ServerSha1) { - if(Debug) - std::clog << "Package file is up-to-date" << std::endl; - Finish(true); - return true; - } - if(Debug) - std::clog << "SHA1-Current: " << ServerSha1 << std::endl; - - // check the historie and see what patches we need - string history = Tags.FindS("SHA1-History"); - std::stringstream hist(history); - DiffInfo d; - string size; - bool found = false; - while(hist >> d.sha1 >> size >> d.file) { - d.size = atoi(size.c_str()); - if(d.sha1 == local_sha1) - found=true; - if(found) { - if(Debug) - std::clog << "Need to get diff: " << d.file << std::endl; - needed_files.push_back(d); - } - } - // no information how to get the patches, bail out - if(!found) { - if(Debug) - std::clog << "Can't find a patch in the index file" << std::endl; - // Failed will queue a big package file - Failed("", NULL); - } else { - // queue the diffs - new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); - Finish(); - return true; - } - } - - return false; -} void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash, @@ -371,41 +488,68 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash, Item::Done(Message,Size,Md5Hash,Cnf); - int len = Desc.URI.size(); - // sucess in downloading the index - if(Desc.URI.substr(len-strlen("Index"),len-1) == "Index") { + string FinalFile; + FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); + + // sucess in downloading a diff, enter ApplyDiff state + if(State == StateFetchDiff) + { - // rename - string FinalFile = _config->FindDir("Dir::State::lists"); - FinalFile += URItoFileName(RealURI) + string(".IndexDiff"); if(Debug) - std::clog << "Renaming: " << DestFile << " -> " << FinalFile - << std::endl; - Rename(DestFile,FinalFile); - chmod(FinalFile.c_str(),0644); - DestFile = FinalFile; + std::clog << "Sending to gzip method: " << FinalFile << std::endl; - if(!ParseIndexDiff(DestFile)) - return Failed("", NULL); - else - return Finish(); - } + string FileName = LookupTag(Message,"Filename"); + State = StateUnzipDiff; + Local = true; + Desc.URI = "gzip:" + FileName; + DestFile += ".decomp"; + QueueURI(Desc); + Mode = "gzip"; + return; + } - // sucess in downloading a diff - if(Desc.URI.find(".diff") != string::npos) { - ApplyDiff(DestFile); - needed_files.erase(needed_files.begin()); + // sucess in downloading a diff, enter ApplyDiff state + if(State == StateUnzipDiff) + { - if(needed_files.size() > 0) { - new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); - } else { - Finish(true); - return; + // rred excepts the patch as $FinalFile.ed + Rename(DestFile,FinalFile+".ed"); + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + State = StateApplyDiff; + Local = true; + Desc.URI = "rred:" + FinalFile; + QueueURI(Desc); + Mode = "rred"; + return; + } + + + // success in download/apply a diff, queue next (if needed) + if(State == StateApplyDiff) + { + // remove the just applied patch + available_patches.erase(available_patches.begin()); + + // move into place + if(Debug) + { + std::clog << "Moving patched file in place: " << std::endl + << DestFile << " -> " << FinalFile << std::endl; } - } + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); - Finish(); + // see if there is more to download + if(available_patches.size() > 0) { + new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, + ExpectedMD5, available_patches); + return Finish(); + } else + return Finish(true); + } } @@ -420,20 +564,21 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, { Decompression = false; Erase = false; - + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; DestFile += URItoFileName(URI); if(comprExt.empty()) { - // autoselect - if(FileExists("/usr/bin/bzip2")) - Desc.URI = URI + ".bz2"; - else - Desc.URI = URI + ".gz"; + // autoselect the compression method + if(FileExists("/bin/bzip2")) + CompressionExtension = ".bz2"; + else + CompressionExtension = ".gz"; } else { - Desc.URI = URI + comprExt; + CompressionExtension = comprExt; } + Desc.URI = URI + CompressionExtension; Desc.Description = URIDesc; Desc.Owner = this; @@ -460,8 +605,9 @@ string pkgAcqIndex::Custom600Headers() void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) { + // no .bz2 found, retry with .gz - if(Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1) == "bz2") { + if(Desc.URI.substr(Desc.URI.size()-3) == "bz2") { Desc.URI = Desc.URI.substr(0,Desc.URI.size()-3) + "gz"; // retry with a gzip one @@ -471,9 +617,15 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) Complete = false; Dequeue(); return; + } + + // on decompression failure, remove bad versions in partial/ + if(Decompression && Erase) { + string s = _config->FindDir("Dir::State::lists") + "partial/"; + s += URItoFileName(RealURI); + unlink(s.c_str()); } - Item::Failed(Message,Cnf); } @@ -567,7 +719,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5, else Local = true; - string compExt = Desc.URI.substr(Desc.URI.size()-3,Desc.URI.size()-1); + string compExt = Desc.URI.substr(Desc.URI.size()-3); char *decompProg; if(compExt == "bz2") decompProg = "bzip2"; @@ -592,10 +744,9 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, const vector* IndexTargets, indexRecords* MetaIndexParser) : Item(Owner), RealURI(URI), MetaIndexURI(MetaIndexURI), - MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc) + MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc), + MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets) { - this->MetaIndexParser = MetaIndexParser; - this->IndexTargets = IndexTargets; DestFile = _config->FindDir("Dir::State::lists") + "partial/"; DestFile += URItoFileName(URI); @@ -667,8 +818,16 @@ void pkgAcqMetaSig::Done(string Message,unsigned long Size,string MD5, /*}}}*/ void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) { - // Delete any existing sigfile, so that this source isn't - // mistakenly trusted + + // if we get a network error we fail gracefully + if(LookupTag(Message,"FailReason") == "Timeout" || + LookupTag(Message,"FailReason") == "TmpResolveFailure" || + LookupTag(Message,"FailReason") == "ConnectionRefused") { + Item::Failed(Message,Cnf); + return; + } + + // Delete any existing sigfile when the acquire failed string Final = _config->FindDir("Dir::State::lists") + URItoFileName(RealURI); unlink(Final.c_str()); @@ -694,11 +853,9 @@ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, string SigFile, const vector* IndexTargets, indexRecords* MetaIndexParser) : - Item(Owner), RealURI(URI), SigFile(SigFile) + Item(Owner), RealURI(URI), SigFile(SigFile), AuthPass(false), + MetaIndexParser(MetaIndexParser), IndexTargets(IndexTargets), IMSHit(false) { - this->AuthPass = false; - this->MetaIndexParser = MetaIndexParser; - this->IndexTargets = IndexTargets; DestFile = _config->FindDir("Dir::State::lists") + "partial/"; DestFile += URItoFileName(URI); @@ -790,6 +947,9 @@ void pkgAcqMetaIndex::RetrievalDone(string Message) return; } + // see if the download was a IMSHit + IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false); + Complete = true; string FinalFile = _config->FindDir("Dir::State::lists"); @@ -801,6 +961,7 @@ void pkgAcqMetaIndex::RetrievalDone(string Message) // Move it into position Rename(DestFile,FinalFile); } + chmod(FinalFile.c_str(),0644); DestFile = FinalFile; } @@ -818,7 +979,7 @@ void pkgAcqMetaIndex::AuthDone(string Message) return; } - if (!VerifyVendor()) + if (!VerifyVendor(Message)) { return; } @@ -870,13 +1031,18 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) } } - // Queue Packages file - new pkgAcqIndexDiffs(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, ExpectedIndexMD5); + // Queue Packages file (either diff or full packages files, depending + // on the users option) + if(_config->FindB("Acquire::PDiffs",true) == true) + new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description, + (*Target)->ShortDesc, ExpectedIndexMD5); + else + new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, + (*Target)->ShortDesc, ExpectedIndexMD5); } } -bool pkgAcqMetaIndex::VerifyVendor() +bool pkgAcqMetaIndex::VerifyVendor(string Message) { // // Maybe this should be made available from above so we don't have // // to read and parse it every time? @@ -901,6 +1067,22 @@ bool pkgAcqMetaIndex::VerifyVendor() // break; // } // } + string::size_type pos; + + // check for missing sigs (that where not fatal because otherwise we had + // bombed earlier) + string missingkeys; + string msg = _("There is no public key available for the " + "following key IDs:\n"); + pos = Message.find("NO_PUBKEY "); + if (pos != std::string::npos) + { + string::size_type start = pos+strlen("NO_PUBKEY "); + string Fingerprint = Message.substr(start, Message.find("\n")-start); + missingkeys += (Fingerprint); + } + if(!missingkeys.empty()) + _error->Warning("%s", string(msg+missingkeys).c_str()); string Transformed = MetaIndexParser->GetExpectedDist(); @@ -909,7 +1091,7 @@ bool pkgAcqMetaIndex::VerifyVendor() Transformed = "experimental"; } - string::size_type pos = Transformed.rfind('/'); + pos = Transformed.rfind('/'); if (pos != string::npos) { Transformed = Transformed.substr(0, pos); @@ -955,10 +1137,30 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) { if (AuthPass == true) { - // gpgv method failed + // if we fail the authentication but got the file via a IMS-Hit + // this means that the file wasn't downloaded and that it might be + // just stale (server problem, proxy etc). we delete what we have + // queue it again without i-m-s + // alternatively we could just unlink the file and let the user try again + if (IMSHit) + { + Complete = false; + Local = false; + AuthPass = false; + unlink(DestFile.c_str()); + + DestFile = _config->FindDir("Dir::State::lists") + "partial/"; + DestFile += URItoFileName(RealURI); + Desc.URI = RealURI; + QueueURI(Desc); + return; + } + + // gpgv method failed _error->Warning("GPG error: %s: %s", Desc.Description.c_str(), LookupTag(Message,"Message").c_str()); + } // No Release file was present, or verification failed, so fall @@ -1034,6 +1236,12 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, } } + // "allow-unauthenticated" restores apts old fetching behaviour + // that means that e.g. unauthenticated file:// uris are higher + // priority than authenticated http:// uris + if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) + Trusted = false; + // Select a source if (QueueNext() == false && _error->PendingError() == false) _error->Error(_("I wasn't able to locate file for the %s package. " @@ -1170,7 +1378,8 @@ void pkgAcqArchive::Done(string Message,unsigned long Size,string Md5Hash, { Status = StatError; ErrorText = _("MD5Sum mismatch"); - Rename(DestFile,DestFile + ".FAILED"); + if(FileExists(DestFile)) + Rename(DestFile,DestFile + ".FAILED"); return; } } @@ -1265,13 +1474,19 @@ void pkgAcqArchive::Finished() // --------------------------------------------------------------------- /* The file is added to the queue */ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5, - unsigned long Size,string Dsc,string ShortDesc) : + unsigned long Size,string Dsc,string ShortDesc, + const string &DestDir, const string &DestFilename) : Item(Owner), Md5Hash(MD5) { Retries = _config->FindI("Acquire::Retries",0); - DestFile = flNotDir(URI); - + if(!DestFilename.empty()) + DestFile = DestFilename; + else if(!DestDir.empty()) + DestFile = DestDir + "/" + flNotDir(URI); + else + DestFile = flNotDir(URI); + // Create the item Desc.URI = URI; Desc.Description = Dsc; @@ -1291,7 +1506,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI,string MD5, else PartialSize = Buf.st_size; } - + QueueURI(Desc); } /*}}}*/