]>
git.saurik.com Git - apt.git/blob - apt-pkg/pkgcachegen.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: pkgcachegen.cc,v 1.12 1998/07/21 05:33:19 jgg 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 #include <apt-pkg/pkgcachegen.h>
18 #include <apt-pkg/error.h>
19 #include <apt-pkg/version.h>
26 // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
27 // ---------------------------------------------------------------------
28 /* We set the diry flag and make sure that is written to the disk */
29 pkgCacheGenerator::pkgCacheGenerator(DynamicMMap
&Map
,OpProgress
&Prog
) :
30 Map(Map
), Cache(Map
), Progress(Prog
)
32 if (_error
->PendingError() == true)
37 Map
.RawAllocate(sizeof(pkgCache::Header
));
38 *Cache
.HeaderP
= pkgCache::Header();
40 Cache
.HeaderP
->Dirty
= true;
41 Map
.Sync(0,sizeof(pkgCache::Header
));
42 Map
.UsePools(*Cache
.HeaderP
->Pools
,sizeof(Cache
.HeaderP
->Pools
)/sizeof(Cache
.HeaderP
->Pools
[0]));
45 // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
46 // ---------------------------------------------------------------------
47 /* We sync the data then unset the dirty flag in two steps so as to
48 advoid a problem during a crash */
49 pkgCacheGenerator::~pkgCacheGenerator()
51 if (_error
->PendingError() == true)
53 if (Map
.Sync() == false)
56 Cache
.HeaderP
->Dirty
= false;
57 Map
.Sync(0,sizeof(pkgCache::Header
));
60 // CacheGenerator::MergeList - Merge the package list /*{{{*/
61 // ---------------------------------------------------------------------
62 /* This provides the generation of the entries in the cache. Each loop
63 goes through a single package record from the underlying parse engine. */
64 bool pkgCacheGenerator::MergeList(ListParser
&List
)
68 while (List
.Step() == true)
70 // Get a pointer to the package structure
71 string PackageName
= List
.Package();
72 pkgCache::PkgIterator Pkg
;
73 if (NewPackage(Pkg
,PackageName
) == false)
75 Progress
.Progress(List
.Offset());
77 /* Get a pointer to the version structure. We know the list is sorted
78 so we use that fact in the search. Insertion of new versions is
79 done with correct sorting */
80 string Version
= List
.Version();
81 if (Version
.empty() == true)
83 if (List
.UsePackage(Pkg
,pkgCache::VerIterator(Cache
)) == false)
88 pkgCache::VerIterator Ver
= Pkg
.VersionList();
89 unsigned long *Last
= &Pkg
->VersionList
;
91 for (; Ver
.end() == false; Last
= &Ver
->NextVer
, Ver
++)
93 Res
= pkgVersionCompare(Version
.begin(),Version
.end(),Ver
.VerStr(),
94 Ver
.VerStr() + strlen(Ver
.VerStr()));
99 /* We already have a version for this item, record that we
103 if (List
.UsePackage(Pkg
,Ver
) == false)
106 if (NewFileVer(Ver
,List
) == false)
113 *Last
= NewVersion(Ver
,Version
,*Last
);
114 Ver
->ParentPkg
= Pkg
.Index();
115 if (List
.NewVersion(Ver
) == false)
118 if (List
.UsePackage(Pkg
,Ver
) == false)
121 if (NewFileVer(Ver
,List
) == false)
128 // CacheGenerator::NewPackage - Add a new package /*{{{*/
129 // ---------------------------------------------------------------------
130 /* This creates a new package structure and adds it to the hash table */
131 bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator
&Pkg
,string Name
)
133 Pkg
= Cache
.FindPkg(Name
);
134 if (Pkg
.end() == false)
138 unsigned long Package
= Map
.Allocate(sizeof(pkgCache::Package
));
142 Pkg
= pkgCache::PkgIterator(Cache
,Cache
.PkgP
+ Package
);
144 // Insert it into the hash table
145 unsigned long Hash
= Cache
.Hash(Name
);
146 Pkg
->NextPackage
= Cache
.HeaderP
->HashTable
[Hash
];
147 Cache
.HeaderP
->HashTable
[Hash
] = Package
;
149 // Set the name and the ID
150 Pkg
->Name
= Map
.WriteString(Name
);
153 Pkg
->ID
= Cache
.HeaderP
->PackageCount
++;
158 // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
159 // ---------------------------------------------------------------------
161 bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator
&Ver
,
165 unsigned long VerFile
= Map
.Allocate(sizeof(pkgCache::VerFile
));
169 pkgCache::VerFileIterator
VF(Cache
,Cache
.VerFileP
+ VerFile
);
170 VF
->File
= CurrentFile
- Cache
.PkgFileP
;
171 VF
->NextFile
= Ver
->FileList
;
172 Ver
->FileList
= VF
.Index();
173 VF
->Offset
= List
.Offset();
174 VF
->Size
= List
.Size();
175 if (Cache
.HeaderP
->MaxVerFileSize
< VF
->Size
)
176 Cache
.HeaderP
->MaxVerFileSize
= VF
->Size
;
180 // CacheGenerator::NewVersion - Create a new Version /*{{{*/
181 // ---------------------------------------------------------------------
182 /* This puts a version structure in the linked list */
183 unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator
&Ver
,
188 unsigned long Version
= Map
.Allocate(sizeof(pkgCache::Version
));
193 Ver
= pkgCache::VerIterator(Cache
,Cache
.VerP
+ Version
);
195 Ver
->ID
= Cache
.HeaderP
->VersionCount
++;
196 Ver
->VerStr
= Map
.WriteString(VerStr
);
197 if (Ver
->VerStr
== 0)
203 // ListParser::NewDepends - Create a dependency element /*{{{*/
204 // ---------------------------------------------------------------------
205 /* This creates a dependency element in the tree. It is linked to the
206 version and to the package that it is pointing to. */
207 bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver
,
213 pkgCache
&Cache
= Owner
->Cache
;
216 unsigned long Dependency
= Owner
->Map
.Allocate(sizeof(pkgCache::Dependency
));
221 pkgCache::DepIterator
Dep(Cache
,Cache
.DepP
+ Dependency
);
222 Dep
->ParentVer
= Ver
.Index();
225 Dep
->ID
= Cache
.HeaderP
->DependsCount
++;
227 // Locate the target package
228 pkgCache::PkgIterator Pkg
;
229 if (Owner
->NewPackage(Pkg
,PackageName
) == false)
232 // Probe the reverse dependency list for a version string that matches
233 if (Version
.empty() == false)
235 for (pkgCache::DepIterator I
= Pkg
.RevDependsList(); I
.end() == false; I
++)
236 if (I
->Version
!= 0 && I
.TargetVer() == Version
)
237 Dep
->Version
= I
->Version
;
238 if (Dep
->Version
== 0)
239 if ((Dep
->Version
= WriteString(Version
)) == 0)
243 // Link it to the package
244 Dep
->Package
= Pkg
.Index();
245 Dep
->NextRevDepends
= Pkg
->RevDepends
;
246 Pkg
->RevDepends
= Dep
.Index();
248 // Link it to the version (at the end of the list)
249 unsigned long *Last
= &Ver
->DependsList
;
250 for (pkgCache::DepIterator D
= Ver
.DependsList(); D
.end() == false; D
++)
251 Last
= &D
->NextDepends
;
252 Dep
->NextDepends
= *Last
;
258 // ListParser::NewProvides - Create a Provides element /*{{{*/
259 // ---------------------------------------------------------------------
261 bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver
,
265 pkgCache
&Cache
= Owner
->Cache
;
267 // We do not add self referencing provides
268 if (Ver
.ParentPkg().Name() == PackageName
)
272 unsigned long Provides
= Owner
->Map
.Allocate(sizeof(pkgCache::Provides
));
277 pkgCache::PrvIterator
Prv(Cache
,Cache
.ProvideP
+ Provides
,Cache
.PkgP
);
278 Prv
->Version
= Ver
.Index();
279 Prv
->NextPkgProv
= Ver
->ProvidesList
;
280 Ver
->ProvidesList
= Prv
.Index();
281 if (Version
.empty() == false && (Prv
->Version
= WriteString(Version
)) == 0)
284 // Locate the target package
285 pkgCache::PkgIterator Pkg
;
286 if (Owner
->NewPackage(Pkg
,PackageName
) == false)
289 // Link it to the package
290 Prv
->ParentPkg
= Pkg
.Index();
291 Prv
->NextProvides
= Pkg
->ProvidesList
;
292 Pkg
->ProvidesList
= Prv
.Index();
297 // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
298 // ---------------------------------------------------------------------
299 /* This is used to select which file is to be associated with all newly
301 bool pkgCacheGenerator::SelectFile(string File
,unsigned long Flags
)
304 if (stat(File
.c_str(),&Buf
) == -1)
305 return _error
->Errno("stat","Couldn't stat ",File
.c_str());
307 // Get some space for the structure
308 CurrentFile
= Cache
.PkgFileP
+ Map
.Allocate(sizeof(*CurrentFile
));
309 if (CurrentFile
== Cache
.PkgFileP
)
313 CurrentFile
->FileName
= Map
.WriteString(File
);
314 CurrentFile
->Size
= Buf
.st_size
;
315 CurrentFile
->mtime
= Buf
.st_mtime
;
316 CurrentFile
->NextFile
= Cache
.HeaderP
->FileList
;
317 CurrentFile
->Flags
= Flags
;
319 Cache
.HeaderP
->FileList
= CurrentFile
- Cache
.PkgFileP
;
321 if (CurrentFile
->FileName
== 0)
324 Progress
.SubProgress(Buf
.st_size
,File
);
328 // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
329 // ---------------------------------------------------------------------
330 /* This is used to create handles to strings. Given the same text it
331 always returns the same number */
332 unsigned long pkgCacheGenerator::WriteUniqString(const char *S
,
335 // Search for an insertion point
336 pkgCache::StringItem
*I
= Cache
.StringItemP
+ Cache
.HeaderP
->StringList
;
338 unsigned long *Last
= &Cache
.HeaderP
->StringList
;
339 for (; I
!= Cache
.StringItemP
; Last
= &I
->NextItem
,
340 I
= Cache
.StringItemP
+ I
->NextItem
)
342 Res
= stringcmp(S
,S
+Size
,Cache
.StrP
+ I
->String
);
352 unsigned long Item
= Map
.Allocate(sizeof(pkgCache::StringItem
));
356 // Fill in the structure
357 pkgCache::StringItem
*ItemP
= Cache
.StringItemP
+ Item
;
358 ItemP
->NextItem
= I
- Cache
.StringItemP
;
360 ItemP
->String
= Map
.WriteString(S
,Size
);
361 if (ItemP
->String
== 0)
364 return ItemP
->String
;