Sync
[ntk/apt.git] / apt-pkg / pkgcache.cc
CommitLineData
578bfd0a
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
6c139d6e 3// $Id: pkgcache.cc,v 1.5 1998/07/07 04:17:02 jgg Exp $
578bfd0a
AL
4/* ######################################################################
5
6 Package Cache - Accessor code for the cache
7
8 Please see doc/pkglib/cache.sgml for a more detailed description of
9 this format. Also be sure to keep that file up-to-date!!
10
11 This is the general utility functions for cache managment. They provide
12 a complete set of accessor functions for the cache. The cacheiterators
13 header contains the STL-like iterators that can be used to easially
14 navigate the cache as well as seemlessly dereference the mmap'd
15 indexes. Use these always.
16
17 The main class provides for ways to get package indexes and some
18 general lookup functions to start the iterators.
19
20 ##################################################################### */
21 /*}}}*/
22// Include Files /*{{{*/
6c139d6e
AL
23#ifdef __GNUG__
24#pragma implementation "pkglib/pkgcache.h"
25#pragma implementation "pkglib/cacheiterators.h"
26#endif
578bfd0a
AL
27#include <pkglib/pkgcache.h>
28#include <pkglib/version.h>
29#include <pkglib/error.h>
30#include <system.h>
31
32#include <string>
33#include <sys/stat.h>
34#include <unistd.h>
35 /*}}}*/
36
37// Cache::Header::Header - Constructor /*{{{*/
38// ---------------------------------------------------------------------
39/* Simply initialize the header */
40pkgCache::Header::Header()
41{
42 Signature = 0x98FE76DC;
43
44 /* Whenever the structures change the major version should be bumped,
45 whenever the generator changes the minor version should be bumped. */
46 MajorVersion = 2;
47 MinorVersion = 0;
48 Dirty = true;
49
50 HeaderSz = sizeof(pkgCache::Header);
51 PackageSz = sizeof(pkgCache::Package);
52 PackageFileSz = sizeof(pkgCache::PackageFile);
53 VersionSz = sizeof(pkgCache::Version);
54 DependencySz = sizeof(pkgCache::Dependency);
55 ProvidesSz = sizeof(pkgCache::Provides);
dcb79bae
AL
56 VerFileSz = sizeof(pkgCache::VerFile);
57
578bfd0a
AL
58 PackageCount = 0;
59 VersionCount = 0;
60 DependsCount = 0;
61 PackageFileCount = 0;
62
63 FileList = 0;
64 StringList = 0;
65 memset(HashTable,0,sizeof(HashTable));
66 memset(Pools,0,sizeof(Pools));
67}
68 /*}}}*/
69// Cache::Header::CheckSizes - Check if the two headers have same *sz /*{{{*/
70// ---------------------------------------------------------------------
71/* */
72bool pkgCache::Header::CheckSizes(Header &Against) const
73{
74 if (HeaderSz == Against.HeaderSz &&
75 PackageSz == Against.PackageSz &&
76 PackageFileSz == Against.PackageFileSz &&
77 VersionSz == Against.VersionSz &&
dcb79bae
AL
78 DependencySz == Against.DependencySz &&
79 VerFileSz == Against.VerFileSz &&
578bfd0a
AL
80 ProvidesSz == Against.ProvidesSz)
81 return true;
82 return false;
83}
84 /*}}}*/
85
86// Cache::pkgCache - Constructor /*{{{*/
87// ---------------------------------------------------------------------
88/* */
89pkgCache::pkgCache(MMap &Map) : Map(Map)
90{
91 ReMap();
92}
93 /*}}}*/
94// Cache::ReMap - Reopen the cache file /*{{{*/
95// ---------------------------------------------------------------------
96/* If the file is already closed then this will open it open it. */
97bool pkgCache::ReMap()
98{
99 // Apply the typecasts.
100 HeaderP = (Header *)Map.Data();
101 PkgP = (Package *)Map.Data();
dcb79bae 102 VerFileP = (VerFile *)Map.Data();
578bfd0a
AL
103 PkgFileP = (PackageFile *)Map.Data();
104 VerP = (Version *)Map.Data();
105 ProvideP = (Provides *)Map.Data();
106 DepP = (Dependency *)Map.Data();
107 StringItemP = (StringItem *)Map.Data();
108 StrP = (char *)Map.Data();
109
578bfd0a
AL
110 if (Map.Size() == 0)
111 return false;
112
113 // Check the header
114 Header DefHeader;
115 if (HeaderP->Signature != DefHeader.Signature ||
116 HeaderP->Dirty == true)
117 return _error->Error("The package cache file is corrupted");
118
119 if (HeaderP->MajorVersion != DefHeader.MajorVersion ||
120 HeaderP->MinorVersion != DefHeader.MinorVersion ||
121 HeaderP->CheckSizes(DefHeader) == false)
122 return _error->Error("The package cache file is an incompatible version");
123
124 return true;
125}
126 /*}}}*/
127// Cache::Hash - Hash a string /*{{{*/
128// ---------------------------------------------------------------------
129/* This is used to generate the hash entries for the HashTable. With my
130 package list from bo this function gets 94% table usage on a 512 item
131 table (480 used items) */
132unsigned long pkgCache::sHash(string Str)
133{
134 unsigned long Hash = 0;
135 for (const char *I = Str.begin(); I != Str.end(); I++)
136 Hash += *I * ((Str.end() - I + 1));
137 Header H;
138 return Hash % _count(H.HashTable);
139}
140
141unsigned long pkgCache::sHash(const char *Str)
142{
143 unsigned long Hash = 0;
144 const char *End = Str + strlen(Str);
145 for (const char *I = Str; I != End; I++)
146 Hash += *I * ((End - I + 1));
147 Header H;
148 return Hash % _count(H.HashTable);
149}
150
151 /*}}}*/
152// Cache::FindPkg - Locate a package by name /*{{{*/
153// ---------------------------------------------------------------------
154/* Returns 0 on error, pointer to the package otherwise */
155pkgCache::PkgIterator pkgCache::FindPkg(string Name)
156{
157 // Look at the hash bucket
158 Package *Pkg = PkgP + HeaderP->HashTable[Hash(Name)];
159 for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage)
160 {
161 if (Pkg->Name != 0 && StrP + Pkg->Name == Name)
162 return PkgIterator(*this,Pkg);
163 }
164 return PkgIterator(*this,0);
165}
166 /*}}}*/
0149949b
AL
167// Cache::Priority - Convert a priority value to a string /*{{{*/
168// ---------------------------------------------------------------------
169/* */
170const char *pkgCache::Priority(unsigned char Prio)
171{
172 const char *Mapping[] = {0,"important","required","standard","optional","extra"};
173 if (Prio < _count(Mapping))
174 return Mapping[Prio];
175 return 0;
176}
177 /*}}}*/
578bfd0a 178
f55a958f
AL
179// Bases for iterator classes /*{{{*/
180void pkgCache::VerIterator::_dummy() {}
181void pkgCache::DepIterator::_dummy() {}
182void pkgCache::PrvIterator::_dummy() {}
183 /*}}}*/
184// PkgIterator::operator ++ - Postfix incr /*{{{*/
578bfd0a
AL
185// ---------------------------------------------------------------------
186/* This will advance to the next logical package in the hash table. */
187void pkgCache::PkgIterator::operator ++(int)
188{
189 // Follow the current links
190 if (Pkg != Owner->PkgP)
191 Pkg = Owner->PkgP + Pkg->NextPackage;
192
193 // Follow the hash table
194 while (Pkg == Owner->PkgP && HashIndex < (signed)_count(Owner->HeaderP->HashTable))
195 {
196 HashIndex++;
197 Pkg = Owner->PkgP + Owner->HeaderP->HashTable[HashIndex];
198 }
199};
200 /*}}}*/
578bfd0a
AL
201// PkgIterator::State - Check the State of the package /*{{{*/
202// ---------------------------------------------------------------------
203/* By this we mean if it is either cleanly installed or cleanly removed. */
204pkgCache::PkgIterator::OkState pkgCache::PkgIterator::State() const
205{
6c139d6e
AL
206 if (Pkg->CurrentState == State::UnPacked ||
207 Pkg->CurrentState == State::HalfConfigured)
578bfd0a
AL
208 return NeedsConfigure;
209
6c139d6e
AL
210 if (Pkg->CurrentState == State::UnInstalled ||
211 Pkg->CurrentState == State::HalfInstalled ||
212 Pkg->InstState != State::Ok)
578bfd0a
AL
213 return NeedsUnpack;
214
215 return NeedsNothing;
216}
217 /*}}}*/
218// DepIterator::IsCritical - Returns true if the dep is important /*{{{*/
219// ---------------------------------------------------------------------
220/* Currently critical deps are defined as depends, predepends and
221 conflicts. */
222bool pkgCache::DepIterator::IsCritical()
223{
6c139d6e
AL
224 if (Dep->Type == Dep::Conflicts || Dep->Type == Dep::Depends ||
225 Dep->Type == Dep::PreDepends)
578bfd0a
AL
226 return true;
227 return false;
228}
229 /*}}}*/
230// DepIterator::SmartTargetPkg - Resolve dep target pointers w/provides /*{{{*/
231// ---------------------------------------------------------------------
232/* This intellegently looks at dep target packages and tries to figure
233 out which package should be used. This is needed to nicely handle
234 provide mapping. If the target package has no other providing packages
235 then it returned. Otherwise the providing list is looked at to
236 see if there is one one unique providing package if so it is returned.
237 Otherwise true is returned and the target package is set. The return
238 result indicates whether the node should be expandable */
239bool pkgCache::DepIterator::SmartTargetPkg(PkgIterator &Result)
240{
241 Result = TargetPkg();
242
243 // No provides at all
244 if (Result->ProvidesList == 0)
245 return false;
246
247 // There is the Base package and the providing ones which is at least 2
248 if (Result->VersionList != 0)
249 return true;
250
251 /* We have to skip over indirect provisions of the package that
252 owns the dependency. For instance, if libc5-dev depends on the
253 virtual package libc-dev which is provided by libc5-dev and libc6-dev
254 we must ignore libc5-dev when considering the provides list. */
255 PrvIterator PStart = Result.ProvidesList();
256 for (; PStart.end() != true && PStart.OwnerPkg() == ParentPkg(); PStart++);
257
258 // Nothing but indirect self provides
259 if (PStart.end() == true)
260 return false;
261
262 // Check for single packages in the provides list
263 PrvIterator P = PStart;
264 for (; P.end() != true; P++)
265 {
266 // Skip over self provides
267 if (P.OwnerPkg() == ParentPkg())
268 continue;
269 if (PStart.OwnerPkg() != P.OwnerPkg())
270 break;
271 }
272
273 // Check for non dups
274 if (P.end() != true)
275 return true;
276 Result = PStart.OwnerPkg();
277 return false;
278}
279 /*}}}*/
280// DepIterator::AllTargets - Returns the set of all possible targets /*{{{*/
281// ---------------------------------------------------------------------
282/* This is a more usefull version of TargetPkg() that follows versioned
283 provides. It includes every possible package-version that could satisfy
284 the dependency. The last item in the list has a 0. */
285pkgCache::Version **pkgCache::DepIterator::AllTargets()
286{
287 Version **Res = 0;
288 unsigned long Size =0;
289 while (1)
290 {
291 Version **End = Res;
292 PkgIterator DPkg = TargetPkg();
293
294 // Walk along the actual package providing versions
295 for (VerIterator I = DPkg.VersionList(); I.end() == false; I++)
296 {
297 if (pkgCheckDep(TargetVer(),I.VerStr(),Dep->CompareOp) == false)
298 continue;
299
6c139d6e 300 if (Dep->Type == Dep::Conflicts && ParentPkg() == I.ParentPkg())
578bfd0a
AL
301 continue;
302
303 Size++;
304 if (Res != 0)
305 *End++ = I;
306 }
307
308 // Follow all provides
309 for (PrvIterator I = DPkg.ProvidesList(); I.end() == false; I++)
310 {
311 if (pkgCheckDep(TargetVer(),I.ProvideVersion(),Dep->CompareOp) == false)
312 continue;
313
6c139d6e 314 if (Dep->Type == Dep::Conflicts && ParentPkg() == I.OwnerPkg())
578bfd0a
AL
315 continue;
316
317 Size++;
318 if (Res != 0)
319 *End++ = I.OwnerVer();
320 }
321
322 // Do it again and write it into the array
323 if (Res == 0)
324 {
325 Res = new Version *[Size+1];
326 Size = 0;
327 }
328 else
329 {
330 *End = 0;
331 break;
332 }
333 }
334
335 return Res;
336}
337 /*}}}*/
338// VerIterator::CompareVer - Fast version compare for same pkgs /*{{{*/
339// ---------------------------------------------------------------------
340/* This just looks over the version list to see if B is listed before A. In
341 most cases this will return in under 4 checks, ver lists are short. */
342int pkgCache::VerIterator::CompareVer(const VerIterator &B) const
343{
344 // Check if they are equal
345 if (*this == B)
346 return 0;
347 if (end() == true)
348 return -1;
349 if (B.end() == true)
350 return 1;
351
352 /* Start at A and look for B. If B is found then A > B otherwise
353 B was before A so A < B */
354 VerIterator I = *this;
355 for (;I.end() == false; I++)
356 if (I == B)
357 return 1;
358 return -1;
359}
360 /*}}}*/
361// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/
362// ---------------------------------------------------------------------
363/* This stats the file and compares its stats with the ones that were
364 stored during generation. Date checks should probably also be
365 included here. */
366bool pkgCache::PkgFileIterator::IsOk()
367{
368 struct stat Buf;
369 if (stat(FileName(),&Buf) != 0)
370 return false;
371
372 if (Buf.st_size != (signed)File->Size || Buf.st_mtime != File->mtime)
373 return false;
374
375 return true;
376}
377 /*}}}*/