]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debindexfile.cc
Double slash bug
[apt.git] / apt-pkg / deb / debindexfile.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: debindexfile.cc,v 1.3 2001/02/23 06:41:55 jgg Exp $
4 /* ######################################################################
5
6 Debian Specific sources.list types and the three sorts of Debian
7 index files.
8
9 ##################################################################### */
10 /*}}}*/
11 // Include Files /*{{{*/
12 #ifdef __GNUG__
13 #pragma implementation "apt-pkg/debindexfile.h"
14 #endif
15
16 #include <apt-pkg/debindexfile.h>
17 #include <apt-pkg/debsrcrecords.h>
18 #include <apt-pkg/deblistparser.h>
19 #include <apt-pkg/debrecords.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/configuration.h>
22 #include <apt-pkg/progress.h>
23 #include <apt-pkg/error.h>
24 #include <apt-pkg/strutl.h>
25 #include <apt-pkg/acquire-item.h>
26
27 #include <sys/stat.h>
28 /*}}}*/
29
30 // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
31 // ---------------------------------------------------------------------
32 /* */
33 debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section) :
34 URI(URI), Dist(Dist), Section(Section)
35 {
36 }
37 /*}}}*/
38 // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
39 // ---------------------------------------------------------------------
40 /* The result looks like:
41 http://foo/ stable/main src 1.1.1 (dsc) */
42 string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
43 pkgSrcRecords::File const &File) const
44 {
45 string Res;
46 Res = ::URI::SiteOnly(URI) + ' ';
47 if (Dist[Dist.size() - 1] == '/')
48 {
49 if (Dist != "/")
50 Res += Dist;
51 }
52 else
53 Res += Dist + '/' + Section;
54
55 Res += " ";
56 Res += Record.Package();
57 Res += " ";
58 Res += Record.Version();
59 if (File.Type.empty() == false)
60 Res += " (" + File.Type + ")";
61 return Res;
62 }
63 /*}}}*/
64 // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
65 // ---------------------------------------------------------------------
66 /* */
67 pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
68 {
69 string SourcesURI = URItoFileName(IndexURI("Sources"));
70 return new debSrcRecordParser(_config->FindDir("Dir::State::lists") +
71 SourcesURI,this);
72 }
73 /*}}}*/
74 // SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
75 // ---------------------------------------------------------------------
76 /* */
77 string debSourcesIndex::Describe() const
78 {
79 char S[300];
80 snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
81 IndexFile("Sources").c_str());
82 return S;
83 }
84 /*}}}*/
85 // SourcesIndex::Info - One liner describing the index URI /*{{{*/
86 // ---------------------------------------------------------------------
87 /* */
88 string debSourcesIndex::Info(const char *Type) const
89 {
90 string Info = ::URI::SiteOnly(URI) + ' ';
91 if (Dist[Dist.size() - 1] == '/')
92 {
93 if (Dist != "/")
94 Info += Dist;
95 }
96 else
97 Info += Dist + '/' + Section;
98 Info += " ";
99 Info += Type;
100 return Info;
101 }
102 /*}}}*/
103 // SourcesIndex::Index* - Return the URI to the index files /*{{{*/
104 // ---------------------------------------------------------------------
105 /* */
106 inline string debSourcesIndex::IndexFile(const char *Type) const
107 {
108 return URItoFileName(IndexURI(Type));
109 }
110 string debSourcesIndex::IndexURI(const char *Type) const
111 {
112 string Res;
113 if (Dist[Dist.size() - 1] == '/')
114 {
115 if (Dist != "/")
116 Res = URI + Dist;
117 else
118 Res = URI;
119 }
120 else
121 Res = URI + "dists/" + Dist + '/' + Section +
122 "/source/";
123
124 Res += Type;
125 return Res;
126 }
127 /*}}}*/
128 // SourcesIndex::GetIndexes - Fetch the index files /*{{{*/
129 // ---------------------------------------------------------------------
130 /* */
131 bool debSourcesIndex::GetIndexes(pkgAcquire *Owner) const
132 {
133 new pkgAcqIndex(Owner,IndexURI("Sources"),Info("Sources"),"Sources");
134 new pkgAcqIndexRel(Owner,IndexURI("Release"),Info("Release"),"Release");
135 return true;
136 }
137 /*}}}*/
138 // SourcesIndex::Exists - Check if the index is available /*{{{*/
139 // ---------------------------------------------------------------------
140 /* */
141 bool debSourcesIndex::Exists() const
142 {
143 return FileExists(IndexFile("Sources"));
144 }
145 /*}}}*/
146 // SourcesIndex::Size - Return the size of the index /*{{{*/
147 // ---------------------------------------------------------------------
148 /* */
149 unsigned long debSourcesIndex::Size() const
150 {
151 struct stat S;
152 if (stat(IndexFile("Sources").c_str(),&S) != 0)
153 return 0;
154 return S.st_size;
155 }
156 /*}}}*/
157
158 // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
159 // ---------------------------------------------------------------------
160 /* */
161 debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section) :
162 URI(URI), Dist(Dist), Section(Section)
163 {
164 }
165 /*}}}*/
166 // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
167 // ---------------------------------------------------------------------
168 /* This is a shorter version that is designed to be < 60 chars or so */
169 string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
170 {
171 string Res = ::URI::SiteOnly(URI) + ' ';
172 if (Dist[Dist.size() - 1] == '/')
173 {
174 if (Dist != "/")
175 Res += Dist;
176 }
177 else
178 Res += Dist + '/' + Section;
179
180 Res += " ";
181 Res += Ver.ParentPkg().Name();
182 Res += " ";
183 Res += Ver.VerStr();
184 return Res;
185 }
186 /*}}}*/
187 // PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/
188 // ---------------------------------------------------------------------
189 /* This should help the user find the index in the sources.list and
190 in the filesystem for problem solving */
191 string debPackagesIndex::Describe() const
192 {
193 char S[300];
194 snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
195 IndexFile("Packages").c_str());
196 return S;
197 }
198 /*}}}*/
199 // PackagesIndex::Info - One liner describing the index URI /*{{{*/
200 // ---------------------------------------------------------------------
201 /* */
202 string debPackagesIndex::Info(const char *Type) const
203 {
204 string Info = ::URI::SiteOnly(URI) + ' ';
205 if (Dist[Dist.size() - 1] == '/')
206 {
207 if (Dist != "/")
208 Info += Dist;
209 }
210 else
211 Info += Dist + '/' + Section;
212 Info += " ";
213 Info += Type;
214 return Info;
215 }
216 /*}}}*/
217 // PackagesIndex::Index* - Return the URI to the index files /*{{{*/
218 // ---------------------------------------------------------------------
219 /* */
220 inline string debPackagesIndex::IndexFile(const char *Type) const
221 {
222 return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
223 }
224 string debPackagesIndex::IndexURI(const char *Type) const
225 {
226 string Res;
227 if (Dist[Dist.size() - 1] == '/')
228 {
229 if (Dist != "/")
230 Res = URI + Dist;
231 else
232 Res = URI;
233 }
234 else
235 Res = URI + "dists/" + Dist + '/' + Section +
236 "/binary-" + _config->Find("APT::Architecture") + '/';
237
238 Res += Type;
239 return Res;
240 }
241 /*}}}*/
242 // PackagesIndex::GetIndexes - Fetch the index files /*{{{*/
243 // ---------------------------------------------------------------------
244 /* */
245 bool debPackagesIndex::GetIndexes(pkgAcquire *Owner) const
246 {
247 new pkgAcqIndex(Owner,IndexURI("Packages"),Info("Packages"),"Packages");
248 new pkgAcqIndexRel(Owner,IndexURI("Release"),Info("Release"),"Release");
249 return true;
250 }
251 /*}}}*/
252 // PackagesIndex::Exists - Check if the index is available /*{{{*/
253 // ---------------------------------------------------------------------
254 /* */
255 bool debPackagesIndex::Exists() const
256 {
257 return FileExists(IndexFile("Packages"));
258 }
259 /*}}}*/
260 // PackagesIndex::Size - Return the size of the index /*{{{*/
261 // ---------------------------------------------------------------------
262 /* This is really only used for progress reporting. */
263 unsigned long debPackagesIndex::Size() const
264 {
265 struct stat S;
266 if (stat(IndexFile("Packages").c_str(),&S) != 0)
267 return 0;
268 return S.st_size;
269 }
270 /*}}}*/
271 // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
272 // ---------------------------------------------------------------------
273 /* */
274 bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
275 {
276 string PackageFile = IndexFile("Packages");
277 FileFd Pkg(PackageFile,FileFd::ReadOnly);
278 debListParser Parser(&Pkg);
279 if (_error->PendingError() == true)
280 return _error->Error("Problem opening %s",PackageFile.c_str());
281
282 Prog.SubProgress(0,Info("Packages"));
283 ::URI Tmp(URI);
284 if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
285 return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
286
287 // Store the IMS information
288 pkgCache::PkgFileIterator File = Gen.GetCurFile();
289 struct stat St;
290 if (fstat(Pkg.Fd(),&St) != 0)
291 return _error->Errno("fstat","Failed to stat");
292 File->Size = St.st_size;
293 File->mtime = St.st_mtime;
294
295 if (Gen.MergeList(Parser) == false)
296 return _error->Error("Problem with MergeList %s",PackageFile.c_str());
297
298 // Check the release file
299 string ReleaseFile = IndexFile("Release");
300 if (FileExists(ReleaseFile) == true)
301 {
302 FileFd Rel(ReleaseFile,FileFd::ReadOnly);
303 if (_error->PendingError() == true)
304 return false;
305 Parser.LoadReleaseInfo(File,Rel);
306 }
307
308 return true;
309 }
310 /*}}}*/
311 // PackagesIndex::FindInCache - Find this index /*{{{*/
312 // ---------------------------------------------------------------------
313 /* */
314 pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
315 {
316 string FileName = IndexFile("Packages");
317 pkgCache::PkgFileIterator File = Cache.FileBegin();
318 for (; File.end() == false; File++)
319 {
320 if (FileName != File.FileName())
321 continue;
322
323 struct stat St;
324 if (stat(File.FileName(),&St) != 0)
325 return pkgCache::PkgFileIterator(Cache);
326 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
327 return pkgCache::PkgFileIterator(Cache);
328 return File;
329 }
330
331 return File;
332 }
333 /*}}}*/
334
335 // StatusIndex::debStatusIndex - Constructor /*{{{*/
336 // ---------------------------------------------------------------------
337 /* */
338 debStatusIndex::debStatusIndex(string File) : File(File)
339 {
340 }
341 /*}}}*/
342 // StatusIndex::Size - Return the size of the index /*{{{*/
343 // ---------------------------------------------------------------------
344 /* */
345 unsigned long debStatusIndex::Size() const
346 {
347 struct stat S;
348 if (stat(File.c_str(),&S) != 0)
349 return 0;
350 return S.st_size;
351 }
352 /*}}}*/
353 // StatusIndex::Merge - Load the index file into a cache /*{{{*/
354 // ---------------------------------------------------------------------
355 /* */
356 bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
357 {
358 FileFd Pkg(File,FileFd::ReadOnly);
359 if (_error->PendingError() == true)
360 return false;
361 debListParser Parser(&Pkg);
362 if (_error->PendingError() == true)
363 return false;
364
365 Prog.SubProgress(0,File);
366 if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
367 return _error->Error("Problem with SelectFile %s",File.c_str());
368
369 // Store the IMS information
370 pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
371 struct stat St;
372 if (fstat(Pkg.Fd(),&St) != 0)
373 return _error->Errno("fstat","Failed to stat");
374 CFile->Size = St.st_size;
375 CFile->mtime = St.st_mtime;
376 CFile->Archive = Gen.WriteUniqString("now");
377
378 if (Gen.MergeList(Parser) == false)
379 return _error->Error("Problem with MergeList %s",File.c_str());
380 return true;
381 }
382 /*}}}*/
383 // StatusIndex::FindInCache - Find this index /*{{{*/
384 // ---------------------------------------------------------------------
385 /* */
386 pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
387 {
388 pkgCache::PkgFileIterator File = Cache.FileBegin();
389 for (; File.end() == false; File++)
390 {
391 if (this->File != File.FileName())
392 continue;
393
394 struct stat St;
395 if (stat(File.FileName(),&St) != 0)
396 return pkgCache::PkgFileIterator(Cache);
397 if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
398 return pkgCache::PkgFileIterator(Cache);
399 return File;
400 }
401 return File;
402 }
403 /*}}}*/
404 // StatusIndex::Exists - Check if the index is available /*{{{*/
405 // ---------------------------------------------------------------------
406 /* */
407 bool debStatusIndex::Exists() const
408 {
409 // Abort if the file does not exist.
410 return true;
411 }
412 /*}}}*/
413
414 // Source List types for Debian /*{{{*/
415 class debSLTypeDeb : public pkgSourceList::Type
416 {
417 public:
418
419 bool CreateItem(vector<pkgIndexFile *> &List,string URI,
420 string Dist,string Section) const
421 {
422 List.push_back(new debPackagesIndex(URI,Dist,Section));
423 return true;
424 };
425
426 debSLTypeDeb()
427 {
428 Name = "deb";
429 Label = "Standard Debian binary tree";
430 }
431 };
432
433 class debSLTypeDebSrc : public pkgSourceList::Type
434 {
435 public:
436
437 bool CreateItem(vector<pkgIndexFile *> &List,string URI,
438 string Dist,string Section) const
439 {
440 List.push_back(new debSourcesIndex(URI,Dist,Section));
441 return true;
442 };
443
444 debSLTypeDebSrc()
445 {
446 Name = "deb-src";
447 Label = "Standard Debian source tree";
448 }
449 };
450
451 debSLTypeDeb _apt_DebType;
452 debSLTypeDebSrc _apt_DebSrcType;
453 /*}}}*/
454 // Index File types for Debian /*{{{*/
455 class debIFTypeSrc : public pkgIndexFile::Type
456 {
457 public:
458
459 debIFTypeSrc() {Label = "Debian Source Index";};
460 };
461 class debIFTypePkg : public pkgIndexFile::Type
462 {
463 public:
464
465 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
466 {
467 return new debRecordParser(File.FileName(),*File.Cache());
468 };
469 debIFTypePkg() {Label = "Debian Package Index";};
470 };
471 class debIFTypeStatus : public pkgIndexFile::Type
472 {
473 public:
474
475 virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
476 {
477 return new debRecordParser(File.FileName(),*File.Cache());
478 };
479 debIFTypeStatus() {Label = "Debian dpkg status file";};
480 };
481 static debIFTypeSrc _apt_Src;
482 static debIFTypePkg _apt_Pkg;
483 static debIFTypeStatus _apt_Status;
484
485 const pkgIndexFile::Type *debSourcesIndex::GetType() const
486 {
487 return &_apt_Src;
488 }
489 const pkgIndexFile::Type *debPackagesIndex::GetType() const
490 {
491 return &_apt_Pkg;
492 }
493 const pkgIndexFile::Type *debStatusIndex::GetType() const
494 {
495 return &_apt_Status;
496 }
497
498 /*}}}*/