diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 436 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 78 | ||||
-rw-r--r-- | apt-pkg/cacheiterators.h | 84 | ||||
-rw-r--r-- | apt-pkg/cdrom.cc | 47 | ||||
-rw-r--r-- | apt-pkg/cdrom.h | 7 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.cc | 45 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.h | 3 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 174 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.h | 30 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 43 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 4 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 15 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.cc | 23 | ||||
-rw-r--r-- | apt-pkg/deb/debrecords.h | 2 | ||||
-rw-r--r-- | apt-pkg/indexcopy.cc | 183 | ||||
-rw-r--r-- | apt-pkg/indexcopy.h | 13 | ||||
-rw-r--r-- | apt-pkg/indexfile.cc | 60 | ||||
-rw-r--r-- | apt-pkg/indexfile.h | 7 | ||||
-rw-r--r-- | apt-pkg/init.cc | 3 | ||||
-rw-r--r-- | apt-pkg/init.h | 2 | ||||
-rw-r--r-- | apt-pkg/makefile | 2 | ||||
-rw-r--r-- | apt-pkg/pkgcache.cc | 32 | ||||
-rw-r--r-- | apt-pkg/pkgcache.h | 44 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.cc | 117 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.h | 6 | ||||
-rw-r--r-- | apt-pkg/pkgrecords.cc | 9 | ||||
-rw-r--r-- | apt-pkg/pkgrecords.h | 2 |
27 files changed, 1432 insertions, 39 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index dea68f3ee..75a7faa2a 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -24,6 +24,8 @@ #include <apt-pkg/strutl.h> #include <apt-pkg/fileutl.h> #include <apt-pkg/md5.h> +#include <apt-pkg/sha1.h> +#include <apt-pkg/tagfile.h> #include <apti18n.h> @@ -31,6 +33,7 @@ #include <unistd.h> #include <errno.h> #include <string> +#include <sstream> #include <stdio.h> /*}}}*/ @@ -131,14 +134,410 @@ void pkgAcquire::Item::Rename(string From,string To) } /*}}}*/ + +// AcqDiffIndex::AcqDiffIndex - Constructor +// --------------------------------------------------------------------- +/* 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 + */ +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, + string URI,string URIDesc,string ShortDesc, + string ExpectedMD5) + : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc) +{ + + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + + 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(!FileExists(CurrentPackagesFile) || + !_config->FindB("Acquire::Diffs",true)) { + // 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; + Failed("", NULL); + return; + } + + 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 pkgAcqDiffIndex::Custom600Headers() +{ + string Final = _config->FindDir("Dir::State::lists"); + Final += URItoFileName(RealURI) + string(".IndexDiff"); + + if(Debug) + 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); +} + + +bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile + << std::endl; + + pkgTagSection Tags; + string ServerSha1; + vector<DiffInfo> 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) { + 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<DiffInfo> 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 << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl + << "Falling back to normal index file aquire" << std::endl; + new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, + ExpectedMD5); + Finish(); +} + + +// helper that cleans the item out of the fetcher queue +void pkgAcqIndexDiffs::Finish(bool allDone) +{ + // we restore the original name, this is required, otherwise + // the file will be cleaned + 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) + std::clog << "Finishing: " << Desc.URI << std::endl; + Complete = false; + Status = StatDone; + Dequeue(); + return; +} + + + +bool pkgAcqIndexDiffs::QueueNextDiff() +{ + + // calc sha1 of the just patched file + string FinalFile = _config->FindDir("Dir::State::lists"); + FinalFile += URItoFileName(RealURI); + + 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 << ")"<<std::endl; + + // remove all patches until the next matching patch is found + // this requires the Index file to be ordered + for(vector<DiffInfo>::iterator I=available_patches.begin(); + available_patches.size() > 0 && I != available_patches.end() + && (*I).sha1 != local_sha1; + I++) { + available_patches.erase(I); + } + + // error checking and falling back if no patch was found + if(available_patches.size() == 0) { + Failed("", NULL); + return false; + } + + // 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 + ".diff/" + available_patches[0].file); + + if(Debug) + std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + + QueueURI(Desc); + + return true; +} + + + +void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; + + Item::Done(Message,Size,Md5Hash,Cnf); + + string FinalFile; + FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI); + + // sucess in downloading a diff, enter ApplyDiff state + if(State == StateFetchDiff) + { + + 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); + + // 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); + } +} + + // AcqIndex::AcqIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* The package file is added to the queue and a second class is instantiated to fetch the revision file */ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc, - string ExpectedMD5, string comprExt) : - Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5) + string ExpectedMD5, string comprExt) + : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5) { Decompression = false; Erase = false; @@ -308,6 +707,35 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string MD5, Mode = decompProg; } +// AcqIndexTrans::pkgAcqIndexTrans - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* The Translation file is added to the queue */ +pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, + string URI,string URIDesc,string ShortDesc) : + pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, "", "") +{ +} + + /*}}}*/ +// AcqIndexTrans::Failed - Silence failure messages for missing files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +{ + if (Cnf->LocalOnly == true || + StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + { + // Ignore this + Status = StatDone; + Complete = false; + Dequeue(); + return; + } + + Item::Failed(Message,Cnf); +} + /*}}}*/ + pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, string URI,string URIDesc,string ShortDesc, string MetaIndexURI, string MetaIndexURIDesc, @@ -607,8 +1035,8 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) } // Queue Packages file - new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, ExpectedIndexMD5); + new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description, + (*Target)->ShortDesc, ExpectedIndexMD5); } } diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 90f80368b..34fcc2a76 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -9,8 +9,8 @@ the Owner Acquire class. Derived classes will then call QueueURI to register all the URI's they wish to fetch at the initial moment. - Two item classes are provided to provide functionality for downloading - of Index files and downloading of Packages. + Three item classes are provided to provide functionality for + downloading of Index, Translation and Packages files. A Archive class is provided for downloading .deb files. It does Md5 checking and source location as well as a retry algorithm. @@ -82,6 +82,70 @@ class pkgAcquire::Item virtual ~Item(); }; +// item for index diffs + +struct DiffInfo { + string file; + string sha1; + unsigned long size; +}; + +class pkgAcqDiffIndex : public pkgAcquire::Item +{ + protected: + bool Debug; + pkgAcquire::ItemDesc Desc; + string RealURI; + string ExpectedMD5; + string CurrentPackagesFile; + string Description; + + public: + // Specialized action members + virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf); + virtual string DescURI() {return RealURI + "Index";}; + virtual string Custom600Headers(); + + // helpers + bool ParseDiffIndex(string IndexDiffFile); + + pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc, + string ShortDesct, string ExpectedMD5); +}; + +class pkgAcqIndexDiffs : public pkgAcquire::Item +{ + protected: + bool Debug; + pkgAcquire::ItemDesc Desc; + string RealURI; + string ExpectedMD5; + + // this is the SHA-1 sum we expect after the patching + string Description; + vector<DiffInfo> available_patches; + enum {StateFetchIndex,StateFetchDiff,StateUnzipDiff,StateApplyDiff} State; + + public: + + // Specialized action members + virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Done(string Message,unsigned long Size,string Md5Hash, + pkgAcquire::MethodConfig *Cnf); + virtual string DescURI() {return RealURI + "Index";}; + + // various helpers + bool QueueNextDiff(); + bool ApplyDiff(string PatchFile); + void Finish(bool allDone=false); + + pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc, + string ShortDesct, string ExpectedMD5, + vector<DiffInfo> diffs=vector<DiffInfo>()); +}; + // Item class for index files class pkgAcqIndex : public pkgAcquire::Item { @@ -107,6 +171,16 @@ class pkgAcqIndex : public pkgAcquire::Item string ShortDesct, string ExpectedMD5, string compressExt=""); }; +// Item class for translated package index files +class pkgAcqIndexTrans : public pkgAcqIndex +{ + public: + + virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf); + pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc, + string ShortDesct); +}; + struct IndexTarget { string URI; diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index c3a0d0a5a..64fa4636e 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -99,7 +99,7 @@ class pkgCache::VerIterator { Version *Ver; pkgCache *Owner; - + void _dummy(); public: @@ -128,6 +128,8 @@ class pkgCache::VerIterator inline const char *Section() const {return Ver->Section == 0?0:Owner->StrP + Ver->Section;}; inline const char *Arch() const {return Ver->Arch == 0?0:Owner->StrP + Ver->Arch;}; inline PkgIterator ParentPkg() const {return PkgIterator(*Owner,Owner->PkgP + Ver->ParentPkg);}; + inline DescIterator DescriptionList() const; + DescIterator TranslatedDescription() const; inline DepIterator DependsList() const; inline PrvIterator ProvidesList() const; inline VerFileIterator FileList() const; @@ -148,6 +150,50 @@ class pkgCache::VerIterator }; }; +// Description Iterator +class pkgCache::DescIterator +{ + Description *Desc; + pkgCache *Owner; + + void _dummy(); + + public: + + // Iteration + void operator ++(int) {if (Desc != Owner->DescP) Desc = Owner->DescP + Desc->NextDesc;}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return Desc == Owner->DescP?true:false;}; + inline void operator =(const DescIterator &B) {Desc = B.Desc; Owner = B.Owner;}; + + // Comparison + inline bool operator ==(const DescIterator &B) const {return Desc == B.Desc;}; + inline bool operator !=(const DescIterator &B) const {return Desc != B.Desc;}; + int CompareDesc(const DescIterator &B) const; + + // Accessors + inline Description *operator ->() {return Desc;}; + inline Description const *operator ->() const {return Desc;}; + inline Description &operator *() {return *Desc;}; + inline Description const &operator *() const {return *Desc;}; + inline operator Description *() {return Desc == Owner->DescP?0:Desc;}; + inline operator Description const *() const {return Desc == Owner->DescP?0:Desc;}; + inline pkgCache *Cache() {return Owner;}; + + inline const char *LanguageCode() const {return Owner->StrP + Desc->language_code;}; + inline const char *md5() const {return Owner->StrP + Desc->md5sum;}; + inline DescFileIterator FileList() const; + inline unsigned long Index() const {return Desc - Owner->DescP;}; + + inline DescIterator() : Desc(0), Owner(0) {}; + inline DescIterator(pkgCache &Owner,Description *Trg = 0) : Desc(Trg), + Owner(&Owner) + { + if (Desc == 0) + Desc = Owner.DescP; + }; +}; + // Dependency iterator class pkgCache::DepIterator { @@ -338,6 +384,38 @@ class pkgCache::VerFileIterator inline VerFileIterator(pkgCache &Owner,VerFile *Trg) : Owner(&Owner), FileP(Trg) {}; }; +// Description File +class pkgCache::DescFileIterator +{ + pkgCache *Owner; + DescFile *FileP; + + public: + + // Iteration + void operator ++(int) {if (FileP != Owner->DescFileP) FileP = Owner->DescFileP + FileP->NextFile;}; + inline void operator ++() {operator ++(0);}; + inline bool end() const {return FileP == Owner->DescFileP?true:false;}; + + // Comparison + inline bool operator ==(const DescFileIterator &B) const {return FileP == B.FileP;}; + inline bool operator !=(const DescFileIterator &B) const {return FileP != B.FileP;}; + + // Accessors + inline DescFile *operator ->() {return FileP;}; + inline DescFile const *operator ->() const {return FileP;}; + inline DescFile const &operator *() const {return *FileP;}; + inline operator DescFile *() {return FileP == Owner->DescFileP?0:FileP;}; + inline operator DescFile const *() const {return FileP == Owner->DescFileP?0:FileP;}; + inline pkgCache *Cache() {return Owner;}; + + inline PkgFileIterator File() const {return PkgFileIterator(*Owner,FileP->File + Owner->PkgFileP);}; + inline unsigned long Index() const {return FileP - Owner->DescFileP;}; + + inline DescFileIterator() : Owner(0), FileP(0) {}; + inline DescFileIterator(pkgCache &Owner,DescFile *Trg) : Owner(&Owner), FileP(Trg) {}; +}; + // Inlined Begin functions cant be in the class because of order problems inline pkgCache::VerIterator pkgCache::PkgIterator::VersionList() const {return VerIterator(*Owner,Owner->VerP + Pkg->VersionList);}; @@ -347,11 +425,15 @@ inline pkgCache::DepIterator pkgCache::PkgIterator::RevDependsList() const {return DepIterator(*Owner,Owner->DepP + Pkg->RevDepends,Pkg);}; inline pkgCache::PrvIterator pkgCache::PkgIterator::ProvidesList() const {return PrvIterator(*Owner,Owner->ProvideP + Pkg->ProvidesList,Pkg);}; +inline pkgCache::DescIterator pkgCache::VerIterator::DescriptionList() const + {return DescIterator(*Owner,Owner->DescP + Ver->DescriptionList);}; inline pkgCache::PrvIterator pkgCache::VerIterator::ProvidesList() const {return PrvIterator(*Owner,Owner->ProvideP + Ver->ProvidesList,Ver);}; inline pkgCache::DepIterator pkgCache::VerIterator::DependsList() const {return DepIterator(*Owner,Owner->DepP + Ver->DependsList,Ver);}; inline pkgCache::VerFileIterator pkgCache::VerIterator::FileList() const {return VerFileIterator(*Owner,Owner->VerFileP + Ver->FileList);}; +inline pkgCache::DescFileIterator pkgCache::DescIterator::FileList() const + {return DescFileIterator(*Owner,Owner->DescFileP + Desc->FileList);}; #endif diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index ce1beb39b..b42c82dd0 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -30,12 +30,16 @@ using namespace std; search that short circuits when it his a package file in the dir. This speeds it up greatly as the majority of the size is in the binary-* sub dirs. */ -bool pkgCdrom::FindPackages(string CD,vector<string> &List, - vector<string> &SList, vector<string> &SigList, +bool pkgCdrom::FindPackages(string CD, + vector<string> &List, + vector<string> &SList, + vector<string> &SigList, + vector<string> &TransList, string &InfoDir, pkgCdromStatus *log, unsigned int Depth) { static ino_t Inodes[9]; + DIR *D; // if we have a look we "pulse" now if(log) @@ -90,8 +94,28 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List, if (_config->FindB("APT::CDROM::Thorough",false) == false) return true; } + + // see if we find translatin indexes + if (stat("i18n",&Buf) == 0) + { + D = opendir("i18n"); + for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) + { + if(strstr(Dir->d_name,"Translation") != NULL) + { + if (_config->FindB("Debug::aptcdrom",false) == true) + std::clog << "found translations: " << Dir->d_name << "\n"; + string file = Dir->d_name; + if(file.substr(file.size()-3,file.size()) == ".gz") + file = file.substr(0,file.size()-3); + TransList.push_back(CD+"i18n/"+ file); + } + } + closedir(D); + } + - DIR *D = opendir("."); + D = opendir("."); if (D == 0) return _error->Errno("opendir","Unable to read %s",CD.c_str()); @@ -127,7 +151,7 @@ bool pkgCdrom::FindPackages(string CD,vector<string> &List, Inodes[Depth] = Buf.st_ino; // Descend - if (FindPackages(CD + Dir->d_name,List,SList,SigList,InfoDir,log,Depth+1) == false) + if (FindPackages(CD + Dir->d_name,List,SList,SigList,TransList,InfoDir,log,Depth+1) == false) break; if (chdir(CD.c_str()) != 0) @@ -612,9 +636,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log) vector<string> List; vector<string> SourceList; vector<string> SigList; + vector<string> TransList; string StartDir = SafeGetCWD(); string InfoDir; - if (FindPackages(CDROM,List,SourceList, SigList,InfoDir,log) == false) + if (FindPackages(CDROM,List,SourceList, SigList,TransList,InfoDir,log) == false) { log->Update("\n"); return false; @@ -642,11 +667,13 @@ bool pkgCdrom::Add(pkgCdromStatus *log) DropRepeats(List,"Packages"); DropRepeats(SourceList,"Sources"); DropRepeats(SigList,"Release.gpg"); + DropRepeats(TransList,""); if(log) { msg.str(""); - ioprintf(msg, _("Found %i package indexes, %i source indexes and " - "%i signatures\n"), - List.size(), SourceList.size(), SigList.size()); + ioprintf(msg, _("Found %i package indexes, %i source indexes, " + "%i translation indexes and %i signatures\n"), + List.size(), SourceList.size(), TransList.size(), + SigList.size()); log->Update(msg.str(), STEP_SCAN); } @@ -736,8 +763,10 @@ bool pkgCdrom::Add(pkgCdromStatus *log) // Copy the package files to the state directory PackageCopy Copy; SourceCopy SrcCopy; + TranslationsCopy TransCopy; if (Copy.CopyPackages(CDROM,Name,List, log) == false || - SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false) + SrcCopy.CopyPackages(CDROM,Name,SourceList, log) == false || + TransCopy.CopyTranslations(CDROM,Name,TransList, log) == false) return false; // reduce the List so that it takes less space in sources.list diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index 085eb64e2..e18aaff3e 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -50,8 +50,11 @@ class pkgCdrom }; - bool FindPackages(string CD,vector<string> &List, - vector<string> &SList, vector<string> &SigList, + bool FindPackages(string CD, + vector<string> &List, + vector<string> &SList, + vector<string> &SigList, + vector<string> &TransList, string &InfoDir, pkgCdromStatus *log, unsigned int Depth = 0); bool DropBinaryArch(vector<string> &List); diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index a75fbdf92..303cb27db 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -32,12 +32,55 @@ #include <regex.h> #include <errno.h> #include <stdarg.h> +#include <iconv.h> #include "config.h" using namespace std; /*}}}*/ +// UTF8ToCodeset - Convert some UTF-8 string for some codeset /*{{{*/ +// --------------------------------------------------------------------- +/* This is handy to use before display some information for enduser */ +bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest) +{ + iconv_t cd; + const char *inbuf; + char *inptr, *outbuf, *outptr; + size_t insize, outsize; + + cd = iconv_open(codeset, "UTF-8"); + if (cd == (iconv_t)(-1)) { + // Something went wrong + if (errno == EINVAL) + _error->Error("conversion from 'UTF-8' to '%s' not available", + codeset); + else + perror("iconv_open"); + + // Clean the destination string + *dest = ""; + + return false; + } + + insize = outsize = orig.size(); + inbuf = orig.data(); + inptr = (char *)inbuf; + outbuf = new char[insize+1]; + outptr = outbuf; + + iconv(cd, &inptr, &insize, &outptr, &outsize); + *outptr = '\0'; + + *dest = outbuf; + delete[] outbuf; + + iconv_close(cd); + + return true; +} + /*}}}*/ // strstrip - Remove white space from the front and back of a string /*{{{*/ // --------------------------------------------------------------------- /* This is handy to use when parsing a file. It also removes \n's left @@ -357,7 +400,7 @@ string URItoFileName(string URI) U.Access = ""; // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF"; - URI = QuoteString(U,"\\|{}[]<>\"^~_=!@#$%^&*"); + URI = QuoteString(U,"\\|{}[]<>\"^~=!@#$%^&*"); string::iterator J = URI.begin(); for (; J != URI.end(); J++) if (*J == '/') diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index 353e78ac9..72fc34d6d 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -38,7 +38,8 @@ using std::ostream; #define APT_FORMAT2 #define APT_FORMAT3 #endif - + +bool UTF8ToCodeset(const char *codeset, const string &orig, string *dest); char *_strstrip(char *String); char *_strtabexpand(char *String,size_t Len); bool ParseQuoteWord(const char *&String,string &Res); diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index ff8bce85d..38ecdd16a 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -320,6 +320,170 @@ pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const } /*}}}*/ +// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ +// --------------------------------------------------------------------- +/* */ +debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) : + pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section) +{ +} + /*}}}*/ +// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +inline string debTranslationsIndex::IndexFile(const char *Type) const +{ + return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); +} +string debTranslationsIndex::IndexURI(const char *Type) const +{ + string Res; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Res = URI + Dist; + else + Res = URI; + } + else + Res = URI + "dists/" + Dist + '/' + Section + + "/i18n/Translation-"; + + Res += Type; + return Res; +} + /*}}}*/ +// TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const +{ + if (TranslationsAvailable()) { + string TranslationFile = "Translation-" + LanguageCode(); + new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()), + Info(TranslationFile.c_str()), + TranslationFile); + } + + return true; +} + /*}}}*/ +// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/ +// --------------------------------------------------------------------- +/* This should help the user find the index in the sources.list and + in the filesystem for problem solving */ +string debTranslationsIndex::Describe(bool Short) const +{ + char S[300]; + if (Short == true) + snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str()); + else + snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(), + IndexFile(LanguageCode().c_str()).c_str()); + return S; +} + /*}}}*/ +// TranslationsIndex::Info - One liner describing the index URI /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string debTranslationsIndex::Info(const char *Type) const +{ + string Info = ::URI::SiteOnly(URI) + ' '; + if (Dist[Dist.size() - 1] == '/') + { + if (Dist != "/") + Info += Dist; + } + else + Info += Dist + '/' + Section; + Info += " "; + Info += Type; + return Info; +} + /*}}}*/ +bool debTranslationsIndex::HasPackages() const +{ + if(!TranslationsAvailable()) + return false; + + return FileExists(IndexFile(LanguageCode().c_str())); +} + +// TranslationsIndex::Exists - Check if the index is available /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debTranslationsIndex::Exists() const +{ + return FileExists(IndexFile(LanguageCode().c_str())); +} + /*}}}*/ +// TranslationsIndex::Size - Return the size of the index /*{{{*/ +// --------------------------------------------------------------------- +/* This is really only used for progress reporting. */ +unsigned long debTranslationsIndex::Size() const +{ + struct stat S; + if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ +// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const +{ + // Check the translation file, if in use + string TranslationFile = IndexFile(LanguageCode().c_str()); + if (TranslationsAvailable() && FileExists(TranslationFile)) + { + FileFd Trans(TranslationFile,FileFd::ReadOnly); + debListParser TransParser(&Trans); + if (_error->PendingError() == true) + return false; + + Prog.SubProgress(0, Info(TranslationFile.c_str())); + if (Gen.SelectFile(TranslationFile,string(),*this) == false) + return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator TransFile = Gen.GetCurFile(); + struct stat TransSt; + if (fstat(Trans.Fd(),&TransSt) != 0) + return _error->Errno("fstat","Failed to stat"); + TransFile->Size = TransSt.st_size; + TransFile->mtime = TransSt.st_mtime; + + if (Gen.MergeList(TransParser) == false) + return _error->Error("Problem with MergeList %s",TranslationFile.c_str()); + } + + return true; +} + /*}}}*/ +// TranslationsIndex::FindInCache - Find this index /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const +{ + string FileName = IndexFile(LanguageCode().c_str()); + + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; File++) + { + if (FileName != File.FileName()) + continue; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + return pkgCache::PkgFileIterator(Cache); + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) + return pkgCache::PkgFileIterator(Cache); + return File; + } + return File; +} + /*}}}*/ // StatusIndex::debStatusIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -416,6 +580,11 @@ class debIFTypePkg : public pkgIndexFile::Type }; debIFTypePkg() {Label = "Debian Package Index";}; }; +class debIFTypeTrans : public debIFTypePkg +{ + public: + debIFTypeTrans() {Label = "Debian Translation Index";}; +}; class debIFTypeStatus : public pkgIndexFile::Type { public: @@ -428,6 +597,7 @@ class debIFTypeStatus : public pkgIndexFile::Type }; static debIFTypeSrc _apt_Src; static debIFTypePkg _apt_Pkg; +static debIFTypeTrans _apt_Trans; static debIFTypeStatus _apt_Status; const pkgIndexFile::Type *debSourcesIndex::GetType() const @@ -438,6 +608,10 @@ const pkgIndexFile::Type *debPackagesIndex::GetType() const { return &_apt_Pkg; } +const pkgIndexFile::Type *debTranslationsIndex::GetType() const +{ + return &_apt_Trans; +} const pkgIndexFile::Type *debStatusIndex::GetType() const { return &_apt_Status; diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index a1b9583a4..57005222f 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -74,6 +74,36 @@ class debPackagesIndex : public pkgIndexFile debPackagesIndex(string URI,string Dist,string Section,bool Trusted); }; +class debTranslationsIndex : public pkgIndexFile +{ + string URI; + string Dist; + string Section; + + string Info(const char *Type) const; + string IndexFile(const char *Type) const; + string IndexURI(const char *Type) const; + + inline string TranslationFile() const {return "Translation-" + LanguageCode();}; + + public: + + virtual const Type *GetType() const; + + // Interface for acquire + virtual string Describe(bool Short) const; + virtual bool GetIndexes(pkgAcquire *Owner) const; + + // Interface for the Cache Generator + virtual bool Exists() const; + virtual bool HasPackages() const; + virtual unsigned long Size() const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + + debTranslationsIndex(string URI,string Dist,string Section); +}; + class debSourcesIndex : public pkgIndexFile { string URI; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 25b533773..97553ab82 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -15,6 +15,7 @@ #include <apt-pkg/configuration.h> #include <apt-pkg/strutl.h> #include <apt-pkg/crc-16.h> +#include <apt-pkg/md5.h> #include <ctype.h> @@ -117,6 +118,48 @@ bool debListParser::NewVersion(pkgCache::VerIterator Ver) return true; } /*}}}*/ +// ListParser::Description - Return the description string /*{{{*/ +// --------------------------------------------------------------------- +/* This is to return the string describing the package in debian + form. If this returns the blank string then the entry is assumed to + only describe package properties */ +string debListParser::Description() +{ + if (DescriptionLanguage().empty()) + return Section.FindS("Description"); + else + return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()); +} + /*}}}*/ +// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/ +// --------------------------------------------------------------------- +/* This is to return the string describing the language of + description. If this returns the blank string then the entry is + assumed to describe original description. */ +string debListParser::DescriptionLanguage() +{ + return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : ""; +} + /*}}}*/ +// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/ +// --------------------------------------------------------------------- +/* This is to return the md5 string to allow the check if it is the right + description. If no Description-md5 is found in the section it will be + calculated. + */ +MD5SumValue debListParser::Description_md5() +{ + string value = Section.FindS("Description-md5"); + + if (value.empty()) + { + MD5Summation md5; + md5.Add((Description() + "\n").c_str()); + return md5.Result(); + } else + return MD5SumValue(value); +} + /*}}}*/ // ListParser::UsePackage - Update a package structure /*{{{*/ // --------------------------------------------------------------------- /* This is called to update the package with any new information diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 3a0e0421b..34bb29c72 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -12,6 +12,7 @@ #define PKGLIB_DEBLISTPARSER_H #include <apt-pkg/pkgcachegen.h> +#include <apt-pkg/indexfile.h> #include <apt-pkg/tagfile.h> class debListParser : public pkgCacheGenerator::ListParser @@ -47,6 +48,9 @@ class debListParser : public pkgCacheGenerator::ListParser virtual string Package(); virtual string Version(); virtual bool NewVersion(pkgCache::VerIterator Ver); + virtual string Description(); + virtual string DescriptionLanguage(); + virtual MD5SumValue Description_md5(); virtual unsigned short VersionHash(); virtual bool UsePackage(pkgCache::PkgIterator Pkg, pkgCache::VerIterator Ver); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 85e5b16b3..d3b6ed957 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -157,6 +157,14 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool GetAll) const ComputeIndexTargets(), new indexRecords (Dist)); + // Queue the translations + for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); I++) { + + debTranslationsIndex i = debTranslationsIndex(URI,Dist,(*I)->Section); + i.GetIndexes(Owner); + } + return true; } @@ -181,11 +189,16 @@ vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() Indexes = new vector <pkgIndexFile*>; for (vector<const debSectionEntry *>::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); I++) + I != SectionEntries.end(); I++) { if ((*I)->IsSrc) Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); else + { Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted())); + Indexes->push_back(new debTranslationsIndex(URI, Dist, (*I)->Section)); + } + } + return Indexes; } diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 6652a6ad9..518988bb6 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -12,7 +12,9 @@ #pragma implementation "apt-pkg/debrecords.h" #endif #include <apt-pkg/debrecords.h> +#include <apt-pkg/strutl.h> #include <apt-pkg/error.h> +#include <langinfo.h> /*}}}*/ // RecordParser::debRecordParser - Constructor /*{{{*/ @@ -31,6 +33,10 @@ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver) { return Tags.Jump(Section,Ver->Offset); } +bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) +{ + return Tags.Jump(Section,Desc->Offset); +} /*}}}*/ // RecordParser::FileName - Return the archive filename on the site /*{{{*/ // --------------------------------------------------------------------- @@ -77,7 +83,7 @@ string debRecordParser::Maintainer() /* */ string debRecordParser::ShortDesc() { - string Res = Section.FindS("Description"); + string Res = LongDesc(); string::size_type Pos = Res.find('\n'); if (Pos == string::npos) return Res; @@ -89,7 +95,20 @@ string debRecordParser::ShortDesc() /* */ string debRecordParser::LongDesc() { - return Section.FindS("Description"); + string orig, dest; + char *codeset = nl_langinfo(CODESET); + + if (!Section.FindS("Description").empty()) + orig = Section.FindS("Description").c_str(); + else + orig = Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str()).c_str(); + + if (strcmp(codeset,"UTF-8") != 0) { + UTF8ToCodeset(codeset, orig, &dest); + orig = dest; + } + + return orig; } /*}}}*/ // RecordParser::SourcePkg - Return the source package name if any /*{{{*/ diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index efef2e588..24e5aab88 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -19,6 +19,7 @@ #endif #include <apt-pkg/pkgrecords.h> +#include <apt-pkg/indexfile.h> #include <apt-pkg/tagfile.h> class debRecordParser : public pkgRecords::Parser @@ -30,6 +31,7 @@ class debRecordParser : public pkgRecords::Parser protected: virtual bool Jump(pkgCache::VerFileIterator const &Ver); + virtual bool Jump(pkgCache::DescFileIterator const &Desc); public: diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 1f65062f7..c9dded134 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -32,6 +32,8 @@ using namespace std; + + // IndexCopy::CopyPackages - Copy the package files from the CD /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -512,10 +514,10 @@ bool SourceCopy::RewriteEntry(FILE *Target,string File) fputc('\n',Target); return true; } - - /*}}}*/ - +// SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/ +// --------------------------------------------------------------------- +/* */ bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) { const indexRecords::checkSum *Record = MetaIndex->Lookup(file); @@ -670,3 +672,178 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector<string> &SigList, return true; } + + +bool TranslationsCopy::CopyTranslations(string CDROM,string Name,vector<string> &List, + pkgCdromStatus *log) +{ + OpProgress *Progress = NULL; + if (List.size() == 0) + return true; + + if(log) + Progress = log->GetOpProgress(); + + bool Debug = _config->FindB("Debug::aptcdrom",false); + + // Prepare the progress indicator + unsigned long TotalSize = 0; + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + struct stat Buf; + if (stat(string(*I).c_str(),&Buf) != 0 && + stat(string(*I + ".gz").c_str(),&Buf) != 0) + return _error->Errno("stat","Stat failed for %s", + string(*I).c_str()); + TotalSize += Buf.st_size; + } + + unsigned long CurrentSize = 0; + unsigned int NotFound = 0; + unsigned int WrongSize = 0; + unsigned int Packages = 0; + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + string OrigPath = string(*I,CDROM.length()); + unsigned long FileSize = 0; + + // Open the package file + FileFd Pkg; + if (FileExists(*I) == true) + { + Pkg.Open(*I,FileFd::ReadOnly); + FileSize = Pkg.Size(); + } + else + { + FileFd From(*I + ".gz",FileFd::ReadOnly); + if (_error->PendingError() == true) + return false; + FileSize = From.Size(); + + // Get a temp file + FILE *tmp = tmpfile(); + if (tmp == 0) + return _error->Errno("tmpfile","Unable to create a tmp file"); + Pkg.Fd(dup(fileno(tmp))); + fclose(tmp); + + // Fork gzip + pid_t Process = fork(); + if (Process < 0) + return _error->Errno("fork","Couldn't fork gzip"); + + // The child + if (Process == 0) + { + dup2(From.Fd(),STDIN_FILENO); + dup2(Pkg.Fd(),STDOUT_FILENO); + SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDOUT_FILENO,false); + + const char *Args[3]; + string Tmp = _config->Find("Dir::bin::gzip","gzip"); + Args[0] = Tmp.c_str(); + Args[1] = "-d"; + Args[2] = 0; + execvp(Args[0],(char **)Args); + exit(100); + } + + // Wait for gzip to finish + if (ExecWait(Process,_config->Find("Dir::bin::gzip","gzip").c_str(),false) == false) + return _error->Error("gzip failed, perhaps the disk is full."); + + Pkg.Seek(0); + } + pkgTagFile Parser(&Pkg); + if (_error->PendingError() == true) + return false; + + // Open the output file + char S[400]; + snprintf(S,sizeof(S),"cdrom:[%s]/%s",Name.c_str(), + (*I).c_str() + CDROM.length()); + string TargetF = _config->FindDir("Dir::State::lists") + "partial/"; + TargetF += URItoFileName(S); + if (_config->FindB("APT::CDROM::NoAct",false) == true) + TargetF = "/dev/null"; + FileFd Target(TargetF,FileFd::WriteEmpty); + FILE *TargetFl = fdopen(dup(Target.Fd()),"w"); + if (_error->PendingError() == true) + return false; + if (TargetFl == 0) + return _error->Errno("fdopen","Failed to reopen fd"); + + // Setup the progress meter + if(Progress) + Progress->OverallProgress(CurrentSize,TotalSize,FileSize, + string("Reading Translation Indexes")); + + // Parse + if(Progress) + Progress->SubProgress(Pkg.Size()); + pkgTagSection Section; + this->Section = &Section; + string Prefix; + unsigned long Hits = 0; + unsigned long Chop = 0; + while (Parser.Step(Section) == true) + { + if(Progress) + Progress->Progress(Parser.Offset()); + + const char *Start; + const char *Stop; + Section.GetSection(Start,Stop); + fwrite(Start,Stop-Start, 1, TargetFl); + fputc('\n',TargetFl); + + Packages++; + Hits++; + } + fclose(TargetFl); + + if (Debug == true) + cout << " Processed by using Prefix '" << Prefix << "' and chop " << Chop << endl; + + if (_config->FindB("APT::CDROM::NoAct",false) == false) + { + // Move out of the partial directory + Target.Close(); + string FinalF = _config->FindDir("Dir::State::lists"); + FinalF += URItoFileName(S); + if (rename(TargetF.c_str(),FinalF.c_str()) != 0) + return _error->Errno("rename","Failed to rename"); + } + + + CurrentSize += FileSize; + } + if(Progress) + Progress->Done(); + + // Some stats + if(log) { + stringstream msg; + if(NotFound == 0 && WrongSize == 0) + ioprintf(msg, _("Wrote %i records.\n"), Packages); + else if (NotFound != 0 && WrongSize == 0) + ioprintf(msg, _("Wrote %i records with %i missing files.\n"), + Packages, NotFound); + else if (NotFound == 0 && WrongSize != 0) + ioprintf(msg, _("Wrote %i records with %i mismatched files\n"), + Packages, WrongSize); + if (NotFound != 0 && WrongSize != 0) + ioprintf(msg, _("Wrote %i records with %i missing files and %i mismatched files\n"), Packages, NotFound, WrongSize); + } + + if (Packages == 0) + _error->Warning("No valid records were found."); + + if (NotFound + WrongSize > 10) + _error->Warning("Alot of entries were discarded, something may be wrong.\n"); + + + return true; +} diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 4dcb2b46d..7778ae595 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -70,6 +70,17 @@ class SourceCopy : public IndexCopy public: }; +class TranslationsCopy +{ + protected: + pkgTagSection *Section; + + public: + bool CopyTranslations(string CDROM,string Name,vector<string> &List, + pkgCdromStatus *log); +}; + + class SigVerify { bool Verify(string prefix,string file, indexRecords *records); @@ -81,4 +92,6 @@ class SigVerify vector<string> PkgList,vector<string> SrcList); }; + + #endif diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 49665161d..496e68b8b 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -12,8 +12,11 @@ #pragma implementation "apt-pkg/indexfile.h" #endif +#include <apt-pkg/configuration.h> #include <apt-pkg/indexfile.h> #include <apt-pkg/error.h> + +#include <clocale> /*}}}*/ // Global list of Item supported @@ -67,3 +70,60 @@ string pkgIndexFile::SourceInfo(pkgSrcRecords::Parser const &Record, return string(); } /*}}}*/ +// IndexFile::TranslationsAvailable - Check if will use Translation /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgIndexFile::TranslationsAvailable() +{ + const string Translation = _config->Find("APT::Acquire::Translation"); + + if (Translation.compare("none") != 0) + return CheckLanguageCode(LanguageCode().c_str()); + else + return false; +} + /*}}}*/ +// IndexFile::CheckLanguageCode - Check the Language Code /*{{{*/ +// --------------------------------------------------------------------- +/* */ +/* common cases: de_DE, de_DE@euro, de_DE.UTF-8, de_DE.UTF-8@euro, + de_DE.ISO8859-1, tig_ER + more in /etc/gdm/locale.conf +*/ + +bool pkgIndexFile::CheckLanguageCode(const char *Lang) +{ + if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_')) + return true; + + if (strcmp(Lang,"C") != 0) + _error->Warning("Wrong language code %s", Lang); + + return false; +} + /*}}}*/ +// IndexFile::LanguageCode - Return the Language Code /*{{{*/ +// --------------------------------------------------------------------- +/* return the language code */ +string pkgIndexFile::LanguageCode() +{ + const string Translation = _config->Find("APT::Acquire::Translation"); + + if (Translation.compare("environment") == 0) + { + string lang = std::setlocale(LC_MESSAGES,NULL); + + // FIXME: this needs to be added + // we have a mapping of the language codes that contains all the language + // codes that need the country code as well + // (like pt_BR, pt_PT, sv_SE, zh_*, en_*) + + if(lang.size() > 2) + return lang.substr(0,2); + else + return lang; + } + else + return Translation; +} + /*}}}*/ diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 61049f4bd..d5d1cf57a 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -5,10 +5,11 @@ Index File - Abstraction for an index of archive/source file. - There are 3 primary sorts of index files, all represented by this + There are 4 primary sorts of index files, all represented by this class: Binary index files + Binary translation files Bianry index files decribing the local system Source index files @@ -80,6 +81,10 @@ class pkgIndexFile virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const {return true;}; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + static bool TranslationsAvailable(); + static bool CheckLanguageCode(const char *Lang); + static string LanguageCode(); + bool IsTrusted() const { return Trusted; }; pkgIndexFile(bool Trusted): Trusted(Trusted) {}; diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index f4b816c0b..6118845e8 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -101,6 +101,9 @@ bool pkgInitConfig(Configuration &Cnf) bindtextdomain(textdomain(0),Cnf.FindDir("Dir::Locale").c_str()); } #endif + + // Translation + Cnf.Set("APT::Acquire::Translation", "environment"); return true; } diff --git a/apt-pkg/init.h b/apt-pkg/init.h index e21351797..8255b406a 100644 --- a/apt-pkg/init.h +++ b/apt-pkg/init.h @@ -18,7 +18,7 @@ // See the makefile #define APT_PKG_MAJOR 3 -#define APT_PKG_MINOR 10 +#define APT_PKG_MINOR 11 #define APT_PKG_RELEASE 0 extern const char *pkgVersion; diff --git a/apt-pkg/makefile b/apt-pkg/makefile index 8de7d945e..0e6aecc65 100644 --- a/apt-pkg/makefile +++ b/apt-pkg/makefile @@ -13,7 +13,7 @@ include ../buildlib/defaults.mak # methods/makefile - FIXME LIBRARY=apt-pkg LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER) -MAJOR=3.10 +MAJOR=3.11 MINOR=0 SLIBS=$(PTHREADLIB) $(INTLLIBS) APT_DOMAIN:=libapt-pkg$(MAJOR) diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 6ef7cafb0..4452079a2 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -26,6 +26,7 @@ #endif #include <apt-pkg/pkgcache.h> +#include <apt-pkg/indexfile.h> #include <apt-pkg/version.h> #include <apt-pkg/error.h> #include <apt-pkg/strutl.h> @@ -43,6 +44,7 @@ using std::string; + // Cache::Header::Header - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Simply initialize the header */ @@ -52,7 +54,7 @@ pkgCache::Header::Header() /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ - MajorVersion = 4; + MajorVersion = 5; MinorVersion = 0; Dirty = false; @@ -60,17 +62,22 @@ pkgCache::Header::Header() PackageSz = sizeof(pkgCache::Package); PackageFileSz = sizeof(pkgCache::PackageFile); VersionSz = sizeof(pkgCache::Version); + DescriptionSz = sizeof(pkgCache::Description); DependencySz = sizeof(pkgCache::Dependency); ProvidesSz = sizeof(pkgCache::Provides); VerFileSz = sizeof(pkgCache::VerFile); + DescFileSz = sizeof(pkgCache::DescFile); PackageCount = 0; VersionCount = 0; + DescriptionCount = 0; DependsCount = 0; PackageFileCount = 0; VerFileCount = 0; + DescFileCount = 0; ProvidesCount = 0; MaxVerFileSize = 0; + MaxDescFileSize = 0; FileList = 0; StringList = 0; @@ -89,8 +96,10 @@ bool pkgCache::Header::CheckSizes(Header &Against) const PackageSz == Against.PackageSz && PackageFileSz == Against.PackageFileSz && VersionSz == Against.VersionSz && + DescriptionSz == Against.DescriptionSz && DependencySz == Against.DependencySz && VerFileSz == Against.VerFileSz && + DescFileSz == Against.DescFileSz && ProvidesSz == Against.ProvidesSz) return true; return false; @@ -115,8 +124,10 @@ bool pkgCache::ReMap() HeaderP = (Header *)Map.Data(); PkgP = (Package *)Map.Data(); VerFileP = (VerFile *)Map.Data(); + DescFileP = (DescFile *)Map.Data(); PkgFileP = (PackageFile *)Map.Data(); VerP = (Version *)Map.Data(); + DescP = (Description *)Map.Data(); ProvideP = (Provides *)Map.Data(); DepP = (Dependency *)Map.Data(); StringItemP = (StringItem *)Map.Data(); @@ -235,11 +246,11 @@ const char *pkgCache::Priority(unsigned char Prio) return 0; } /*}}}*/ - // Bases for iterator classes /*{{{*/ void pkgCache::VerIterator::_dummy() {} void pkgCache::DepIterator::_dummy() {} void pkgCache::PrvIterator::_dummy() {} +void pkgCache::DescIterator::_dummy() {} /*}}}*/ // PkgIterator::operator ++ - Postfix incr /*{{{*/ // --------------------------------------------------------------------- @@ -599,3 +610,20 @@ string pkgCache::PkgFileIterator::RelStr() return Res; } /*}}}*/ +// VerIterator::TranslatedDescription - Return the a DescIter for locale/*{{{*/ +// --------------------------------------------------------------------- +/* return a DescIter for the current locale or the default if none is + * found + */ +pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const +{ + pkgCache::DescIterator DescDefault = DescriptionList(); + pkgCache::DescIterator Desc = DescDefault; + for (; Desc.end() == false; Desc++) + if (pkgIndexFile::LanguageCode() == Desc.LanguageCode()) + break; + if (Desc.end() == true) Desc = DescDefault; + return Desc; +}; + + /*}}}*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index b07951dfb..6a54ad5ba 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -38,24 +38,30 @@ class pkgCache struct Package; struct PackageFile; struct Version; + struct Description; struct Provides; struct Dependency; struct StringItem; struct VerFile; + struct DescFile; // Iterators class PkgIterator; class VerIterator; + class DescIterator; class DepIterator; class PrvIterator; class PkgFileIterator; class VerFileIterator; + class DescFileIterator; friend class PkgIterator; friend class VerIterator; + friend class DescInterator; friend class DepIterator; friend class PrvIterator; friend class PkgFileIterator; friend class VerFileIterator; + friend class DescFileIterator; class Namespace; @@ -98,8 +104,10 @@ class pkgCache Header *HeaderP; Package *PkgP; VerFile *VerFileP; + DescFile *DescFileP; PackageFile *PkgFileP; Version *VerP; + Description *DescP; Provides *ProvideP; Dependency *DepP; StringItem *StringItemP; @@ -151,16 +159,20 @@ struct pkgCache::Header unsigned short PackageSz; unsigned short PackageFileSz; unsigned short VersionSz; + unsigned short DescriptionSz; unsigned short DependencySz; unsigned short ProvidesSz; unsigned short VerFileSz; + unsigned short DescFileSz; // Structure counts unsigned long PackageCount; unsigned long VersionCount; + unsigned long DescriptionCount; unsigned long DependsCount; unsigned long PackageFileCount; unsigned long VerFileCount; + unsigned long DescFileCount; unsigned long ProvidesCount; // Offsets @@ -169,10 +181,11 @@ struct pkgCache::Header map_ptrloc VerSysName; // StringTable map_ptrloc Architecture; // StringTable unsigned long MaxVerFileSize; + unsigned long MaxDescFileSize; /* Allocation pools, there should be one of these for each structure excluding the header */ - DynamicMMap::Pool Pools[7]; + DynamicMMap::Pool Pools[8]; // Rapid package name lookup map_ptrloc HashTable[2*1048]; @@ -193,7 +206,7 @@ struct pkgCache::Package map_ptrloc NextPackage; // Package map_ptrloc RevDepends; // Dependency map_ptrloc ProvidesList; // Provides - + // Install/Remove/Purge etc unsigned char SelectedState; // What unsigned char InstState; // Flags @@ -232,6 +245,14 @@ struct pkgCache::VerFile unsigned short Size; }; +struct pkgCache::DescFile +{ + map_ptrloc File; // PackageFile + map_ptrloc NextFile; // PkgVerFile + map_ptrloc Offset; // File offset + unsigned short Size; +}; + struct pkgCache::Version { map_ptrloc VerStr; // Stringtable @@ -241,6 +262,7 @@ struct pkgCache::Version // Lists map_ptrloc FileList; // VerFile map_ptrloc NextVer; // Version + map_ptrloc DescriptionList; // Description map_ptrloc DependsList; // Dependency map_ptrloc ParentPkg; // Package map_ptrloc ProvidesList; // Provides @@ -252,6 +274,22 @@ struct pkgCache::Version unsigned char Priority; }; +struct pkgCache::Description +{ + // Language Code store the description translation language code. If + // the value has a 0 lenght then this is readed using the Package + // file else the Translation-CODE are used. + map_ptrloc language_code; // StringTable + map_ptrloc md5sum; // StringTable + + // Linked list + map_ptrloc FileList; // DescFile + map_ptrloc NextDesc; // Description + map_ptrloc ParentPkg; // Package + + unsigned short ID; +}; + struct pkgCache::Dependency { map_ptrloc Version; // Stringtable @@ -299,11 +337,13 @@ class pkgCache::Namespace typedef pkgCache::PkgIterator PkgIterator; typedef pkgCache::VerIterator VerIterator; + typedef pkgCache::DescIterator DescIterator; typedef pkgCache::DepIterator DepIterator; typedef pkgCache::PrvIterator PrvIterator; typedef pkgCache::PkgFileIterator PkgFileIterator; typedef pkgCache::VerFileIterator VerFileIterator; typedef pkgCache::Version Version; + typedef pkgCache::Description Description; typedef pkgCache::Package Package; typedef pkgCache::Header Header; typedef pkgCache::Dep Dep; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 2340f97fd..1ba791b45 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -125,16 +125,46 @@ bool pkgCacheGenerator::MergeList(ListParser &List, string Version = List.Version(); if (Version.empty() == true) { + // we first process the package, then the descriptions + // (this has the bonus that we get MMap error when we run out + // of MMap space) if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false) return _error->Error(_("Error occurred while processing %s (UsePackage1)"), PackageName.c_str()); + + // Find the right version to write the description + MD5SumValue CurMd5 = List.Description_md5(); + pkgCache::VerIterator Ver = Pkg.VersionList(); + map_ptrloc *LastVer = &Pkg->VersionList; + + for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) + { + pkgCache::DescIterator Desc = Ver.DescriptionList(); + map_ptrloc *LastDesc = &Ver->DescriptionList; + + for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++) + { + + if (MD5SumValue(Desc.md5()) == CurMd5) + { + // Add new description + *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), CurMd5, *LastDesc); + Desc->ParentPkg = Pkg.Index(); + + if (NewFileDesc(Desc,List) == false) + return _error->Error(_("Error occured while processing %s (NewFileDesc1)"),PackageName.c_str()); + break; + } + } + } + continue; } pkgCache::VerIterator Ver = Pkg.VersionList(); - map_ptrloc *Last = &Pkg->VersionList; + map_ptrloc *LastVer = &Pkg->VersionList; int Res = 1; - for (; Ver.end() == false; Last = &Ver->NextVer, Ver++) + for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) { Res = Cache.VS->CmpVersion(Version,Ver.VerStr()); if (Res >= 0) @@ -168,7 +198,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, // Skip to the end of the same version set. if (Res == 0) { - for (; Ver.end() == false; Last = &Ver->NextVer, Ver++) + for (; Ver.end() == false; LastVer = &Ver->NextVer, Ver++) { Res = Cache.VS->CmpVersion(Version,Ver.VerStr()); if (Res != 0) @@ -177,9 +207,10 @@ bool pkgCacheGenerator::MergeList(ListParser &List, } // Add a new version - *Last = NewVersion(Ver,Version,*Last); + *LastVer = NewVersion(Ver,Version,*LastVer); Ver->ParentPkg = Pkg.Index(); Ver->Hash = Hash; + if (List.NewVersion(Ver) == false) return _error->Error(_("Error occurred while processing %s (NewVersion1)"), PackageName.c_str()); @@ -199,6 +230,21 @@ bool pkgCacheGenerator::MergeList(ListParser &List, FoundFileDeps |= List.HasFileDeps(); return true; } + + /* Record the Description data. Description data always exist in + Packages and Translation-* files. */ + pkgCache::DescIterator Desc = Ver.DescriptionList(); + map_ptrloc *LastDesc = &Ver->DescriptionList; + + // Skip to the end of description set + for (; Desc.end() == false; LastDesc = &Desc->NextDesc, Desc++); + + // Add new description + *LastDesc = NewDescription(Desc, List.DescriptionLanguage(), List.Description_md5(), *LastDesc); + Desc->ParentPkg = Pkg.Index(); + + if (NewFileDesc(Desc,List) == false) + return _error->Error(_("Error occured while processing %s (NewFileDesc2)"),PackageName.c_str()); } FoundFileDeps |= List.HasFileDeps(); @@ -209,6 +255,9 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if (Cache.HeaderP->VersionCount >= (1ULL<<(sizeof(Cache.VerP->ID)*8))-1) return _error->Error(_("Wow, you exceeded the number of versions " "this APT is capable of.")); + if (Cache.HeaderP->DescriptionCount >= (1ULL<<(sizeof(Cache.DescP->ID)*8))-1) + return _error->Error(_("Wow, you exceeded the number of descriptions " + "this APT is capable of.")); if (Cache.HeaderP->DependsCount >= (1ULL<<(sizeof(Cache.DepP->ID)*8))-1ULL) return _error->Error(_("Wow, you exceeded the number of dependencies " "this APT is capable of.")); @@ -271,7 +320,7 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name) Pkg = Cache.FindPkg(Name); if (Pkg.end() == false) return true; - + // Get a structure unsigned long Package = Map.Allocate(sizeof(pkgCache::Package)); if (Package == 0) @@ -349,6 +398,62 @@ unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver, return Version; } /*}}}*/ +// CacheGenerator::NewFileDesc - Create a new File<->Desc association /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool pkgCacheGenerator::NewFileDesc(pkgCache::DescIterator &Desc, + ListParser &List) +{ + if (CurrentFile == 0) + return true; + + // Get a structure + unsigned long DescFile = Map.Allocate(sizeof(pkgCache::DescFile)); + if (DescFile == 0) + return 0; + + pkgCache::DescFileIterator DF(Cache,Cache.DescFileP + DescFile); + DF->File = CurrentFile - Cache.PkgFileP; + + // Link it to the end of the list + map_ptrloc *Last = &Desc->FileList; + for (pkgCache::DescFileIterator D = Desc.FileList(); D.end() == false; D++) + Last = &D->NextFile; + + DF->NextFile = *Last; + *Last = DF.Index(); + + DF->Offset = List.Offset(); + DF->Size = List.Size(); + if (Cache.HeaderP->MaxDescFileSize < DF->Size) + Cache.HeaderP->MaxDescFileSize = DF->Size; + Cache.HeaderP->DescFileCount++; + + return true; +} + /*}}}*/ +// CacheGenerator::NewDescription - Create a new Description /*{{{*/ +// --------------------------------------------------------------------- +/* This puts a description structure in the linked list */ +map_ptrloc pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, + const string &Lang, const MD5SumValue &md5sum, + map_ptrloc Next) +{ + // Get a structure + map_ptrloc Description = Map.Allocate(sizeof(pkgCache::Description)); + if (Description == 0) + return 0; + + // Fill it in + Desc = pkgCache::DescIterator(Cache,Cache.DescP + Description); + Desc->NextDesc = Next; + Desc->ID = Cache.HeaderP->DescriptionCount++; + Desc->language_code = Map.WriteString(Lang); + Desc->md5sum = Map.WriteString(md5sum.Value()); + + return Description; +} + /*}}}*/ // ListParser::NewDepends - Create a dependency element /*{{{*/ // --------------------------------------------------------------------- /* This creates a dependency element in the tree. It is linked to the @@ -580,7 +685,7 @@ static bool CheckValidity(string CacheFile, FileIterator Start, pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache); if (File.end() == true) return false; - + Visited[File->ID] = true; } diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 7d0920629..6ab8594d9 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -24,6 +24,7 @@ #endif #include <apt-pkg/pkgcache.h> +#include <apt-pkg/md5.h> class pkgSourceList; class OpProgress; @@ -55,7 +56,9 @@ class pkgCacheGenerator bool NewPackage(pkgCache::PkgIterator &Pkg,string Pkg); bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); + bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List); unsigned long NewVersion(pkgCache::VerIterator &Ver,string VerStr,unsigned long Next); + map_ptrloc NewDescription(pkgCache::DescIterator &Desc,const string &Lang,const MD5SumValue &md5sum,map_ptrloc Next); public: @@ -107,6 +110,9 @@ class pkgCacheGenerator::ListParser virtual string Package() = 0; virtual string Version() = 0; virtual bool NewVersion(pkgCache::VerIterator Ver) = 0; + virtual string Description() = 0; + virtual string DescriptionLanguage() = 0; + virtual MD5SumValue Description_md5() = 0; virtual unsigned short VersionHash() = 0; virtual bool UsePackage(pkgCache::PkgIterator Pkg, pkgCache::VerIterator Ver) = 0; diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc index 9c2655d6a..b22f3e73f 100644 --- a/apt-pkg/pkgrecords.cc +++ b/apt-pkg/pkgrecords.cc @@ -63,3 +63,12 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::VerFileIterator const &Ver) return *Files[Ver.File()->ID]; } /*}}}*/ +// Records::Lookup - Get a parser for the package description file /*{{{*/ +// --------------------------------------------------------------------- +/* */ +pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc) +{ + Files[Desc.File()->ID]->Jump(Desc); + return *Files[Desc.File()->ID]; +} + /*}}}*/ diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index 08f004414..31c444dbf 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -38,6 +38,7 @@ class pkgRecords // Lookup function Parser &Lookup(pkgCache::VerFileIterator const &Ver); + Parser &Lookup(pkgCache::DescFileIterator const &Desc); // Construct destruct pkgRecords(pkgCache &Cache); @@ -49,6 +50,7 @@ class pkgRecords::Parser protected: virtual bool Jump(pkgCache::VerFileIterator const &Ver) = 0; + virtual bool Jump(pkgCache::DescFileIterator const &Desc) = 0; public: friend class pkgRecords; |