]>
git.saurik.com Git - apt.git/blob - apt-pkg/deb/deblistparser.cc
86cd526fb58dfe9a435021a6b07263d8e7acfbd5
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: deblistparser.cc,v 1.21 1999/07/26 17:46:08 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 /*{{{*/
13 #include <apt-pkg/deblistparser.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/configuration.h>
16 #include <apt-pkg/strutl.h>
17 #include <apt-pkg/crc-16.h>
22 // ListParser::debListParser - Constructor /*{{{*/
23 // ---------------------------------------------------------------------
25 debListParser::debListParser(FileFd
&File
) : Tags(File
)
27 Arch
= _config
->Find("APT::architecture");
30 // ListParser::UniqFindTagWrite - Find the tag and write a unq string /*{{{*/
31 // ---------------------------------------------------------------------
33 unsigned long debListParser::UniqFindTagWrite(const char *Tag
)
37 if (Section
.Find(Tag
,Start
,Stop
) == false)
39 return WriteUniqString(Start
,Stop
- Start
);
42 // ListParser::Package - Return the package name /*{{{*/
43 // ---------------------------------------------------------------------
44 /* This is to return the name of the package this section describes */
45 string
debListParser::Package()
47 string Result
= Section
.FindS("Package");
48 if (Result
.empty() == true)
49 _error
->Error("Encountered a section with no Package: header");
53 // ListParser::Version - Return the version string /*{{{*/
54 // ---------------------------------------------------------------------
55 /* This is to return the string describing the version in debian form,
56 epoch:upstream-release. If this returns the blank string then the
57 entry is assumed to only describe package properties */
58 string
debListParser::Version()
60 return Section
.FindS("Version");
63 // ListParser::NewVersion - Fill in the version structure /*{{{*/
64 // ---------------------------------------------------------------------
66 bool debListParser::NewVersion(pkgCache::VerIterator Ver
)
69 Ver
->Section
= UniqFindTagWrite("Section");
70 Ver
->Arch
= UniqFindTagWrite("Architecture");
73 Ver
->Size
= (unsigned)Section
.FindI("Size");
75 // Unpacked Size (in K)
76 Ver
->InstalledSize
= (unsigned)Section
.FindI("Installed-Size");
77 Ver
->InstalledSize
*= 1024;
82 if (Section
.Find("Priority",Start
,Stop
) == true)
84 WordList PrioList
[] = {{"important",pkgCache::State::Important
},
85 {"required",pkgCache::State::Required
},
86 {"standard",pkgCache::State::Standard
},
87 {"optional",pkgCache::State::Optional
},
88 {"extra",pkgCache::State::Extra
}};
89 if (GrabWord(string(Start
,Stop
-Start
),PrioList
,
90 _count(PrioList
),Ver
->Priority
) == false)
91 return _error
->Error("Malformed Priority line");
94 if (ParseDepends(Ver
,"Depends",pkgCache::Dep::Depends
) == false)
96 if (ParseDepends(Ver
,"Pre-Depends",pkgCache::Dep::PreDepends
) == false)
98 if (ParseDepends(Ver
,"Suggests",pkgCache::Dep::Suggests
) == false)
100 if (ParseDepends(Ver
,"Recommends",pkgCache::Dep::Recommends
) == false)
102 if (ParseDepends(Ver
,"Conflicts",pkgCache::Dep::Conflicts
) == false)
104 if (ParseDepends(Ver
,"Replaces",pkgCache::Dep::Replaces
) == false)
107 if (ParseProvides(Ver
) == false)
113 // ListParser::UsePackage - Update a package structure /*{{{*/
114 // ---------------------------------------------------------------------
115 /* This is called to update the package with any new information
116 that might be found in the section */
117 bool debListParser::UsePackage(pkgCache::PkgIterator Pkg
,
118 pkgCache::VerIterator Ver
)
120 if (Pkg
->Section
== 0)
121 Pkg
->Section
= UniqFindTagWrite("Section");
122 if (Section
.FindFlag("Essential",Pkg
->Flags
,pkgCache::Flag::Essential
) == false)
124 if (Section
.FindFlag("Important",Pkg
->Flags
,pkgCache::Flag::Important
) == false)
127 if (strcmp(Pkg
.Name(),"apt") == 0)
128 Pkg
->Flags
|= pkgCache::Flag::Important
;
130 if (ParseStatus(Pkg
,Ver
) == false)
135 // ListParser::VersionHash - Compute a unique hash for this version /*{{{*/
136 // ---------------------------------------------------------------------
138 unsigned short debListParser::VersionHash()
140 const char *Sections
[] ={"Installed-Size",
147 unsigned long Result
= INIT_FCS
;
149 for (const char **I
= Sections
; *I
!= 0; I
++)
153 if (Section
.Find(*I
,Start
,End
) == false || End
- Start
>= (signed)sizeof(S
))
156 /* Strip out any spaces from the text, this undoes dpkgs reformatting
159 for (; Start
!= End
; Start
++)
160 if (isspace(*Start
) == 0)
161 *I
++ = tolower(*Start
);
163 Result
= AddCRC16(Result
,S
,I
- S
);
169 // ListParser::ParseStatus - Parse the status field /*{{{*/
170 // ---------------------------------------------------------------------
171 /* Status lines are of the form,
172 Status: want flag status
173 want = unknown, install, hold, deinstall, purge
174 flag = ok, reinstreq, hold, hold-reinstreq
175 status = not-installed, unpacked, half-configured, uninstalled,
176 half-installed, config-files, post-inst-failed,
177 removal-failed, installed
179 Some of the above are obsolete (I think?) flag = hold-* and
180 status = post-inst-failed, removal-failed at least.
182 bool debListParser::ParseStatus(pkgCache::PkgIterator Pkg
,
183 pkgCache::VerIterator Ver
)
187 if (Section
.Find("Status",Start
,Stop
) == false)
190 // Isolate the first word
191 const char *I
= Start
;
192 for(; I
< Stop
&& *I
!= ' '; I
++);
193 if (I
>= Stop
|| *I
!= ' ')
194 return _error
->Error("Malformed Status line");
196 // Process the want field
197 WordList WantList
[] = {{"unknown",pkgCache::State::Unknown
},
198 {"install",pkgCache::State::Install
},
199 {"hold",pkgCache::State::Hold
},
200 {"deinstall",pkgCache::State::DeInstall
},
201 {"purge",pkgCache::State::Purge
}};
202 if (GrabWord(string(Start
,I
-Start
),WantList
,
203 _count(WantList
),Pkg
->SelectedState
) == false)
204 return _error
->Error("Malformed 1st word in the Status line");
206 // Isloate the next word
209 for(; I
< Stop
&& *I
!= ' '; I
++);
210 if (I
>= Stop
|| *I
!= ' ')
211 return _error
->Error("Malformed status line, no 2nd word");
213 // Process the flag field
214 WordList FlagList
[] = {{"ok",pkgCache::State::Ok
},
215 {"reinstreq",pkgCache::State::ReInstReq
},
216 {"hold",pkgCache::State::HoldInst
},
217 {"hold-reinstreq",pkgCache::State::HoldReInstReq
}};
218 if (GrabWord(string(Start
,I
-Start
),FlagList
,
219 _count(FlagList
),Pkg
->InstState
) == false)
220 return _error
->Error("Malformed 2nd word in the Status line");
222 // Isloate the last word
225 for(; I
< Stop
&& *I
!= ' '; I
++);
227 return _error
->Error("Malformed Status line, no 3rd word");
229 // Process the flag field
230 WordList StatusList
[] = {{"not-installed",pkgCache::State::NotInstalled
},
231 {"unpacked",pkgCache::State::UnPacked
},
232 {"half-configured",pkgCache::State::HalfConfigured
},
233 {"installed",pkgCache::State::Installed
},
234 {"uninstalled",pkgCache::State::UnInstalled
},
235 {"half-installed",pkgCache::State::HalfInstalled
},
236 {"config-files",pkgCache::State::ConfigFiles
},
237 {"post-inst-failed",pkgCache::State::HalfConfigured
},
238 {"removal-failed",pkgCache::State::HalfInstalled
}};
239 if (GrabWord(string(Start
,I
-Start
),StatusList
,
240 _count(StatusList
),Pkg
->CurrentState
) == false)
241 return _error
->Error("Malformed 3rd word in the Status line");
243 /* A Status line marks the package as indicating the current
244 version as well. Only if it is actually installed.. Otherwise
245 the interesting dpkg handling of the status file creates bogus
247 if (!(Pkg
->CurrentState
== pkgCache::State::NotInstalled
||
248 Pkg
->CurrentState
== pkgCache::State::ConfigFiles
))
250 if (Ver
.end() == true)
251 _error
->Warning("Encountered status field in a non-version description");
253 Pkg
->CurrentVer
= Ver
.Index();
259 // ListParser::ParseDepends - Parse a dependency element /*{{{*/
260 // ---------------------------------------------------------------------
261 /* This parses the dependency elements out of a standard string in place,
263 const char *debListParser::ParseDepends(const char *Start
,const char *Stop
,
264 string
&Package
,string
&Ver
,
267 // Strip off leading space
268 for (;Start
!= Stop
&& isspace(*Start
) != 0; Start
++);
270 // Parse off the package name
271 const char *I
= Start
;
272 for (;I
!= Stop
&& isspace(*I
) == 0 && *I
!= '(' && *I
!= ')' &&
273 *I
!= ',' && *I
!= '|'; I
++);
276 if (I
!= Stop
&& *I
== ')')
282 // Stash the package name
283 Package
.assign(Start
,I
- Start
);
285 // Skip white space to the '('
286 for (;I
!= Stop
&& isspace(*I
) != 0 ; I
++);
289 if (I
!= Stop
&& *I
== '(')
292 for (I
++; I
!= Stop
&& isspace(*I
) != 0 ; I
++);
296 // Determine the operator
304 Op
= pkgCache::Dep::LessEq
;
311 Op
= pkgCache::Dep::Less
;
315 // < is the same as <= and << is really Cs < for some reason
316 Op
= pkgCache::Dep::LessEq
;
324 Op
= pkgCache::Dep::GreaterEq
;
331 Op
= pkgCache::Dep::Greater
;
335 // > is the same as >= and >> is really Cs > for some reason
336 Op
= pkgCache::Dep::GreaterEq
;
340 Op
= pkgCache::Dep::Equals
;
344 // HACK around bad package definitions
346 Op
= pkgCache::Dep::Equals
;
351 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
353 for (;I
!= Stop
&& *I
!= ')'; I
++);
354 if (I
== Stop
|| Start
== I
)
357 // Skip trailing whitespace
359 for (; End
> Start
&& isspace(End
[-1]); End
--);
361 Ver
= string(Start
,End
-Start
);
367 Op
= pkgCache::Dep::NoOp
;
371 for (;I
!= Stop
&& isspace(*I
) != 0; I
++);
372 if (I
!= Stop
&& *I
== '|')
373 Op
|= pkgCache::Dep::Or
;
375 if (I
== Stop
|| *I
== ',' || *I
== '|')
378 for (I
++; I
!= Stop
&& isspace(*I
) != 0; I
++);
385 // ListParser::ParseDepends - Parse a dependency list /*{{{*/
386 // ---------------------------------------------------------------------
387 /* This is the higher level depends parser. It takes a tag and generates
388 a complete depends tree for the given version. */
389 bool debListParser::ParseDepends(pkgCache::VerIterator Ver
,
390 const char *Tag
,unsigned int Type
)
394 if (Section
.Find(Tag
,Start
,Stop
) == false)
403 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
405 return _error
->Error("Problem parsing dependency %s",Tag
);
407 if (NewDepends(Ver
,Package
,Version
,Op
,Type
) == false)
415 // ListParser::ParseProvides - Parse the provides list /*{{{*/
416 // ---------------------------------------------------------------------
418 bool debListParser::ParseProvides(pkgCache::VerIterator Ver
)
422 if (Section
.Find("Provides",Start
,Stop
) == false)
431 Start
= ParseDepends(Start
,Stop
,Package
,Version
,Op
);
433 return _error
->Error("Problem parsing Provides line");
434 if (Op
!= pkgCache::Dep::NoOp
)
435 return _error
->Error("Malformed provides line");
437 if (NewProvides(Ver
,Package
,Version
) == false)
447 // ListParser::GrabWord - Matches a word and returns /*{{{*/
448 // ---------------------------------------------------------------------
449 /* Looks for a word in a list of words - for ParseStatus */
450 bool debListParser::GrabWord(string Word
,WordList
*List
,int Count
,
453 for (int C
= 0; C
!= Count
; C
++)
455 if (strcasecmp(Word
.c_str(),List
[C
].Str
) == 0)
464 // ListParser::Step - Move to the next section in the file /*{{{*/
465 // ---------------------------------------------------------------------
466 /* This has to be carefull to only process the correct architecture */
467 bool debListParser::Step()
469 iOffset
= Tags
.Offset();
470 while (Tags
.Step(Section
) == true)
472 /* See if this is the correct Architecture, if it isn't then we
473 drop the whole section. A missing arch tag only happens (in theory)
474 inside the Status file, so that is a positive return */
477 if (Section
.Find("Architecture",Start
,Stop
) == false)
480 if (stringcmp(Start
,Stop
,Arch
.begin(),Arch
.end()) == 0)
483 if (stringcmp(Start
,Stop
,"all") == 0)
486 iOffset
= Tags
.Offset();
491 // ListParser::LoadReleaseInfo - Load the release information /*{{{*/
492 // ---------------------------------------------------------------------
494 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator FileI
,
497 pkgTagFile
Tags(File
);
498 pkgTagSection Section
;
499 if (Tags
.Step(Section
) == false)
504 if (Section
.Find("Archive",Start
,Stop
) == true)
505 FileI
->Archive
= WriteUniqString(Start
,Stop
- Start
);
506 if (Section
.Find("Component",Start
,Stop
) == true)
507 FileI
->Component
= WriteUniqString(Start
,Stop
- Start
);
508 if (Section
.Find("Version",Start
,Stop
) == true)
509 FileI
->Version
= WriteUniqString(Start
,Stop
- Start
);
510 if (Section
.Find("Origin",Start
,Stop
) == true)
511 FileI
->Origin
= WriteUniqString(Start
,Stop
- Start
);
512 if (Section
.Find("Label",Start
,Stop
) == true)
513 FileI
->Label
= WriteUniqString(Start
,Stop
- Start
);
514 if (Section
.Find("Architecture",Start
,Stop
) == true)
515 FileI
->Architecture
= WriteUniqString(Start
,Stop
- Start
);
517 if (Section
.FindFlag("NotAutomatic",FileI
->Flags
,
518 pkgCache::Flag::NotAutomatic
) == false)
519 _error
->Warning("Bad NotAutomatic flag");
521 return !_error
->PendingError();