20827039a07cd9dcc379302144164a51f5a67f12
[platform/upstream/rpm.git] / lib / dbindex.c
1 #include <db.h>
2 #include <errno.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "dbindex.h"
7 #include "rpmlib.h"
8
9 dbiIndex * dbiOpenIndex(char * filename, int flags, int perms) {
10     dbiIndex * db;
11         
12     db = malloc(sizeof(*db));
13     db->indexname = strdup(filename);
14     db->db = dbopen(filename, flags, perms, DB_HASH, NULL);
15     if (!db->db) {
16         free(db->indexname);
17         free(db);
18         rpmError(RPMERR_DBOPEN, "cannot open file %s: ", filename, 
19                               strerror(errno));
20         return NULL;
21     }
22
23     return db;
24 }
25
26 void dbiCloseIndex(dbiIndex * dbi) {
27     dbi->db->close(dbi->db);
28     free(dbi->indexname);
29     free(dbi);
30 }
31
32 void dbiSyncIndex(dbiIndex * dbi) {
33     dbi->db->sync(dbi->db, 0);
34 }
35
36 int dbiSearchIndex(dbiIndex * dbi, char * str, dbiIndexSet * set) {
37     DBT key, data;
38     int rc;
39
40     key.data = str;
41     key.size = strlen(str);
42
43     rc = dbi->db->get(dbi->db, &key, &data, 0);
44     if (rc == -1) {
45         rpmError(RPMERR_DBGETINDEX, "error getting record %s from %s",
46                 str, dbi->indexname);
47         return -1;
48     } else if (rc == 1) {
49         return 1;
50     } 
51
52     set->recs = data.data;
53     set->recs = malloc(data.size);
54     memcpy(set->recs, data.data, data.size);
55     set->count = data.size / sizeof(dbiIndexRecord);
56     return 0;
57 }
58
59 int dbiUpdateIndex(dbiIndex * dbi, char * str, dbiIndexSet * set) {
60    /* 0 on success */
61     DBT key, data;
62     int rc;
63
64     key.data = str;
65     key.size = strlen(str);
66
67     if (set->count) {
68         data.data = set->recs;
69         data.size = set->count * sizeof(dbiIndexRecord);
70
71         rc = dbi->db->put(dbi->db, &key, &data, 0);
72         if (rc) {
73             rpmError(RPMERR_DBPUTINDEX, "error storing record %s into %s",
74                     str, dbi->indexname);
75             return 1;
76         }
77     } else {
78         rc = dbi->db->del(dbi->db, &key, 0);
79         if (rc) {
80             rpmError(RPMERR_DBPUTINDEX, "error removing record %s into %s",
81                     str, dbi->indexname);
82             return 1;
83         }
84     }
85
86     return 0;
87 }
88
89 int dbiAppendIndexRecord(dbiIndexSet * set, dbiIndexRecord rec) {
90     set->count++;
91
92     if (set->count == 1) {
93         set->recs = malloc(set->count * sizeof(dbiIndexRecord));
94     } else {
95         set->recs = realloc(set->recs, set->count * sizeof(dbiIndexRecord));
96     }
97     set->recs[set->count - 1] = rec;
98
99     return 0;
100 }
101
102 dbiIndexSet dbiCreateIndexRecord(void) {
103     dbiIndexSet set;
104
105     set.count = 0;
106     return set;
107 }
108     
109 void dbiFreeIndexRecord(dbiIndexSet set) {
110     free(set.recs);
111 }
112
113 /* returns 1 on failure */
114 int dbiRemoveIndexRecord(dbiIndexSet * set, dbiIndexRecord rec) {
115     int from;
116     int to = 0;
117     int num = set->count;
118     int numCopied = 0;
119   
120     for (from = 0; from < num; from++) {
121         if (rec.recOffset != set->recs[from].recOffset ||
122             rec.fileNumber != set->recs[from].fileNumber) {
123             if (from != to) set->recs[to] = set->recs[from];
124             to++;
125             numCopied++;
126         } else {
127             set->count--;
128         }
129     }
130
131     return (numCopied == num);
132 }