]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/deblistparser.cc
* support non-mmapable files again
[apt.git] / apt-pkg / deb / deblistparser.cc
CommitLineData
f55a958f
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
7db98ffc 3// $Id: deblistparser.cc,v 1.29.2.5 2004/01/06 01:43:44 mdz Exp $
f55a958f
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 /*{{{*/
094a497d
AL
13#include <apt-pkg/deblistparser.h>
14#include <apt-pkg/error.h>
15#include <apt-pkg/configuration.h>
cdcc6d34 16#include <apt-pkg/strutl.h>
204fbdcc 17#include <apt-pkg/crc-16.h>
a52f938b 18#include <apt-pkg/md5.h>
9c14e3d6 19
e7b470ee
AL
20#include <ctype.h>
21
f55a958f
AL
22#include <system.h>
23 /*}}}*/
24
b2e465d6
AL
25static debListParser::WordList PrioList[] = {{"important",pkgCache::State::Important},
26 {"required",pkgCache::State::Required},
27 {"standard",pkgCache::State::Standard},
28 {"optional",pkgCache::State::Optional},
29 {"extra",pkgCache::State::Extra},
30 {}};
31
f55a958f
AL
32// ListParser::debListParser - Constructor /*{{{*/
33// ---------------------------------------------------------------------
34/* */
b2e465d6 35debListParser::debListParser(FileFd *File) : Tags(File)
f55a958f 36{
ddc1d8d0 37 Arch = _config->Find("APT::architecture");
0149949b
AL
38}
39 /*}}}*/
f55a958f
AL
40// ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
41// ---------------------------------------------------------------------
42/* */
43unsigned long debListParser::UniqFindTagWrite(const char *Tag)
44{
45 const char *Start;
46 const char *Stop;
47 if (Section.Find(Tag,Start,Stop) == false)
48 return 0;
49 return WriteUniqString(Start,Stop - Start);
50}
51 /*}}}*/
f55a958f
AL
52// ListParser::Package - Return the package name /*{{{*/
53// ---------------------------------------------------------------------
54/* This is to return the name of the package this section describes */
55string debListParser::Package()
56{
b0b4efb9 57 string Result = Section.FindS("Package");
f55a958f 58 if (Result.empty() == true)
65a1e968 59 _error->Error("Encountered a section with no Package: header");
f55a958f
AL
60 return Result;
61}
62 /*}}}*/
63// ListParser::Version - Return the version string /*{{{*/
64// ---------------------------------------------------------------------
65/* This is to return the string describing the version in debian form,
66 epoch:upstream-release. If this returns the blank string then the
67 entry is assumed to only describe package properties */
68string debListParser::Version()
69{
b0b4efb9 70 return Section.FindS("Version");
f55a958f
AL
71}
72 /*}}}*/
f55a958f
AL
73// ListParser::NewVersion - Fill in the version structure /*{{{*/
74// ---------------------------------------------------------------------
75/* */
76bool debListParser::NewVersion(pkgCache::VerIterator Ver)
0149949b
AL
77{
78 // Parse the section
b35d2f5f 79 Ver->Section = UniqFindTagWrite("Section");
17caf1b1 80 Ver->Arch = UniqFindTagWrite("Architecture");
0149949b
AL
81
82 // Archive Size
b0b4efb9 83 Ver->Size = (unsigned)Section.FindI("Size");
0149949b
AL
84
85 // Unpacked Size (in K)
b0b4efb9 86 Ver->InstalledSize = (unsigned)Section.FindI("Installed-Size");
0149949b
AL
87 Ver->InstalledSize *= 1024;
88
89 // Priority
90 const char *Start;
91 const char *Stop;
92 if (Section.Find("Priority",Start,Stop) == true)
b2e465d6
AL
93 {
94 if (GrabWord(string(Start,Stop-Start),PrioList,Ver->Priority) == false)
421c8d10 95 Ver->Priority = pkgCache::State::Extra;
0149949b 96 }
dcb79bae 97
6c139d6e 98 if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false)
dcb79bae 99 return false;
8efa2a3b 100 if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false)
dcb79bae 101 return false;
6c139d6e 102 if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false)
dcb79bae 103 return false;
6c139d6e 104 if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false)
dcb79bae 105 return false;
6c139d6e 106 if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false)
dcb79bae 107 return false;
f55ece0e 108 if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false)
dcb79bae
AL
109 return false;
110
b2e465d6
AL
111 // Obsolete.
112 if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false)
113 return false;
114
dcb79bae
AL
115 if (ParseProvides(Ver) == false)
116 return false;
0149949b 117
f55a958f
AL
118 return true;
119}
120 /*}}}*/
a52f938b
OS
121// ListParser::Description - Return the description string /*{{{*/
122// ---------------------------------------------------------------------
123/* This is to return the string describing the package in debian
124 form. If this returns the blank string then the entry is assumed to
125 only describe package properties */
126string debListParser::Description()
127{
128 if (DescriptionLanguage().empty())
129 return Section.FindS("Description");
130 else
131 return Section.FindS(("Description-" + pkgIndexFile::LanguageCode()).c_str());
132}
133 /*}}}*/
134// ListParser::DescriptionLanguage - Return the description lang string /*{{{*/
135// ---------------------------------------------------------------------
136/* This is to return the string describing the language of
137 description. If this returns the blank string then the entry is
138 assumed to describe original description. */
139string debListParser::DescriptionLanguage()
140{
141 return Section.FindS("Description").empty() ? pkgIndexFile::LanguageCode() : "";
142}
143 /*}}}*/
144// ListParser::Description - Return the description_md5 MD5SumValue /*{{{*/
145// ---------------------------------------------------------------------
770c32ec
MV
146/* This is to return the md5 string to allow the check if it is the right
147 description. If no Description-md5 is found in the section it will be
148 calculated.
149 */
a52f938b
OS
150MD5SumValue debListParser::Description_md5()
151{
152 string value = Section.FindS("Description-md5");
153
770c32ec
MV
154 if (value.empty())
155 {
a52f938b
OS
156 MD5Summation md5;
157 md5.Add((Description() + "\n").c_str());
158 return md5.Result();
159 } else
160 return MD5SumValue(value);
161}
162 /*}}}*/
f55a958f
AL
163// ListParser::UsePackage - Update a package structure /*{{{*/
164// ---------------------------------------------------------------------
165/* This is called to update the package with any new information
166 that might be found in the section */
167bool debListParser::UsePackage(pkgCache::PkgIterator Pkg,
168 pkgCache::VerIterator Ver)
169{
170 if (Pkg->Section == 0)
b35d2f5f 171 Pkg->Section = UniqFindTagWrite("Section");
b0b4efb9 172 if (Section.FindFlag("Essential",Pkg->Flags,pkgCache::Flag::Essential) == false)
f55a958f 173 return false;
138d4b3d 174 if (Section.FindFlag("Important",Pkg->Flags,pkgCache::Flag::Important) == false)
f55a958f 175 return false;
138d4b3d
AL
176
177 if (strcmp(Pkg.Name(),"apt") == 0)
178 Pkg->Flags |= pkgCache::Flag::Important;
179
f55a958f
AL
180 if (ParseStatus(Pkg,Ver) == false)
181 return false;
182 return true;
183}
184 /*}}}*/
204fbdcc
AL
185// ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
186// ---------------------------------------------------------------------
187/* */
188unsigned short debListParser::VersionHash()
189{
190 const char *Sections[] ={"Installed-Size",
191 "Depends",
192 "Pre-Depends",
f78439bf
AL
193// "Suggests",
194// "Recommends",
204fbdcc
AL
195 "Conflicts",
196 "Replaces",0};
197 unsigned long Result = INIT_FCS;
418a471f 198 char S[1024];
204fbdcc
AL
199 for (const char **I = Sections; *I != 0; I++)
200 {
201 const char *Start;
202 const char *End;
203 if (Section.Find(*I,Start,End) == false || End - Start >= (signed)sizeof(S))
204 continue;
205
206 /* Strip out any spaces from the text, this undoes dpkgs reformatting
421c8d10
AL
207 of certain fields. dpkg also has the rather interesting notion of
208 reformatting depends operators < -> <= */
204fbdcc
AL
209 char *I = S;
210 for (; Start != End; Start++)
421c8d10 211 {
204fbdcc 212 if (isspace(*Start) == 0)
ddc1d8d0 213 *I++ = tolower(*Start);
421c8d10
AL
214 if (*Start == '<' && Start[1] != '<' && Start[1] != '=')
215 *I++ = '=';
216 if (*Start == '>' && Start[1] != '>' && Start[1] != '=')
217 *I++ = '=';
218 }
418a471f 219
204fbdcc
AL
220 Result = AddCRC16(Result,S,I - S);
221 }
222
223 return Result;
224}
225 /*}}}*/
dcb79bae 226// ListParser::ParseStatus - Parse the status field /*{{{*/
f55a958f
AL
227// ---------------------------------------------------------------------
228/* Status lines are of the form,
229 Status: want flag status
230 want = unknown, install, hold, deinstall, purge
231 flag = ok, reinstreq, hold, hold-reinstreq
a005475e 232 status = not-installed, unpacked, half-configured,
f55a958f
AL
233 half-installed, config-files, post-inst-failed,
234 removal-failed, installed
235
236 Some of the above are obsolete (I think?) flag = hold-* and
237 status = post-inst-failed, removal-failed at least.
238 */
239bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg,
240 pkgCache::VerIterator Ver)
241{
242 const char *Start;
243 const char *Stop;
244 if (Section.Find("Status",Start,Stop) == false)
245 return true;
246
247 // Isolate the first word
248 const char *I = Start;
249 for(; I < Stop && *I != ' '; I++);
250 if (I >= Stop || *I != ' ')
251 return _error->Error("Malformed Status line");
252
253 // Process the want field
6c139d6e
AL
254 WordList WantList[] = {{"unknown",pkgCache::State::Unknown},
255 {"install",pkgCache::State::Install},
256 {"hold",pkgCache::State::Hold},
257 {"deinstall",pkgCache::State::DeInstall},
b2e465d6
AL
258 {"purge",pkgCache::State::Purge},
259 {}};
260 if (GrabWord(string(Start,I-Start),WantList,Pkg->SelectedState) == false)
f55a958f
AL
261 return _error->Error("Malformed 1st word in the Status line");
262
263 // Isloate the next word
264 I++;
265 Start = I;
266 for(; I < Stop && *I != ' '; I++);
267 if (I >= Stop || *I != ' ')
268 return _error->Error("Malformed status line, no 2nd word");
269
270 // Process the flag field
6c139d6e
AL
271 WordList FlagList[] = {{"ok",pkgCache::State::Ok},
272 {"reinstreq",pkgCache::State::ReInstReq},
273 {"hold",pkgCache::State::HoldInst},
b2e465d6
AL
274 {"hold-reinstreq",pkgCache::State::HoldReInstReq},
275 {}};
276 if (GrabWord(string(Start,I-Start),FlagList,Pkg->InstState) == false)
f55a958f
AL
277 return _error->Error("Malformed 2nd word in the Status line");
278
279 // Isloate the last word
280 I++;
281 Start = I;
282 for(; I < Stop && *I != ' '; I++);
283 if (I != Stop)
284 return _error->Error("Malformed Status line, no 3rd word");
285
286 // Process the flag field
6c139d6e
AL
287 WordList StatusList[] = {{"not-installed",pkgCache::State::NotInstalled},
288 {"unpacked",pkgCache::State::UnPacked},
289 {"half-configured",pkgCache::State::HalfConfigured},
290 {"installed",pkgCache::State::Installed},
6c139d6e
AL
291 {"half-installed",pkgCache::State::HalfInstalled},
292 {"config-files",pkgCache::State::ConfigFiles},
293 {"post-inst-failed",pkgCache::State::HalfConfigured},
b2e465d6
AL
294 {"removal-failed",pkgCache::State::HalfInstalled},
295 {}};
296 if (GrabWord(string(Start,I-Start),StatusList,Pkg->CurrentState) == false)
f55a958f
AL
297 return _error->Error("Malformed 3rd word in the Status line");
298
299 /* A Status line marks the package as indicating the current
300 version as well. Only if it is actually installed.. Otherwise
301 the interesting dpkg handling of the status file creates bogus
302 entries. */
6c139d6e
AL
303 if (!(Pkg->CurrentState == pkgCache::State::NotInstalled ||
304 Pkg->CurrentState == pkgCache::State::ConfigFiles))
f55a958f
AL
305 {
306 if (Ver.end() == true)
307 _error->Warning("Encountered status field in a non-version description");
308 else
309 Pkg->CurrentVer = Ver.Index();
310 }
311
dcb79bae
AL
312 return true;
313}
a1826878 314
b2e465d6
AL
315const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
316{
317 // Determine the operator
318 switch (*I)
319 {
320 case '<':
321 I++;
322 if (*I == '=')
323 {
324 I++;
325 Op = pkgCache::Dep::LessEq;
326 break;
327 }
328
329 if (*I == '<')
330 {
331 I++;
332 Op = pkgCache::Dep::Less;
333 break;
334 }
335
336 // < is the same as <= and << is really Cs < for some reason
337 Op = pkgCache::Dep::LessEq;
338 break;
339
340 case '>':
341 I++;
342 if (*I == '=')
343 {
344 I++;
345 Op = pkgCache::Dep::GreaterEq;
346 break;
347 }
348
349 if (*I == '>')
350 {
351 I++;
352 Op = pkgCache::Dep::Greater;
353 break;
354 }
355
356 // > is the same as >= and >> is really Cs > for some reason
357 Op = pkgCache::Dep::GreaterEq;
358 break;
359
360 case '=':
361 Op = pkgCache::Dep::Equals;
362 I++;
363 break;
364
365 // HACK around bad package definitions
366 default:
367 Op = pkgCache::Dep::Equals;
368 break;
369 }
370 return I;
371}
372
a1826878
AL
373 /*}}}*/
374// ListParser::ParseDepends - Parse a dependency element /*{{{*/
375// ---------------------------------------------------------------------
376/* This parses the dependency elements out of a standard string in place,
377 bit by bit. */
dcb79bae
AL
378const char *debListParser::ParseDepends(const char *Start,const char *Stop,
379 string &Package,string &Ver,
b2e465d6 380 unsigned int &Op, bool ParseArchFlags)
dcb79bae
AL
381{
382 // Strip off leading space
383 for (;Start != Stop && isspace(*Start) != 0; Start++);
384
385 // Parse off the package name
386 const char *I = Start;
387 for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
388 *I != ',' && *I != '|'; I++);
389
390 // Malformed, no '('
391 if (I != Stop && *I == ')')
392 return 0;
393
394 if (I == Start)
395 return 0;
396
397 // Stash the package name
398 Package.assign(Start,I - Start);
399
400 // Skip white space to the '('
401 for (;I != Stop && isspace(*I) != 0 ; I++);
402
403 // Parse a version
404 if (I != Stop && *I == '(')
405 {
406 // Skip the '('
407 for (I++; I != Stop && isspace(*I) != 0 ; I++);
408 if (I + 3 >= Stop)
409 return 0;
b2e465d6 410 I = ConvertRelation(I,Op);
dcb79bae
AL
411
412 // Skip whitespace
413 for (;I != Stop && isspace(*I) != 0; I++);
414 Start = I;
415 for (;I != Stop && *I != ')'; I++);
416 if (I == Stop || Start == I)
417 return 0;
418
02f000a9
AL
419 // Skip trailing whitespace
420 const char *End = I;
421 for (; End > Start && isspace(End[-1]); End--);
422
171c75f1 423 Ver.assign(Start,End-Start);
dcb79bae
AL
424 I++;
425 }
426 else
427 {
171c75f1 428 Ver.clear();
6c139d6e 429 Op = pkgCache::Dep::NoOp;
dcb79bae
AL
430 }
431
432 // Skip whitespace
433 for (;I != Stop && isspace(*I) != 0; I++);
b2e465d6
AL
434
435 if (ParseArchFlags == true)
436 {
437 string arch = _config->Find("APT::Architecture");
9e10ad8a 438
b2e465d6
AL
439 // Parse an architecture
440 if (I != Stop && *I == '[')
441 {
442 // malformed
443 I++;
444 if (I == Stop)
445 return 0;
446
447 const char *End = I;
448 bool Found = false;
9e10ad8a 449 bool NegArch = false;
b2e465d6
AL
450 while (I != Stop)
451 {
452 // look for whitespace or ending ']'
453 while (End != Stop && !isspace(*End) && *End != ']')
454 End++;
455
456 if (End == Stop)
457 return 0;
9e10ad8a
AL
458
459 if (*I == '!')
460 {
461 NegArch = true;
462 I++;
463 }
464
3e18cc75 465 if (stringcmp(arch,I,End) == 0)
b2e465d6
AL
466 Found = true;
467
468 if (*End++ == ']') {
469 I = End;
470 break;
471 }
472
473 I = End;
474 for (;I != Stop && isspace(*I) != 0; I++);
475 }
9e10ad8a
AL
476
477 if (NegArch)
478 Found = !Found;
b2e465d6 479
9e10ad8a 480 if (Found == false)
b2e465d6
AL
481 Package = ""; /* not for this arch */
482 }
483
484 // Skip whitespace
485 for (;I != Stop && isspace(*I) != 0; I++);
486 }
487
dcb79bae 488 if (I != Stop && *I == '|')
6c139d6e 489 Op |= pkgCache::Dep::Or;
dcb79bae
AL
490
491 if (I == Stop || *I == ',' || *I == '|')
492 {
493 if (I != Stop)
494 for (I++; I != Stop && isspace(*I) != 0; I++);
495 return I;
496 }
497
498 return 0;
499}
500 /*}}}*/
501// ListParser::ParseDepends - Parse a dependency list /*{{{*/
502// ---------------------------------------------------------------------
503/* This is the higher level depends parser. It takes a tag and generates
504 a complete depends tree for the given version. */
505bool debListParser::ParseDepends(pkgCache::VerIterator Ver,
506 const char *Tag,unsigned int Type)
507{
508 const char *Start;
509 const char *Stop;
510 if (Section.Find(Tag,Start,Stop) == false)
511 return true;
512
513 string Package;
514 string Version;
515 unsigned int Op;
516
8efa2a3b 517 while (1)
dcb79bae 518 {
8efa2a3b 519 Start = ParseDepends(Start,Stop,Package,Version,Op);
dcb79bae
AL
520 if (Start == 0)
521 return _error->Error("Problem parsing dependency %s",Tag);
8efa2a3b 522
dcb79bae
AL
523 if (NewDepends(Ver,Package,Version,Op,Type) == false)
524 return false;
8efa2a3b
AL
525 if (Start == Stop)
526 break;
dcb79bae
AL
527 }
528 return true;
529}
530 /*}}}*/
531// ListParser::ParseProvides - Parse the provides list /*{{{*/
532// ---------------------------------------------------------------------
533/* */
534bool debListParser::ParseProvides(pkgCache::VerIterator Ver)
535{
536 const char *Start;
537 const char *Stop;
538 if (Section.Find("Provides",Start,Stop) == false)
539 return true;
540
541 string Package;
542 string Version;
543 unsigned int Op;
544
545 while (1)
546 {
547 Start = ParseDepends(Start,Stop,Package,Version,Op);
548 if (Start == 0)
549 return _error->Error("Problem parsing Provides line");
b63380b0
MV
550 if (Op != pkgCache::Dep::NoOp) {
551 _error->Warning("Ignoring Provides line with DepCompareOp for package %s", Package.c_str());
552 } else {
553 if (NewProvides(Ver,Package,Version) == false)
554 return false;
555 }
dcb79bae
AL
556
557 if (Start == Stop)
558 break;
559 }
560
f55a958f
AL
561 return true;
562}
563 /*}}}*/
564// ListParser::GrabWord - Matches a word and returns /*{{{*/
565// ---------------------------------------------------------------------
566/* Looks for a word in a list of words - for ParseStatus */
b2e465d6 567bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
f55a958f 568{
b2e465d6 569 for (unsigned int C = 0; List[C].Str != 0; C++)
f55a958f
AL
570 {
571 if (strcasecmp(Word.c_str(),List[C].Str) == 0)
572 {
573 Out = List[C].Val;
574 return true;
575 }
576 }
577 return false;
578}
579 /*}}}*/
580// ListParser::Step - Move to the next section in the file /*{{{*/
581// ---------------------------------------------------------------------
0149949b 582/* This has to be carefull to only process the correct architecture */
f55a958f
AL
583bool debListParser::Step()
584{
dcb79bae 585 iOffset = Tags.Offset();
0149949b 586 while (Tags.Step(Section) == true)
ddc1d8d0
AL
587 {
588 /* See if this is the correct Architecture, if it isn't then we
589 drop the whole section. A missing arch tag only happens (in theory)
590 inside the Status file, so that is a positive return */
0149949b
AL
591 const char *Start;
592 const char *Stop;
593 if (Section.Find("Architecture",Start,Stop) == false)
594 return true;
9c14e3d6 595
3e18cc75 596 if (stringcmp(Arch,Start,Stop) == 0)
0149949b
AL
597 return true;
598
9c14e3d6 599 if (stringcmp(Start,Stop,"all") == 0)
0149949b 600 return true;
dcb79bae
AL
601
602 iOffset = Tags.Offset();
0149949b
AL
603 }
604 return false;
f55a958f
AL
605}
606 /*}}}*/
b0b4efb9
AL
607// ListParser::LoadReleaseInfo - Load the release information /*{{{*/
608// ---------------------------------------------------------------------
609/* */
610bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI,
e011829d 611 FileFd &File, string component)
b0b4efb9 612{
7db98ffc 613 pkgTagFile Tags(&File, File.Size() + 256); // XXX
b0b4efb9
AL
614 pkgTagSection Section;
615 if (Tags.Step(Section) == false)
616 return false;
617
e011829d
MV
618 //mvo: I don't think we need to fill that in (it's unused since apt-0.6)
619 //FileI->Architecture = WriteUniqString(Arch);
620
621 // apt-secure does no longer download individual (per-section) Release
622 // file. to provide Component pinning we use the section name now
623 FileI->Component = WriteUniqString(component);
624
b0b4efb9
AL
625 const char *Start;
626 const char *Stop;
7db98ffc 627 if (Section.Find("Suite",Start,Stop) == true)
b0b4efb9
AL
628 FileI->Archive = WriteUniqString(Start,Stop - Start);
629 if (Section.Find("Component",Start,Stop) == true)
630 FileI->Component = WriteUniqString(Start,Stop - Start);
631 if (Section.Find("Version",Start,Stop) == true)
632 FileI->Version = WriteUniqString(Start,Stop - Start);
633 if (Section.Find("Origin",Start,Stop) == true)
634 FileI->Origin = WriteUniqString(Start,Stop - Start);
635 if (Section.Find("Label",Start,Stop) == true)
636 FileI->Label = WriteUniqString(Start,Stop - Start);
637 if (Section.Find("Architecture",Start,Stop) == true)
638 FileI->Architecture = WriteUniqString(Start,Stop - Start);
0dbb95d8 639
3c124dde
AL
640 if (Section.FindFlag("NotAutomatic",FileI->Flags,
641 pkgCache::Flag::NotAutomatic) == false)
0dbb95d8 642 _error->Warning("Bad NotAutomatic flag");
e011829d 643
b0b4efb9
AL
644 return !_error->PendingError();
645}
646 /*}}}*/
b2e465d6
AL
647// ListParser::GetPrio - Convert the priority from a string /*{{{*/
648// ---------------------------------------------------------------------
649/* */
650unsigned char debListParser::GetPrio(string Str)
651{
652 unsigned char Out;
653 if (GrabWord(Str,PrioList,Out) == false)
654 Out = pkgCache::State::Extra;
655
656 return Out;
657}
658 /*}}}*/