X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/ac5b205a831168ee76e8760e19eb7d43aa361851..6040f5893a85c0206d3fd234c46a608b87a5e9ac:/apt-pkg/acquire-item.cc diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 8c519e3f7..b8886a750 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -141,8 +141,9 @@ void pkgAcquire::Item::Rename(string From,string To) */ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc, - string ExpectedMD5, vector diffs) - : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), needed_files(diffs) + string ExpectedMD5, vector diffs) + : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), + available_patches(diffs) { DestFile = _config->FindDir("Dir::State::lists") + "partial/"; @@ -171,10 +172,13 @@ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, return; } - if(needed_files.size() == 0) + if(available_patches.size() == 0) { + State = StateFetchIndex; QueueDiffIndex(URI); - else + } else { + State = StateFetchDiff; QueueNextDiff(); + } } void pkgAcqIndexDiffs::QueueDiffIndex(string URI) @@ -190,11 +194,32 @@ void pkgAcqIndexDiffs::QueueDiffIndex(string URI) QueueURI(Desc); } -void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqIndexDiffs::Custom600Headers() { + // we only care for the IndexDiff file + if(State != StateFetchIndex) + return string(""); + + string Final = _config->FindDir("Dir::State::lists"); + Final += URItoFileName(RealURI) + string(".IndexDiff"); + if(Debug) - std::clog << "Failed(): " << Desc.URI << std::endl - << "Falling back to big package file" << std::endl; + std::clog << "Custom600Header-IMS: " << Final << std::endl; + + struct stat Buf; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true"; + + return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); +} + +void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +{ + std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl + << "Falling back to normal index file aquire" << std::endl; new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc, ExpectedMD5); Finish(); @@ -227,41 +252,43 @@ 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) - { - chdir(_config->FindDir("Dir::State::lists").c_str()); - string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | ed " + FinalFile + " >/dev/null 2>/dev/null"; - if(Debug) - std::clog << "Runing: " << cmd << std::endl; - res = system(cmd.c_str()); - _exit(WEXITSTATUS(res)); + 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++) { + 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() -{ - // queue diff - Desc.URI = string(RealURI) + string(".diff/") + needed_files[0] + string(".gz"); - Desc.Description = Description + string("-diff"); + // queue the right diff + Desc.URI = string(RealURI) + string(".diff/") + available_patches[0].file + string(".gz"); + Desc.Description = available_patches[0].file + string(".pdiff"); DestFile = _config->FindDir("Dir::State::lists") + "partial/"; - DestFile += URItoFileName(RealURI + string(".diff/") + needed_files[0]); + DestFile += URItoFileName(RealURI + string(".diff/") + available_patches[0].file); if(Debug) std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; @@ -306,17 +333,22 @@ bool pkgAcqIndexDiffs::ParseIndexDiff(string IndexDiffFile) // check the historie and see what patches we need string history = Tags.FindS("SHA1-History"); std::stringstream hist(history); - string sha1, size, file; + DiffInfo d; + string size; bool found = false; - while(hist >> sha1 >> size >> file) { - if(sha1 == local_sha1) + 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: " << file << std::endl; - needed_files.push_back(file); + 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) @@ -326,7 +358,7 @@ bool pkgAcqIndexDiffs::ParseIndexDiff(string IndexDiffFile) } else { // queue the diffs new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); + ExpectedMD5, available_patches); Finish(); return true; } @@ -344,30 +376,83 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash, Item::Done(Message,Size,Md5Hash,Cnf); - int len = Desc.URI.size(); + string FinalFile; + FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); + // sucess in downloading the index - if(Desc.URI.substr(len-strlen("Index"),len-1) == "Index") { + if(State == StateFetchIndex) + { + // 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(!ParseIndexDiff(DestFile)) return Failed("", NULL); - else + else return Finish(); } - // 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 == StateFetchDiff) + { - if(needed_files.size() > 0) { - new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc, - ExpectedMD5, needed_files); - } else { - Finish(true); - return; + if(Debug) + std::clog << "Sending to gzip method: " << FinalFile << std::endl; + + string FileName = LookupTag(Message,"Filename"); + State = StateUnzipDiff; + Desc.URI = "gzip:" + FileName; + DestFile += ".decomp"; + QueueURI(Desc); + Mode = "gzip"; + return; + } + + // sucess in downloading a diff, enter ApplyDiff state + if(State == StateUnzipDiff) + { + + // rred excepts the patch as $FinalFile.ed + Rename(DestFile,FinalFile+".ed"); + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + State = StateApplyDiff; + 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); - 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); + } } @@ -580,6 +665,12 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, // File was already in place. It needs to be re-verified // because Release might have changed, so Move it into partial Rename(Final,DestFile); + // unlink the file and do not try to use I-M-S and Last-Modified + // if the users proxy is broken + if(_config->FindB("Acquire::BrokenProxy", false) == true) { + std::cerr << "forcing re-get of the signature file as requested" << std::endl; + unlink(DestFile.c_str()); + } } QueueURI(Desc);