- merge repomd branch
[apt.git] / apt-pkg / rpm / rpmrecords.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 /* ######################################################################
4    
5    RPM Package Records - Parser for RPM package records
6      
7    ##################################################################### 
8  */
9                                                                         /*}}}*/
10 // Include Files                                                        /*{{{*/
11 #ifdef __GNUG__
12 #pragma implementation "apt-pkg/rpmrecords.h"
13 #endif
14
15 #include <config.h>
16
17 #ifdef HAVE_RPM
18
19 #include <assert.h>
20
21 #include <apt-pkg/rpmrecords.h>
22 #include <apt-pkg/error.h>
23 #include <apt-pkg/rpmhandler.h>
24 #include <apt-pkg/rpmsystem.h>
25
26 #include <apti18n.h>
27
28 using namespace std;
29
30 // RecordParser::rpmRecordParser - Constructor                          /*{{{*/
31 // ---------------------------------------------------------------------
32 /* */
33 rpmRecordParser::rpmRecordParser(string File, pkgCache &Cache)
34    : Handler(0), Buffer(0), BufSize(0), BufUsed(0)
35 {
36    if (File == RPMDBHandler::DataPath(false)) {
37       IsDatabase = true;
38       Handler = rpmSys.GetDBHandler();
39    } else {
40       IsDatabase = false;
41       struct stat Buf;
42       if (stat(File.c_str(),&Buf) == 0 && S_ISDIR(Buf.st_mode))
43          Handler = new RPMDirHandler(File);
44       else if (flExtension(File) == "rpm")
45          Handler = new RPMSingleFileHandler(File);
46       else if (flExtension(File) == "xml")
47          Handler = new RPMRepomdHandler(File);
48       else
49          Handler = new RPMFileHandler(File);
50    }
51 }
52                                                                         /*}}}*/
53 // RecordParser::~rpmRecordParser - Destructor                          /*{{{*/
54 // ---------------------------------------------------------------------
55 /* */
56 rpmRecordParser::~rpmRecordParser()
57 {
58    // Can't use Handler->IsDatabase here, since the RPMDBHandler
59    // could already have been destroyed.
60    if (IsDatabase == false)
61       delete Handler;
62    free(Buffer);
63 }
64                                                                         /*}}}*/
65 // RecordParser::Jump - Jump to a specific record                       /*{{{*/
66 // ---------------------------------------------------------------------
67 /* */
68 bool rpmRecordParser::Jump(pkgCache::VerFileIterator const &Ver)
69 {
70    return Handler->Jump(Ver->Offset);
71 }
72                                                                         /*}}}*/
73 // RecordParser::FileName - Return the archive filename on the site     /*{{{*/
74 // ---------------------------------------------------------------------
75 /* */
76 string rpmRecordParser::FileName()
77 {
78    string Dir = Handler->Directory();
79    if (Dir.empty() == true)
80       return Handler->FileName();
81    return flCombine(Dir, Handler->FileName());
82 }
83                                                                         /*}}}*/
84 // RecordParser::Name - Return the package name                         /*{{{*/
85 // ---------------------------------------------------------------------
86 /* */
87 string rpmRecordParser::Name()
88 {
89    return Handler->Name();
90 }
91                                                                         /*}}}*/
92 // RecordParser::MD5Hash - Return the archive hash                      /*{{{*/
93 // ---------------------------------------------------------------------
94 /* */
95 string rpmRecordParser::MD5Hash()
96 {
97    return Handler->MD5Sum();
98 }
99                                                                         /*}}}*/
100 string rpmRecordParser::SHA1Hash()
101 {
102    return Handler->SHA1Sum();
103 }
104
105 // RecordParser::Maintainer - Return the maintainer email               /*{{{*/
106 // ---------------------------------------------------------------------
107 /* */
108 string rpmRecordParser::Maintainer()
109 {
110    return Handler->Packager();
111 }
112                                                                         /*}}}*/
113 // RecordParser::ShortDesc - Return a 1 line description                /*{{{*/
114 // ---------------------------------------------------------------------
115 /* */
116 string rpmRecordParser::ShortDesc()
117 {
118    return Handler->Summary();
119 }
120                                                                         /*}}}*/
121 // RecordParser::LongDesc - Return a longer description                 /*{{{*/
122 // ---------------------------------------------------------------------
123 /* */
124 string rpmRecordParser::LongDesc()
125 {
126    return Handler->Description();
127 }
128                                                                         /*}}}*/
129 // RecordParser::SourcePkg - Return the source package name if any      /*{{{*/
130 // ---------------------------------------------------------------------
131 /* */
132 string rpmRecordParser::SourcePkg()
133 {
134    // This must be the *package* name, not the *file* name. We have no
135    // current way to extract it safely from the file name.
136    return "";
137 }
138                                                                         /*}}}*/
139
140 void rpmRecordParser::BufCat(const char *text)
141 {
142    if (text != NULL)
143       BufCat(text, text+strlen(text));
144 }
145
146 void rpmRecordParser::BufCat(const char *begin, const char *end)
147 {
148    unsigned len = end - begin;
149     
150    if (BufUsed+len+1 >= BufSize)
151    {
152       BufSize += 512;
153       char *tmp = (char*)realloc(Buffer, BufSize);
154       if (tmp == NULL)
155       {
156          _error->Errno("realloc", _("Could not allocate buffer for record text"));
157          return;
158       }
159       Buffer = tmp;
160    }
161
162    strncpy(Buffer+BufUsed, begin, len);
163    BufUsed += len;
164 }
165
166 void rpmRecordParser::BufCatTag(const char *tag, const char *value)
167 {
168    BufCat(tag);
169    BufCat(value);
170 }
171
172 void rpmRecordParser::BufCatDep(Dependency *Dep)
173 {
174    string buf;
175
176    BufCat(Dep->Name.c_str());
177    if (Dep->Version.empty() == false) 
178    {
179       BufCat(" ");
180       switch (Dep->Op) {
181          case pkgCache::Dep::Less:
182             buf += "<";
183             break;
184          case pkgCache::Dep::LessEq:
185             buf += "<=";
186             break;
187          case pkgCache::Dep::Equals: 
188             buf += "=";
189             break;
190          case pkgCache::Dep::Greater:
191             buf += ">";
192             break;
193          case pkgCache::Dep::GreaterEq:
194             buf += ">=";
195             break;
196       }
197
198       BufCat(buf.c_str());
199       BufCat(" ");
200       BufCat(Dep->Version.c_str());
201    }
202 }
203
204 void rpmRecordParser::BufCatDescr(const char *descr)
205 {
206    const char *begin = descr;
207
208    while (*descr) 
209    {
210       if (*descr=='\n') 
211       {
212          BufCat(" ");
213          BufCat(begin, descr+1);
214          begin = descr+1;
215       }
216       descr++;
217    }
218    BufCat(" ");
219    BufCat(begin, descr);
220    BufCat("\n");
221 }
222
223
224 // RecordParser::GetRec - The record in raw text, in std Debian format  /*{{{*/
225 // ---------------------------------------------------------------------
226 void rpmRecordParser::GetRec(const char *&Start,const char *&Stop) 
227 {
228    // FIXME: This method is leaking memory from headerGetEntry().
229    int type, type2, type3, count;
230    char *str;
231    char **strv;
232    char **strv2;
233    int_32 *numv;
234    char buf[32];
235
236    BufUsed = 0;
237
238    BufCatTag("Package: ", Handler->Name().c_str());
239
240    BufCatTag("\nSection: ", Handler->Group().c_str());
241
242    snprintf(buf, sizeof(buf), "%d", Handler->InstalledSize());
243    BufCatTag("\nInstalled Size: ", buf);
244
245    BufCatTag("\nPackager: ", Handler->Packager().c_str());
246    //BufCatTag("\nVendor: ", Handler->Vendor().c_str());
247    
248    BufCat("\nVersion: ");
249    
250    string e, v, r, verstr;
251    e = Handler->Epoch();
252    v = Handler->Version();
253    r = Handler->Release();
254    
255    if (e.empty() == false)
256       verstr = e + ":" + v + "-" + r;
257    else
258       verstr = v + "-" + r;
259       
260    BufCat(verstr.c_str());
261
262
263    vector<Dependency*> Deps, Provides, Obsoletes, Conflicts;
264    vector<Dependency*>::iterator I;
265    bool start = true;
266
267    Handler->Depends(pkgCache::Dep::Depends, Deps);
268    for (I = Deps.begin(); I != Deps.end(); I++) {
269       if ((*I)->Type != pkgCache::Dep::PreDepends)
270          continue;
271       if (start) {
272          BufCat("\nPre-Depends: ");
273          start = false;
274       } else {
275          BufCat(", ");
276       }
277       BufCatDep(*I);
278    }
279
280    start = true;
281    for (I = Deps.begin(); I != Deps.end(); I++) {
282       if ((*I)->Type != pkgCache::Dep::Depends)
283          continue;
284       if (start) {
285          BufCat("\nDepends: ");
286          start = false;
287       } else {
288          BufCat(", ");
289       }
290       BufCatDep(*I);
291    }
292       
293    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
294    I = Conflicts.begin();
295    if (I != Conflicts.end()) {
296       BufCat("\nConflicts: ");
297       BufCatDep(*I);
298    }
299    for (; I != Conflicts.end(); I++) {
300       BufCat(", ");
301       BufCatDep(*I);
302    }
303
304    Handler->Provides(Provides);
305    I = Provides.begin();
306    if (I != Provides.end()) {
307       BufCat("\nProvides: ");
308       BufCatDep(*I);
309    }
310    for (; I != Provides.end(); I++) {
311       BufCat(", ");
312       BufCatDep(*I);
313    }
314
315    Handler->Depends(pkgCache::Dep::Obsoletes, Obsoletes);
316    I = Obsoletes.begin();
317    if (I != Obsoletes.end()) {
318       BufCat("\nObsoletes: ");
319       BufCatDep(*I);
320    }
321    for (; I != Obsoletes.end(); I++) {
322       BufCat(", ");
323       BufCatDep(*I);
324    }
325
326    BufCatTag("\nArchitecture: ", Handler->Arch().c_str());
327    
328    snprintf(buf, sizeof(buf), "%d", Handler->FileSize());
329    BufCatTag("\nSize: ", buf);
330
331    BufCatTag("\nMD5Sum: ", Handler->MD5Sum().c_str());
332
333    BufCatTag("\nFilename: ", Handler->FileName().c_str());
334
335    BufCatTag("\nSummary: ", Handler->Summary().c_str());
336    BufCat("\nDescription: ");
337    BufCat("\n");
338    BufCatDescr(Handler->Description().c_str());
339    BufCat("\n");
340    
341    Start = Buffer;
342    Stop = Buffer + BufUsed;
343 }
344                                                                         /*}}}*/
345
346 bool rpmRecordParser::HasFile(const char *File)
347 {
348    return Handler->HasFile(File);
349 }
350
351 #endif /* HAVE_RPM */
352
353 // vim:sts=3:sw=3