]> git.saurik.com Git - apt.git/blame - apt-pkg/pkgcachegen.cc
Fixed some display glitches
[apt.git] / apt-pkg / pkgcachegen.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
404ec98e 3// $Id: pkgcachegen.cc,v 1.12 1998/07/21 05:33:19 jgg Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache Generator - Generator for the cache structure.
7
8 This builds the cache structure from the abstract package list parser.
9
10 ##################################################################### */
11 /*}}}*/
12// Include Files /*{{{*/
6c139d6e 13#ifdef __GNUG__
094a497d 14#pragma implementation "apt-pkg/pkgcachegen.h"
6c139d6e
AL
15#endif
16
094a497d
AL
17#include <apt-pkg/pkgcachegen.h>
18#include <apt-pkg/error.h>
19#include <apt-pkg/version.h>
9c14e3d6 20#include <strutl.h>
578bfd0a
AL
21
22#include <sys/stat.h>
23#include <unistd.h>
24 /*}}}*/
25
26// CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
27// ---------------------------------------------------------------------
28/* We set the diry flag and make sure that is written to the disk */
404ec98e
AL
29pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map,OpProgress &Prog) :
30 Map(Map), Cache(Map), Progress(Prog)
578bfd0a
AL
31{
32 if (_error->PendingError() == true)
33 return;
34
35 if (Map.Size() == 0)
36 {
37 Map.RawAllocate(sizeof(pkgCache::Header));
38 *Cache.HeaderP = pkgCache::Header();
39 }
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]));
43}
44 /*}}}*/
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 */
49pkgCacheGenerator::~pkgCacheGenerator()
50{
51 if (_error->PendingError() == true)
52 return;
53 if (Map.Sync() == false)
54 return;
55
56 Cache.HeaderP->Dirty = false;
57 Map.Sync(0,sizeof(pkgCache::Header));
58}
59 /*}}}*/
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. */
64bool pkgCacheGenerator::MergeList(ListParser &List)
65{
66 List.Owner = this;
0149949b
AL
67
68 while (List.Step() == true)
578bfd0a
AL
69 {
70 // Get a pointer to the package structure
9ddf7030
AL
71 string PackageName = List.Package();
72 pkgCache::PkgIterator Pkg;
8efa2a3b
AL
73 if (NewPackage(Pkg,PackageName) == false)
74 return false;
404ec98e 75 Progress.Progress(List.Offset());
578bfd0a
AL
76
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();
f55a958f
AL
81 if (Version.empty() == true)
82 {
83 if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
84 return false;
85 continue;
86 }
87
578bfd0a
AL
88 pkgCache::VerIterator Ver = Pkg.VersionList();
89 unsigned long *Last = &Pkg->VersionList;
2246928b 90 int Res = 1;
f55a958f 91 for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
578bfd0a
AL
92 {
93 Res = pkgVersionCompare(Version.begin(),Version.end(),Ver.VerStr(),
94 Ver.VerStr() + strlen(Ver.VerStr()));
95 if (Res >= 0)
96 break;
97 }
98
99 /* We already have a version for this item, record that we
100 saw it */
101 if (Res == 0)
102 {
f55a958f
AL
103 if (List.UsePackage(Pkg,Ver) == false)
104 return false;
105
578bfd0a
AL
106 if (NewFileVer(Ver,List) == false)
107 return false;
108
109 continue;
110 }
111
112 // Add a new version
f55a958f
AL
113 *Last = NewVersion(Ver,Version,*Last);
114 Ver->ParentPkg = Pkg.Index();
578bfd0a
AL
115 if (List.NewVersion(Ver) == false)
116 return false;
0149949b 117
f55a958f
AL
118 if (List.UsePackage(Pkg,Ver) == false)
119 return false;
120
578bfd0a
AL
121 if (NewFileVer(Ver,List) == false)
122 return false;
123 }
0149949b 124
578bfd0a
AL
125 return true;
126}
127 /*}}}*/
128// CacheGenerator::NewPackage - Add a new package /*{{{*/
129// ---------------------------------------------------------------------
130/* This creates a new package structure and adds it to the hash table */
f55a958f 131bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name)
578bfd0a 132{
8efa2a3b
AL
133 Pkg = Cache.FindPkg(Name);
134 if (Pkg.end() == false)
135 return true;
136
578bfd0a
AL
137 // Get a structure
138 unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
139 if (Package == 0)
140 return false;
141
f55a958f 142 Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
578bfd0a
AL
143
144 // Insert it into the hash table
f55a958f 145 unsigned long Hash = Cache.Hash(Name);
578bfd0a
AL
146 Pkg->NextPackage = Cache.HeaderP->HashTable[Hash];
147 Cache.HeaderP->HashTable[Hash] = Package;
148
149 // Set the name and the ID
150 Pkg->Name = Map.WriteString(Name);
151 if (Pkg->Name == 0)
152 return false;
153 Pkg->ID = Cache.HeaderP->PackageCount++;
154
155 return true;
156}
157 /*}}}*/
158// CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
159// ---------------------------------------------------------------------
160/* */
f55a958f 161bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
578bfd0a
AL
162 ListParser &List)
163{
dcb79bae
AL
164 // Get a structure
165 unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
166 if (VerFile == 0)
167 return 0;
168
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();
ad00ae81
AL
175 if (Cache.HeaderP->MaxVerFileSize < VF->Size)
176 Cache.HeaderP->MaxVerFileSize = VF->Size;
f55a958f 177 return true;
578bfd0a
AL
178}
179 /*}}}*/
180// CacheGenerator::NewVersion - Create a new Version /*{{{*/
181// ---------------------------------------------------------------------
f55a958f 182/* This puts a version structure in the linked list */
578bfd0a 183unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
f55a958f 184 string VerStr,
578bfd0a
AL
185 unsigned long Next)
186{
f55a958f
AL
187 // Get a structure
188 unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
189 if (Version == 0)
0149949b 190 return 0;
f55a958f
AL
191
192 // Fill it in
193 Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
f55a958f
AL
194 Ver->NextVer = Next;
195 Ver->ID = Cache.HeaderP->VersionCount++;
196 Ver->VerStr = Map.WriteString(VerStr);
197 if (Ver->VerStr == 0)
0149949b 198 return 0;
f55a958f 199
0149949b 200 return Version;
578bfd0a
AL
201}
202 /*}}}*/
dcb79bae
AL
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. */
207bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
9ddf7030
AL
208 string PackageName,
209 string Version,
dcb79bae
AL
210 unsigned int Op,
211 unsigned int Type)
212{
213 pkgCache &Cache = Owner->Cache;
214
215 // Get a structure
216 unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
217 if (Dependency == 0)
218 return false;
219
220 // Fill it in
221 pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
222 Dep->ParentVer = Ver.Index();
223 Dep->Type = Type;
224 Dep->CompareOp = Op;
225 Dep->ID = Cache.HeaderP->DependsCount++;
226
227 // Locate the target package
8efa2a3b
AL
228 pkgCache::PkgIterator Pkg;
229 if (Owner->NewPackage(Pkg,PackageName) == false)
230 return false;
dcb79bae
AL
231
232 // Probe the reverse dependency list for a version string that matches
233 if (Version.empty() == false)
234 {
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)
240 return false;
241 }
242
243 // Link it to the package
244 Dep->Package = Pkg.Index();
245 Dep->NextRevDepends = Pkg->RevDepends;
246 Pkg->RevDepends = Dep.Index();
247
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;
253 *Last = Dep.Index();
254
255 return true;
256}
257 /*}}}*/
258// ListParser::NewProvides - Create a Provides element /*{{{*/
259// ---------------------------------------------------------------------
260/* */
261bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
8efa2a3b 262 string PackageName,
9ddf7030 263 string Version)
dcb79bae
AL
264{
265 pkgCache &Cache = Owner->Cache;
8efa2a3b
AL
266
267 // We do not add self referencing provides
268 if (Ver.ParentPkg().Name() == PackageName)
269 return true;
dcb79bae
AL
270
271 // Get a structure
272 unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
273 if (Provides == 0)
274 return false;
275
276 // Fill it in
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)
282 return false;
283
284 // Locate the target package
8efa2a3b
AL
285 pkgCache::PkgIterator Pkg;
286 if (Owner->NewPackage(Pkg,PackageName) == false)
287 return false;
dcb79bae
AL
288
289 // Link it to the package
290 Prv->ParentPkg = Pkg.Index();
291 Prv->NextProvides = Pkg->ProvidesList;
292 Pkg->ProvidesList = Prv.Index();
293
294 return true;
295}
296 /*}}}*/
578bfd0a
AL
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
300 added versions. */
301bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags)
302{
303 struct stat Buf;
304 if (stat(File.c_str(),&Buf) == -1)
305 return _error->Errno("stat","Couldn't stat ",File.c_str());
306
307 // Get some space for the structure
308 CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
309 if (CurrentFile == Cache.PkgFileP)
310 return false;
311
312 // Fill it in
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;
318 PkgFileName = File;
ad00ae81
AL
319 Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
320
578bfd0a
AL
321 if (CurrentFile->FileName == 0)
322 return false;
404ec98e
AL
323
324 Progress.SubProgress(Buf.st_size,File);
8efa2a3b 325 return true;
578bfd0a
AL
326}
327 /*}}}*/
f55a958f
AL
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 */
332unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
333 unsigned int Size)
334{
335 // Search for an insertion point
336 pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
337 int Res = 1;
338 unsigned long *Last = &Cache.HeaderP->StringList;
339 for (; I != Cache.StringItemP; Last = &I->NextItem,
340 I = Cache.StringItemP + I->NextItem)
341 {
9c14e3d6 342 Res = stringcmp(S,S+Size,Cache.StrP + I->String);
f55a958f
AL
343 if (Res >= 0)
344 break;
345 }
346
347 // Match
348 if (Res == 0)
0149949b 349 return I->String;
f55a958f
AL
350
351 // Get a structure
352 unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
353 if (Item == 0)
0149949b
AL
354 return 0;
355
f55a958f
AL
356 // Fill in the structure
357 pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
358 ItemP->NextItem = I - Cache.StringItemP;
359 *Last = Item;
360 ItemP->String = Map.WriteString(S,Size);
361 if (ItemP->String == 0)
0149949b 362 return 0;
f55a958f 363
0149949b 364 return ItemP->String;
f55a958f
AL
365}
366 /*}}}*/