Added routines for retrieving GIFs
[tools/librpm-tizen.git] / oldrpmdb.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "rpmerr.h"
6 #include "rpm_malloc.h"
7 #include "messages.h"
8 #include "misc.h"
9 #include "oldrpmdb.h"
10
11 static int labelstrlistToLabelList(char * str, int length, 
12                                    struct rpmdbLabel ** list);
13 static char * prefix = "/var/lib/rpm";
14
15 char * rpmdbLabelToLabelstr(struct rpmdbLabel label, int withFileNum) {
16     char * c;
17     char buffer[50];
18  
19     if (withFileNum && label.fileNumber > -1) 
20         c = malloc(strlen(label.name) + strlen(label.version) + 
21                    strlen(label.release) + 10);
22     else
23         c = malloc(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 rpmdbLabelstrToLabel(char * str, int length, struct rpmdbLabel * 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 rpmdbLabel ** list) {
75     char * start, * chptr;
76     struct rpmdbLabel * head = NULL;
77     struct rpmdbLabel * tail = NULL;
78     struct rpmdbLabel * 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 rpmdbLabel));
85             if (!label) {
86                 rpmdbFreeLabelList(head);
87                 return 1;
88             }
89             if (rpmdbLabelstrToLabel(start, chptr - start, label)) {
90                 free(label);
91                 rpmdbFreeLabelList(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 rpmdbLabel));
110         if (!label) {
111             rpmdbFreeLabelList(head);
112             return 1;
113         }
114         if (rpmdbLabelstrToLabel(start, chptr - start, label)) {
115             free(label);
116             rpmdbFreeLabelList(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 rpmdbOpen(struct rpmdb * rpmdb) {
137     unsigned int gdbmFlags;
138     char path[255];
139     int goterr = 0;
140
141     rpmdb->rpmdbError = RPMDB_NONE;
142
143     gdbmFlags = GDBM_READER;
144
145     strcpy(path, prefix);
146     strcat(path, "/packages");
147     rpmdb->packages = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
148     if (!rpmdb->packages) {
149         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
150         goterr = 1;
151     }
152
153     strcpy(path, prefix);
154     strcat(path, "/nameidx");
155     rpmdb->nameIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
156     if (!rpmdb->packages) {
157         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
158         goterr = 1;
159     }
160
161     strcpy(path, prefix);
162     strcat(path, "/pathidx");
163     rpmdb->pathIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
164     if (!rpmdb->packages) {
165         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
166         goterr = 1;
167     }
168
169     strcpy(path, prefix);
170     strcat(path, "/iconidx");
171     rpmdb->iconIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
172     if (!rpmdb->iconIndex) {
173         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
174         goterr = 1;
175     }
176
177     strcpy(path, prefix);
178     strcat(path, "/groupindex");
179     rpmdb->groupIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
180     if (!rpmdb->packages) {
181         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
182         goterr = 1;
183     }
184
185     strcpy(path, prefix);
186     strcat(path, "/postidx");
187     rpmdb->postIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
188     if (!rpmdb->postIndex) {
189         error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
190         goterr = 1;
191     }
192
193     if (goterr) {
194         rpmdbClose(rpmdb);
195         return -1;
196     }
197
198     return 0;
199 }
200
201 void rpmdbClose(struct rpmdb * rpmdb) {
202     gdbm_close(rpmdb->packages);
203     gdbm_close(rpmdb->nameIndex);
204     gdbm_close(rpmdb->pathIndex);
205     gdbm_close(rpmdb->postIndex);
206     gdbm_close(rpmdb->groupIndex);
207     gdbm_close(rpmdb->iconIndex);
208 }
209
210 struct rpmdbLabel * rpmdbGetAllLabels(struct rpmdb * rpmdb) {
211     datum rec;
212
213     struct rpmdbLabel * head = NULL;
214     struct rpmdbLabel * tail = NULL;
215     struct rpmdbLabel * label;
216
217     rpmdb->rpmdbError = RPMDB_NONE;
218
219     rec = gdbm_firstkey(rpmdb->packages);
220     while (rec.dptr) {
221         label = malloc(sizeof(struct rpmdbLabel));
222         if (!label) {
223             rpmdbFreeLabelList(head);
224             rpmdb->rpmdbError = RPMDB_NO_MEMORY;
225             return NULL;
226         }
227         if (rpmdbLabelstrToLabel(rec.dptr, rec.dsize, label)) {
228             free(label);
229             rpmdbFreeLabelList(head);
230             rpmdb->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(rpmdb->packages, rec);
243     }
244
245     return head;
246 }
247
248 struct rpmdbLabel * rpmdbFindPackagesByFile(struct rpmdb * rpmdb, char * path) {
249     datum rec;
250     datum key;
251     struct rpmdbLabel * list;
252
253     rpmdb->rpmdbError = RPMDB_NONE;
254
255     key.dptr = path;
256     key.dsize = strlen(path);
257     rec = gdbm_fetch(rpmdb->pathIndex, key);
258     
259     if (!rec.dptr) 
260         return NULL;
261     if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
262         free(rec.dptr);
263         rpmdb->rpmdbError = RPMDB_NO_MEMORY;
264         return NULL;
265     }
266     free(rec.dptr);
267
268     return list;
269 }
270
271 struct rpmdbLabel * rpmdbFindPackagesByLabel(struct rpmdb * rpmdb, 
272                                              struct rpmdbLabel 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 rpmdbLabel * list;
281     struct rpmdbLabel * prospect;
282     struct rpmdbLabel * parent;
283     int bad;
284
285     rpmdb->rpmdbError = RPMDB_NONE;
286
287     key.dptr = label.name;
288     key.dsize = strlen(label.name);
289     rec = gdbm_fetch(rpmdb->nameIndex, key);
290     
291     if (!rec.dptr) 
292         return NULL;
293     if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
294         free(rec.dptr);
295         rpmdb->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             rpmdbFreeLabel(*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 rpmdbLabel rpmdbMakeLabel(char * name, char * version, char * release,
329                                  int fileNumber, enum rpmdbFreeType freeType) {
330     struct rpmdbLabel 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 rpmdbFreeLabelList(struct rpmdbLabel * list) {
343     struct rpmdbLabel * saved;
344
345     while (list) {
346         rpmdbFreeLabel(*list);
347         saved = list->next;
348         free(list);
349         list = saved;
350     }
351 }
352
353 void rpmdbFreeLabel(struct rpmdbLabel 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 * rpmdbGetPackageGroup(struct rpmdb * rpmdb, struct rpmdbLabel 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(rpmdb->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 /* Returns NULL on error or if no icon exists */
385 char * rpmdbGetPackageGif(struct rpmdb * rpmdb, struct rpmdbLabel label,
386                           int * size) {
387     datum key, rec;
388     char * labelstr;
389
390     labelstr = rpmdbLabelToLabelstr(label, 0);
391     
392     key.dptr = labelstr;
393     key.dsize = strlen(labelstr);
394     
395     rec = gdbm_fetch(rpmdb->iconIndex, key);
396     free(labelstr);
397     if (!rec.dptr) {
398         return NULL;
399     }
400
401     *size = rec.dsize;
402
403     return rec.dptr;
404 }
405
406 /* return 0 on success, 1 on failure */
407 int rpmdbGetPackageInfo(struct rpmdb * rpmdb, struct rpmdbLabel label,
408                         struct rpmdbPackageInfo * pinfo) {
409     char * labelstr;
410     char ** list, ** prelist;
411     char ** strptr;
412     datum key, rec;
413     int i, j;
414
415     labelstr = rpmdbLabelToLabelstr(label, 0);
416
417     message(MESS_DEBUG, "pulling %s from database\n", labelstr);
418
419     key.dptr = labelstr;
420     key.dsize = strlen(labelstr);
421     
422     rec = gdbm_fetch(rpmdb->packages, key);
423     if (!rec.dptr) {
424         error(RPMERR_OLDDBCORRUPT, "package not found in database");
425         return 1;
426     }
427
428     free(labelstr);
429
430     list = splitString(rec.dptr, rec.dsize, '\1');
431     free(rec.dptr);
432
433     pinfo->version = strdup(list[1]); 
434     pinfo->release = strdup(list[2]); 
435     /* list[3] == "1" always */
436     pinfo->name = malloc(strlen(list[0]) + strlen(list[4]) + 2);
437     strcpy(pinfo->name, list[0]);
438     if (strlen(list[4])) {
439         strcat(pinfo->name, "-");
440         strcat(pinfo->name, list[4]);
441     }
442     pinfo->labelstr = malloc(strlen(pinfo->name) + strlen(pinfo->version) +
443                              strlen(pinfo->release) + 3);
444     strcpy(pinfo->labelstr, pinfo->name);
445     strcat(pinfo->labelstr, ":");
446     strcat(pinfo->labelstr, pinfo->version);
447     strcat(pinfo->labelstr, ":");
448     strcat(pinfo->labelstr, pinfo->release);
449
450     pinfo->preamble = strdup(list[5]);
451     pinfo->installTime = atoi(list[6]);
452     pinfo->fileCount = atoi(list[7]);
453     
454     prelist = splitString(pinfo->preamble, strlen(pinfo->preamble), '\n');
455
456     /* these are optional */
457     pinfo->distribution = NULL;
458     pinfo->vendor = NULL;
459     pinfo->description = NULL;
460     pinfo->copyright = NULL;
461
462     for (strptr = prelist; *strptr; strptr++) {
463         if (!strncasecmp("Description: ", *strptr, 13))
464             pinfo->description = strdup((*strptr) + 13);
465         else if (!strncasecmp("Copyright: ", *strptr, 11))
466             pinfo->copyright = strdup((*strptr) + 11);
467         else if (!strncasecmp("Distribution: ", *strptr, 14))
468             pinfo->distribution = strdup((*strptr) + 14);
469         else if (!strncasecmp("Vendor: ", *strptr, 8))
470             pinfo->vendor = strdup((*strptr) + 8);
471         else if (!strncasecmp("size: ", *strptr, 6))
472             pinfo->size = atoi((*strptr) + 6);
473         else if (!strncasecmp("BuildDate: ", *strptr, 11))
474             pinfo->buildTime =atoi((*strptr) + 11);
475         else if (!strncasecmp("BuildHost: ", *strptr, 11))
476             pinfo->buildHost = strdup((*strptr) + 11);
477     }
478     freeSplitString(prelist);
479
480     if (!pinfo->vendor) pinfo->vendor = strdup("");
481     if (!pinfo->description) pinfo->description = strdup("");
482     if (!pinfo->distribution) pinfo->distribution = strdup("");
483     if (!pinfo->copyright) {
484         pinfo->copyright = strdup("");
485         printf("no copyright!\n");
486     }
487
488     pinfo->files = malloc(sizeof(struct rpmFileInfo) * pinfo->fileCount);
489
490     j = 8;
491     for (i = 0; i < pinfo->fileCount; i++) {
492         rpmfileFromInfoLine(list[j], list[j + 1], list[j + 2],
493                             &pinfo->files[i]);
494         j += 3;
495     }
496
497     freeSplitString(list);
498                 
499     return 0;
500 }
501
502 void rpmdbFreePackageInfo(struct rpmdbPackageInfo package) {
503     int i;
504
505     free(package.version);
506     free(package.release);
507     free(package.name);
508     free(package.labelstr);
509     free(package.buildHost);
510     free(package.vendor);
511     free(package.description);
512     free(package.copyright);
513     free(package.distribution);
514     free(package.preamble);
515
516     for (i = 0; i < package.fileCount; i++) {
517         rpmfileFree(&package.files[i]);
518     }
519
520     free(package.files);
521 }
522
523 int rpmdbLabelCmp(struct rpmdbLabel * one, struct rpmdbLabel * two) {
524     int i;
525
526     if ((i = strcmp(one->name, two->name)))
527         return i;
528     else if ((i = strcmp(one->version, two->version)))
529         return i;
530     else
531         return strcmp(one->release, two->release);
532 }
533
534 void rpmdbSetPrefix(char * new) {
535     prefix = new;
536 }