]> git.saurik.com Git - apt.git/blob - ftparchive/override.cc
merged lp:~mvo/apt/mvo
[apt.git] / ftparchive / override.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: override.cc,v 1.4 2003/02/10 07:34:41 doogie Exp $
4 /* ######################################################################
5
6 Override
7
8 Store the override file.
9
10 ##################################################################### */
11 /*}}}*/
12 // Include Files /*{{{*/
13 #include <config.h>
14
15 #include <apt-pkg/strutl.h>
16 #include <apt-pkg/error.h>
17
18 #include <stdio.h>
19
20 #include "override.h"
21
22 #include <apti18n.h>
23 /*}}}*/
24
25 // Override::ReadOverride - Read the override file /*{{{*/
26 // ---------------------------------------------------------------------
27 /* This parses the override file and reads it into the map */
28 bool Override::ReadOverride(string const &File,bool const &Source)
29 {
30 if (File.empty() == true)
31 return true;
32
33 FILE *F = fopen(File.c_str(),"r");
34 if (F == 0)
35 return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
36
37 char Line[500];
38 unsigned long long Counter = 0;
39 while (fgets(Line,sizeof(Line),F) != 0)
40 {
41 Counter++;
42 Item Itm;
43
44 // Silence
45 for (char *I = Line; *I != 0; I++)
46 if (*I == '#')
47 *I = 0;
48
49 // Strip space leading up to the package name, skip blank lines
50 char *Pkg = Line;
51 for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
52 if (Pkg == 0)
53 continue;
54
55 // Find the package and zero..
56 char *Start = Pkg;
57 char *End = Pkg;
58 for (; isspace(*End) == 0 && *End != 0; End++);
59 if (*End == 0)
60 {
61 _error->Warning(_("Malformed override %s line %llu #1"),File.c_str(),
62 Counter);
63 continue;
64 }
65 *End = 0;
66
67 // Find the priority
68 if (Source == false)
69 {
70 for (End++; isspace(*End) != 0 && *End != 0; End++);
71 Start = End;
72 for (; isspace(*End) == 0 && *End != 0; End++);
73 if (*End == 0)
74 {
75 _error->Warning(_("Malformed override %s line %llu #2"),File.c_str(),
76 Counter);
77 continue;
78 }
79 *End = 0;
80 Itm.Priority = Start;
81 }
82
83 // Find the Section
84 for (End++; isspace(*End) != 0 && *End != 0; End++);
85 Start = End;
86 for (; isspace(*End) == 0 && *End != 0; End++);
87 if (*End == 0)
88 {
89 _error->Warning(_("Malformed override %s line %llu #3"),File.c_str(),
90 Counter);
91 continue;
92 }
93 *End = 0;
94 Itm.FieldOverride["Section"] = Start;
95
96 // Source override files only have the two columns
97 if (Source == true)
98 {
99 Mapping[Pkg] = Itm;
100 continue;
101 }
102
103 // Find the =>
104 for (End++; isspace(*End) != 0 && *End != 0; End++);
105 if (*End != 0)
106 {
107 Start = End;
108 for (; *End != 0 && (End[0] != '=' || End[1] != '>'); End++);
109 if (*End == 0 || strlen(End) < 4)
110 {
111 Itm.OldMaint = "*";
112 Itm.NewMaint = _strstrip(Start);
113 }
114 else
115 {
116 *End = 0;
117 Itm.OldMaint = _strstrip(Start);
118
119 End += 3;
120 Itm.NewMaint = _strstrip(End);
121 }
122 }
123
124 Mapping[Pkg] = Itm;
125 }
126
127 if (ferror(F))
128 _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
129 fclose(F);
130 return true;
131 }
132 /*}}}*/
133 // Override::ReadExtraOverride - Read the extra override file /*{{{*/
134 // ---------------------------------------------------------------------
135 /* This parses the extra override file and reads it into the map */
136 bool Override::ReadExtraOverride(string const &File,bool const &Source)
137 {
138 if (File.empty() == true)
139 return true;
140
141 FILE *F = fopen(File.c_str(),"r");
142 if (F == 0)
143 return _error->Errno("fopen",_("Unable to open %s"),File.c_str());
144
145 char Line[500];
146 unsigned long long Counter = 0;
147 while (fgets(Line,sizeof(Line),F) != 0)
148 {
149 Counter++;
150
151 // Silence
152 for (char *I = Line; *I != 0; I++)
153 if (*I == '#')
154 *I = 0;
155
156 // Strip space leading up to the package name, skip blank lines
157 char *Pkg = Line;
158 for (; isspace(*Pkg) && *Pkg != 0;Pkg++);
159 if (Pkg == 0)
160 continue;
161
162 // Find the package and zero..
163 char *End = Pkg;
164 for (; isspace(*End) == 0 && *End != 0; End++);
165 if (*End == 0)
166 {
167 _error->Warning(_("Malformed override %s line %llu #1"),File.c_str(),
168 Counter);
169 continue;
170 }
171 *End = 0;
172
173 // Find the field
174 for (End++; isspace(*End) != 0 && *End != 0; End++);
175 char *Field = End;
176 for (; isspace(*End) == 0 && *End != 0; End++);
177 if (*End == 0)
178 {
179 _error->Warning(_("Malformed override %s line %llu #2"),File.c_str(),
180 Counter);
181 continue;
182 }
183 *End = 0;
184
185 // Find the field value
186 for (End++; isspace(*End) != 0 && *End != 0; End++);
187 char *Value = End;
188 for (; *End != 0; End++);
189 for (; isspace(*(End-1)) && End > Value; End--);
190 if (End == Value)
191 {
192 _error->Warning(_("Malformed override %s line %llu #3"),File.c_str(),
193 Counter);
194 continue;
195 }
196 *End = 0;
197
198 Mapping[Pkg].FieldOverride[Field] = Value;
199 }
200
201 if (ferror(F))
202 _error->Errno("fgets",_("Failed to read the override file %s"),File.c_str());
203 fclose(F);
204 return true;
205 }
206 /*}}}*/
207
208 // Override::GetItem - Get a architecture specific item /*{{{*/
209 // ---------------------------------------------------------------------
210 /* Returns a override item for the given package and the given architecture.
211 * Treats "all" special
212 */
213 Override::Item* Override::GetItem(string const &Package, string const &Architecture)
214 {
215 map<string,Item>::const_iterator I = Mapping.find(Package);
216 map<string,Item>::iterator J = Mapping.find(Package + "/" + Architecture);
217
218 if (I == Mapping.end() && J == Mapping.end())
219 {
220 return 0;
221 }
222
223 Item *result = new Item;
224 if (I == Mapping.end()) *result = J->second;
225 else
226 {
227 *result = I->second;
228 if (J != Mapping.end())
229 {
230 Item *R = &J->second;
231 if (R->Priority != "") result->Priority = R->Priority;
232 if (R->OldMaint != "") result->OldMaint = R->OldMaint;
233 if (R->NewMaint != "") result->NewMaint = R->NewMaint;
234 for (map<string,string>::const_iterator foI = R->FieldOverride.begin();
235 foI != R->FieldOverride.end(); ++foI)
236 {
237 result->FieldOverride[foI->first] = foI->second;
238 }
239 }
240 }
241 return result;
242 };
243
244
245 // Override::Item::SwapMaint - Swap the maintainer field if necessary /*{{{*/
246 // ---------------------------------------------------------------------
247 /* Returns the new maintainer string after evaluating the rewriting rule. If
248 there is a rule but it does not match then the empty string is returned,
249 also if there was no rewrite rule the empty string is returned. Failed
250 indicates if there was some kind of problem while rewriting. */
251 string Override::Item::SwapMaint(string const &Orig,bool &Failed)
252 {
253 Failed = false;
254
255 // Degenerate case..
256 if (NewMaint.empty() == true)
257 return OldMaint;
258
259 if (OldMaint == "*")
260 return NewMaint;
261
262 /* James: ancient, eliminate it, however it is still being used in the main
263 override file. Thus it persists.*/
264 #if 1
265 // Break OldMaint up into little bits on double slash boundaries.
266 string::const_iterator End = OldMaint.begin();
267 while (1)
268 {
269 string::const_iterator Start = End;
270 for (; End < OldMaint.end() &&
271 (End + 3 >= OldMaint.end() || End[0] != ' ' ||
272 End[1] != '/' || End[2] != '/'); ++End);
273 if (stringcasecmp(Start,End,Orig.begin(),Orig.end()) == 0)
274 return NewMaint;
275
276 if (End >= OldMaint.end())
277 break;
278
279 // Skip the divider and white space
280 for (; End < OldMaint.end() && (*End == '/' || *End == ' '); ++End);
281 }
282 #else
283 if (stringcasecmp(OldMaint.begin(),OldMaint.end(),Orig.begin(),Orig.end()) == 0)
284 return NewMaint;
285 #endif
286
287 Failed = true;
288 return string();
289 }
290 /*}}}*/