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