rpm  5.2.1
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 
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:
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 
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 
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:
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,
1606  sql_stat
1607 };
1608 
1609 /*@=evalorderuncon@*/
1610 /*@=modfilesystem@*/
1611 /*@=compmempass@*/
1612 /*@=compdef@*/
1613 /*@=moduncon@*/
1614 /*@=noeffectuncon@*/
1615 /*@=globuse@*/
1616 /*@=paramuse@*/
1617 /*@=mustmod@*/