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