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