Pare down to internal only libelf.
[platform/upstream/rpm.git] / oldrpmdb.c
1 #include "system.h"
2
3 #include <rpmbuild.h>
4
5 #include "rpm_malloc.h"
6 #include "oldrpmdb.h"
7 #include "debug.h"
8
9 static int labelstrlistToLabelList(char * str, int length, 
10                                    struct oldrpmdbLabel ** list);
11 static char * getScript(char * which, struct oldrpmdb *oldrpmdb, 
12                         struct oldrpmdbLabel label);
13
14 static char * prefix = "/var/lib/rpm";
15
16 char * oldrpmdbLabelToLabelstr(struct oldrpmdbLabel label, int withFileNum) {
17     char * c;
18     char buffer[50];
19  
20     if (withFileNum && label.fileNumber > -1) 
21         c = xmalloc(strlen(label.name) + strlen(label.version) + 
22                    strlen(label.release) + 10);
23     else
24         c = xmalloc(strlen(label.name) + strlen(label.version) + 
25                    strlen(label.release) + 3);
26
27     strcpy(c, label.name);
28     strcat(c, ":");
29     strcat(c, label.version);
30     strcat(c, ":");
31     strcat(c, label.release);
32
33     if (withFileNum && label.fileNumber > -1)  {
34         sprintf(buffer, "%d", label.fileNumber);
35         strcat(c, ":");
36         strcat(c, buffer);
37     }
38
39     return c;
40 }
41
42 int oldrpmdbLabelstrToLabel(char * str, int length, struct oldrpmdbLabel * label) {
43     char * chptr;
44
45     label->freeType = RPMDB_FREENAME;
46     label->next = NULL;
47     label->name = malloc(length + 1);
48     if (!label->name) {
49         return 1;
50     }
51     memcpy(label->name, str, length);
52     label->name[length] = '\0';
53
54     chptr = label->name;
55     while (*chptr != ':') chptr++;
56     *chptr = '\0';
57     label->version = ++chptr;
58     while (*chptr != ':') chptr++;
59     *chptr = '\0';
60     label->release = chptr + 1;
61
62     label->fileNumber = -1;
63
64     /* there might be a path number tagged on to the end of this */
65     while ((chptr - label->name) < length && *chptr != ':') chptr++;
66     if ((chptr - label->name) < length) {
67         *chptr = '\0';
68         label->fileNumber = atoi(chptr + 1);
69     }
70
71     return 0;
72 }
73
74 static int labelstrlistToLabelList(char * str, int length, 
75                                    struct oldrpmdbLabel ** list) {
76     char * start, * chptr;
77     struct oldrpmdbLabel * head = NULL;
78     struct oldrpmdbLabel * tail = NULL;
79     struct oldrpmdbLabel * label;
80     
81     start = str;
82     for (chptr = start; (chptr - str) < length; chptr++) {
83         /* spaces following a space get ignored */
84         if (*chptr == ' ' && start < chptr) {
85             label = malloc(sizeof(struct oldrpmdbLabel));
86             if (!label) {
87                 oldrpmdbFreeLabelList(head);
88                 return 1;
89             }
90             if (oldrpmdbLabelstrToLabel(start, chptr - start, label)) {
91                 free(label);
92                 oldrpmdbFreeLabelList(head);
93                 return 1;
94             }
95
96             if (!head) {
97                 head = label;
98                 tail = label;
99             } else {
100                 tail->next = label;
101                 tail = tail->next;
102             }
103
104             start = chptr + 1;
105         }
106     }
107
108     /* a space on the end would break things horribly w/o this test */
109     if (start < chptr) {
110         label = malloc(sizeof(struct oldrpmdbLabel));
111         if (!label) {
112             oldrpmdbFreeLabelList(head);
113             return 1;
114         }
115         if (oldrpmdbLabelstrToLabel(start, chptr - start, label)) {
116             free(label);
117             oldrpmdbFreeLabelList(head);
118             return 1;
119         }
120
121         if (!head) {
122             head = label;
123             tail = label;
124         } else {
125             tail->next = label;
126             tail = tail->next;
127         }
128
129         start = chptr + 1;
130     }
131
132     *list = head;
133     return 0;
134 }
135
136 /* returns 0 on success, -1 on failure */
137 int oldrpmdbOpen(struct oldrpmdb * oldrpmdb) {
138     unsigned int gdbmFlags;
139     char path[255];
140     int goterr = 0;
141
142     oldrpmdb->rpmdbError = RPMDB_NONE;
143
144     gdbmFlags = GDBM_READER;
145
146     strcpy(path, prefix);
147     strcat(path, "/packages");
148     oldrpmdb->packages = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
149     if (!oldrpmdb->packages) {
150         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
151         goterr = 1;
152     }
153
154     strcpy(path, prefix);
155     strcat(path, "/nameidx");
156     oldrpmdb->nameIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
157     if (!oldrpmdb->packages) {
158         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
159         goterr = 1;
160     }
161
162     strcpy(path, prefix);
163     strcat(path, "/pathidx");
164     oldrpmdb->pathIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
165     if (!oldrpmdb->packages) {
166         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
167         goterr = 1;
168     }
169
170     strcpy(path, prefix);
171     strcat(path, "/iconidx");
172     oldrpmdb->iconIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
173     if (!oldrpmdb->iconIndex) {
174         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
175         goterr = 1;
176     }
177
178     strcpy(path, prefix);
179     strcat(path, "/groupindex");
180     oldrpmdb->groupIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
181     if (!oldrpmdb->packages) {
182         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
183         goterr = 1;
184     }
185
186     strcpy(path, prefix);
187     strcat(path, "/postidx");
188     oldrpmdb->postIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
189     if (!oldrpmdb->postIndex) {
190         rpmError(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
191         goterr = 1;
192     }
193
194     if (goterr) {
195         oldrpmdbClose(oldrpmdb);
196         return -1;
197     }
198
199     return 0;
200 }
201
202 void oldrpmdbClose(struct oldrpmdb * oldrpmdb) {
203     gdbm_close(oldrpmdb->packages);
204     gdbm_close(oldrpmdb->nameIndex);
205     gdbm_close(oldrpmdb->pathIndex);
206     gdbm_close(oldrpmdb->postIndex);
207     gdbm_close(oldrpmdb->groupIndex);
208     gdbm_close(oldrpmdb->iconIndex);
209 }
210
211 struct oldrpmdbLabel * oldrpmdbGetAllLabels(struct oldrpmdb * oldrpmdb) {
212     datum rec;
213
214     struct oldrpmdbLabel * head = NULL;
215     struct oldrpmdbLabel * tail = NULL;
216     struct oldrpmdbLabel * label;
217
218     oldrpmdb->rpmdbError = RPMDB_NONE;
219
220     rec = gdbm_firstkey(oldrpmdb->packages);
221     while (rec.dptr) {
222         label = malloc(sizeof(struct oldrpmdbLabel));
223         if (!label) {
224             oldrpmdbFreeLabelList(head);
225             oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
226             return NULL;
227         }
228         if (oldrpmdbLabelstrToLabel(rec.dptr, rec.dsize, label)) {
229             free(label);
230             oldrpmdbFreeLabelList(head);
231             oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
232             return NULL;
233         }
234
235         if (!head) {
236             head = label;
237             tail = label;
238         } else {
239             tail->next = label;
240             tail = tail->next;
241         }
242
243         rec = gdbm_nextkey(oldrpmdb->packages, rec);
244     }
245
246     return head;
247 }
248
249 struct oldrpmdbLabel * oldrpmdbFindPackagesByFile(struct oldrpmdb * oldrpmdb, char * path) {
250     datum rec;
251     datum key;
252     struct oldrpmdbLabel * list;
253
254     oldrpmdb->rpmdbError = RPMDB_NONE;
255
256     key.dptr = path;
257     key.dsize = strlen(path);
258     rec = gdbm_fetch(oldrpmdb->pathIndex, key);
259     
260     if (!rec.dptr) 
261         return NULL;
262     if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
263         free(rec.dptr);
264         oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
265         return NULL;
266     }
267     free(rec.dptr);
268
269     return list;
270 }
271
272 struct oldrpmdbLabel * oldrpmdbFindPackagesByLabel(struct oldrpmdb * oldrpmdb, 
273                                              struct oldrpmdbLabel label)
274
275 /* the Name has to be here. The version/release fields optionally
276    restrict the search. Either will do. */
277
278 {
279     datum rec;
280     datum key;
281     struct oldrpmdbLabel * list;
282     struct oldrpmdbLabel * prospect;
283     struct oldrpmdbLabel * parent;
284     int bad;
285
286     oldrpmdb->rpmdbError = RPMDB_NONE;
287
288     key.dptr = label.name;
289     key.dsize = strlen(label.name);
290     rec = gdbm_fetch(oldrpmdb->nameIndex, key);
291     
292     if (!rec.dptr) 
293         return NULL;
294     if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
295         free(rec.dptr);
296         oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
297         return NULL;
298     }
299     free(rec.dptr);
300
301     prospect = list;
302     parent = NULL;
303     while (prospect) {
304         bad = 0;
305         if (label.version && strcmp(label.version, prospect->version))
306             bad = 1;
307         else if (label.release && strcmp(label.release, prospect->release))
308             bad = 1;
309
310         if (bad) {
311             oldrpmdbFreeLabel(*prospect);
312             if (!parent) {
313                 list = prospect->next;
314                 free(prospect);
315                 prospect = list;
316             } else {
317                 parent->next = prospect->next;
318                 free(prospect);
319                 prospect = parent->next;
320             }
321         } else {
322             prospect = prospect->next;
323         }
324     }
325
326     return list;
327 }
328
329 struct oldrpmdbLabel oldrpmdbMakeLabel(char * name, char * version, char * release,
330                                  int fileNumber, enum oldrpmdbFreeType freeType) {
331     struct oldrpmdbLabel label;
332
333     label.next = NULL;
334     label.freeType = freeType;
335     label.name = name;
336     label.version = version;
337     label.release = release;
338     label.fileNumber = fileNumber;
339
340     return label;
341 }
342
343 void oldrpmdbFreeLabelList(struct oldrpmdbLabel * list) {
344     struct oldrpmdbLabel * saved;
345
346     while (list) {
347         oldrpmdbFreeLabel(*list);
348         saved = list->next;
349         free(list);
350         list = saved;
351     }
352 }
353
354 void oldrpmdbFreeLabel(struct oldrpmdbLabel label) {
355     if (label.freeType == RPMDB_NOFREE) return;
356
357     free(label.name);
358     if (label.freeType == RPMDB_FREEALL) {
359         free(label.version);
360         free(label.release);
361     }
362 }
363
364 /* Returns NULL on error */
365 char * oldrpmdbGetPackageGroup(struct oldrpmdb * oldrpmdb, struct oldrpmdbLabel label) {
366     datum key, rec;
367     char * g;
368     
369     key.dptr = label.name;
370     key.dsize = strlen(label.name);
371     
372     rec = gdbm_fetch(oldrpmdb->groupIndex, key);
373     if (!rec.dptr) {
374         return xstrdup("Unknown");
375     }
376     
377     g = malloc(rec.dsize + 1);
378     strncpy(g, rec.dptr, rec.dsize);
379     g[rec.dsize] = '\0';
380     free(rec.dptr);
381
382     return g;
383 }
384
385 static char * getScript(char * which, struct oldrpmdb *oldrpmdb, 
386                         struct oldrpmdbLabel label) {
387     datum key, rec;
388     char * labelstr, * l;
389
390     labelstr = oldrpmdbLabelToLabelstr(label, 0);
391     labelstr = xrealloc(labelstr, strlen(labelstr) + 10);
392     strcat(labelstr, ":");
393     strcat(labelstr, which);
394
395     key.dptr = labelstr;
396     key.dsize = strlen(labelstr);
397     
398     rec = gdbm_fetch(oldrpmdb->postIndex, key);
399     free(labelstr);
400
401     if (!rec.dptr) return NULL;
402
403     l = malloc(rec.dsize + 1);
404     strncpy(l, rec.dptr, rec.dsize);
405     l[rec.dsize] = '\0';
406
407     free(rec.dptr);
408
409     return l;
410 }
411
412 char *oldrpmdbGetPackagePostun (struct oldrpmdb *oldrpmdb, 
413                                 struct oldrpmdbLabel label) {
414     return getScript("post", oldrpmdb, label);
415 }
416
417 char *oldrpmdbGetPackagePreun (struct oldrpmdb *oldrpmdb, 
418                                 struct oldrpmdbLabel label) {
419     return getScript("pre", oldrpmdb, label);
420 }
421
422 /* Returns NULL on error or if no icon exists */
423 char * oldrpmdbGetPackageGif(struct oldrpmdb * oldrpmdb, 
424                              struct oldrpmdbLabel label, int * size) {
425     datum key, rec;
426     char * labelstr;
427
428     labelstr = oldrpmdbLabelToLabelstr(label, 0);
429     
430     key.dptr = labelstr;
431     key.dsize = strlen(labelstr);
432     
433     rec = gdbm_fetch(oldrpmdb->iconIndex, key);
434     free(labelstr);
435     if (!rec.dptr) {
436         return NULL;
437     }
438
439     *size = rec.dsize;
440
441     return rec.dptr;
442 }
443
444 /* return 0 on success, 1 on failure */
445 int oldrpmdbGetPackageInfo(struct oldrpmdb * oldrpmdb, struct oldrpmdbLabel label,
446                         struct oldrpmdbPackageInfo * pinfo) {
447     char * labelstr;
448     char ** list, ** prelist;
449     char ** strptr;
450     datum key, rec;
451     int i, j;
452
453     labelstr = oldrpmdbLabelToLabelstr(label, 0);
454
455     rpmMessage(RPMMESS_DEBUG, _("pulling %s from database\n"), labelstr);
456
457     key.dptr = labelstr;
458     key.dsize = strlen(labelstr);
459     
460     rec = gdbm_fetch(oldrpmdb->packages, key);
461     if (!rec.dptr) {
462         rpmError(RPMERR_OLDDBCORRUPT, _("package not found in database\n"));
463         return 1;
464     }
465
466     free(labelstr);
467
468     list = splitString(rec.dptr, rec.dsize, '\1');
469     free(rec.dptr);
470
471     pinfo->version = xstrdup(list[1]); 
472     pinfo->release = xstrdup(list[2]); 
473     /* list[3] == "1" always */
474     pinfo->name = malloc(strlen(list[0]) + strlen(list[4]) + 2);
475     strcpy(pinfo->name, list[0]);
476     if (strlen(list[4])) {
477         strcat(pinfo->name, "-");
478         strcat(pinfo->name, list[4]);
479     }
480     pinfo->labelstr = malloc(strlen(pinfo->name) + strlen(pinfo->version) +
481                              strlen(pinfo->release) + 3);
482     strcpy(pinfo->labelstr, pinfo->name);
483     strcat(pinfo->labelstr, ":");
484     strcat(pinfo->labelstr, pinfo->version);
485     strcat(pinfo->labelstr, ":");
486     strcat(pinfo->labelstr, pinfo->release);
487
488     pinfo->preamble = xstrdup(list[5]);
489     pinfo->installTime = atoi(list[6]);
490     pinfo->fileCount = atoi(list[7]);
491     
492     prelist = splitString(pinfo->preamble, strlen(pinfo->preamble), '\n');
493
494     /* these are optional */
495     pinfo->distribution = NULL;
496     pinfo->vendor = NULL;
497     pinfo->description = NULL;
498     pinfo->copyright = NULL;
499
500     for (strptr = prelist; *strptr; strptr++) {
501         if (!strncasecmp("Description: ", *strptr, 13))
502             pinfo->description = xstrdup((*strptr) + 13);
503         else if (!strncasecmp("Copyright: ", *strptr, 11))
504             pinfo->copyright = xstrdup((*strptr) + 11);
505         else if (!strncasecmp("Distribution: ", *strptr, 14))
506             pinfo->distribution = xstrdup((*strptr) + 14);
507         else if (!strncasecmp("Vendor: ", *strptr, 8))
508             pinfo->vendor = xstrdup((*strptr) + 8);
509         else if (!strncasecmp("size: ", *strptr, 6))
510             pinfo->size = atoi((*strptr) + 6);
511         else if (!strncasecmp("BuildDate: ", *strptr, 11))
512             pinfo->buildTime =atoi((*strptr) + 11);
513         else if (!strncasecmp("BuildHost: ", *strptr, 11))
514             pinfo->buildHost = xstrdup((*strptr) + 11);
515     }
516     freeSplitString(prelist);
517
518     if (!pinfo->vendor) pinfo->vendor = xstrdup("");
519     if (!pinfo->description) pinfo->description = xstrdup("");
520     if (!pinfo->distribution) pinfo->distribution = xstrdup("");
521     if (!pinfo->copyright) {
522         pinfo->copyright = xstrdup("");
523         fprintf(stdout, _("no copyright!\n"));
524     }
525
526     pinfo->files = malloc(sizeof(struct oldrpmFileInfo) * pinfo->fileCount);
527
528     j = 8;
529     for (i = 0; i < pinfo->fileCount; i++) {
530         oldrpmfileFromInfoLine(list[j], list[j + 1], list[j + 2],
531                             &pinfo->files[i]);
532         j += 3;
533     }
534
535     freeSplitString(list);
536                 
537     return 0;
538 }
539
540 void oldrpmdbFreePackageInfo(struct oldrpmdbPackageInfo package) {
541     int i;
542
543     free(package.version);
544     free(package.release);
545     free(package.name);
546     free(package.labelstr);
547     free(package.buildHost);
548     free(package.vendor);
549     free(package.description);
550     free(package.copyright);
551     free(package.distribution);
552     free(package.preamble);
553
554     for (i = 0; i < package.fileCount; i++) {
555         oldrpmfileFree(&package.files[i]);
556     }
557
558     free(package.files);
559 }
560
561 int oldrpmdbLabelCmp(struct oldrpmdbLabel * one, struct oldrpmdbLabel * two) {
562     int i;
563
564     if ((i = strcmp(one->name, two->name)))
565         return i;
566     else if ((i = strcmp(one->version, two->version)))
567         return i;
568     else
569         return strcmp(one->release, two->release);
570 }
571
572 void oldrpmdbSetPrefix(char * new) {
573     prefix = new;
574 }