X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/b2e465d6d32d2dc884f58b94acb7e35f671a87fe..e0c4f06387ade5761e644b5b96e41284c12da23c:/apt-pkg/pkgcachegen.cc diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 2fcccaf4a..1ba791b45 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgcachegen.cc,v 1.46 2001/02/20 07:03:17 jgg Exp $ +// $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -27,19 +27,23 @@ #include #include - + +#include + #include #include #include #include #include /*}}}*/ +typedef vector::iterator FileIterator; // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/ // --------------------------------------------------------------------- /* We set the diry flag and make sure that is written to the disk */ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : - Map(*pMap), Cache(pMap,false), Progress(Prog) + Map(*pMap), Cache(pMap,false), Progress(Prog), + FoundFileDeps(0) { CurrentFile = 0; memset(UniqHash,0,sizeof(UniqHash)); @@ -110,7 +114,7 @@ bool pkgCacheGenerator::MergeList(ListParser &List, pkgCache::PkgIterator Pkg; if (NewPackage(Pkg,PackageName) == false) - return _error->Error(_("Error occured while processing %s (NewPackage)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewPackage)"),PackageName.c_str()); Counter++; if (Counter % 100 == 0 && Progress != 0) Progress->Progress(List.Offset()); @@ -121,18 +125,48 @@ 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 occured while processing %s (UsePackage1)"),PackageName.c_str()); + 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->DoCmpVersion(Version.begin(),Version.end(),Ver.VerStr(), - Ver.VerStr() + strlen(Ver.VerStr())); + Res = Cache.VS->CmpVersion(Version,Ver.VerStr()); if (Res >= 0) break; } @@ -143,15 +177,18 @@ bool pkgCacheGenerator::MergeList(ListParser &List, if (Res == 0 && Ver->Hash == Hash) { if (List.UsePackage(Pkg,Ver) == false) - return _error->Error(_("Error occured while processing %s (UsePackage2)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (UsePackage2)"), + PackageName.c_str()); if (NewFileVer(Ver,List) == false) - return _error->Error(_("Error occured while processing %s (NewFileVer1)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewFileVer1)"), + PackageName.c_str()); // Read only a single record and return if (OutVer != 0) { *OutVer = Ver; + FoundFileDeps |= List.HasFileDeps(); return true; } @@ -161,34 +198,115 @@ 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->DoCmpVersion(Version.begin(),Version.end(),Ver.VerStr(), - Ver.VerStr() + strlen(Ver.VerStr())); + Res = Cache.VS->CmpVersion(Version,Ver.VerStr()); if (Res != 0) break; } } // 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 occured while processing %s (NewVersion1)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewVersion1)"), + PackageName.c_str()); if (List.UsePackage(Pkg,Ver) == false) - return _error->Error(_("Error occured while processing %s (UsePackage3)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (UsePackage3)"), + PackageName.c_str()); if (NewFileVer(Ver,List) == false) - return _error->Error(_("Error occured while processing %s (NewVersion2)"),PackageName.c_str()); + return _error->Error(_("Error occurred while processing %s (NewVersion2)"), + PackageName.c_str()); // Read only a single record and return if (OutVer != 0) { *OutVer = Ver; + 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(); + + if (Cache.HeaderP->PackageCount >= (1ULL<ID)*8)-1) + return _error->Error(_("Wow, you exceeded the number of package " + "names this APT is capable of.")); + 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.")); + return true; +} + /*}}}*/ +// CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/ +// --------------------------------------------------------------------- +/* If we found any file depends while parsing the main list we need to + resolve them. Since it is undesired to load the entire list of files + into the cache as virtual packages we do a two stage effort. MergeList + identifies the file depends and this creates Provdies for them by + re-parsing all the indexs. */ +bool pkgCacheGenerator::MergeFileProvides(ListParser &List) +{ + List.Owner = this; + + unsigned int Counter = 0; + while (List.Step() == true) + { + string PackageName = List.Package(); + if (PackageName.empty() == true) + return false; + string Version = List.Version(); + if (Version.empty() == true) + continue; + + pkgCache::PkgIterator Pkg = Cache.FindPkg(PackageName); + if (Pkg.end() == true) + return _error->Error(_("Error occurred while processing %s (FindPkg)"), + PackageName.c_str()); + Counter++; + if (Counter % 100 == 0 && Progress != 0) + Progress->Progress(List.Offset()); + + unsigned long Hash = List.VersionHash(); + pkgCache::VerIterator Ver = Pkg.VersionList(); + for (; Ver.end() == false; Ver++) + { + if (Ver->Hash == Hash && Version.c_str() == Ver.VerStr()) + { + if (List.CollectFileProvides(Cache,Ver) == false) + return _error->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName.c_str()); + break; + } + } + + if (Ver.end() == true) + _error->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName.c_str(),Version.c_str()); } return true; @@ -202,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) @@ -280,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 @@ -334,6 +508,10 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver, OldDepLast = &D->NextDepends; OldDepVer = Ver; } + + // Is it a file dependency? + if (PackageName[0] == '/') + FoundFileDeps = true; Dep->NextDepends = *OldDepLast; *OldDepLast = Dep.Index(); @@ -470,8 +648,8 @@ unsigned long pkgCacheGenerator::WriteUniqString(const char *S, /* This just verifies that each file in the list of index files exists, has matching attributes with the cache and the cache does not have any extra files. */ -static bool CheckValidity(string CacheFile,pkgIndexFile **Start, - pkgIndexFile **End,MMap **OutMap = 0) +static bool CheckValidity(string CacheFile, FileIterator Start, + FileIterator End,MMap **OutMap = 0) { // No file, certainly invalid if (CacheFile.empty() == true || FileExists(CacheFile) == false) @@ -492,10 +670,10 @@ static bool CheckValidity(string CacheFile,pkgIndexFile **Start, SPtrArray Visited = new bool[Cache.HeaderP->PackageFileCount]; memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount); for (; Start != End; Start++) - { + { if ((*Start)->HasPackages() == false) continue; - + if ((*Start)->Exists() == false) { _error->WarningE("stat",_("Couldn't stat source package list %s"), @@ -507,7 +685,7 @@ static bool CheckValidity(string CacheFile,pkgIndexFile **Start, pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache); if (File.end() == true) return false; - + Visited[File->ID] = true; } @@ -530,7 +708,7 @@ static bool CheckValidity(string CacheFile,pkgIndexFile **Start, // --------------------------------------------------------------------- /* Size is kind of an abstract notion that is only used for the progress meter */ -static unsigned long ComputeSize(pkgIndexFile **Start,pkgIndexFile **End) +static unsigned long ComputeSize(FileIterator Start,FileIterator End) { unsigned long TotalSize = 0; for (; Start != End; Start++) @@ -548,23 +726,46 @@ static unsigned long ComputeSize(pkgIndexFile **Start,pkgIndexFile **End) static bool BuildCache(pkgCacheGenerator &Gen, OpProgress &Progress, unsigned long &CurrentSize,unsigned long TotalSize, - pkgIndexFile **Start,pkgIndexFile **End) + FileIterator Start, FileIterator End) { - for (; Start != End; Start++) + FileIterator I; + for (I = Start; I != End; I++) { - if ((*Start)->HasPackages() == false) + if ((*I)->HasPackages() == false) continue; - if ((*Start)->Exists() == false) + if ((*I)->Exists() == false) continue; - unsigned long Size = (*Start)->Size(); - Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Reading Package Lists")); + if ((*I)->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*I)->Describe().c_str()); + continue; + } + + unsigned long Size = (*I)->Size(); + Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); CurrentSize += Size; - if ((*Start)->Merge(Gen,Progress) == false) + if ((*I)->Merge(Gen,Progress) == false) return false; } + + if (Gen.HasFileDeps() == true) + { + Progress.Done(); + TotalSize = ComputeSize(Start, End); + CurrentSize = 0; + for (I = Start; I != End; I++) + { + unsigned long Size = (*I)->Size(); + Progress.OverallProgress(CurrentSize,TotalSize,Size,_("Collecting File Provides")); + CurrentSize += Size; + if ((*I)->MergeFileProvides(Gen,Progress) == false) + return false; + } + } return true; } @@ -580,9 +781,20 @@ static bool BuildCache(pkgCacheGenerator &Gen, bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, MMap **OutMap,bool AllowMem) { - unsigned long MapSize = _config->FindI("APT::Cache-Limit",4*1024*1024); + unsigned long MapSize = _config->FindI("APT::Cache-Limit",12*1024*1024); + + vector Files; + for (vector::const_iterator i = List.begin(); + i != List.end(); + i++) + { + vector *Indexes = (*i)->GetIndexFiles(); + for (vector::const_iterator j = Indexes->begin(); + j != Indexes->end(); + j++) + Files.push_back (*j); + } - vector Files(List.begin(),List.end()); unsigned long EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; @@ -602,12 +814,12 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, if (Writeable == false && AllowMem == false && CacheFile.empty() == false) return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str()); - Progress.OverallProgress(0,1,1,_("Reading Package Lists")); + Progress.OverallProgress(0,1,1,_("Reading package lists")); // Cache is OK, Fin. if (CheckValidity(CacheFile,Files.begin(),Files.end(),OutMap) == true) { - Progress.OverallProgress(1,1,1,_("Reading Package Lists")); + Progress.OverallProgress(1,1,1,_("Reading package lists")); return true; } @@ -619,6 +831,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, { unlink(CacheFile.c_str()); CacheF = new FileFd(CacheFile,FileFd::WriteEmpty); + fchmod(CacheF->Fd(),0644); Map = new DynamicMMap(*CacheF,MMap::Public,MapSize); if (_error->PendingError() == true) return false; @@ -669,6 +882,9 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, FileFd SCacheF(SrcCacheFile,FileFd::WriteEmpty); if (_error->PendingError() == true) return false; + + fchmod(SCacheF.Fd(),0644); + // Write out the main data if (SCacheF.Write(Map->Data(),Map->Size()) == false) return _error->Error(_("IO Error saving source cache")); @@ -679,8 +895,8 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, if (SCacheF.Seek(0) == false || SCacheF.Write(Map->Data(),sizeof(*Gen.GetCache().HeaderP)) == false) return _error->Error(_("IO Error saving source cache")); - SCacheF.Sync(); Gen.GetCache().HeaderP->Dirty = true; + SCacheF.Sync(); } // Build the status cache @@ -712,7 +928,7 @@ bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, /* */ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap) { - unsigned long MapSize = _config->FindI("APT::Cache-Limit",4*1024*1024); + unsigned long MapSize = _config->FindI("APT::Cache-Limit",8*1024*1024); vector Files; unsigned long EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) @@ -726,7 +942,7 @@ bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **OutMap) TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); // Build the status cache - Progress.OverallProgress(0,1,1,_("Reading Package Lists")); + Progress.OverallProgress(0,1,1,_("Reading package lists")); pkgCacheGenerator Gen(Map.Get(),&Progress); if (_error->PendingError() == true) return false;