G++3 fixes from Randolph
[ntk/apt.git] / apt-pkg / sourcelist.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: sourcelist.cc,v 1.19 2001/03/13 06:51:46 jgg Exp $
4 /* ######################################################################
5
6 List of Sources
7
8 ##################################################################### */
9 /*}}}*/
10 // Include Files /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/sourcelist.h"
13 #endif
14
15 #include <apt-pkg/sourcelist.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/fileutl.h>
18 #include <apt-pkg/configuration.h>
19 #include <apt-pkg/strutl.h>
20
21 #include <apti18n.h>
22
23 #include <fstream.h>
24 /*}}}*/
25
26 // Global list of Item supported
27 static pkgSourceList::Type *ItmList[10];
28 pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList;
29 unsigned long pkgSourceList::Type::GlobalListLen = 0;
30
31 // Type::Type - Constructor /*{{{*/
32 // ---------------------------------------------------------------------
33 /* Link this to the global list of items*/
34 pkgSourceList::Type::Type()
35 {
36 ItmList[GlobalListLen] = this;
37 GlobalListLen++;
38 }
39 /*}}}*/
40 // Type::GetType - Get a specific meta for a given type /*{{{*/
41 // ---------------------------------------------------------------------
42 /* */
43 pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type)
44 {
45 for (unsigned I = 0; I != GlobalListLen; I++)
46 if (strcmp(GlobalList[I]->Name,Type) == 0)
47 return GlobalList[I];
48 return 0;
49 }
50 /*}}}*/
51 // Type::FixupURI - Normalize the URI and check it.. /*{{{*/
52 // ---------------------------------------------------------------------
53 /* */
54 bool pkgSourceList::Type::FixupURI(string &URI) const
55 {
56 if (URI.empty() == true)
57 return false;
58
59 if (URI.find(':') == string::npos)
60 return false;
61
62 URI = SubstVar(URI,"$(ARCH)",_config->Find("APT::Architecture"));
63
64 // Make sure that the URI is / postfixed
65 if (URI[URI.size() - 1] != '/')
66 URI += '/';
67
68 return true;
69 }
70 /*}}}*/
71 // Type::ParseLine - Parse a single line /*{{{*/
72 // ---------------------------------------------------------------------
73 /* This is a generic one that is the 'usual' format for sources.list
74 Weird types may override this. */
75 bool pkgSourceList::Type::ParseLine(vector<pkgIndexFile *> &List,
76 Vendor const *Vendor,
77 const char *Buffer,
78 unsigned long CurLine,
79 string File) const
80 {
81 string URI;
82 string Dist;
83 string Section;
84
85 if (ParseQuoteWord(Buffer,URI) == false)
86 return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str());
87 if (ParseQuoteWord(Buffer,Dist) == false)
88 return _error->Error(_("Malformed line %lu in source list %s (dist)"),CurLine,File.c_str());
89
90 if (FixupURI(URI) == false)
91 return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str());
92
93 // Check for an absolute dists specification.
94 if (Dist.empty() == false && Dist[Dist.size() - 1] == '/')
95 {
96 if (ParseQuoteWord(Buffer,Section) == true)
97 return _error->Error(_("Malformed line %lu in source list %s (Absolute dist)"),CurLine,File.c_str());
98 Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture"));
99 return CreateItem(List,URI,Dist,Section,Vendor);
100 }
101
102 // Grab the rest of the dists
103 if (ParseQuoteWord(Buffer,Section) == false)
104 return _error->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine,File.c_str());
105
106 do
107 {
108 if (CreateItem(List,URI,Dist,Section,Vendor) == false)
109 return false;
110 }
111 while (ParseQuoteWord(Buffer,Section) == true);
112
113 return true;
114 }
115 /*}}}*/
116
117 // SourceList::pkgSourceList - Constructors /*{{{*/
118 // ---------------------------------------------------------------------
119 /* */
120 pkgSourceList::pkgSourceList()
121 {
122 }
123
124 pkgSourceList::pkgSourceList(string File)
125 {
126 Read(File);
127 }
128 /*}}}*/
129 // SourceList::ReadVendors - Read list of known package vendors /*{{{*/
130 // ---------------------------------------------------------------------
131 /* This also scans a directory of vendor files similar to apt.conf.d
132 which can contain the usual suspects of distribution provided data.
133 The APT config mechanism allows the user to override these in their
134 configuration file. */
135 bool pkgSourceList::ReadVendors()
136 {
137 Configuration Cnf;
138
139 string CnfFile = _config->FindDir("Dir::Etc::vendorparts");
140 if (FileExists(CnfFile) == true)
141 if (ReadConfigDir(Cnf,CnfFile,true) == false)
142 return false;
143 CnfFile = _config->FindFile("Dir::Etc::vendorlist");
144 if (FileExists(CnfFile) == true)
145 if (ReadConfigFile(Cnf,CnfFile,true) == false)
146 return false;
147
148 // Process 'simple-key' type sections
149 const Configuration::Item *Top = Cnf.Tree("simple-key");
150 for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next)
151 {
152 Configuration Block(Top);
153 Vendor *Vendor;
154
155 Vendor = new pkgSourceList::Vendor;
156
157 Vendor->VendorID = Top->Tag;
158 Vendor->FingerPrint = Block.Find("Fingerprint");
159 Vendor->Description = Block.Find("Name");
160
161 if (Vendor->FingerPrint.empty() == true ||
162 Vendor->Description.empty() == true)
163 {
164 _error->Error(_("Vendor block %s is invalid"), Vendor->VendorID.c_str());
165 delete Vendor;
166 continue;
167 }
168
169 VendorList.push_back(Vendor);
170 }
171
172 return !_error->PendingError();
173 }
174 /*}}}*/
175 // SourceList::ReadMainList - Read the main source list from etc /*{{{*/
176 // ---------------------------------------------------------------------
177 /* */
178 bool pkgSourceList::ReadMainList()
179 {
180 return ReadVendors() && Read(_config->FindFile("Dir::Etc::sourcelist"));
181 }
182 /*}}}*/
183 // SourceList::Read - Parse the sourcelist file /*{{{*/
184 // ---------------------------------------------------------------------
185 /* */
186 bool pkgSourceList::Read(string File)
187 {
188 // Open the stream for reading
189 ifstream F(File.c_str(),ios::in | ios::nocreate);
190 if (!F != 0)
191 return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
192
193 SrcList.erase(SrcList.begin(),SrcList.end());
194 char Buffer[300];
195
196 int CurLine = 0;
197 while (F.eof() == false)
198 {
199 F.getline(Buffer,sizeof(Buffer));
200 CurLine++;
201 _strtabexpand(Buffer,sizeof(Buffer));
202
203
204 char *I;
205 for (I = Buffer; *I != 0 && *I != '#'; I++);
206 *I = 0;
207
208 const char *C = _strstrip(Buffer);
209
210 // Comment or blank
211 if (C[0] == '#' || C[0] == 0)
212 continue;
213
214 // Grok it
215 string LineType;
216 if (ParseQuoteWord(C,LineType) == false)
217 return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str());
218
219 Type *Parse = Type::GetType(LineType.c_str());
220 if (Parse == 0)
221 return _error->Error(_("Type '%s' is not known in on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
222
223 // Authenticated repository
224 Vendor const *Vndr = 0;
225 if (C[0] == '[')
226 {
227 string VendorID;
228
229 if (ParseQuoteWord(C,VendorID) == false)
230 return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
231
232 if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
233 return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
234 VendorID = string(VendorID,1,VendorID.size()-2);
235
236 for (vector<Vendor const *>::const_iterator iter = VendorList.begin();
237 iter != VendorList.end(); iter++)
238 {
239 if ((*iter)->VendorID == VendorID)
240 {
241 Vndr = *iter;
242 break;
243 }
244 }
245
246 if (Vndr == 0)
247 return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
248 VendorID.c_str(),CurLine,File.c_str());
249 }
250
251 if (Parse->ParseLine(SrcList,Vndr,C,CurLine,File) == false)
252 return false;
253 }
254 return true;
255 }
256 /*}}}*/
257 // SourceList::FindIndex - Get the index associated with a file /*{{{*/
258 // ---------------------------------------------------------------------
259 /* */
260 bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File,
261 pkgIndexFile *&Found) const
262 {
263 for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
264 {
265 if ((*I)->FindInCache(*File.Cache()) == File)
266 {
267 Found = *I;
268 return true;
269 }
270 }
271
272 return false;
273 }
274 /*}}}*/
275 // SourceList::GetIndexes - Load the index files into the downloader /*{{{*/
276 // ---------------------------------------------------------------------
277 /* */
278 bool pkgSourceList::GetIndexes(pkgAcquire *Owner) const
279 {
280 for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
281 if ((*I)->GetIndexes(Owner) == false)
282 return false;
283 return true;
284 }
285 /*}}}*/