]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: pkgcachegen.cc,v 1.53.2.1 2003/12/24 23:09:17 mdz Exp $
4 /* ######################################################################
6 Package Cache Generator - Generator for the cache structure.
8 This builds the cache structure from the abstract package list parser.
10 ##################################################################### */
12 // Include Files /*{{{*/
14 #pragma implementation "apt-pkg/pkgcachegen.h"
17 #define APT_COMPATIBILITY 986
19 #include <apt-pkg/pkgcachegen.h>
20 #include <apt-pkg/error.h>
21 #include <apt-pkg/version.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/sourcelist.h>
24 #include <apt-pkg/configuration.h>
25 #include <apt-pkg/strutl.h>
26 #include <apt-pkg/sptr.h>
27 #include <apt-pkg/pkgsystem.h>
29 #include <apt-pkg/tagfile.h>
41 typedef vector
<pkgIndexFile
*>::iterator FileIterator
;
43 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
44 // ---------------------------------------------------------------------
45 /* We set the diry flag and make sure that is written to the disk */
46 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
*pMap
,OpProgress
*Prog
) :
47 Map(*pMap
), Cache(pMap
,false), Progress(Prog
),
51 memset(UniqHash
,0,sizeof(UniqHash
));
53 if (_error
->PendingError() == true)
58 // Setup the map interface..
59 Cache
.HeaderP
= (pkgCache::Header
*)Map
.Data();
60 Map
.RawAllocate(sizeof(pkgCache::Header
));
61 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
64 *Cache
.HeaderP
= pkgCache::Header();
65 Cache
.HeaderP
->VerSysName
= Map
.WriteString(_system
->VS
->Label
);
66 Cache
.HeaderP
->Architecture
= Map
.WriteString(_config
->Find("APT::Architecture"));
71 // Map directly from the existing file
73 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
74 if (Cache
.VS
!= _system
->VS
)
76 _error
->Error(_("Cache has an incompatible versioning system"));
81 Cache
.HeaderP
->Dirty
= true;
82 Map
.Sync(0,sizeof(pkgCache::Header
));
85 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
86 // ---------------------------------------------------------------------
87 /* We sync the data then unset the dirty flag in two steps so as to
88 advoid a problem during a crash */
89 pkgCacheGenerator::~pkgCacheGenerator()
91 if (_error
->PendingError() == true)
93 if (Map
.Sync() == false)
96 Cache
.HeaderP
->Dirty
= false;
97 Map
.Sync(0,sizeof(pkgCache::Header
));
100 // CacheGenerator::MergeList - Merge the package list /*{{{*/
101 // ---------------------------------------------------------------------
102 /* This provides the generation of the entries in the cache. Each loop
103 goes through a single package record from the underlying parse engine. */
104 bool pkgCacheGenerator::MergeList(ListParser
&List
,
105 pkgCache::VerIterator
*OutVer
)
109 unsigned int Counter
= 0;
110 while (List
.Step() == true)
112 // Get a pointer to the package structure
113 string PackageName
= List
.Package();
114 if (PackageName
.empty() == true)
117 pkgCache::PkgIterator Pkg
;
118 if (NewPackage(Pkg
,PackageName
) == false)
119 return _error
->Error(_("Error occurred while processing %s (NewPackage)"),PackageName
.c_str());
121 if (Counter
% 100 == 0 && Progress
!= 0)
122 Progress
->Progress(List
.Offset());
124 /* Get a pointer to the version structure. We know the list is sorted
125 so we use that fact in the search. Insertion of new versions is
126 done with correct sorting */
127 string Version
= List
.Version();
128 if (Version
.empty() == true)
130 if (List
.UsePackage(Pkg
,pkgCache::VerIterator(Cache
)) == false)
131 return _error
->Error(_("Error occurred while processing %s (UsePackage1)"),
132 PackageName
.c_str());
136 pkgCache::VerIterator Ver
= Pkg
.VersionList();
137 map_ptrloc
*Last
= &Pkg
->VersionList
;
139 for (; Ver
.end() == false; Last
= &Ver
->NextVer
, Ver
++)
141 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
146 /* We already have a version for this item, record that we
148 unsigned long Hash
= List
.VersionHash();
149 if (Res
== 0 && Ver
->Hash
== Hash
)
151 if (List
.UsePackage(Pkg
,Ver
) == false)
152 return _error
->Error(_("Error occurred while processing %s (UsePackage2)"),
153 PackageName
.c_str());
155 if (NewFileVer(Ver
,List
) == false)
156 return _error
->Error(_("Error occurred while processing %s (NewFileVer1)"),
157 PackageName
.c_str());
159 // Read only a single record and return
163 FoundFileDeps
|= List
.HasFileDeps();
170 // Skip to the end of the same version set.
173 for (; Ver
.end() == false; Last
= &Ver
->NextVer
, Ver
++)
175 Res
= Cache
.VS
->CmpVersion(Version
,Ver
.VerStr());
182 *Last
= NewVersion(Ver
,Version
,*Last
);
183 Ver
->ParentPkg
= Pkg
.Index();
185 if (List
.NewVersion(Ver
) == false)
186 return _error
->Error(_("Error occurred while processing %s (NewVersion1)"),
187 PackageName
.c_str());
189 if (List
.UsePackage(Pkg
,Ver
) == false)
190 return _error
->Error(_("Error occurred while processing %s (UsePackage3)"),
191 PackageName
.c_str());
193 if (NewFileVer(Ver
,List
) == false)
194 return _error
->Error(_("Error occurred while processing %s (NewVersion2)"),
195 PackageName
.c_str());
197 // Read only a single record and return
201 FoundFileDeps
|= List
.HasFileDeps();
206 FoundFileDeps
|= List
.HasFileDeps();
208 if (Cache
.HeaderP
->PackageCount
>= (1ULL<<sizeof(Cache
.PkgP
->ID
)*8)-1)
209 return _error
->Error(_("Wow, you exceeded the number of package "
210 "names this APT is capable of."));
211 if (Cache
.HeaderP
->VersionCount
>= (1ULL<<(sizeof(Cache
.VerP
->ID
)*8))-1)
212 return _error
->Error(_("Wow, you exceeded the number of versions "
213 "this APT is capable of."));
214 if (Cache
.HeaderP
->DependsCount
>= (1ULL<<(sizeof(Cache
.DepP
->ID
)*8))-1ULL)
215 return _error
->Error(_("Wow, you exceeded the number of dependencies "
216 "this APT is capable of."));
220 // CacheGenerator::MergeFileProvides - Merge file provides /*{{{*/
221 // ---------------------------------------------------------------------
222 /* If we found any file depends while parsing the main list we need to
223 resolve them. Since it is undesired to load the entire list of files
224 into the cache as virtual packages we do a two stage effort. MergeList
225 identifies the file depends and this creates Provdies for them by
226 re-parsing all the indexs. */
227 bool pkgCacheGenerator::MergeFileProvides(ListParser
&List
)
231 unsigned int Counter
= 0;
232 while (List
.Step() == true)
234 string PackageName
= List
.Package();
235 if (PackageName
.empty() == true)
237 string Version
= List
.Version();
238 if (Version
.empty() == true)
241 pkgCache::PkgIterator Pkg
= Cache
.FindPkg(PackageName
);
242 if (Pkg
.end() == true)
243 return _error
->Error(_("Error occurred while processing %s (FindPkg)"),
244 PackageName
.c_str());
246 if (Counter
% 100 == 0 && Progress
!= 0)
247 Progress
->Progress(List
.Offset());
249 unsigned long Hash
= List
.VersionHash();
250 pkgCache::VerIterator Ver
= Pkg
.VersionList();
251 for (; Ver
.end() == false; Ver
++)
253 if (Ver
->Hash
== Hash
&& Version
.c_str() == Ver
.VerStr())
255 if (List
.CollectFileProvides(Cache
,Ver
) == false)
256 return _error
->Error(_("Error occurred while processing %s (CollectFileProvides)"),PackageName
.c_str());
261 if (Ver
.end() == true)
262 _error
->Warning(_("Package %s %s was not found while processing file dependencies"),PackageName
.c_str(),Version
.c_str());
268 // CacheGenerator::NewPackage - Add a new package /*{{{*/
269 // ---------------------------------------------------------------------
270 /* This creates a new package structure and adds it to the hash table */
271 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,const string
&Name
)
273 Pkg
= Cache
.FindPkg(Name
);
274 if (Pkg
.end() == false)
278 unsigned long Package
= Map
.Allocate(sizeof(pkgCache::Package
));
282 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
284 // Insert it into the hash table
285 unsigned long Hash
= Cache
.Hash(Name
);
286 Pkg
->NextPackage
= Cache
.HeaderP
->HashTable
[Hash
];
287 Cache
.HeaderP
->HashTable
[Hash
] = Package
;
289 // Set the name and the ID
290 Pkg
->Name
= Map
.WriteString(Name
);
293 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
298 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
299 // ---------------------------------------------------------------------
301 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
304 if (CurrentFile
== 0)
308 unsigned long VerFile
= Map
.Allocate(sizeof(pkgCache::VerFile
));
312 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
313 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
315 // Link it to the end of the list
316 map_ptrloc
*Last
= &Ver
->FileList
;
317 for (pkgCache::VerFileIterator V
= Ver
.FileList(); V
.end() == false; V
++)
319 VF
->NextFile
= *Last
;
322 VF
->Offset
= List
.Offset();
323 VF
->Size
= List
.Size();
324 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
325 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
326 Cache
.HeaderP
->VerFileCount
++;
331 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
332 // ---------------------------------------------------------------------
333 /* This puts a version structure in the linked list */
334 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
335 const string
&VerStr
,
339 unsigned long Version
= Map
.Allocate(sizeof(pkgCache::Version
));
344 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
346 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
347 Ver
->VerStr
= Map
.WriteString(VerStr
);
348 if (Ver
->VerStr
== 0)
354 // ListParser::NewDepends - Create a dependency element /*{{{*/
355 // ---------------------------------------------------------------------
356 /* This creates a dependency element in the tree. It is linked to the
357 version and to the package that it is pointing to. */
358 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver
,
359 const string
&PackageName
,
360 const string
&Version
,
364 pkgCache
&Cache
= Owner
->Cache
;
367 unsigned long Dependency
= Owner
->Map
.Allocate(sizeof(pkgCache::Dependency
));
372 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
373 Dep
->ParentVer
= Ver
.Index();
376 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
378 // Locate the target package
379 pkgCache::PkgIterator Pkg
;
380 if (Owner
->NewPackage(Pkg
,PackageName
) == false)
383 // Probe the reverse dependency list for a version string that matches
384 if (Version
.empty() == false)
386 /* for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
387 if (I->Version != 0 && I.TargetVer() == Version)
388 Dep->Version = I->Version;*/
389 if (Dep
->Version
== 0)
390 if ((Dep
->Version
= WriteString(Version
)) == 0)
394 // Link it to the package
395 Dep
->Package
= Pkg
.Index();
396 Dep
->NextRevDepends
= Pkg
->RevDepends
;
397 Pkg
->RevDepends
= Dep
.Index();
399 /* Link it to the version (at the end of the list)
400 Caching the old end point speeds up generation substantially */
401 if (OldDepVer
!= Ver
)
403 OldDepLast
= &Ver
->DependsList
;
404 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
405 OldDepLast
= &D
->NextDepends
;
409 // Is it a file dependency?
410 if (PackageName
[0] == '/')
411 FoundFileDeps
= true;
413 Dep
->NextDepends
= *OldDepLast
;
414 *OldDepLast
= Dep
.Index();
415 OldDepLast
= &Dep
->NextDepends
;
420 // ListParser::NewProvides - Create a Provides element /*{{{*/
421 // ---------------------------------------------------------------------
423 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver
,
424 const string
&PackageName
,
425 const string
&Version
)
427 pkgCache
&Cache
= Owner
->Cache
;
429 // We do not add self referencing provides
430 if (Ver
.ParentPkg().Name() == PackageName
)
434 unsigned long Provides
= Owner
->Map
.Allocate(sizeof(pkgCache::Provides
));
437 Cache
.HeaderP
->ProvidesCount
++;
440 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
441 Prv
->Version
= Ver
.Index();
442 Prv
->NextPkgProv
= Ver
->ProvidesList
;
443 Ver
->ProvidesList
= Prv
.Index();
444 if (Version
.empty() == false && (Prv
->ProvideVersion
= WriteString(Version
)) == 0)
447 // Locate the target package
448 pkgCache::PkgIterator Pkg
;
449 if (Owner
->NewPackage(Pkg
,PackageName
) == false)
452 // Link it to the package
453 Prv
->ParentPkg
= Pkg
.Index();
454 Prv
->NextProvides
= Pkg
->ProvidesList
;
455 Pkg
->ProvidesList
= Prv
.Index();
460 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
461 // ---------------------------------------------------------------------
462 /* This is used to select which file is to be associated with all newly
463 added versions. The caller is responsible for setting the IMS fields. */
464 bool pkgCacheGenerator::SelectFile(const string
&File
,const string
&Site
,
465 const pkgIndexFile
&Index
,
468 // Get some space for the structure
469 CurrentFile
= Cache
.PkgFileP
+ Map
.Allocate(sizeof(*CurrentFile
));
470 if (CurrentFile
== Cache
.PkgFileP
)
474 CurrentFile
->FileName
= Map
.WriteString(File
);
475 CurrentFile
->Site
= WriteUniqString(Site
);
476 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
477 CurrentFile
->Flags
= Flags
;
478 CurrentFile
->ID
= Cache
.HeaderP
->PackageFileCount
;
479 CurrentFile
->IndexType
= WriteUniqString(Index
.GetType()->Label
);
481 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
482 Cache
.HeaderP
->PackageFileCount
++;
484 if (CurrentFile
->FileName
== 0)
488 Progress
->SubProgress(Index
.Size());
492 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
493 // ---------------------------------------------------------------------
494 /* This is used to create handles to strings. Given the same text it
495 always returns the same number */
496 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
499 /* We use a very small transient hash table here, this speeds up generation
500 by a fair amount on slower machines */
501 pkgCache::StringItem
*&Bucket
= UniqHash
[(S
[0]*5 + S
[1]) % _count(UniqHash
)];
503 stringcmp(S
,S
+Size
,Cache
.StrP
+ Bucket
->String
) == 0)
504 return Bucket
->String
;
506 // Search for an insertion point
507 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
509 map_ptrloc
*Last
= &Cache
.HeaderP
->StringList
;
510 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
511 I
= Cache
.StringItemP
+ I
->NextItem
)
513 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
526 unsigned long Item
= Map
.Allocate(sizeof(pkgCache::StringItem
));
530 // Fill in the structure
531 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
532 ItemP
->NextItem
= I
- Cache
.StringItemP
;
534 ItemP
->String
= Map
.WriteString(S
,Size
);
535 if (ItemP
->String
== 0)
539 return ItemP
->String
;
543 // CheckValidity - Check that a cache is up-to-date /*{{{*/
544 // ---------------------------------------------------------------------
545 /* This just verifies that each file in the list of index files exists,
546 has matching attributes with the cache and the cache does not have
548 static bool CheckValidity(const string
&CacheFile
, FileIterator Start
,
549 FileIterator End
,MMap
**OutMap
= 0)
551 // No file, certainly invalid
552 if (CacheFile
.empty() == true || FileExists(CacheFile
) == false)
556 FileFd
CacheF(CacheFile
,FileFd::ReadOnly
);
557 SPtr
<MMap
> Map
= new MMap(CacheF
,MMap::Public
| MMap::ReadOnly
);
559 if (_error
->PendingError() == true || Map
->Size() == 0)
565 /* Now we check every index file, see if it is in the cache,
566 verify the IMS data and check that it is on the disk too.. */
567 SPtrArray
<bool> Visited
= new bool[Cache
.HeaderP
->PackageFileCount
];
568 memset(Visited
,0,sizeof(*Visited
)*Cache
.HeaderP
->PackageFileCount
);
569 for (; Start
!= End
; Start
++)
571 if ((*Start
)->HasPackages() == false)
574 if ((*Start
)->Exists() == false)
576 #if 0 // mvo: we no longer give a message here (Default Sources spec)
577 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
578 (*Start
)->Describe().c_str());
583 // FindInCache is also expected to do an IMS check.
584 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
585 if (File
.end() == true)
588 Visited
[File
->ID
] = true;
591 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
592 if (Visited
[I
] == false)
595 if (_error
->PendingError() == true)
602 *OutMap
= Map
.UnGuard();
606 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
607 // ---------------------------------------------------------------------
608 /* Size is kind of an abstract notion that is only used for the progress
610 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
612 unsigned long TotalSize
= 0;
613 for (; Start
!= End
; Start
++)
615 if ((*Start
)->HasPackages() == false)
617 TotalSize
+= (*Start
)->Size();
622 // BuildCache - Merge the list of index files into the cache /*{{{*/
623 // ---------------------------------------------------------------------
625 static bool BuildCache(pkgCacheGenerator
&Gen
,
626 OpProgress
&Progress
,
627 unsigned long &CurrentSize
,unsigned long TotalSize
,
628 FileIterator Start
, FileIterator End
)
631 for (I
= Start
; I
!= End
; I
++)
633 if ((*I
)->HasPackages() == false)
636 if ((*I
)->Exists() == false)
639 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
641 _error
->Warning("Duplicate sources.list entry %s",
642 (*I
)->Describe().c_str());
646 unsigned long Size
= (*I
)->Size();
647 Progress
.OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
650 if ((*I
)->Merge(Gen
,Progress
) == false)
654 if (Gen
.HasFileDeps() == true)
657 TotalSize
= ComputeSize(Start
, End
);
659 for (I
= Start
; I
!= End
; I
++)
661 unsigned long Size
= (*I
)->Size();
662 Progress
.OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
664 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
672 // MakeStatusCache - Construct the status cache /*{{{*/
673 // ---------------------------------------------------------------------
674 /* This makes sure that the status cache (the cache that has all
675 index files from the sources list and all local ones) is ready
676 to be mmaped. If OutMap is not zero then a MMap object representing
677 the cache will be stored there. This is pretty much mandetory if you
678 are using AllowMem. AllowMem lets the function be run as non-root
679 where it builds the cache 'fast' into a memory buffer. */
680 bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
681 MMap
**OutMap
,bool AllowMem
)
683 unsigned long MapSize
= _config
->FindI("APT::Cache-Limit",12*1024*1024);
685 vector
<pkgIndexFile
*> Files
;
686 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
690 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
691 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
694 Files
.push_back (*j
);
697 unsigned long EndOfSource
= Files
.size();
698 if (_system
->AddStatusFiles(Files
) == false)
701 // Decide if we can write to the files..
702 string CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
703 string SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
705 // Decide if we can write to the cache
706 bool Writeable
= false;
707 if (CacheFile
.empty() == false)
708 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
710 if (SrcCacheFile
.empty() == false)
711 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
713 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
714 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
716 Progress
.OverallProgress(0,1,1,_("Reading package lists"));
719 if (CheckValidity(CacheFile
,Files
.begin(),Files
.end(),OutMap
) == true)
721 Progress
.OverallProgress(1,1,1,_("Reading package lists"));
725 /* At this point we know we need to reconstruct the package cache,
728 SPtr
<DynamicMMap
> Map
;
729 if (Writeable
== true && CacheFile
.empty() == false)
731 unlink(CacheFile
.c_str());
732 CacheF
= new FileFd(CacheFile
,FileFd::WriteEmpty
);
733 fchmod(CacheF
->Fd(),0644);
734 Map
= new DynamicMMap(*CacheF
,MMap::Public
,MapSize
);
735 if (_error
->PendingError() == true)
740 // Just build it in memory..
741 Map
= new DynamicMMap(MMap::Public
,MapSize
);
744 // Lets try the source cache.
745 unsigned long CurrentSize
= 0;
746 unsigned long TotalSize
= 0;
747 if (CheckValidity(SrcCacheFile
,Files
.begin(),
748 Files
.begin()+EndOfSource
) == true)
750 // Preload the map with the source cache
751 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
752 if (SCacheF
.Read((unsigned char *)Map
->Data() + Map
->RawAllocate(SCacheF
.Size()),
753 SCacheF
.Size()) == false)
756 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
758 // Build the status cache
759 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
760 if (_error
->PendingError() == true)
762 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
763 Files
.begin()+EndOfSource
,Files
.end()) == false)
768 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
770 // Build the source cache
771 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
772 if (_error
->PendingError() == true)
774 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
775 Files
.begin(),Files
.begin()+EndOfSource
) == false)
779 if (Writeable
== true && SrcCacheFile
.empty() == false)
781 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteEmpty
);
782 if (_error
->PendingError() == true)
785 fchmod(SCacheF
.Fd(),0644);
787 // Write out the main data
788 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
789 return _error
->Error(_("IO Error saving source cache"));
792 // Write out the proper header
793 Gen
.GetCache().HeaderP
->Dirty
= false;
794 if (SCacheF
.Seek(0) == false ||
795 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
796 return _error
->Error(_("IO Error saving source cache"));
797 Gen
.GetCache().HeaderP
->Dirty
= true;
801 // Build the status cache
802 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
803 Files
.begin()+EndOfSource
,Files
.end()) == false)
807 if (_error
->PendingError() == true)
813 delete Map
.UnGuard();
814 *OutMap
= new MMap(*CacheF
,MMap::Public
| MMap::ReadOnly
);
818 *OutMap
= Map
.UnGuard();
825 // MakeOnlyStatusCache - Build a cache with just the status files /*{{{*/
826 // ---------------------------------------------------------------------
828 bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
830 unsigned long MapSize
= _config
->FindI("APT::Cache-Limit",8*1024*1024);
831 vector
<pkgIndexFile
*> Files
;
832 unsigned long EndOfSource
= Files
.size();
833 if (_system
->AddStatusFiles(Files
) == false)
836 SPtr
<DynamicMMap
> Map
;
837 Map
= new DynamicMMap(MMap::Public
,MapSize
);
838 unsigned long CurrentSize
= 0;
839 unsigned long TotalSize
= 0;
841 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
843 // Build the status cache
844 Progress
.OverallProgress(0,1,1,_("Reading package lists"));
845 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
846 if (_error
->PendingError() == true)
848 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
849 Files
.begin()+EndOfSource
,Files
.end()) == false)
852 if (_error
->PendingError() == true)
854 *OutMap
= Map
.UnGuard();