1) added copyright field for packages
[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 /* return 0 on success, 1 on failure */
385 int rpmdbGetPackageInfo(struct rpmdb * rpmdb, struct rpmdbLabel label,
386                         struct rpmdbPackageInfo * pinfo) {
387     char * labelstr;
388     char ** list, ** prelist;
389     char ** strptr;
390     datum key, rec;
391     int i, j;
392
393     labelstr = rpmdbLabelToLabelstr(label, 0);
394
395     message(MESS_DEBUG, "pulling %s from database\n", labelstr);
396
397     key.dptr = labelstr;
398     key.dsize = strlen(labelstr);
399     
400     rec = gdbm_fetch(rpmdb->packages, key);
401     if (!rec.dptr) {
402         error(RPMERR_OLDDBCORRUPT, "package not found in database");
403         return 1;
404     }
405
406     free(labelstr);
407
408     list = splitString(rec.dptr, rec.dsize, '\1');
409     free(rec.dptr);
410
411     pinfo->version = strdup(list[1]); 
412     pinfo->release = strdup(list[2]); 
413     /* list[3] == "1" always */
414     pinfo->name = malloc(strlen(list[0]) + strlen(list[4]) + 2);
415     strcpy(pinfo->name, list[0]);
416     if (strlen(list[4])) {
417         strcat(pinfo->name, "-");
418         strcat(pinfo->name, list[4]);
419     }
420     pinfo->labelstr = malloc(strlen(pinfo->name) + strlen(pinfo->version) +
421                              strlen(pinfo->release) + 3);
422     strcpy(pinfo->labelstr, pinfo->name);
423     strcat(pinfo->labelstr, ":");
424     strcat(pinfo->labelstr, pinfo->version);
425     strcat(pinfo->labelstr, ":");
426     strcat(pinfo->labelstr, pinfo->release);
427
428     pinfo->preamble = strdup(list[5]);
429     pinfo->installTime = atoi(list[6]);
430     pinfo->fileCount = atoi(list[7]);
431     
432     prelist = splitString(pinfo->preamble, strlen(pinfo->preamble), '\n');
433
434     /* these are optional */
435     pinfo->distribution = NULL;
436     pinfo->vendor = NULL;
437     pinfo->description = NULL;
438     pinfo->copyright = NULL;
439
440     for (strptr = prelist; *strptr; strptr++) {
441         if (!strncasecmp("Description: ", *strptr, 13))
442             pinfo->description = strdup((*strptr) + 13);
443         else if (!strncasecmp("Copyright: ", *strptr, 11))
444             pinfo->copyright = strdup((*strptr) + 11);
445         else if (!strncasecmp("Distribution: ", *strptr, 14))
446             pinfo->distribution = strdup((*strptr) + 14);
447         else if (!strncasecmp("Vendor: ", *strptr, 8))
448             pinfo->vendor = strdup((*strptr) + 8);
449         else if (!strncasecmp("size: ", *strptr, 6))
450             pinfo->size = atoi((*strptr) + 6);
451         else if (!strncasecmp("BuildDate: ", *strptr, 11))
452             pinfo->buildTime =atoi((*strptr) + 11);
453         else if (!strncasecmp("BuildHost: ", *strptr, 11))
454             pinfo->buildHost = strdup((*strptr) + 11);
455     }
456     freeSplitString(prelist);
457
458     if (!pinfo->vendor) pinfo->vendor = strdup("");
459     if (!pinfo->description) pinfo->description = strdup("");
460     if (!pinfo->distribution) pinfo->distribution = strdup("");
461     if (!pinfo->copyright) {
462         pinfo->copyright = strdup("");
463         printf("no copyright!\n");
464     }
465
466     pinfo->files = malloc(sizeof(struct rpmFileInfo) * pinfo->fileCount);
467
468     j = 8;
469     for (i = 0; i < pinfo->fileCount; i++) {
470         rpmfileFromInfoLine(list[j], list[j + 1], list[j + 2],
471                             &pinfo->files[i]);
472         j += 3;
473     }
474
475     freeSplitString(list);
476                 
477     return 0;
478 }
479
480 void rpmdbFreePackageInfo(struct rpmdbPackageInfo package) {
481     int i;
482
483     free(package.version);
484     free(package.release);
485     free(package.name);
486     free(package.labelstr);
487     free(package.buildHost);
488     free(package.vendor);
489     free(package.description);
490     free(package.copyright);
491     free(package.distribution);
492     free(package.preamble);
493
494     for (i = 0; i < package.fileCount; i++) {
495         rpmfileFree(&package.files[i]);
496     }
497
498     free(package.files);
499 }
500
501 int rpmdbLabelCmp(struct rpmdbLabel * one, struct rpmdbLabel * two) {
502     int i;
503
504     if ((i = strcmp(one->name, two->name)))
505         return i;
506     else if ((i = strcmp(one->version, two->version)))
507         return i;
508     else
509         return strcmp(one->release, two->release);
510 }
511
512 void rpmdbSetPrefix(char * new) {
513     prefix = new;
514 }