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