- try to deduct srpm package name from srpm filename (Ralf Corsepius)
[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, false);
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
137 // A wild guess, hopefully covering most cases:
138 // Check for string "-$(version)-$(release)." in string srpm
139    string srpm = Handler->SourceRpm();
140    string versarch = "-" + Handler->Version() + "-" + Handler->Release() + ".";
141    string::size_type idx1 = srpm.find(versarch);
142
143 // not found
144    if ( idx1 < 0 )
145      return "";
146
147 // check if the first dot in "srpm" is the dot at the end of versarch
148    string::size_type idx2 = srpm.find('.');
149
150    if ( idx2 < idx1 )
151 // no, the packager is playing dirty tricks with srpm names
152      return "";
153
154    return srpm.substr(0,idx1);
155 }
156                                                                         /*}}}*/
157
158 void rpmRecordParser::BufCat(const char *text)
159 {
160    if (text != NULL)
161       BufCat(text, text+strlen(text));
162 }
163
164 void rpmRecordParser::BufCat(const char *begin, const char *end)
165 {
166    unsigned len = end - begin;
167     
168    if (BufUsed+len+1 >= BufSize)
169    {
170       BufSize += 512;
171       char *tmp = (char*)realloc(Buffer, BufSize);
172       if (tmp == NULL)
173       {
174          _error->Errno("realloc", _("Could not allocate buffer for record text"));
175          return;
176       }
177       Buffer = tmp;
178    }
179
180    strncpy(Buffer+BufUsed, begin, len);
181    BufUsed += len;
182 }
183
184 void rpmRecordParser::BufCatTag(const char *tag, const char *value)
185 {
186    BufCat(tag);
187    BufCat(value);
188 }
189
190 void rpmRecordParser::BufCatDep(Dependency *Dep)
191 {
192    string buf;
193
194    BufCat(Dep->Name.c_str());
195    if (Dep->Version.empty() == false) 
196    {
197       BufCat(" ");
198       switch (Dep->Op) {
199          case pkgCache::Dep::Less:
200             buf += "<";
201             break;
202          case pkgCache::Dep::LessEq:
203             buf += "<=";
204             break;
205          case pkgCache::Dep::Equals: 
206             buf += "=";
207             break;
208          case pkgCache::Dep::Greater:
209             buf += ">";
210             break;
211          case pkgCache::Dep::GreaterEq:
212             buf += ">=";
213             break;
214       }
215
216       BufCat(buf.c_str());
217       BufCat(" ");
218       BufCat(Dep->Version.c_str());
219    }
220 }
221
222 void rpmRecordParser::BufCatDescr(const char *descr)
223 {
224    const char *begin = descr;
225
226    while (*descr) 
227    {
228       if (*descr=='\n') 
229       {
230          BufCat(" ");
231          BufCat(begin, descr+1);
232          begin = descr+1;
233       }
234       descr++;
235    }
236    BufCat(" ");
237    BufCat(begin, descr);
238    BufCat("\n");
239 }
240
241
242 // RecordParser::GetRec - The record in raw text, in std Debian format  /*{{{*/
243 // ---------------------------------------------------------------------
244 void rpmRecordParser::GetRec(const char *&Start,const char *&Stop) 
245 {
246    // FIXME: This method is leaking memory from headerGetEntry().
247    char buf[32];
248
249    BufUsed = 0;
250
251    BufCatTag("Package: ", Handler->Name().c_str());
252
253    BufCatTag("\nSection: ", Handler->Group().c_str());
254
255    snprintf(buf, sizeof(buf), "%lu", Handler->InstalledSize());
256    BufCatTag("\nInstalled Size: ", buf);
257
258    BufCatTag("\nPackager: ", Handler->Packager().c_str());
259    //BufCatTag("\nVendor: ", Handler->Vendor().c_str());
260    
261    BufCat("\nVersion: ");
262    
263    BufCat(Handler->EVR().c_str());
264
265
266    vector<Dependency*> Deps, Provides, Obsoletes, Conflicts;
267    vector<Dependency*>::iterator I;
268    bool start = true;
269
270    Handler->Depends(pkgCache::Dep::Depends, Deps);
271    for (I = Deps.begin(); I != Deps.end(); I++) {
272       if ((*I)->Type != pkgCache::Dep::PreDepends)
273          continue;
274       if (start) {
275          BufCat("\nPre-Depends: ");
276          start = false;
277       } else {
278          BufCat(", ");
279       }
280       BufCatDep(*I);
281    }
282
283    start = true;
284    for (I = Deps.begin(); I != Deps.end(); I++) {
285       if ((*I)->Type != pkgCache::Dep::Depends)
286          continue;
287       if (start) {
288          BufCat("\nDepends: ");
289          start = false;
290       } else {
291          BufCat(", ");
292       }
293       BufCatDep(*I);
294    }
295       
296    Handler->Depends(pkgCache::Dep::Conflicts, Conflicts);
297    start = true;
298    for (I = Conflicts.begin(); I != Conflicts.end(); I++) {
299       if (start) {
300          BufCat("\nConflicts: ");
301          start = false;
302       } else {
303          BufCat(", ");
304       }
305       BufCatDep(*I);
306    }
307
308    Handler->Provides(Provides);
309    start = true;
310    for (I = Provides.begin(); I != Provides.end(); I++) {
311       if (start) {
312          BufCat("\nProvides: ");
313          start = false;
314       } else {
315          BufCat(", ");
316       }
317       BufCatDep(*I);
318    }
319
320    Handler->Depends(pkgCache::Dep::Obsoletes, Obsoletes);
321    start = true;
322    for (I = Obsoletes.begin(); I != Obsoletes.end(); I++) {
323       if (start) {
324          BufCat("\nObsoletes: ");
325          start = false;
326       } else {
327          BufCat(", ");
328       }
329       BufCatDep(*I);
330    }
331
332    BufCatTag("\nArchitecture: ", Handler->Arch().c_str());
333    
334    snprintf(buf, sizeof(buf), "%lu", Handler->FileSize());
335    BufCatTag("\nSize: ", buf);
336
337    BufCatTag("\nMD5Sum: ", Handler->MD5Sum().c_str());
338
339    BufCatTag("\nFilename: ", Handler->FileName().c_str());
340
341    BufCatTag("\nSummary: ", Handler->Summary().c_str());
342    BufCat("\nDescription: ");
343    BufCat("\n");
344    BufCatDescr(Handler->Description().c_str());
345    BufCat("\n");
346    
347    Start = Buffer;
348    Stop = Buffer + BufUsed;
349 }
350                                                                         /*}}}*/
351
352 bool rpmRecordParser::HasFile(const char *File)
353 {
354    return Handler->HasFile(File);
355 }
356
357 #endif /* HAVE_RPM */
358
359 // vim:sts=3:sw=3