rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

sqlite.c
Go to the documentation of this file.
1 /*@-mustmod@*/
2 /*@-paramuse@*/
3 /*@-globuse@*/
4 /*@-moduncon@*/
5 /*@-noeffectuncon@*/
6 /*@-compdef@*/
7 /*@-compmempass@*/
8 /*@-modfilesystem@*/
9 /*@-evalorderuncon@*/
10
11 /*
12 * sqlite.c
13 * sqlite interface for rpmdb
14 *
15 * Author: Mark Hatle <mhatle@mvista.com> or <fray@kernel.crashing.org>
16 * Copyright (c) 2004 MontaVista Software, Inc.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * or GNU Library General Public License, at your option,
21 * as published by the Free Software Foundation; either version 2
22 * of the License, or (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * and GNU Library Public License along with this program;
31 * if not, write to the Free Software Foundation, Inc.,
32 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 *
34 */
35
36 #include "system.h"
37
38 #include <rpmio.h>
39 #include <rpmlog.h>
40 #include <rpmmacro.h>
41 #include <rpmurl.h> /* XXX urlPath proto */
42
43 #include <rpmtag.h>
44 #define _RPMDB_INTERNAL
45 #include <rpmdb.h>
46
47 #include <sqlite3.h>
48
49 #include "debug.h"
50
51 #if defined(__LCLINT__)
52 #define UINT32_T u_int32_t
53 #else
54 #define UINT32_T rpmuint32_t
55 #endif
56
57 /*@access rpmdb @*/
58 /*@access dbiIndex @*/
59
60 /* XXX retrofit the *BSD typedef for the deprived. */
61 #if defined(__QNXNTO__)
62 typedef rpmuint32_t u_int32_t;
63 #endif
64
65 /*@unchecked@*/
66 static int _debug = 0;
67
68 /* Define the things normally in a header... */
69 struct _sql_db_s; typedef struct _sql_db_s SQL_DB;
70 struct _sql_dbcursor_s; typedef struct _sql_dbcursor_s *SCP_t;
71
72 struct _sql_db_s {
73 sqlite3 * db; /* Database pointer */
74 int transaction; /* Do we have a transaction open? */
75 };
76
77 struct _sql_dbcursor_s {
78 /*@shared@*/
79 DB *dbp;
80
81 /*@only@*/ /*@relnull@*/
82 char * cmd; /* SQL command string */
83 /*@only@*/ /*@relnull@*/
84 sqlite3_stmt *pStmt; /* SQL byte code */
85 const char * pzErrmsg; /* SQL error msg */
86
87 /* Table -- result of query */
88 /*@only@*/ /*@relnull@*/
89 char ** av; /* item ptrs */
90 /*@only@*/ /*@relnull@*/
91 size_t * avlen; /* item sizes */
92 int nalloc;
93 int ac; /* no. of items */
94 int rx; /* Which row are we on? 1, 2, 3 ... */
95 int nr; /* no. of rows */
96 int nc; /* no. of columns */
97
98 int all; /* sequential iteration cursor */
99 /*@relnull@*/
100 DBT ** keys; /* array of package keys */
101 int nkeys;
102
103 int count;
104
105 /*@null@*/
106 void * lkey; /* Last key returned */
107 /*@null@*/
108 void * ldata; /* Last data returned */
109
110 int used;
111 };
112
113 /*@-redef@*/
114 union _dbswap {
115 rpmuint32_t ui;
116 unsigned char uc[4];
117 };
118 /*@=redef@*/
119
120 #define _DBSWAP(_a) \
121 { unsigned char _b, *_c = (_a).uc; \
122 _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \
123 _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \
124 }
125
126 /*@unchecked@*/
127 static unsigned int endian = 0x11223344;
128
129 /*@unchecked@*/ /*@only@*/ /*@null@*/
130 static const char * sqlCwd = NULL;
131 /*@unchecked@*/
132 static int sqlInRoot = 0;
133
134 static void enterChroot(dbiIndex dbi)
135 /*@globals sqlCwd, sqlInRoot, internalState @*/
136 /*@modifies sqlCwd, sqlInRoot, internalState @*/
137 {
138 char * currDir = NULL;
139 int xx;
140
141 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || sqlInRoot)
142 /* Nothing to do, was not already in chroot */
143 return;
144
145 if (_debug)
146 fprintf(stderr, "sql:chroot(%s)\n", dbi->dbi_root);
147
148 {
149 int currDirLen = 0;
150
151 do {
152 currDirLen += 128;
153 currDir = xrealloc(currDir, currDirLen);
154 memset(currDir, 0, currDirLen);
155 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
156 }
157
158 sqlCwd = currDir;
159 /*@-globs@*/
160 xx = Chdir("/");
161 /*@=globs@*/
162 /*@-modobserver@*/
163 xx = Chroot(dbi->dbi_root);
164 /*@=modobserver@*/
165 assert(xx == 0);
166 sqlInRoot=1;
167 }
168
169 static void leaveChroot(dbiIndex dbi)
170 /*@globals sqlCwd, sqlInRoot, internalState @*/
171 /*@modifies sqlCwd, sqlInRoot, internalState @*/
172 {
173 int xx;
174
175 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || !sqlInRoot)
176 /* Nothing to do, not in chroot */
177 return;
178
179 if (_debug)
180 fprintf(stderr, "sql:chroot(.)\n");
181
182 /*@-modobserver@*/
183 xx = Chroot(".");
184 /*@=modobserver@*/
185 assert(xx == 0);
186 if (sqlCwd != NULL) {
187 /*@-globs@*/
188 xx = Chdir(sqlCwd);
189 /*@=globs@*/
190 sqlCwd = _free(sqlCwd);
191 }
192
193 sqlInRoot = 0;
194 }
195
196 static void dbg_scp(void *ptr)
197 /*@globals stderr, fileSystem @*/
198 /*@modifies stderr, fileSystem @*/
199 {
200 SCP_t scp = ptr;
201
202 if (_debug)
203 fprintf(stderr, "\tscp %p [%d:%d] av %p avlen %p nr [%d:%d] nc %d all %d\n", scp, scp->ac, scp->nalloc, scp->av, scp->avlen, scp->rx, scp->nr, scp->nc, scp->all);
204
205 }
206
207 static void dbg_keyval(const char * msg, dbiIndex dbi, /*@null@*/ DBC * dbcursor,
208 DBT * key, DBT * data, unsigned int flags)
209 /*@globals stderr, fileSystem @*/
210 /*@modifies stderr, fileSystem @*/
211 {
212
213 if (!_debug) return;
214
215 fprintf(stderr, "%s on %s (%p,%p,%p,0x%x)", msg, dbi->dbi_subfile, dbcursor, key, data, flags);
216
217 /* XXX FIXME: ptr alignment is fubar here. */
218 if (key != NULL && key->data != NULL) {
219 fprintf(stderr, " key 0x%x[%d]", *(unsigned int *)key->data, key->size);
220 if (dbi->dbi_rpmtag == RPMTAG_NAME)
221 fprintf(stderr, " \"%s\"", (const char *)key->data);
222 }
223 if (data != NULL && data->data != NULL)
224 fprintf(stderr, " data 0x%x[%d]", *(unsigned int *)data->data, data->size);
225
226 fprintf(stderr, "\n");
227 if (dbcursor != NULL)
228 dbg_scp(dbcursor);
229 }
230
231 /*@only@*/
232 static SCP_t scpResetKeys(/*@only@*/ SCP_t scp)
233 /*@modifies scp @*/
234 {
235 int ix;
236
237 if (_debug)
238 fprintf(stderr, "*** scpResetKeys(%p)\n", scp);
239 dbg_scp(scp);
240
241 for ( ix =0 ; ix < scp->nkeys ; ix++ ) {
242 scp->keys[ix]->data = _free(scp->keys[ix]->data);
243 /*@-unqualifiedtrans@*/
244 scp->keys[ix] = _free(scp->keys[ix]);
245 /*@=unqualifiedtrans@*/
246 }
247 scp->keys = _free(scp->keys);
248 scp->nkeys = 0;
249
250 return scp;
251 }
252
253 /*@only@*/
254 static SCP_t scpResetAv(/*@only@*/ SCP_t scp)
255 /*@modifies scp @*/
256 {
257 int xx;
258
259 if (_debug)
260 fprintf(stderr, "*** scpResetAv(%p)\n", scp);
261 dbg_scp(scp);
262
263 if (scp->av != NULL) {
264 if (scp->nalloc <= 0) {
265 /* Clean up SCP_t used by sqlite3_get_table(). */
266 sqlite3_free_table(scp->av);
267 scp->av = NULL;
268 scp->nalloc = 0;
269 } else {
270 /* Clean up SCP_t used by sql_step(). */
271 /*@-unqualifiedtrans@*/
272 for (xx = 0; xx < scp->ac; xx++)
273 scp->av[xx] = _free(scp->av[xx]);
274 /*@=unqualifiedtrans@*/
275 if (scp->av != NULL)
276 memset(scp->av, 0, scp->nalloc * sizeof(*scp->av));
277 if (scp->avlen != NULL)
278 memset(scp->avlen, 0, scp->nalloc * sizeof(*scp->avlen));
279 scp->av = _free(scp->av);
280 scp->avlen = _free(scp->avlen);
281 scp->nalloc = 0;
282 }
283 } else
284 scp->nalloc = 0;
285 scp->ac = 0;
286 scp->nr = 0;
287 scp->nc = 0;
288
289 return scp;
290 }
291
292 /*@only@*/
293 static SCP_t scpReset(/*@only@*/ SCP_t scp)
294 /*@modifies scp @*/
295 {
296 int xx;
297
298 if (_debug)
299 fprintf(stderr, "*** scpReset(%p)\n", scp);
300 dbg_scp(scp);
301
302 if (scp->cmd) {
303 sqlite3_free(scp->cmd);
304 scp->cmd = NULL;
305 }
306 if (scp->pStmt) {
307 xx = sqlite3_reset(scp->pStmt);
308 if (xx) rpmlog(RPMLOG_WARNING, "reset %d\n", xx);
309 xx = sqlite3_finalize(scp->pStmt);
310 if (xx) rpmlog(RPMLOG_WARNING, "finalize %d\n", xx);
311 scp->pStmt = NULL;
312 }
313
314 scp = scpResetAv(scp);
315
316 scp->rx = 0;
317 return scp;
318 }
319
320 /*@null@*/
321 static SCP_t scpFree(/*@only@*/ SCP_t scp)
322 /*@modifies scp @*/
323 {
324 scp = scpReset(scp);
325 scp = scpResetKeys(scp);
326 scp->av = _free(scp->av);
327 scp->avlen = _free(scp->avlen);
328
329 if (_debug)
330 fprintf(stderr, "*** scpFree(%p)\n", scp);
331 scp = _free(scp);
332 return NULL;
333 }
334
335 static SCP_t scpNew(DB * dbp)
336 /*@*/
337 {
338 SCP_t scp = xcalloc(1, sizeof(*scp));
339 /*@-temptrans@*/
340 scp->dbp = dbp;
341 /*@=temptrans@*/
342
343 scp->used = 0;
344
345 scp->lkey = NULL;
346 scp->ldata = NULL;
347
348 if (_debug)
349 fprintf(stderr, "*** scpNew(%p)\n", scp);
350 return scp;
351 }
352
353 static int sql_step(dbiIndex dbi, SCP_t scp)
354 /*@modifies dbi, scp @*/
355 {
356 int swapped = dbiByteSwapped(dbi);
357 const char * cname;
358 const char * vtype;
359 size_t nb;
360 int loop;
361 int need;
362 int rc;
363 int i;
364
365 scp->nc = sqlite3_column_count(scp->pStmt);
366
367 if (scp->nr == 0 && scp->av != NULL)
368 need = 2 * scp->nc;
369 else
370 need = scp->nc;
371
372 /* XXX scp->nc = need = scp->nalloc = 0 case forces + 1 here */
373 if (!scp->ac && !need && !scp->nalloc)
374 need++;
375
376 if (scp->ac + need >= scp->nalloc) {
377 /* XXX +4 is bogus, was +1 */
378 scp->nalloc = 2 * scp->nalloc + need + 4;
379 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
380 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
381 }
382
383 if (scp->av != NULL && scp->nr == 0) {
384 for (i = 0; i < scp->nc; i++) {
385 scp->av[scp->ac] = xstrdup(sqlite3_column_name(scp->pStmt, i));
386 if (scp->avlen) scp->avlen[scp->ac] = strlen(scp->av[scp->ac]) + 1;
387 scp->ac++;
388 assert(scp->ac <= scp->nalloc);
389 }
390 }
391
392 /*@-infloopsuncon@*/
393 loop = 1;
394 while (loop) {
395 rc = sqlite3_step(scp->pStmt);
396 switch (rc) {
397 case SQLITE_DONE:
398 if (_debug)
399 fprintf(stderr, "sqlite3_step: DONE scp %p [%d:%d] av %p avlen %p\n", scp, scp->ac, scp->nalloc, scp->av, scp->avlen);
400 loop = 0;
401 /*@switchbreak@*/ break;
402 case SQLITE_ROW:
403 if (scp->av != NULL)
404 for (i = 0; i < scp->nc; i++) {
405 /* Expand the row array for new elements */
406 if (scp->ac + need >= scp->nalloc) {
407 /* XXX +4 is bogus, was +1 */
408 scp->nalloc = 2 * scp->nalloc + need + 4;
409 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av));
410 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen));
411 }
412 assert(scp->av != NULL);
413 assert(scp->avlen != NULL);
414
415 cname = sqlite3_column_name(scp->pStmt, i);
416 vtype = sqlite3_column_decltype(scp->pStmt, i);
417 nb = 0;
418
419 if (!strcmp(vtype, "blob")) {
420 const void * v = sqlite3_column_blob(scp->pStmt, i);
421 nb = sqlite3_column_bytes(scp->pStmt, i);
422 if (_debug)
423 fprintf(stderr, "\t%d %s %s %p[%d]\n", i, cname, vtype, v, (int)nb);
424 if (nb > 0) {
425 void * t = xmalloc(nb);
426 scp->av[scp->ac] = memcpy(t, v, nb);
427 scp->avlen[scp->ac] = nb;
428 scp->ac++;
429 }
430 } else
431 if (!strcmp(vtype, "double")) {
432 double v = sqlite3_column_double(scp->pStmt, i);
433 nb = sizeof(v);
434 if (_debug)
435 fprintf(stderr, "\t%d %s %s %g\n", i, cname, vtype, v);
436 if (nb > 0) {
437 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
438 scp->avlen[scp->ac] = nb;
439 assert(swapped == 0); /* Byte swap?! */
440 scp->ac++;
441 }
442 } else
443 if (!strcmp(vtype, "int")) {
444 rpmint32_t v = sqlite3_column_int(scp->pStmt, i);
445 nb = sizeof(v);
446 if (_debug)
447 fprintf(stderr, "\t%d %s %s %d\n", i, cname, vtype, (int) v);
448 if (nb > 0) {
449 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
450 scp->avlen[scp->ac] = nb;
451 if (swapped == 1) {
452 union _dbswap dbswap;
453 memcpy(&dbswap.ui, scp->av[scp->ac], sizeof(dbswap.ui));
454 _DBSWAP(dbswap);
455 memcpy(scp->av[scp->ac], &dbswap.ui, sizeof(dbswap.ui));
456 }
457 scp->ac++;
458 }
459 } else
460 if (!strcmp(vtype, "int64")) {
461 int64_t v = sqlite3_column_int64(scp->pStmt, i);
462 nb = sizeof(v);
463 if (_debug)
464 fprintf(stderr, "\t%d %s %s %ld\n", i, cname, vtype, (long)v);
465 if (nb > 0) {
466 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb);
467 scp->avlen[scp->ac] = nb;
468 assert(swapped == 0); /* Byte swap?! */
469 scp->ac++;
470 }
471 } else
472 if (!strcmp(vtype, "text")) {
473 const char * v = (const char *)sqlite3_column_text(scp->pStmt, i);
474 nb = strlen(v) + 1;
475 if (_debug)
476 fprintf(stderr, "\t%d %s %s \"%s\"\n", i, cname, vtype, v);
477 if (nb > 0) {
478 scp->av[scp->ac] = memcpy(xmalloc(nb), v, nb);
479 scp->avlen[scp->ac] = nb;
480 scp->ac++;
481 }
482 }
483 assert(scp->ac <= scp->nalloc);
484 }
485 scp->nr++;
486 /*@switchbreak@*/ break;
487 case SQLITE_BUSY:
488 fprintf(stderr, "sqlite3_step: BUSY %d\n", rc);
489 /*@switchbreak@*/ break;
490 case SQLITE_ERROR:
491 fprintf(stderr, "sqlite3_step: ERROR %d -- %s\n", rc, scp->cmd);
492 fprintf(stderr, " %s (%d)\n",
493 sqlite3_errmsg(((SQL_DB*)dbi->dbi_db)->db), sqlite3_errcode(((SQL_DB*)dbi->dbi_db)->db));
494 /*@-nullpass@*/
495 fprintf(stderr, " cwd '%s'\n", getcwd(NULL,0));
496 /*@=nullpass@*/
497 loop = 0;
498 /*@switchbreak@*/ break;
499 case SQLITE_MISUSE:
500 fprintf(stderr, "sqlite3_step: MISUSE %d\n", rc);
501 loop = 0;
502 /*@switchbreak@*/ break;
503 default:
504 fprintf(stderr, "sqlite3_step: rc %d\n", rc);
505 loop = 0;
506 /*@switchbreak@*/ break;
507 }
508 }
509 /*@=infloopsuncon@*/
510
511 if (rc == SQLITE_DONE)
512 rc = SQLITE_OK;
513
514 return rc;
515 }
516
517 static int sql_bind_key(dbiIndex dbi, SCP_t scp, int pos, DBT * key)
518 /*@modifies dbi, scp @*/
519 {
520 int swapped = dbiByteSwapped(dbi);
521 int rc = 0;
522 union _dbswap dbswap;
523
524 assert(key->data != NULL);
525 switch (dbi->dbi_rpmtag) {
526 case RPMDBI_PACKAGES:
527 { unsigned int hnum;
528 /*@i@*/ assert(key->size == sizeof(rpmuint32_t));
529 memcpy(&hnum, key->data, sizeof(hnum));
530
531 if (swapped == 1) {
532 memcpy(&dbswap.ui, &hnum, sizeof(dbswap.ui));
533 _DBSWAP(dbswap);
534 memcpy(&hnum, &dbswap.ui, sizeof(dbswap.ui));
535 }
536 rc = sqlite3_bind_int(scp->pStmt, pos, hnum);
537 } break;
538 default:
539 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) {
540 case RPM_BIN_TYPE:
541 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite. */
542 rc = sqlite3_bind_blob(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC);
543 /*@=castfcnptr =nullpass@*/
544 /*@innerbreak@*/ break;
545 case RPM_UINT8_TYPE:
546 { unsigned char i;
547 /*@i@*/ assert(key->size == sizeof(unsigned char));
548 assert(swapped == 0); /* Byte swap?! */
549 memcpy(&i, key->data, sizeof(i));
550 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i);
551 } /*@innerbreak@*/ break;
552 case RPM_UINT16_TYPE:
553 { unsigned short i;
554 /*@i@*/ assert(key->size == sizeof(rpmuint16_t));
555 assert(swapped == 0); /* Byte swap?! */
556 memcpy(&i, key->data, sizeof(i));
557 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i);
558 } /*@innerbreak@*/ break;
559 case RPM_UINT64_TYPE:
560 assert(0); /* borken */
561 /*@innerbreak@*/ break;
562 case RPM_UINT32_TYPE:
563 default:
564 { unsigned int i;
565 /*@i@*/ assert(key->size == sizeof(rpmuint32_t));
566 memcpy(&i, key->data, sizeof(i));
567
568 if (swapped == 1)
569 {
570 memcpy(&dbswap.ui, &i, sizeof(dbswap.ui));
571 _DBSWAP(dbswap);
572 memcpy(&i, &dbswap.ui, sizeof(dbswap.ui));
573 }
574 rc = sqlite3_bind_int(scp->pStmt, pos, i);
575 } /*@innerbreak@*/ break;
576 case RPM_STRING_TYPE:
577 case RPM_STRING_ARRAY_TYPE:
578 case RPM_I18NSTRING_TYPE:
579 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite. */
580 rc = sqlite3_bind_text(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC);
581 /*@=castfcnptr =nullpass@*/
582 /*@innerbreak@*/ break;
583 }
584 }
585
586 return rc;
587 }
588
589 static int sql_bind_data(/*@unused@*/ dbiIndex dbi, SCP_t scp,
590 int pos, DBT * data)
591 /*@modifies scp @*/
592 {
593 int rc;
594
595 assert(data->data != NULL);
596 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite */
597 rc = sqlite3_bind_blob(scp->pStmt, pos, data->data, data->size, SQLITE_STATIC);
598 /*@=castfcnptr =nullpass@*/
599
600 return rc;
601 }
602
603 /*===================================================================*/
604 /*
605 * Transaction support
606 */
607
608 static int sql_startTransaction(dbiIndex dbi)
609 /*@*/
610 {
611 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
612 int rc = 0;
613
614 /* XXX: Transaction Support */
615 if (!sqldb->transaction) {
616 char * pzErrmsg;
617 rc = sqlite3_exec(sqldb->db, "BEGIN TRANSACTION;", NULL, NULL, &pzErrmsg);
618
619 if (_debug)
620 fprintf(stderr, "Begin %s SQL transaction %s (%d)\n",
621 dbi->dbi_subfile, pzErrmsg, rc);
622
623 if (rc == 0)
624 sqldb->transaction = 1;
625 }
626
627 return rc;
628 }
629
630 static int sql_endTransaction(dbiIndex dbi)
631 /*@*/
632 {
633 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
634 int rc=0;
635
636 /* XXX: Transaction Support */
637 if (sqldb->transaction) {
638 char * pzErrmsg;
639 rc = sqlite3_exec(sqldb->db, "END TRANSACTION;", NULL, NULL, &pzErrmsg);
640
641 if (_debug)
642 fprintf(stderr, "End %s SQL transaction %s (%d)\n",
643 dbi->dbi_subfile, pzErrmsg, rc);
644
645 if (rc == 0)
646 sqldb->transaction = 0;
647 }
648
649 return rc;
650 }
651
652 static int sql_commitTransaction(dbiIndex dbi, int flag)
653 /*@*/
654 {
655 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
656 int rc = 0;
657
658 /* XXX: Transactions */
659 if ( sqldb->transaction ) {
660 char * pzErrmsg;
661 rc = sqlite3_exec(sqldb->db, "COMMIT;", NULL, NULL, &pzErrmsg);
662
663 if (_debug)
664 fprintf(stderr, "Commit %s SQL transaction(s) %s (%d)\n",
665 dbi->dbi_subfile, pzErrmsg, rc);
666
667 sqldb->transaction=0;
668
669 /* Start a new transaction if we were in the middle of one */
670 if ( flag == 0 )
671 rc = sql_startTransaction(dbi);
672 }
673
674 return rc;
675 }
676
677 static int sql_busy_handler(void * dbi_void, int time)
678 /*@*/
679 {
680 /*@-castexpose@*/
681 dbiIndex dbi = (dbiIndex) dbi_void;
682 /*@=castexpose@*/
683
684 rpmlog(RPMLOG_WARNING, _("Unable to get lock on db %s, retrying... (%d)\n"),
685 dbi->dbi_file, time);
686
687 (void) sleep(1);
688
689 return 1;
690 }
691
692 /*===================================================================*/
693
699 static int sql_initDB(dbiIndex dbi)
700 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
701 /*@modifies internalState @*/
702 {
703 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
704 SCP_t scp = scpNew(dbi->dbi_db);
705 char cmd[BUFSIZ];
706 int rc = 0;
707
708 if (dbi->dbi_tmpdir) {
709 const char *root;
710 const char *tmpdir;
711 int xx;
712 root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root);
713 if ((root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone)
714 root = NULL;
715 /*@-mods@*/
716 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
717 /*@=mods@*/
718 sprintf(cmd, "PRAGMA temp_store_directory = '%s';", tmpdir);
719 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
720 tmpdir = _free(tmpdir);
721 }
722 if (dbi->dbi_eflags & DB_EXCL) {
723 int xx;
724 sprintf(cmd, "PRAGMA locking_mode = EXCLUSIVE;");
725 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
726 }
727 if (dbi->dbi_pagesize > 0) {
728 int xx;
729 sprintf(cmd, "PRAGMA cache_size = %d;", dbi->dbi_cachesize);
730 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
731 }
732 if (dbi->dbi_cachesize > 0) {
733 int xx;
734 sprintf(cmd, "PRAGMA page_size = %d;", dbi->dbi_pagesize);
735 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
736 }
737
738 /* Check if the table exists... */
739 sprintf(cmd,
740 "SELECT name FROM 'sqlite_master' WHERE type='table' and name='%s';",
741 dbi->dbi_subfile);
742 /*@-nullstate@*/
743 rc = sqlite3_get_table(sqldb->db, cmd,
744 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
745 /*@=nullstate@*/
746 if (rc)
747 goto exit;
748
749 if (scp->nr < 1) {
750 const char * valtype = "blob";
751 const char * keytype;
752
753 switch (dbi->dbi_rpmtag) {
754 case RPMDBI_PACKAGES:
755 keytype = "int UNIQUE PRIMARY KEY";
756 valtype = "blob";
757 break;
758 default:
759 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) {
760 case RPM_BIN_TYPE:
761 default:
762 keytype = "blob UNIQUE";
763 /*@innerbreak@*/ break;
764 case RPM_UINT8_TYPE:
765 case RPM_UINT16_TYPE:
766 case RPM_UINT32_TYPE:
767 case RPM_UINT64_TYPE:
768 keytype = "int UNIQUE";
769 /*@innerbreak@*/ break;
770 case RPM_STRING_TYPE:
771 case RPM_STRING_ARRAY_TYPE:
772 case RPM_I18NSTRING_TYPE:
773 keytype = "text UNIQUE";
774 /*@innerbreak@*/ break;
775 }
776 }
777 if (_debug)
778 fprintf(stderr, "\t%s(%d) type(%d) keytype %s\n", tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), keytype);
779 sprintf(cmd, "CREATE %sTABLE '%s' (key %s, value %s)",
780 dbi->dbi_temporary ? "TEMPORARY " : "",
781 dbi->dbi_subfile, keytype, valtype);
782 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
783 if (rc)
784 goto exit;
785
786 sprintf(cmd, "CREATE %sTABLE 'db_info' (endian TEXT)",
787 dbi->dbi_temporary ? "TEMPORARY " : "");
788 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
789 if (rc)
790 goto exit;
791
792 sprintf(cmd, "INSERT INTO 'db_info' values('%u')", (unsigned)((union _dbswap *)&endian)->uc[0]);
793 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
794 if (rc)
795 goto exit;
796 }
797
798 if (dbi->dbi_no_fsync) {
799 int xx;
800 sprintf(cmd, "PRAGMA synchronous = OFF;");
801 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg);
802 }
803
804 exit:
805 if (rc)
806 rpmlog(RPMLOG_WARNING, "Unable to initDB %s (%d)\n",
807 scp->pzErrmsg, rc);
808
809 scp = scpFree(scp);
810
811 return rc;
812 }
813
821 static int sql_cclose (dbiIndex dbi, /*@only@*/ DBC * dbcursor,
822 unsigned int flags)
823 /*@globals fileSystem, internalState @*/
824 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
825 {
826 SCP_t scp = (SCP_t)dbcursor;
827 int rc;
828
829 if (_debug)
830 fprintf(stderr, "==> sql_cclose(%p)\n", scp);
831
832 if (scp->lkey)
833 scp->lkey = _free(scp->lkey);
834
835 if (scp->ldata)
836 scp->ldata = _free(scp->ldata);
837
838 enterChroot(dbi);
839
840 if (flags == DB_WRITECURSOR)
841 rc = sql_commitTransaction(dbi, 1);
842 else
843 rc = sql_endTransaction(dbi);
844
845 /*@-kepttrans -nullstate@*/
846 scp = scpFree(scp);
847 /*@=kepttrans =nullstate@*/
848
849 leaveChroot(dbi);
850
851 return rc;
852 }
853
860 static int sql_close(/*@only@*/ dbiIndex dbi, unsigned int flags)
861 /*@globals fileSystem, internalState @*/
862 /*@modifies dbi, fileSystem, internalState @*/
863 {
864 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
865 int rc = 0;
866
867 if (sqldb) {
868 enterChroot(dbi);
869
870 /* Commit, don't open a new one */
871 rc = sql_commitTransaction(dbi, 1);
872
873 (void) sqlite3_close(sqldb->db);
874
875 rpmlog(RPMLOG_DEBUG, D_("closed sql db %s\n"),
876 dbi->dbi_subfile);
877
878 #if defined(MAYBE) /* XXX should SQLite and BDB have different semantics? */
879 if (dbi->dbi_temporary && !(dbi->dbi_eflags & DB_PRIVATE)) {
880 const char * dbhome = NULL;
881 urltype ut = urlPath(dbi->dbi_home, &dbhome);
882 const char * dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
883 int xx = (dbfname ? Unlink(dbfname) : 0);
884 ut = ut; xx = xx; /* XXX tell gcc to be quiet. */
885 dbfname = _free(dbfname);
886 }
887 #endif
888
889 dbi->dbi_stats = _free(dbi->dbi_stats);
890 dbi->dbi_file = _free(dbi->dbi_file);
891 dbi->dbi_db = _free(dbi->dbi_db);
892
893 leaveChroot(dbi);
894 }
895
896 dbi = _free(dbi);
897
898 return rc;
899 }
900
908 static int sql_open(rpmdb rpmdb, rpmTag rpmtag, /*@out@*/ dbiIndex * dbip)
909 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
910 /*@modifies *dbip, rpmGlobalMacroContext, fileSystem, internalState @*/
911 {
912 /*@-nestedextern -shadow @*/
913 extern struct _dbiVec sqlitevec;
914 /*@=nestedextern -shadow @*/
915
916 const char * urlfn = NULL;
917 const char * root;
918 const char * home;
919 const char * dbhome;
920 const char * dbfile;
921 const char * dbfname;
922 const char * sql_errcode;
923 mode_t umask_safed = 0002;
924 dbiIndex dbi;
925 SQL_DB * sqldb;
926 size_t len;
927 int rc = 0;
928 int xx;
929
930 if (dbip)
931 *dbip = NULL;
932
933 /*
934 * Parse db configuration parameters.
935 */
936 /*@-mods@*/
937 if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
938 /*@-nullstate@*/
939 return 1;
940 /*@=nullstate@*/
941 /*@=mods@*/
942
943 /*
944 * Get the prefix/root component and directory path
945 */
946 root = rpmdb->db_root;
947 home = rpmdb->db_home;
948
949 dbi->dbi_root = root;
950 dbi->dbi_home = home;
951
952 dbfile = tagName(dbi->dbi_rpmtag);
953
954 enterChroot(dbi);
955
956 /*
957 * Make a copy of the tagName result..
958 * use this for the filename and table name
959 */
960 {
961 char * t;
962 len = strlen(dbfile);
963 t = xcalloc(len + 1, sizeof(*t));
964 (void) stpcpy( t, dbfile );
965 dbi->dbi_file = t;
966 /*@-kepttrans@*/ /* WRONG */
967 dbi->dbi_subfile = t;
968 /*@=kepttrans@*/
969 }
970
971 dbi->dbi_mode = O_RDWR;
972
973 /*
974 * Either the root or directory components may be a URL. Concatenate,
975 * convert the URL to a path, and add the name of the file.
976 */
977 /*@-mods@*/
978 urlfn = rpmGenPath(NULL, home, NULL);
979 /*@=mods@*/
980 (void) urlPath(urlfn, &dbhome);
981
982 /*
983 * Create the /var/lib/rpm directory if it doesn't exist (root only).
984 */
985 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
986
987 if (dbi->dbi_eflags & DB_PRIVATE)
988 dbfname = xstrdup(":memory:");
989 else
990 dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL);
991
992 rpmlog(RPMLOG_DEBUG, D_("opening sql db %s (%s) mode=0x%x\n"),
993 dbfname, dbi->dbi_subfile, dbi->dbi_mode);
994
995 /* Open the Database */
996 sqldb = xcalloc(1, sizeof(*sqldb));
997
998 sql_errcode = NULL;
999 /*@+longunsignedintegral@*/
1000 if (dbi->dbi_perms)
1001 /* mask-out permission bits which are not requested (security) */
1002 umask_safed = umask(~((mode_t)(dbi->dbi_perms)));
1003 /*@=longunsignedintegral@*/
1004 xx = sqlite3_open(dbfname, &sqldb->db);
1005 if (dbi->dbi_perms) {
1006 if ((0644 /* = SQLite hard-coded default */ & dbi->dbi_perms) != dbi->dbi_perms) {
1007 /* add requested permission bits which are still missing (semantic) */
1008 (void) Chmod(dbfname, dbi->dbi_perms);
1009 }
1010 /*@+longunsignedintegral@*/
1011 (void) umask(umask_safed);
1012 /*@=longunsignedintegral@*/
1013 }
1014 if (xx != SQLITE_OK)
1015 sql_errcode = sqlite3_errmsg(sqldb->db);
1016
1017 if (sqldb->db)
1018 (void) sqlite3_busy_handler(sqldb->db, &sql_busy_handler, dbi);
1019
1020 sqldb->transaction = 0; /* Initialize no current transactions */
1021
1022 dbi->dbi_db = (DB *)sqldb;
1023
1024 if (sql_errcode != NULL) {
1025 rpmlog(RPMLOG_DEBUG, D_("Unable to open database: %s\n"), sql_errcode);
1026 rc = EINVAL;
1027 }
1028
1029 /* initialize table */
1030 if (rc == 0)
1031 rc = sql_initDB(dbi);
1032
1033 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
1034 dbi->dbi_vec = &sqlitevec;
1035 *dbip = dbi;
1036 } else {
1037 (void) sql_close(dbi, 0);
1038 }
1039
1040 urlfn = _free(urlfn);
1041 dbfname = _free(dbfname);
1042
1043 /*@-usereleased@*/
1044 leaveChroot(dbi);
1045 /*@=usereleased@*/
1046
1047 return rc;
1048 }
1049
1056 static int sql_sync (dbiIndex dbi, /*@unused@*/ unsigned int flags)
1057 /*@globals fileSystem, internalState @*/
1058 /*@modifies fileSystem, internalState @*/
1059 {
1060 int rc = 0;
1061
1062 enterChroot(dbi);
1063 rc = sql_commitTransaction(dbi, 0);
1064 leaveChroot(dbi);
1065
1066 return rc;
1067 }
1068
1077 static int sql_copen (dbiIndex dbi,
1078 /*@unused@*/ /*@null@*/ DB_TXN * txnid,
1079 /*@out@*/ DBC ** dbcp, unsigned int flags)
1080 /*@globals fileSystem, internalState @*/
1081 /*@modifies dbi, *txnid, *dbcp, fileSystem, internalState @*/
1082 {
1083 SCP_t scp = scpNew(dbi->dbi_db);
1084 DBC * dbcursor = (DBC *)scp;
1085 int rc = 0;
1086
1087 if (_debug)
1088 fprintf(stderr, "==> sql_copen(%s) tag %d type %d scp %p\n", tagName(dbi->dbi_rpmtag), dbi->dbi_rpmtag, (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE), scp);
1089
1090 enterChroot(dbi);
1091
1092 /* If we're going to write, start a transaction (lock the DB) */
1093 if (flags == DB_WRITECURSOR)
1094 rc = sql_startTransaction(dbi);
1095
1096 if (dbcp)
1097 /*@-onlytrans@*/ *dbcp = dbcursor; /*@=onlytrans@*/
1098 else
1099 /*@-kepttrans -nullstate @*/ (void) sql_cclose(dbi, dbcursor, 0); /*@=kepttrans =nullstate @*/
1100
1101 leaveChroot(dbi);
1102
1103 return rc;
1104 }
1105
1115 static int sql_cdel (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1116 DBT * data, unsigned int flags)
1117 /*@globals fileSystem, internalState @*/
1118 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
1119 {
1120 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
1121 SCP_t scp = scpNew(dbi->dbi_db);
1122 int rc = 0;
1123
1124 dbg_keyval("sql_cdel", dbi, dbcursor, key, data, flags);
1125 enterChroot(dbi);
1126
1127 scp->cmd = sqlite3_mprintf("DELETE FROM '%q' WHERE key=? AND value=?;",
1128 dbi->dbi_subfile);
1129
1130 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
1131 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1132 rc = sql_bind_key(dbi, scp, 1, key);
1133 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind key %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1134 rc = sql_bind_data(dbi, scp, 2, data);
1135 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind data %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1136
1137 rc = sql_step(dbi, scp);
1138 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1139
1140 scp = scpFree(scp);
1141
1142 leaveChroot(dbi);
1143
1144 return rc;
1145 }
1146
1156 static int sql_cget (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1157 DBT * data, unsigned int flags)
1158 /*@globals fileSystem, internalState @*/
1159 /*@modifies dbi, dbcursor, *key, *data, fileSystem, internalState @*/
1160 {
1161 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
1162 SCP_t scp = (SCP_t)dbcursor;
1163 int rc = 0;
1164 int ix;
1165
1166 assert(dbcursor != NULL);
1167 dbg_keyval("sql_cget", dbi, dbcursor, key, data, flags);
1168
1169 enterChroot(dbi);
1170
1171 /*
1172 * First determine if this is a new scan or existing scan
1173 */
1174
1175 if (_debug)
1176 fprintf(stderr, "\tcget(%s) scp %p rc %d flags %d av %p\n",
1177 dbi->dbi_subfile, scp, rc, flags, scp->av);
1178 if ( flags == DB_SET || scp->used == 0 ) {
1179 scp->used = 1; /* Signal this scp as now in use... */
1180 /*@i@*/ scp = scpReset(scp); /* Free av and avlen, reset counters.*/
1181
1182 /* XXX: Should we also reset the key table here? Can you re-use a cursor? */
1183
1184 /*
1185 * If we're scanning everything, load the iterator key table
1186 */
1187 if ( key->size == 0) {
1188 scp->all = 1;
1189
1190 /*
1191 * The only condition not dealt with is if there are multiple identical keys. This can lead
1192 * to later iteration confusion. (It may return the same value for the multiple keys.)
1193 */
1194
1195 #ifdef DYING
1196 /* Only RPMDBI_PACKAGES is supposed to be iterating, and this is guarenteed to be unique */
1197 assert(dbi->dbi_rpmtag == RPMDBI_PACKAGES);
1198 #endif
1199
1200 switch (dbi->dbi_rpmtag) {
1201 case RPMDBI_PACKAGES:
1202 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q' ORDER BY key;",
1203 dbi->dbi_subfile);
1204 break;
1205 default:
1206 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q';",
1207 dbi->dbi_subfile);
1208 break;
1209 }
1210 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
1211 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1212
1213 rc = sql_step(dbi, scp);
1214 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential sql_step rc %d\n", dbi->dbi_subfile, rc);
1215
1216 scp = scpResetKeys(scp);
1217 scp->nkeys = scp->nr;
1218 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys));
1219 for (ix = 0; ix < scp->nkeys; ix++) {
1220 scp->keys[ix] = xmalloc(sizeof(*scp->keys[0]));
1221 scp->keys[ix]->size = (UINT32_T) scp->avlen[ix+1];
1222 scp->keys[ix]->data = xmalloc(scp->keys[ix]->size);
1223 memcpy(scp->keys[ix]->data, scp->av[ix+1], scp->avlen[ix+1]);
1224 }
1225 } else {
1226 /*
1227 * We're only scanning ONE element
1228 */
1229 scp = scpResetKeys(scp);
1230 scp->nkeys = 1;
1231 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys));
1232 scp->keys[0] = xmalloc(sizeof(*scp->keys[0]));
1233 scp->keys[0]->size = key->size;
1234 scp->keys[0]->data = xmalloc(scp->keys[0]->size);
1235 memcpy(scp->keys[0]->data, key->data, key->size);
1236 }
1237
1238 /*@i@*/ scp = scpReset(scp); /* reset */
1239
1240 /* Prepare SQL statement to retrieve the value for the current key */
1241 scp->cmd = sqlite3_mprintf("SELECT value FROM '%q' WHERE key=?;", dbi->dbi_subfile);
1242 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
1243
1244 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1245 }
1246
1247 /*@i@*/ scp = scpResetAv(scp); /* Free av and avlen, reset counters.*/
1248
1249 /* Now continue with a normal retrive based on key */
1250 if ((scp->rx + 1) > scp->nkeys )
1251 rc = DB_NOTFOUND; /* At the end of the list */
1252
1253 if (rc != 0)
1254 goto exit;
1255
1256 /* Bind key to prepared statement */
1257 rc = sql_bind_key(dbi, scp, 1, scp->keys[scp->rx]);
1258 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1259
1260 rc = sql_step(dbi, scp);
1261 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1262
1263 rc = sqlite3_reset(scp->pStmt);
1264 if (rc) rpmlog(RPMLOG_WARNING, "reset %d\n", rc);
1265
1266 /* 1 key should return 0 or 1 row/value */
1267 assert(scp->nr < 2);
1268
1269 if (scp->nr == 0 && scp->all == 0)
1270 rc = DB_NOTFOUND; /* No data for that key found! */
1271
1272 if (rc != 0)
1273 goto exit;
1274
1275 /* If we're looking at the whole db, return the key */
1276 if (scp->all) {
1277
1278 /* To get this far there has to be _1_ key returned! (protect against dup keys) */
1279 assert(scp->nr == 1);
1280
1281 if ( scp->lkey ) {
1282 scp->lkey = _free(scp->lkey);
1283 }
1284
1285 key->size = scp->keys[scp->rx]->size;
1286 key->data = xmalloc(key->size);
1287 if (! (key->flags & DB_DBT_MALLOC))
1288 scp->lkey = key->data;
1289
1290 (void) memcpy(key->data, scp->keys[scp->rx]->data, key->size);
1291 }
1292
1293 /* Construct and return the data element (element 0 is "value", 1 is _THE_ value)*/
1294 switch (dbi->dbi_rpmtag) {
1295 default:
1296 if ( scp->ldata ) {
1297 scp->ldata = _free(scp->ldata);
1298 }
1299
1300 data->size = (UINT32_T) scp->avlen[1];
1301 data->data = xmalloc(data->size);
1302 if (! (data->flags & DB_DBT_MALLOC) )
1303 scp->ldata = data->data;
1304
1305 (void) memcpy(data->data, scp->av[1], data->size);
1306 }
1307
1308 scp->rx++;
1309
1310 /* XXX FIXME: ptr alignment is fubar here. */
1311 if (_debug)
1312 fprintf(stderr, "\tcget(%s) found key 0x%x (%d)\n", dbi->dbi_subfile,
1313 key->data == NULL ? 0 : *(unsigned int *)key->data, key->size);
1314 if (_debug)
1315 fprintf(stderr, "\tcget(%s) found data 0x%x (%d)\n", dbi->dbi_subfile,
1316 key->data == NULL ? 0 : *(unsigned int *)data->data, data->size);
1317
1318 exit:
1319 if (rc == DB_NOTFOUND) {
1320 if (_debug)
1321 fprintf(stderr, "\tcget(%s) not found\n", dbi->dbi_subfile);
1322 }
1323
1324 leaveChroot(dbi);
1325
1326 return rc;
1327 }
1328
1338 static int sql_cput (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key,
1339 DBT * data, unsigned int flags)
1340 /*@globals fileSystem, internalState @*/
1341 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/
1342 {
1343 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
1344 SCP_t scp = scpNew(dbi->dbi_db);
1345 int rc = 0;
1346
1347 dbg_keyval("sql_cput", dbi, dbcursor, key, data, flags);
1348
1349 enterChroot(dbi);
1350
1351 switch (dbi->dbi_rpmtag) {
1352 default:
1353 scp->cmd = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' VALUES(?, ?);",
1354 dbi->dbi_subfile);
1355 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg);
1356 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) prepare %s (%d)\n",dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1357 rc = sql_bind_key(dbi, scp, 1, key);
1358 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1359 rc = sql_bind_data(dbi, scp, 2, data);
1360 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) data bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc);
1361
1362 rc = sql_step(dbi, scp);
1363 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) sql_step rc %d\n", dbi->dbi_subfile, rc);
1364
1365 break;
1366 }
1367
1368 scp = scpFree(scp);
1369
1370 leaveChroot(dbi);
1371
1372 return rc;
1373 }
1374
1380 static int sql_byteswapped (dbiIndex dbi)
1381 /*@globals fileSystem, internalState @*/
1382 /*@modifies fileSystem, internalState @*/
1383 {
1384 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
1385 SCP_t scp = scpNew(dbi->dbi_db);
1386 int sql_rc, rc = 0;
1387 union _dbswap db_endian;
1388
1389 enterChroot(dbi);
1390
1391 /*@-nullstate@*/
1392 sql_rc = sqlite3_get_table(sqldb->db, "SELECT endian FROM 'db_info';",
1393 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
1394 /*@=nullstate@*/
1395
1396 if (sql_rc == 0 && scp->nr > 0) {
1397 assert(scp->av != NULL);
1398 db_endian.uc[0] = (unsigned char) strtol(scp->av[1], NULL, 10);
1399
1400 if ( db_endian.uc[0] == ((union _dbswap *)&endian)->uc[0] )
1401 rc = 0; /* Native endian */
1402 else
1403 rc = 1; /* swapped */
1404
1405 } else {
1406 if ( sql_rc ) {
1407 rpmlog(RPMLOG_DEBUG, D_("db_info failed %s (%d)\n"),
1408 scp->pzErrmsg, sql_rc);
1409 }
1410 rpmlog(RPMLOG_WARNING, "Unable to determine DB endian.\n");
1411 }
1412
1413 scp = scpFree(scp);
1414
1415 leaveChroot(dbi);
1416
1417 return rc;
1418 }
1419
1420 /**************************************************
1421 *
1422 * All of the following are not implemented!
1423 * they are not used by the rest of the system
1424 *
1425 **************************************************/
1426
1435 static int sql_associate (/*@unused@*/ dbiIndex dbi,
1436 /*@unused@*/ dbiIndex dbisecondary,
1437 /*@unused@*/int (*callback) (DB *, const DBT *, const DBT *, DBT *),
1438 /*@unused@*/ unsigned int flags)
1439 /*@*/
1440 {
1441 if (_debug)
1442 fprintf(stderr, "*** sql_associate:\n");
1443 return EINVAL;
1444 }
1445
1454 static int sql_join (/*@unused@*/ dbiIndex dbi,
1455 /*@unused@*/ DBC ** curslist,
1456 /*@unused@*/ /*@out@*/ DBC ** dbcp,
1457 /*@unused@*/ unsigned int flags)
1458 /*@globals fileSystem @*/
1459 /*@modifies dbi, *dbcp, fileSystem @*/
1460 {
1461 if (_debug)
1462 fprintf(stderr, "*** sql_join:\n");
1463 return EINVAL;
1464 }
1465
1474 static int sql_cdup (/*@unused@*/ dbiIndex dbi,
1475 /*@unused@*/ DBC * dbcursor,
1476 /*@unused@*/ /*@out@*/ DBC ** dbcp,
1477 /*@unused@*/ unsigned int flags)
1478 /*@globals fileSystem @*/
1479 /*@modifies dbi, *dbcp, fileSystem @*/
1480 {
1481 if (_debug)
1482 fprintf(stderr, "*** sql_cdup:\n");
1483 return EINVAL;
1484 }
1485
1496 static int sql_cpget (/*@unused@*/ dbiIndex dbi,
1497 /*@unused@*/ /*@null@*/ DBC * dbcursor,
1498 /*@unused@*/ DBT * key,
1499 /*@unused@*/ DBT * pkey,
1500 /*@unused@*/ DBT * data,
1501 /*@unused@*/ unsigned int flags)
1502 /*@globals fileSystem @*/
1503 /*@modifies *dbcursor, *key, *pkey, *data, fileSystem @*/
1504 {
1505 if (_debug)
1506 fprintf(stderr, "*** sql_cpget:\n");
1507 return EINVAL;
1508 }
1509
1518 static int sql_ccount (/*@unused@*/ dbiIndex dbi,
1519 /*@unused@*/ DBC * dbcursor,
1520 /*@unused@*/ /*@out@*/ unsigned int * countp,
1521 /*@unused@*/ unsigned int flags)
1522 /*@globals fileSystem @*/
1523 /*@modifies *dbcursor, fileSystem @*/
1524 {
1525 if (_debug)
1526 fprintf(stderr, "*** sql_ccount:\n");
1527 return EINVAL;
1528 }
1529
1536 static int sql_stat (dbiIndex dbi, /*@unused@*/ unsigned int flags)
1537 /*@globals fileSystem, internalState @*/
1538 /*@modifies dbi, fileSystem, internalState @*/
1539 {
1540 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db;
1541 SCP_t scp = scpNew(dbi->dbi_db);
1542 int rc = 0;
1543 long nkeys = -1;
1544
1545 enterChroot(dbi);
1546
1547 dbi->dbi_stats = _free(dbi->dbi_stats);
1548
1549 /*@-sizeoftype@*/
1550 dbi->dbi_stats = xcalloc(1, sizeof(DB_HASH_STAT));
1551 /*@=sizeoftype@*/
1552
1553 scp->cmd = sqlite3_mprintf("SELECT COUNT('key') FROM '%q';", dbi->dbi_subfile);
1554 /*@-nullstate@*/
1555 rc = sqlite3_get_table(sqldb->db, scp->cmd,
1556 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg);
1557 /*@=nullstate@*/
1558
1559 if ( rc == 0 && scp->nr > 0) {
1560 assert(scp->av != NULL);
1561 nkeys = strtol(scp->av[1], NULL, 10);
1562
1563 rpmlog(RPMLOG_DEBUG, D_(" stat on %s nkeys %ld\n"),
1564 dbi->dbi_subfile, nkeys);
1565 } else {
1566 if ( rc ) {
1567 rpmlog(RPMLOG_DEBUG, D_("stat failed %s (%d)\n"),
1568 scp->pzErrmsg, rc);
1569 }
1570 }
1571
1572 if (nkeys < 0)
1573 nkeys = 4096; /* Good high value */
1574
1575 ((DB_HASH_STAT *)(dbi->dbi_stats))->hash_nkeys = nkeys;
1576
1577 scp = scpFree(scp);
1578
1579 leaveChroot(dbi);
1580
1581 return rc;
1582 }
1583
1584 /* Major, minor, patch version of DB.. we're not using db.. so set to 0 */
1585 /* open, close, sync, associate, join */
1586 /* cursor_open, cursor_close, cursor_dup, cursor_delete, cursor_get, */
1587 /* cursor_pget?, cursor_put, cursor_count */
1588 /* db_bytewapped, stat */
1589 /*@observer@*/ /*@unchecked@*/
1590 struct _dbiVec sqlitevec = {
1591 0, 0, 0,
1592 sql_open,
1593 sql_close,
1594 sql_sync,
1595 sql_associate,
1596 sql_join,
1597 sql_copen,
1598 sql_cclose,
1599 sql_cdup,
1600 sql_cdel,
1601 sql_cget,
1602 sql_cpget,
1603 sql_cput,
1604 sql_ccount,
1605 sql_byteswapped,
1606 sql_stat
1607 };
1608
1609 /*@=evalorderuncon@*/
1610 /*@=modfilesystem@*/
1611 /*@=compmempass@*/
1612 /*@=compdef@*/
1613 /*@=moduncon@*/
1614 /*@=noeffectuncon@*/
1615 /*@=globuse@*/
1616 /*@=paramuse@*/
1617 /*@=mustmod@*/