]>
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
,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
,
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
,
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
,
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(string File
,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(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 _error
->WarningE("stat",_("Couldn't stat source package list %s"),
577 (*Start
)->Describe().c_str());
581 // FindInCache is also expected to do an IMS check.
582 pkgCache::PkgFileIterator File
= (*Start
)->FindInCache(Cache
);
583 if (File
.end() == true)
586 Visited
[File
->ID
] = true;
589 for (unsigned I
= 0; I
!= Cache
.HeaderP
->PackageFileCount
; I
++)
590 if (Visited
[I
] == false)
593 if (_error
->PendingError() == true)
600 *OutMap
= Map
.UnGuard();
604 // ComputeSize - Compute the total size of a bunch of files /*{{{*/
605 // ---------------------------------------------------------------------
606 /* Size is kind of an abstract notion that is only used for the progress
608 static unsigned long ComputeSize(FileIterator Start
,FileIterator End
)
610 unsigned long TotalSize
= 0;
611 for (; Start
!= End
; Start
++)
613 if ((*Start
)->HasPackages() == false)
615 TotalSize
+= (*Start
)->Size();
620 // BuildCache - Merge the list of index files into the cache /*{{{*/
621 // ---------------------------------------------------------------------
623 static bool BuildCache(pkgCacheGenerator
&Gen
,
624 OpProgress
&Progress
,
625 unsigned long &CurrentSize
,unsigned long TotalSize
,
626 FileIterator Start
, FileIterator End
)
629 for (I
= Start
; I
!= End
; I
++)
631 if ((*I
)->HasPackages() == false)
634 if ((*I
)->Exists() == false)
637 if ((*I
)->FindInCache(Gen
.GetCache()).end() == false)
639 _error
->Warning("Duplicate sources.list entry %s",
640 (*I
)->Describe().c_str());
644 unsigned long Size
= (*I
)->Size();
645 Progress
.OverallProgress(CurrentSize
,TotalSize
,Size
,_("Reading package lists"));
648 if ((*I
)->Merge(Gen
,Progress
) == false)
652 if (Gen
.HasFileDeps() == true)
655 TotalSize
= ComputeSize(Start
, End
);
657 for (I
= Start
; I
!= End
; I
++)
659 unsigned long Size
= (*I
)->Size();
660 Progress
.OverallProgress(CurrentSize
,TotalSize
,Size
,_("Collecting File Provides"));
662 if ((*I
)->MergeFileProvides(Gen
,Progress
) == false)
670 // MakeStatusCache - Construct the status cache /*{{{*/
671 // ---------------------------------------------------------------------
672 /* This makes sure that the status cache (the cache that has all
673 index files from the sources list and all local ones) is ready
674 to be mmaped. If OutMap is not zero then a MMap object representing
675 the cache will be stored there. This is pretty much mandetory if you
676 are using AllowMem. AllowMem lets the function be run as non-root
677 where it builds the cache 'fast' into a memory buffer. */
678 bool pkgMakeStatusCache(pkgSourceList
&List
,OpProgress
&Progress
,
679 MMap
**OutMap
,bool AllowMem
)
681 unsigned long MapSize
= _config
->FindI("APT::Cache-Limit",12*1024*1024);
683 vector
<pkgIndexFile
*> Files
;
684 for (vector
<metaIndex
*>::const_iterator i
= List
.begin();
688 vector
<pkgIndexFile
*> *Indexes
= (*i
)->GetIndexFiles();
689 for (vector
<pkgIndexFile
*>::const_iterator j
= Indexes
->begin();
692 Files
.push_back (*j
);
695 unsigned long EndOfSource
= Files
.size();
696 if (_system
->AddStatusFiles(Files
) == false)
699 // Decide if we can write to the files..
700 string CacheFile
= _config
->FindFile("Dir::Cache::pkgcache");
701 string SrcCacheFile
= _config
->FindFile("Dir::Cache::srcpkgcache");
703 // Decide if we can write to the cache
704 bool Writeable
= false;
705 if (CacheFile
.empty() == false)
706 Writeable
= access(flNotFile(CacheFile
).c_str(),W_OK
) == 0;
708 if (SrcCacheFile
.empty() == false)
709 Writeable
= access(flNotFile(SrcCacheFile
).c_str(),W_OK
) == 0;
711 if (Writeable
== false && AllowMem
== false && CacheFile
.empty() == false)
712 return _error
->Error(_("Unable to write to %s"),flNotFile(CacheFile
).c_str());
714 Progress
.OverallProgress(0,1,1,_("Reading package lists"));
717 if (CheckValidity(CacheFile
,Files
.begin(),Files
.end(),OutMap
) == true)
719 Progress
.OverallProgress(1,1,1,_("Reading package lists"));
723 /* At this point we know we need to reconstruct the package cache,
726 SPtr
<DynamicMMap
> Map
;
727 if (Writeable
== true && CacheFile
.empty() == false)
729 unlink(CacheFile
.c_str());
730 CacheF
= new FileFd(CacheFile
,FileFd::WriteEmpty
);
731 fchmod(CacheF
->Fd(),0644);
732 Map
= new DynamicMMap(*CacheF
,MMap::Public
,MapSize
);
733 if (_error
->PendingError() == true)
738 // Just build it in memory..
739 Map
= new DynamicMMap(MMap::Public
,MapSize
);
742 // Lets try the source cache.
743 unsigned long CurrentSize
= 0;
744 unsigned long TotalSize
= 0;
745 if (CheckValidity(SrcCacheFile
,Files
.begin(),
746 Files
.begin()+EndOfSource
) == true)
748 // Preload the map with the source cache
749 FileFd
SCacheF(SrcCacheFile
,FileFd::ReadOnly
);
750 if (SCacheF
.Read((unsigned char *)Map
->Data() + Map
->RawAllocate(SCacheF
.Size()),
751 SCacheF
.Size()) == false)
754 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
756 // Build the status cache
757 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
758 if (_error
->PendingError() == true)
760 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
761 Files
.begin()+EndOfSource
,Files
.end()) == false)
766 TotalSize
= ComputeSize(Files
.begin(),Files
.end());
768 // Build the source cache
769 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
770 if (_error
->PendingError() == true)
772 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
773 Files
.begin(),Files
.begin()+EndOfSource
) == false)
777 if (Writeable
== true && SrcCacheFile
.empty() == false)
779 FileFd
SCacheF(SrcCacheFile
,FileFd::WriteEmpty
);
780 if (_error
->PendingError() == true)
783 fchmod(SCacheF
.Fd(),0644);
785 // Write out the main data
786 if (SCacheF
.Write(Map
->Data(),Map
->Size()) == false)
787 return _error
->Error(_("IO Error saving source cache"));
790 // Write out the proper header
791 Gen
.GetCache().HeaderP
->Dirty
= false;
792 if (SCacheF
.Seek(0) == false ||
793 SCacheF
.Write(Map
->Data(),sizeof(*Gen
.GetCache().HeaderP
)) == false)
794 return _error
->Error(_("IO Error saving source cache"));
795 Gen
.GetCache().HeaderP
->Dirty
= true;
799 // Build the status cache
800 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
801 Files
.begin()+EndOfSource
,Files
.end()) == false)
805 if (_error
->PendingError() == true)
811 delete Map
.UnGuard();
812 *OutMap
= new MMap(*CacheF
,MMap::Public
| MMap::ReadOnly
);
816 *OutMap
= Map
.UnGuard();
823 // MakeOnlyStatusCache - Build a cache with just the status files /*{{{*/
824 // ---------------------------------------------------------------------
826 bool pkgMakeOnlyStatusCache(OpProgress
&Progress
,DynamicMMap
**OutMap
)
828 unsigned long MapSize
= _config
->FindI("APT::Cache-Limit",8*1024*1024);
829 vector
<pkgIndexFile
*> Files
;
830 unsigned long EndOfSource
= Files
.size();
831 if (_system
->AddStatusFiles(Files
) == false)
834 SPtr
<DynamicMMap
> Map
;
835 Map
= new DynamicMMap(MMap::Public
,MapSize
);
836 unsigned long CurrentSize
= 0;
837 unsigned long TotalSize
= 0;
839 TotalSize
= ComputeSize(Files
.begin()+EndOfSource
,Files
.end());
841 // Build the status cache
842 Progress
.OverallProgress(0,1,1,_("Reading package lists"));
843 pkgCacheGenerator
Gen(Map
.Get(),&Progress
);
844 if (_error
->PendingError() == true)
846 if (BuildCache(Gen
,Progress
,CurrentSize
,TotalSize
,
847 Files
.begin()+EndOfSource
,Files
.end()) == false)
850 if (_error
->PendingError() == true)
852 *OutMap
= Map
.UnGuard();