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