summaryrefslogtreecommitdiff
path: root/lib/backend/dbi.c
blob: 809d013bf1678d2146cee5f4bb27b05268aa51d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/** \ingroup rpmdb
 * \file lib/dbi.c
 */

#include "system.h"

#include <stdlib.h>
#include <fcntl.h>
#include <rpm/rpmtypes.h>
#include <rpm/rpmstring.h>
#include <rpm/rpmmacro.h>
#include <rpm/rpmlog.h>
#include "lib/rpmdb_internal.h"
#include "debug.h"

const struct rpmdbOps_s *backends[] = {
#if defined(WITH_SQLITE)
    &sqlite_dbops,
#endif
#ifdef ENABLE_NDB
    &ndb_dbops,
#endif
#if defined(WITH_BDB)
    &db3_dbops,
#endif
#if defined(WITH_BDB_RO)
    &bdbro_dbops,
#endif
    &dummydb_dbops,
    NULL
};

dbiIndex dbiFree(dbiIndex dbi)
{
    if (dbi) {
	free(dbi);
    }
    return NULL;
}

dbiIndex dbiNew(rpmdb rdb, rpmDbiTagVal rpmtag)
{
    dbiIndex dbi = xcalloc(1, sizeof(*dbi));
    /* FIX: figger lib/dbi refcounts */
    dbi->dbi_rpmdb = rdb;
    dbi->dbi_file = rpmTagGetName(rpmtag);
    dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY;
    dbi->dbi_byteswapped = -1;	/* -1 unknown, 0 native order, 1 alien order */
    return dbi;
}

/* Test whether there's a database for this backend, return true/false */
static int tryBackend(const char *dbhome, const struct rpmdbOps_s *be)
{
    int rc = 0;
    if (be && be->path) {
	char *path = rstrscat(NULL, dbhome, "/", be->path, NULL);
	rc = (access(path, F_OK) == 0);
	free(path);
    }
    return rc;
}

static void
dbDetectBackend(rpmdb rdb)
{
    const char *dbhome = rpmdbHome(rdb);
    char *db_backend = rpmExpand("%{?_db_backend}", NULL);
    const struct rpmdbOps_s **ops;
    const struct rpmdbOps_s *cfg = NULL;
    const struct rpmdbOps_s *ondisk = NULL;

    /* Find configured backend */
    for (ops = backends; ops && *ops; ops++) {
	if (rstreq(db_backend, (*ops)->name)) {
	    cfg = *ops;
	    break;
	}
    }

    if (!cfg && ((rdb->db_mode & O_ACCMODE) != O_RDONLY || (rdb->db_flags & RPMDB_FLAG_REBUILD) != 0)) {
	rpmlog(RPMLOG_WARNING, _("invalid %%_db_backend: %s\n"), db_backend);
	goto exit;
    }

    /* If configured database doesn't exist, try autodetection */
    if (!tryBackend(dbhome, cfg)) {
	for (ops = backends; ops && *ops; ops++) {
	    if (tryBackend(dbhome, *ops)) {
		ondisk = *ops;
		break;
	    }
	}

	/* On-disk database differs from configuration */
	if (ondisk && ondisk != cfg) {
	    if (*db_backend) {
		if (rdb->db_flags & RPMDB_FLAG_REBUILD) {
		    rpmlog(RPMLOG_WARNING,
			    _("Converting database from %s to %s backend\n"),
			    ondisk->name, db_backend);
		} else {
		    rpmlog(RPMLOG_WARNING,
			_("Found %s %s database while attempting %s backend: "
			"using %s backend.\n"),
			ondisk->name, ondisk->path, db_backend, ondisk->name);
		}
	    } else {
		rpmlog(RPMLOG_DEBUG, "Found %s %s database: using %s backend.\n",
		    ondisk->name, ondisk->path, ondisk->name);
	    }
	    rdb->db_ops = ondisk;
	}
    }

    /* Newly created database, use configured backend */
    if (rdb->db_ops == NULL && cfg)
	rdb->db_ops = cfg;

exit:
    /* If all else fails... */
    if (rdb->db_ops == NULL) {
	rdb->db_ops = &dummydb_dbops;
	rpmlog(RPMLOG_WARNING, "using dummy database, installs not possible\n");
    }

    rdb->db_descr = rdb->db_ops->name;

    if (db_backend)
	free(db_backend);
}

const char * dbiName(dbiIndex dbi)
{
    return dbi->dbi_file;
}

int dbiFlags(dbiIndex dbi)
{
    return dbi->dbi_flags;
}

void dbSetFSync(rpmdb rdb, int enable)
{
    if (!rdb->db_ops)
	dbDetectBackend(rdb);
    rdb->db_ops->setFSync(rdb, enable);
}

int dbCtrl(rpmdb rdb, dbCtrlOp ctrl)
{
    if (!rdb->db_ops)
	dbDetectBackend(rdb);
    return rdb->db_ops->ctrl(rdb, ctrl);
}

int dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
{
    if (!rdb->db_ops)
	dbDetectBackend(rdb);
    return rdb->db_ops->open(rdb, rpmtag, dbip, flags);
}

int dbiClose(dbiIndex dbi, unsigned int flags)
{
    return dbi ? dbi->dbi_rpmdb->db_ops->close(dbi, flags) : 0;
}

int dbiVerify(dbiIndex dbi, unsigned int flags)
{
    return dbi->dbi_rpmdb->db_ops->verify(dbi, flags);
}

dbiCursor dbiCursorInit(dbiIndex dbi, unsigned int flags)
{
    return dbi->dbi_rpmdb->db_ops->cursorInit(dbi, flags);
}

dbiCursor dbiCursorFree(dbiIndex dbi, dbiCursor dbc)
{
    return dbi->dbi_rpmdb->db_ops->cursorFree(dbi, dbc);
}

rpmRC pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum, unsigned char *hdrBlob, unsigned int hdrLen)
{
    return dbi->dbi_rpmdb->db_ops->pkgdbPut(dbi, dbc, hdrNum, hdrBlob, hdrLen);
}

rpmRC pkgdbDel(dbiIndex dbi, dbiCursor dbc,  unsigned int hdrNum)
{
    return dbi->dbi_rpmdb->db_ops->pkgdbDel(dbi, dbc, hdrNum);
}

rpmRC pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen)
{
    return dbi->dbi_rpmdb->db_ops->pkgdbGet(dbi, dbc, hdrNum, hdrBlob, hdrLen);
}

unsigned int pkgdbKey(dbiIndex dbi, dbiCursor dbc)
{
    return dbi->dbi_rpmdb->db_ops->pkgdbKey(dbi, dbc);
}

rpmRC idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int curFlags)
{
    return dbi->dbi_rpmdb->db_ops->idxdbGet(dbi, dbc, keyp, keylen, set, curFlags);
}

rpmRC idxdbPut(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h)
{
    return dbi->dbi_rpmdb->db_ops->idxdbPut(dbi, rpmtag, hdrNum, h);
}

rpmRC idxdbDel(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h)
{
    return dbi->dbi_rpmdb->db_ops->idxdbDel(dbi, rpmtag, hdrNum, h);
}

const void * idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen)
{
    return dbi->dbi_rpmdb->db_ops->idxdbKey(dbi, dbc, keylen);
}