rpm 5.3.7
|
00001 /*@-mustmod@*/ 00002 /*@-paramuse@*/ 00003 /*@-globuse@*/ 00004 /*@-moduncon@*/ 00005 /*@-noeffectuncon@*/ 00006 /*@-compdef@*/ 00007 /*@-compmempass@*/ 00008 /*@-modfilesystem@*/ 00009 /*@-evalorderuncon@*/ 00010 00011 /* 00012 * sqlite.c 00013 * sqlite interface for rpmdb 00014 * 00015 * Author: Mark Hatle <mhatle@mvista.com> or <fray@kernel.crashing.org> 00016 * Copyright (c) 2004 MontaVista Software, Inc. 00017 * 00018 * This program is free software; you can redistribute it and/or 00019 * modify it under the terms of the GNU General Public License 00020 * or GNU Library General Public License, at your option, 00021 * as published by the Free Software Foundation; either version 2 00022 * of the License, or (at your option) any later version. 00023 * 00024 * This program is distributed in the hope that it will be useful, 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00027 * GNU General Public License for more details. 00028 * 00029 * You should have received a copy of the GNU General Public License 00030 * and GNU Library Public License along with this program; 00031 * if not, write to the Free Software Foundation, Inc., 00032 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00033 * 00034 */ 00035 00036 #include "system.h" 00037 00038 #include <rpmio.h> 00039 #include <rpmlog.h> 00040 #include <rpmmacro.h> 00041 #include <rpmurl.h> /* XXX urlPath proto */ 00042 00043 #include <rpmtag.h> 00044 #define _RPMDB_INTERNAL 00045 #include <rpmdb.h> 00046 00047 #include <sqlite3.h> 00048 00049 #include "debug.h" 00050 00051 #if defined(__LCLINT__) 00052 #define UINT32_T u_int32_t 00053 #else 00054 #define UINT32_T rpmuint32_t 00055 #endif 00056 00057 /*@access rpmdb @*/ 00058 /*@access dbiIndex @*/ 00059 00060 /* XXX retrofit the *BSD typedef for the deprived. */ 00061 #if defined(__QNXNTO__) 00062 typedef rpmuint32_t u_int32_t; 00063 #endif 00064 00065 /*@unchecked@*/ 00066 static int _debug = 0; 00067 00068 /* Define the things normally in a header... */ 00069 struct _sql_db_s; typedef struct _sql_db_s SQL_DB; 00070 struct _sql_dbcursor_s; typedef struct _sql_dbcursor_s *SCP_t; 00071 00072 struct _sql_db_s { 00073 sqlite3 * db; /* Database pointer */ 00074 int transaction; /* Do we have a transaction open? */ 00075 }; 00076 00077 struct _sql_dbcursor_s { 00078 /*@shared@*/ 00079 DB *dbp; 00080 00081 /*@only@*/ /*@relnull@*/ 00082 char * cmd; /* SQL command string */ 00083 /*@only@*/ /*@relnull@*/ 00084 sqlite3_stmt *pStmt; /* SQL byte code */ 00085 const char * pzErrmsg; /* SQL error msg */ 00086 00087 /* Table -- result of query */ 00088 /*@only@*/ /*@relnull@*/ 00089 char ** av; /* item ptrs */ 00090 /*@only@*/ /*@relnull@*/ 00091 size_t * avlen; /* item sizes */ 00092 int nalloc; 00093 int ac; /* no. of items */ 00094 int rx; /* Which row are we on? 1, 2, 3 ... */ 00095 int nr; /* no. of rows */ 00096 int nc; /* no. of columns */ 00097 00098 int all; /* sequential iteration cursor */ 00099 /*@relnull@*/ 00100 DBT ** keys; /* array of package keys */ 00101 int nkeys; 00102 00103 int count; 00104 00105 /*@null@*/ 00106 void * lkey; /* Last key returned */ 00107 /*@null@*/ 00108 void * ldata; /* Last data returned */ 00109 00110 int used; 00111 }; 00112 00113 /*@-redef@*/ 00114 union _dbswap { 00115 rpmuint32_t ui; 00116 unsigned char uc[4]; 00117 }; 00118 /*@=redef@*/ 00119 00120 #define _DBSWAP(_a) \ 00121 { unsigned char _b, *_c = (_a).uc; \ 00122 _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \ 00123 _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \ 00124 } 00125 00126 /*@unchecked@*/ 00127 static unsigned int endian = 0x11223344; 00128 00129 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00130 static const char * sqlCwd = NULL; 00131 /*@unchecked@*/ 00132 static int sqlInRoot = 0; 00133 00134 static void enterChroot(dbiIndex dbi) 00135 /*@globals sqlCwd, sqlInRoot, internalState @*/ 00136 /*@modifies sqlCwd, sqlInRoot, internalState @*/ 00137 { 00138 char * currDir = NULL; 00139 int xx; 00140 00141 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || sqlInRoot) 00142 /* Nothing to do, was not already in chroot */ 00143 return; 00144 00145 if (_debug) 00146 fprintf(stderr, "sql:chroot(%s)\n", dbi->dbi_root); 00147 00148 { 00149 int currDirLen = 0; 00150 00151 do { 00152 currDirLen += 128; 00153 currDir = xrealloc(currDir, currDirLen); 00154 memset(currDir, 0, currDirLen); 00155 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE); 00156 } 00157 00158 sqlCwd = currDir; 00159 /*@-globs@*/ 00160 xx = Chdir("/"); 00161 /*@=globs@*/ 00162 /*@-modobserver@*/ 00163 xx = Chroot(dbi->dbi_root); 00164 /*@=modobserver@*/ 00165 assert(xx == 0); 00166 sqlInRoot=1; 00167 } 00168 00169 static void leaveChroot(dbiIndex dbi) 00170 /*@globals sqlCwd, sqlInRoot, internalState @*/ 00171 /*@modifies sqlCwd, sqlInRoot, internalState @*/ 00172 { 00173 int xx; 00174 00175 if ((dbi->dbi_root[0] == '/' && dbi->dbi_root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone || !sqlInRoot) 00176 /* Nothing to do, not in chroot */ 00177 return; 00178 00179 if (_debug) 00180 fprintf(stderr, "sql:chroot(.)\n"); 00181 00182 /*@-modobserver@*/ 00183 xx = Chroot("."); 00184 /*@=modobserver@*/ 00185 assert(xx == 0); 00186 if (sqlCwd != NULL) { 00187 /*@-globs@*/ 00188 xx = Chdir(sqlCwd); 00189 /*@=globs@*/ 00190 sqlCwd = _free(sqlCwd); 00191 } 00192 00193 sqlInRoot = 0; 00194 } 00195 00196 static void dbg_scp(void *ptr) 00197 /*@globals stderr, fileSystem @*/ 00198 /*@modifies stderr, fileSystem @*/ 00199 { 00200 SCP_t scp = ptr; 00201 00202 if (_debug) 00203 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); 00204 00205 } 00206 00207 static void dbg_keyval(const char * msg, dbiIndex dbi, /*@null@*/ DBC * dbcursor, 00208 DBT * key, DBT * data, unsigned int flags) 00209 /*@globals stderr, fileSystem @*/ 00210 /*@modifies stderr, fileSystem @*/ 00211 { 00212 00213 if (!_debug) return; 00214 00215 fprintf(stderr, "%s on %s (%p,%p,%p,0x%x)", msg, dbi->dbi_subfile, dbcursor, key, data, flags); 00216 00217 /* XXX FIXME: ptr alignment is fubar here. */ 00218 if (key != NULL && key->data != NULL) { 00219 fprintf(stderr, " key 0x%x[%d]", *(unsigned int *)key->data, key->size); 00220 if (dbi->dbi_rpmtag == RPMTAG_NAME) 00221 fprintf(stderr, " \"%s\"", (const char *)key->data); 00222 } 00223 if (data != NULL && data->data != NULL) 00224 fprintf(stderr, " data 0x%x[%d]", *(unsigned int *)data->data, data->size); 00225 00226 fprintf(stderr, "\n"); 00227 if (dbcursor != NULL) 00228 dbg_scp(dbcursor); 00229 } 00230 00231 /*@only@*/ 00232 static SCP_t scpResetKeys(/*@only@*/ SCP_t scp) 00233 /*@modifies scp @*/ 00234 { 00235 int ix; 00236 00237 if (_debug) 00238 fprintf(stderr, "*** scpResetKeys(%p)\n", scp); 00239 dbg_scp(scp); 00240 00241 for ( ix =0 ; ix < scp->nkeys ; ix++ ) { 00242 scp->keys[ix]->data = _free(scp->keys[ix]->data); 00243 /*@-unqualifiedtrans@*/ 00244 scp->keys[ix] = _free(scp->keys[ix]); 00245 /*@=unqualifiedtrans@*/ 00246 } 00247 scp->keys = _free(scp->keys); 00248 scp->nkeys = 0; 00249 00250 return scp; 00251 } 00252 00253 /*@only@*/ 00254 static SCP_t scpResetAv(/*@only@*/ SCP_t scp) 00255 /*@modifies scp @*/ 00256 { 00257 int xx; 00258 00259 if (_debug) 00260 fprintf(stderr, "*** scpResetAv(%p)\n", scp); 00261 dbg_scp(scp); 00262 00263 if (scp->av != NULL) { 00264 if (scp->nalloc <= 0) { 00265 /* Clean up SCP_t used by sqlite3_get_table(). */ 00266 sqlite3_free_table(scp->av); 00267 scp->av = NULL; 00268 scp->nalloc = 0; 00269 } else { 00270 /* Clean up SCP_t used by sql_step(). */ 00271 /*@-unqualifiedtrans@*/ 00272 for (xx = 0; xx < scp->ac; xx++) 00273 scp->av[xx] = _free(scp->av[xx]); 00274 /*@=unqualifiedtrans@*/ 00275 if (scp->av != NULL) 00276 memset(scp->av, 0, scp->nalloc * sizeof(*scp->av)); 00277 if (scp->avlen != NULL) 00278 memset(scp->avlen, 0, scp->nalloc * sizeof(*scp->avlen)); 00279 scp->av = _free(scp->av); 00280 scp->avlen = _free(scp->avlen); 00281 scp->nalloc = 0; 00282 } 00283 } else 00284 scp->nalloc = 0; 00285 scp->ac = 0; 00286 scp->nr = 0; 00287 scp->nc = 0; 00288 00289 return scp; 00290 } 00291 00292 /*@only@*/ 00293 static SCP_t scpReset(/*@only@*/ SCP_t scp) 00294 /*@modifies scp @*/ 00295 { 00296 int xx; 00297 00298 if (_debug) 00299 fprintf(stderr, "*** scpReset(%p)\n", scp); 00300 dbg_scp(scp); 00301 00302 if (scp->cmd) { 00303 sqlite3_free(scp->cmd); 00304 scp->cmd = NULL; 00305 } 00306 if (scp->pStmt) { 00307 xx = sqlite3_reset(scp->pStmt); 00308 if (xx) rpmlog(RPMLOG_WARNING, "reset %d\n", xx); 00309 xx = sqlite3_finalize(scp->pStmt); 00310 if (xx) rpmlog(RPMLOG_WARNING, "finalize %d\n", xx); 00311 scp->pStmt = NULL; 00312 } 00313 00314 scp = scpResetAv(scp); 00315 00316 scp->rx = 0; 00317 return scp; 00318 } 00319 00320 /*@null@*/ 00321 static SCP_t scpFree(/*@only@*/ SCP_t scp) 00322 /*@modifies scp @*/ 00323 { 00324 scp = scpReset(scp); 00325 scp = scpResetKeys(scp); 00326 scp->av = _free(scp->av); 00327 scp->avlen = _free(scp->avlen); 00328 00329 if (_debug) 00330 fprintf(stderr, "*** scpFree(%p)\n", scp); 00331 scp = _free(scp); 00332 return NULL; 00333 } 00334 00335 static SCP_t scpNew(DB * dbp) 00336 /*@*/ 00337 { 00338 SCP_t scp = xcalloc(1, sizeof(*scp)); 00339 /*@-temptrans@*/ 00340 scp->dbp = dbp; 00341 /*@=temptrans@*/ 00342 00343 scp->used = 0; 00344 00345 scp->lkey = NULL; 00346 scp->ldata = NULL; 00347 00348 if (_debug) 00349 fprintf(stderr, "*** scpNew(%p)\n", scp); 00350 return scp; 00351 } 00352 00353 static int sql_step(dbiIndex dbi, SCP_t scp) 00354 /*@modifies dbi, scp @*/ 00355 { 00356 int swapped = dbiByteSwapped(dbi); 00357 const char * cname; 00358 const char * vtype; 00359 size_t nb; 00360 int loop; 00361 int need; 00362 int rc; 00363 int i; 00364 00365 scp->nc = sqlite3_column_count(scp->pStmt); 00366 00367 if (scp->nr == 0 && scp->av != NULL) 00368 need = 2 * scp->nc; 00369 else 00370 need = scp->nc; 00371 00372 /* XXX scp->nc = need = scp->nalloc = 0 case forces + 1 here */ 00373 if (!scp->ac && !need && !scp->nalloc) 00374 need++; 00375 00376 if (scp->ac + need >= scp->nalloc) { 00377 /* XXX +4 is bogus, was +1 */ 00378 scp->nalloc = 2 * scp->nalloc + need + 4; 00379 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av)); 00380 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen)); 00381 } 00382 00383 if (scp->av != NULL && scp->nr == 0) { 00384 for (i = 0; i < scp->nc; i++) { 00385 scp->av[scp->ac] = xstrdup(sqlite3_column_name(scp->pStmt, i)); 00386 if (scp->avlen) scp->avlen[scp->ac] = strlen(scp->av[scp->ac]) + 1; 00387 scp->ac++; 00388 assert(scp->ac <= scp->nalloc); 00389 } 00390 } 00391 00392 /*@-infloopsuncon@*/ 00393 loop = 1; 00394 while (loop) { 00395 rc = sqlite3_step(scp->pStmt); 00396 switch (rc) { 00397 case SQLITE_DONE: 00398 if (_debug) 00399 fprintf(stderr, "sqlite3_step: DONE scp %p [%d:%d] av %p avlen %p\n", scp, scp->ac, scp->nalloc, scp->av, scp->avlen); 00400 loop = 0; 00401 /*@switchbreak@*/ break; 00402 case SQLITE_ROW: 00403 if (scp->av != NULL) 00404 for (i = 0; i < scp->nc; i++) { 00405 /* Expand the row array for new elements */ 00406 if (scp->ac + need >= scp->nalloc) { 00407 /* XXX +4 is bogus, was +1 */ 00408 scp->nalloc = 2 * scp->nalloc + need + 4; 00409 scp->av = xrealloc(scp->av, scp->nalloc * sizeof(*scp->av)); 00410 scp->avlen = xrealloc(scp->avlen, scp->nalloc * sizeof(*scp->avlen)); 00411 } 00412 assert(scp->av != NULL); 00413 assert(scp->avlen != NULL); 00414 00415 cname = sqlite3_column_name(scp->pStmt, i); 00416 vtype = sqlite3_column_decltype(scp->pStmt, i); 00417 nb = 0; 00418 00419 if (!strcmp(vtype, "blob")) { 00420 const void * v = sqlite3_column_blob(scp->pStmt, i); 00421 nb = sqlite3_column_bytes(scp->pStmt, i); 00422 if (_debug) 00423 fprintf(stderr, "\t%d %s %s %p[%d]\n", i, cname, vtype, v, (int)nb); 00424 if (nb > 0) { 00425 void * t = xmalloc(nb); 00426 scp->av[scp->ac] = memcpy(t, v, nb); 00427 scp->avlen[scp->ac] = nb; 00428 scp->ac++; 00429 } 00430 } else 00431 if (!strcmp(vtype, "double")) { 00432 double v = sqlite3_column_double(scp->pStmt, i); 00433 nb = sizeof(v); 00434 if (_debug) 00435 fprintf(stderr, "\t%d %s %s %g\n", i, cname, vtype, v); 00436 if (nb > 0) { 00437 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb); 00438 scp->avlen[scp->ac] = nb; 00439 assert(swapped == 0); /* Byte swap?! */ 00440 scp->ac++; 00441 } 00442 } else 00443 if (!strcmp(vtype, "int")) { 00444 rpmint32_t v = sqlite3_column_int(scp->pStmt, i); 00445 nb = sizeof(v); 00446 if (_debug) 00447 fprintf(stderr, "\t%d %s %s %d\n", i, cname, vtype, (int) v); 00448 if (nb > 0) { 00449 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb); 00450 scp->avlen[scp->ac] = nb; 00451 if (swapped == 1) { 00452 union _dbswap dbswap; 00453 memcpy(&dbswap.ui, scp->av[scp->ac], sizeof(dbswap.ui)); 00454 _DBSWAP(dbswap); 00455 memcpy(scp->av[scp->ac], &dbswap.ui, sizeof(dbswap.ui)); 00456 } 00457 scp->ac++; 00458 } 00459 } else 00460 if (!strcmp(vtype, "int64")) { 00461 int64_t v = sqlite3_column_int64(scp->pStmt, i); 00462 nb = sizeof(v); 00463 if (_debug) 00464 fprintf(stderr, "\t%d %s %s %ld\n", i, cname, vtype, (long)v); 00465 if (nb > 0) { 00466 scp->av[scp->ac] = memcpy(xmalloc(nb), &v, nb); 00467 scp->avlen[scp->ac] = nb; 00468 assert(swapped == 0); /* Byte swap?! */ 00469 scp->ac++; 00470 } 00471 } else 00472 if (!strcmp(vtype, "text")) { 00473 const char * v = (const char *)sqlite3_column_text(scp->pStmt, i); 00474 nb = strlen(v) + 1; 00475 if (_debug) 00476 fprintf(stderr, "\t%d %s %s \"%s\"\n", i, cname, vtype, v); 00477 if (nb > 0) { 00478 scp->av[scp->ac] = memcpy(xmalloc(nb), v, nb); 00479 scp->avlen[scp->ac] = nb; 00480 scp->ac++; 00481 } 00482 } 00483 assert(scp->ac <= scp->nalloc); 00484 } 00485 scp->nr++; 00486 /*@switchbreak@*/ break; 00487 case SQLITE_BUSY: 00488 fprintf(stderr, "sqlite3_step: BUSY %d\n", rc); 00489 /*@switchbreak@*/ break; 00490 case SQLITE_ERROR: 00491 fprintf(stderr, "sqlite3_step: ERROR %d -- %s\n", rc, scp->cmd); 00492 fprintf(stderr, " %s (%d)\n", 00493 sqlite3_errmsg(((SQL_DB*)dbi->dbi_db)->db), sqlite3_errcode(((SQL_DB*)dbi->dbi_db)->db)); 00494 /*@-nullpass@*/ 00495 fprintf(stderr, " cwd '%s'\n", getcwd(NULL,0)); 00496 /*@=nullpass@*/ 00497 loop = 0; 00498 /*@switchbreak@*/ break; 00499 case SQLITE_MISUSE: 00500 fprintf(stderr, "sqlite3_step: MISUSE %d\n", rc); 00501 loop = 0; 00502 /*@switchbreak@*/ break; 00503 default: 00504 fprintf(stderr, "sqlite3_step: rc %d\n", rc); 00505 loop = 0; 00506 /*@switchbreak@*/ break; 00507 } 00508 } 00509 /*@=infloopsuncon@*/ 00510 00511 if (rc == SQLITE_DONE) 00512 rc = SQLITE_OK; 00513 00514 return rc; 00515 } 00516 00517 static int sql_bind_key(dbiIndex dbi, SCP_t scp, int pos, DBT * key) 00518 /*@modifies dbi, scp @*/ 00519 { 00520 int swapped = dbiByteSwapped(dbi); 00521 int rc = 0; 00522 union _dbswap dbswap; 00523 00524 assert(key->data != NULL); 00525 switch (dbi->dbi_rpmtag) { 00526 case RPMDBI_PACKAGES: 00527 { unsigned int hnum; 00528 /*@i@*/ assert(key->size == sizeof(rpmuint32_t)); 00529 memcpy(&hnum, key->data, sizeof(hnum)); 00530 00531 if (swapped == 1) { 00532 memcpy(&dbswap.ui, &hnum, sizeof(dbswap.ui)); 00533 _DBSWAP(dbswap); 00534 memcpy(&hnum, &dbswap.ui, sizeof(dbswap.ui)); 00535 } 00536 rc = sqlite3_bind_int(scp->pStmt, pos, hnum); 00537 } break; 00538 default: 00539 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) { 00540 case RPM_BIN_TYPE: 00541 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite. */ 00542 rc = sqlite3_bind_blob(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC); 00543 /*@=castfcnptr =nullpass@*/ 00544 /*@innerbreak@*/ break; 00545 case RPM_UINT8_TYPE: 00546 { unsigned char i; 00547 /*@i@*/ assert(key->size == sizeof(unsigned char)); 00548 assert(swapped == 0); /* Byte swap?! */ 00549 memcpy(&i, key->data, sizeof(i)); 00550 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i); 00551 } /*@innerbreak@*/ break; 00552 case RPM_UINT16_TYPE: 00553 { unsigned short i; 00554 /*@i@*/ assert(key->size == sizeof(rpmuint16_t)); 00555 assert(swapped == 0); /* Byte swap?! */ 00556 memcpy(&i, key->data, sizeof(i)); 00557 rc = sqlite3_bind_int(scp->pStmt, pos, (int) i); 00558 } /*@innerbreak@*/ break; 00559 case RPM_UINT64_TYPE: 00560 assert(0); /* borken */ 00561 /*@innerbreak@*/ break; 00562 case RPM_UINT32_TYPE: 00563 default: 00564 { unsigned int i; 00565 /*@i@*/ assert(key->size == sizeof(rpmuint32_t)); 00566 memcpy(&i, key->data, sizeof(i)); 00567 00568 if (swapped == 1) 00569 { 00570 memcpy(&dbswap.ui, &i, sizeof(dbswap.ui)); 00571 _DBSWAP(dbswap); 00572 memcpy(&i, &dbswap.ui, sizeof(dbswap.ui)); 00573 } 00574 rc = sqlite3_bind_int(scp->pStmt, pos, i); 00575 } /*@innerbreak@*/ break; 00576 case RPM_STRING_TYPE: 00577 case RPM_STRING_ARRAY_TYPE: 00578 case RPM_I18NSTRING_TYPE: 00579 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite. */ 00580 rc = sqlite3_bind_text(scp->pStmt, pos, key->data, key->size, SQLITE_STATIC); 00581 /*@=castfcnptr =nullpass@*/ 00582 /*@innerbreak@*/ break; 00583 } 00584 } 00585 00586 return rc; 00587 } 00588 00589 static int sql_bind_data(/*@unused@*/ dbiIndex dbi, SCP_t scp, 00590 int pos, DBT * data) 00591 /*@modifies scp @*/ 00592 { 00593 int rc; 00594 00595 assert(data->data != NULL); 00596 /*@-castfcnptr -nullpass@*/ /* FIX: annotate sqlite */ 00597 rc = sqlite3_bind_blob(scp->pStmt, pos, data->data, data->size, SQLITE_STATIC); 00598 /*@=castfcnptr =nullpass@*/ 00599 00600 return rc; 00601 } 00602 00603 /*===================================================================*/ 00604 /* 00605 * Transaction support 00606 */ 00607 00608 static int sql_startTransaction(dbiIndex dbi) 00609 /*@*/ 00610 { 00611 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 00612 int rc = 0; 00613 00614 /* XXX: Transaction Support */ 00615 if (!sqldb->transaction) { 00616 char * pzErrmsg; 00617 rc = sqlite3_exec(sqldb->db, "BEGIN TRANSACTION;", NULL, NULL, &pzErrmsg); 00618 00619 if (_debug) 00620 fprintf(stderr, "Begin %s SQL transaction %s (%d)\n", 00621 dbi->dbi_subfile, pzErrmsg, rc); 00622 00623 if (rc == 0) 00624 sqldb->transaction = 1; 00625 } 00626 00627 return rc; 00628 } 00629 00630 static int sql_endTransaction(dbiIndex dbi) 00631 /*@*/ 00632 { 00633 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 00634 int rc=0; 00635 00636 /* XXX: Transaction Support */ 00637 if (sqldb->transaction) { 00638 char * pzErrmsg; 00639 rc = sqlite3_exec(sqldb->db, "END TRANSACTION;", NULL, NULL, &pzErrmsg); 00640 00641 if (_debug) 00642 fprintf(stderr, "End %s SQL transaction %s (%d)\n", 00643 dbi->dbi_subfile, pzErrmsg, rc); 00644 00645 if (rc == 0) 00646 sqldb->transaction = 0; 00647 } 00648 00649 return rc; 00650 } 00651 00652 static int sql_commitTransaction(dbiIndex dbi, int flag) 00653 /*@*/ 00654 { 00655 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 00656 int rc = 0; 00657 00658 /* XXX: Transactions */ 00659 if ( sqldb->transaction ) { 00660 char * pzErrmsg; 00661 rc = sqlite3_exec(sqldb->db, "COMMIT;", NULL, NULL, &pzErrmsg); 00662 00663 if (_debug) 00664 fprintf(stderr, "Commit %s SQL transaction(s) %s (%d)\n", 00665 dbi->dbi_subfile, pzErrmsg, rc); 00666 00667 sqldb->transaction=0; 00668 00669 /* Start a new transaction if we were in the middle of one */ 00670 if ( flag == 0 ) 00671 rc = sql_startTransaction(dbi); 00672 } 00673 00674 return rc; 00675 } 00676 00677 static int sql_busy_handler(void * dbi_void, int time) 00678 /*@*/ 00679 { 00680 /*@-castexpose@*/ 00681 dbiIndex dbi = (dbiIndex) dbi_void; 00682 /*@=castexpose@*/ 00683 00684 rpmlog(RPMLOG_WARNING, _("Unable to get lock on db %s, retrying... (%d)\n"), 00685 dbi->dbi_file, time); 00686 00687 (void) sleep(1); 00688 00689 return 1; 00690 } 00691 00692 /*===================================================================*/ 00693 00699 static int sql_initDB(dbiIndex dbi) 00700 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00701 /*@modifies internalState @*/ 00702 { 00703 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 00704 SCP_t scp = scpNew(dbi->dbi_db); 00705 char cmd[BUFSIZ]; 00706 int rc = 0; 00707 00708 if (dbi->dbi_tmpdir) { 00709 const char *root; 00710 const char *tmpdir; 00711 int xx; 00712 root = (dbi->dbi_root ? dbi->dbi_root : dbi->dbi_rpmdb->db_root); 00713 if ((root[0] == '/' && root[1] == '\0') || dbi->dbi_rpmdb->db_chrootDone) 00714 root = NULL; 00715 /*@-mods@*/ 00716 tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL); 00717 /*@=mods@*/ 00718 sprintf(cmd, "PRAGMA temp_store_directory = '%s';", tmpdir); 00719 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00720 tmpdir = _free(tmpdir); 00721 } 00722 if (dbi->dbi_eflags & DB_EXCL) { 00723 int xx; 00724 sprintf(cmd, "PRAGMA locking_mode = EXCLUSIVE;"); 00725 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00726 } 00727 #ifdef DYING 00728 if (dbi->dbi_pagesize > 0) { 00729 int xx; 00730 sprintf(cmd, "PRAGMA cache_size = %d;", dbi->dbi_cachesize); 00731 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00732 } 00733 if (dbi->dbi_cachesize > 0) { 00734 int xx; 00735 sprintf(cmd, "PRAGMA page_size = %d;", dbi->dbi_pagesize); 00736 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00737 } 00738 #endif 00739 00740 /* Check if the table exists... */ 00741 sprintf(cmd, 00742 "SELECT name FROM 'sqlite_master' WHERE type='table' and name='%s';", 00743 dbi->dbi_subfile); 00744 /*@-nullstate@*/ 00745 rc = sqlite3_get_table(sqldb->db, cmd, 00746 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg); 00747 /*@=nullstate@*/ 00748 if (rc) 00749 goto exit; 00750 00751 if (scp->nr < 1) { 00752 const char * valtype = "blob"; 00753 const char * keytype; 00754 00755 switch (dbi->dbi_rpmtag) { 00756 case RPMDBI_PACKAGES: 00757 keytype = "int UNIQUE PRIMARY KEY"; 00758 valtype = "blob"; 00759 break; 00760 default: 00761 switch (tagType(dbi->dbi_rpmtag) & RPM_MASK_TYPE) { 00762 case RPM_BIN_TYPE: 00763 default: 00764 keytype = "blob UNIQUE"; 00765 /*@innerbreak@*/ break; 00766 case RPM_UINT8_TYPE: 00767 case RPM_UINT16_TYPE: 00768 case RPM_UINT32_TYPE: 00769 case RPM_UINT64_TYPE: 00770 keytype = "int UNIQUE"; 00771 /*@innerbreak@*/ break; 00772 case RPM_STRING_TYPE: 00773 case RPM_STRING_ARRAY_TYPE: 00774 case RPM_I18NSTRING_TYPE: 00775 keytype = "text UNIQUE"; 00776 /*@innerbreak@*/ break; 00777 } 00778 } 00779 if (_debug) 00780 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); 00781 sprintf(cmd, "CREATE %sTABLE '%s' (key %s, value %s)", 00782 dbi->dbi_temporary ? "TEMPORARY " : "", 00783 dbi->dbi_subfile, keytype, valtype); 00784 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00785 if (rc) 00786 goto exit; 00787 00788 sprintf(cmd, "CREATE %sTABLE 'db_info' (endian TEXT)", 00789 dbi->dbi_temporary ? "TEMPORARY " : ""); 00790 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00791 if (rc) 00792 goto exit; 00793 00794 sprintf(cmd, "INSERT INTO 'db_info' values('%u')", (unsigned)((union _dbswap *)&endian)->uc[0]); 00795 rc = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00796 if (rc) 00797 goto exit; 00798 } 00799 00800 if (dbi->dbi_no_fsync) { 00801 int xx; 00802 sprintf(cmd, "PRAGMA synchronous = OFF;"); 00803 xx = sqlite3_exec(sqldb->db, cmd, NULL, NULL, (char **)&scp->pzErrmsg); 00804 } 00805 00806 exit: 00807 if (rc) 00808 rpmlog(RPMLOG_WARNING, "Unable to initDB %s (%d)\n", 00809 scp->pzErrmsg, rc); 00810 00811 scp = scpFree(scp); 00812 00813 return rc; 00814 } 00815 00823 static int sql_cclose (dbiIndex dbi, /*@only@*/ DBC * dbcursor, 00824 unsigned int flags) 00825 /*@globals fileSystem, internalState @*/ 00826 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/ 00827 { 00828 SCP_t scp = (SCP_t)dbcursor; 00829 int rc; 00830 00831 if (_debug) 00832 fprintf(stderr, "==> sql_cclose(%p)\n", scp); 00833 00834 if (scp->lkey) 00835 scp->lkey = _free(scp->lkey); 00836 00837 if (scp->ldata) 00838 scp->ldata = _free(scp->ldata); 00839 00840 enterChroot(dbi); 00841 00842 if (flags == DB_WRITECURSOR) 00843 rc = sql_commitTransaction(dbi, 1); 00844 else 00845 rc = sql_endTransaction(dbi); 00846 00847 /*@-kepttrans -nullstate@*/ 00848 scp = scpFree(scp); 00849 /*@=kepttrans =nullstate@*/ 00850 00851 leaveChroot(dbi); 00852 00853 return rc; 00854 } 00855 00862 static int sql_close(/*@only@*/ dbiIndex dbi, unsigned int flags) 00863 /*@globals fileSystem, internalState @*/ 00864 /*@modifies dbi, fileSystem, internalState @*/ 00865 { 00866 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 00867 int rc = 0; 00868 00869 if (sqldb) { 00870 enterChroot(dbi); 00871 00872 /* Commit, don't open a new one */ 00873 rc = sql_commitTransaction(dbi, 1); 00874 00875 (void) sqlite3_close(sqldb->db); 00876 00877 rpmlog(RPMLOG_DEBUG, D_("closed sql db %s\n"), 00878 dbi->dbi_subfile); 00879 00880 #if defined(MAYBE) /* XXX should SQLite and BDB have different semantics? */ 00881 if (dbi->dbi_temporary && !(dbi->dbi_eflags & DB_PRIVATE)) { 00882 const char * dbhome = NULL; 00883 urltype ut = urlPath(dbi->dbi_home, &dbhome); 00884 const char * dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL); 00885 int xx = (dbfname ? Unlink(dbfname) : 0); 00886 ut = ut; xx = xx; /* XXX tell gcc to be quiet. */ 00887 dbfname = _free(dbfname); 00888 } 00889 #endif 00890 00891 dbi->dbi_stats = _free(dbi->dbi_stats); 00892 dbi->dbi_file = _free(dbi->dbi_file); 00893 dbi->dbi_db = _free(dbi->dbi_db); 00894 00895 leaveChroot(dbi); 00896 } 00897 00898 dbi = _free(dbi); 00899 00900 return rc; 00901 } 00902 00910 static int sql_open(rpmdb rpmdb, rpmTag rpmtag, /*@out@*/ dbiIndex * dbip) 00911 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ 00912 /*@modifies *dbip, rpmGlobalMacroContext, fileSystem, internalState @*/ 00913 { 00914 /*@-nestedextern -shadow @*/ 00915 extern struct _dbiVec sqlitevec; 00916 /*@=nestedextern -shadow @*/ 00917 00918 const char * urlfn = NULL; 00919 const char * root; 00920 const char * home; 00921 const char * dbhome; 00922 const char * dbfile; 00923 const char * dbfname; 00924 const char * sql_errcode; 00925 mode_t umask_safed = 0002; 00926 dbiIndex dbi; 00927 SQL_DB * sqldb; 00928 size_t len; 00929 int rc = 0; 00930 int xx; 00931 00932 if (dbip) 00933 *dbip = NULL; 00934 00935 /* 00936 * Parse db configuration parameters. 00937 */ 00938 /*@-mods@*/ 00939 if ((dbi = db3New(rpmdb, rpmtag)) == NULL) 00940 /*@-nullstate@*/ 00941 return 1; 00942 /*@=nullstate@*/ 00943 /*@=mods@*/ 00944 00945 /* 00946 * Get the prefix/root component and directory path 00947 */ 00948 root = rpmdb->db_root; 00949 home = rpmdb->db_home; 00950 00951 dbi->dbi_root = root; 00952 dbi->dbi_home = home; 00953 00954 dbfile = tagName(dbi->dbi_rpmtag); 00955 00956 enterChroot(dbi); 00957 00958 /* 00959 * Make a copy of the tagName result.. 00960 * use this for the filename and table name 00961 */ 00962 { 00963 char * t; 00964 len = strlen(dbfile); 00965 t = xcalloc(len + 1, sizeof(*t)); 00966 (void) stpcpy( t, dbfile ); 00967 dbi->dbi_file = t; 00968 /*@-kepttrans@*/ /* WRONG */ 00969 dbi->dbi_subfile = t; 00970 /*@=kepttrans@*/ 00971 } 00972 00973 dbi->dbi_mode = O_RDWR; 00974 00975 /* 00976 * Either the root or directory components may be a URL. Concatenate, 00977 * convert the URL to a path, and add the name of the file. 00978 */ 00979 /*@-mods@*/ 00980 urlfn = rpmGenPath(NULL, home, NULL); 00981 /*@=mods@*/ 00982 (void) urlPath(urlfn, &dbhome); 00983 00984 /* 00985 * Create the /var/lib/rpm directory if it doesn't exist (root only). 00986 */ 00987 (void) rpmioMkpath(dbhome, 0755, getuid(), getgid()); 00988 00989 if (dbi->dbi_eflags & DB_PRIVATE) 00990 dbfname = xstrdup(":memory:"); 00991 else 00992 dbfname = rpmGenPath(dbhome, dbi->dbi_file, NULL); 00993 00994 rpmlog(RPMLOG_DEBUG, D_("opening sql db %s (%s) mode=0x%x\n"), 00995 dbfname, dbi->dbi_subfile, dbi->dbi_mode); 00996 00997 /* Open the Database */ 00998 sqldb = xcalloc(1, sizeof(*sqldb)); 00999 01000 sql_errcode = NULL; 01001 /*@+longunsignedintegral@*/ 01002 if (dbi->dbi_perms) 01003 /* mask-out permission bits which are not requested (security) */ 01004 umask_safed = umask(~((mode_t)(dbi->dbi_perms))); 01005 /*@=longunsignedintegral@*/ 01006 xx = sqlite3_open(dbfname, &sqldb->db); 01007 if (dbi->dbi_perms) { 01008 if ((0644 /* = SQLite hard-coded default */ & dbi->dbi_perms) != dbi->dbi_perms) { 01009 /* add requested permission bits which are still missing (semantic) */ 01010 (void) Chmod(dbfname, dbi->dbi_perms); 01011 } 01012 /*@+longunsignedintegral@*/ 01013 (void) umask(umask_safed); 01014 /*@=longunsignedintegral@*/ 01015 } 01016 if (xx != SQLITE_OK) 01017 sql_errcode = sqlite3_errmsg(sqldb->db); 01018 01019 if (sqldb->db) 01020 (void) sqlite3_busy_handler(sqldb->db, &sql_busy_handler, dbi); 01021 01022 sqldb->transaction = 0; /* Initialize no current transactions */ 01023 01024 dbi->dbi_db = (DB *)sqldb; 01025 01026 if (sql_errcode != NULL) { 01027 rpmlog(RPMLOG_DEBUG, D_("Unable to open database: %s\n"), sql_errcode); 01028 rc = EINVAL; 01029 } 01030 01031 /* initialize table */ 01032 if (rc == 0) 01033 rc = sql_initDB(dbi); 01034 01035 if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { 01036 dbi->dbi_vec = &sqlitevec; 01037 *dbip = dbi; 01038 } else { 01039 (void) sql_close(dbi, 0); 01040 } 01041 01042 urlfn = _free(urlfn); 01043 dbfname = _free(dbfname); 01044 01045 /*@-usereleased@*/ 01046 leaveChroot(dbi); 01047 /*@=usereleased@*/ 01048 01049 return rc; 01050 } 01051 01058 static int sql_sync (dbiIndex dbi, /*@unused@*/ unsigned int flags) 01059 /*@globals fileSystem, internalState @*/ 01060 /*@modifies fileSystem, internalState @*/ 01061 { 01062 int rc = 0; 01063 01064 enterChroot(dbi); 01065 rc = sql_commitTransaction(dbi, 0); 01066 leaveChroot(dbi); 01067 01068 return rc; 01069 } 01070 01078 static int sql_exists(dbiIndex dbi, DBT * key, unsigned int flags) 01079 /*@globals fileSystem @*/ 01080 /*@modifies fileSystem @*/ 01081 { 01082 if (_debug) 01083 fprintf(stderr, "*** sql_exists:\n"); 01084 return EINVAL; 01085 } 01086 01094 static int sql_seqno(dbiIndex dbi, int64_t * seqnop, unsigned int flags) 01095 { 01096 if (_debug) 01097 fprintf(stderr, "*** sql_seqno:\n"); 01098 return EINVAL; 01099 } 01100 01109 static int sql_copen (dbiIndex dbi, 01110 /*@unused@*/ /*@null@*/ DB_TXN * txnid, 01111 /*@out@*/ DBC ** dbcp, unsigned int flags) 01112 /*@globals fileSystem, internalState @*/ 01113 /*@modifies dbi, *txnid, *dbcp, fileSystem, internalState @*/ 01114 { 01115 SCP_t scp = scpNew(dbi->dbi_db); 01116 DBC * dbcursor = (DBC *)scp; 01117 int rc = 0; 01118 01119 if (_debug) 01120 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); 01121 01122 enterChroot(dbi); 01123 01124 /* If we're going to write, start a transaction (lock the DB) */ 01125 if (flags == DB_WRITECURSOR) 01126 rc = sql_startTransaction(dbi); 01127 01128 if (dbcp) 01129 /*@-onlytrans@*/ *dbcp = dbcursor; /*@=onlytrans@*/ 01130 else 01131 /*@-kepttrans -nullstate @*/ (void) sql_cclose(dbi, dbcursor, 0); /*@=kepttrans =nullstate @*/ 01132 01133 leaveChroot(dbi); 01134 01135 return rc; 01136 } 01137 01147 static int sql_cdel (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, 01148 DBT * data, unsigned int flags) 01149 /*@globals fileSystem, internalState @*/ 01150 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/ 01151 { 01152 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 01153 SCP_t scp = scpNew(dbi->dbi_db); 01154 int rc = 0; 01155 01156 dbg_keyval("sql_cdel", dbi, dbcursor, key, data, flags); 01157 enterChroot(dbi); 01158 01159 scp->cmd = sqlite3_mprintf("DELETE FROM '%q' WHERE key=? AND value=?;", 01160 dbi->dbi_subfile); 01161 01162 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg); 01163 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01164 rc = sql_bind_key(dbi, scp, 1, key); 01165 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind key %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01166 rc = sql_bind_data(dbi, scp, 2, data); 01167 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) bind data %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01168 01169 rc = sql_step(dbi, scp); 01170 if (rc) rpmlog(RPMLOG_WARNING, "cdel(%s) sql_step rc %d\n", dbi->dbi_subfile, rc); 01171 01172 scp = scpFree(scp); 01173 01174 leaveChroot(dbi); 01175 01176 return rc; 01177 } 01178 01188 static int sql_cget (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, 01189 DBT * data, unsigned int flags) 01190 /*@globals fileSystem, internalState @*/ 01191 /*@modifies dbi, dbcursor, *key, *data, fileSystem, internalState @*/ 01192 { 01193 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 01194 SCP_t scp = (SCP_t)dbcursor; 01195 int rc = 0; 01196 int ix; 01197 01198 assert(dbcursor != NULL); 01199 dbg_keyval("sql_cget", dbi, dbcursor, key, data, flags); 01200 01201 enterChroot(dbi); 01202 01203 /* 01204 * First determine if this is a new scan or existing scan 01205 */ 01206 01207 if (_debug) 01208 fprintf(stderr, "\tcget(%s) scp %p rc %d flags %d av %p\n", 01209 dbi->dbi_subfile, scp, rc, flags, scp->av); 01210 if ( flags == DB_SET || scp->used == 0 ) { 01211 scp->used = 1; /* Signal this scp as now in use... */ 01212 /*@i@*/ scp = scpReset(scp); /* Free av and avlen, reset counters.*/ 01213 01214 /* XXX: Should we also reset the key table here? Can you re-use a cursor? */ 01215 01216 /* 01217 * If we're scanning everything, load the iterator key table 01218 */ 01219 if ( key->size == 0) { 01220 scp->all = 1; 01221 01222 /* 01223 * The only condition not dealt with is if there are multiple identical keys. This can lead 01224 * to later iteration confusion. (It may return the same value for the multiple keys.) 01225 */ 01226 01227 #ifdef DYING 01228 /* Only RPMDBI_PACKAGES is supposed to be iterating, and this is guarenteed to be unique */ 01229 assert(dbi->dbi_rpmtag == RPMDBI_PACKAGES); 01230 #endif 01231 01232 switch (dbi->dbi_rpmtag) { 01233 case RPMDBI_PACKAGES: 01234 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q' ORDER BY key;", 01235 dbi->dbi_subfile); 01236 break; 01237 default: 01238 scp->cmd = sqlite3_mprintf("SELECT key FROM '%q';", 01239 dbi->dbi_subfile); 01240 break; 01241 } 01242 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg); 01243 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01244 01245 rc = sql_step(dbi, scp); 01246 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sequential sql_step rc %d\n", dbi->dbi_subfile, rc); 01247 01248 scp = scpResetKeys(scp); 01249 scp->nkeys = scp->nr; 01250 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys)); 01251 for (ix = 0; ix < scp->nkeys; ix++) { 01252 scp->keys[ix] = xmalloc(sizeof(*scp->keys[0])); 01253 scp->keys[ix]->size = (UINT32_T) scp->avlen[ix+1]; 01254 scp->keys[ix]->data = xmalloc(scp->keys[ix]->size); 01255 memcpy(scp->keys[ix]->data, scp->av[ix+1], scp->avlen[ix+1]); 01256 } 01257 } else { 01258 /* 01259 * We're only scanning ONE element 01260 */ 01261 scp = scpResetKeys(scp); 01262 scp->nkeys = 1; 01263 scp->keys = xcalloc(scp->nkeys, sizeof(*scp->keys)); 01264 scp->keys[0] = xmalloc(sizeof(*scp->keys[0])); 01265 scp->keys[0]->size = key->size; 01266 scp->keys[0]->data = xmalloc(scp->keys[0]->size); 01267 memcpy(scp->keys[0]->data, key->data, key->size); 01268 } 01269 01270 /*@i@*/ scp = scpReset(scp); /* reset */ 01271 01272 /* Prepare SQL statement to retrieve the value for the current key */ 01273 scp->cmd = sqlite3_mprintf("SELECT value FROM '%q' WHERE key=?;", dbi->dbi_subfile); 01274 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg); 01275 01276 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) prepare %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01277 } 01278 01279 /*@i@*/ scp = scpResetAv(scp); /* Free av and avlen, reset counters.*/ 01280 01281 /* Now continue with a normal retrive based on key */ 01282 if ((scp->rx + 1) > scp->nkeys ) 01283 rc = DB_NOTFOUND; /* At the end of the list */ 01284 01285 if (rc != 0) 01286 goto exit; 01287 01288 /* Bind key to prepared statement */ 01289 rc = sql_bind_key(dbi, scp, 1, scp->keys[scp->rx]); 01290 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01291 01292 rc = sql_step(dbi, scp); 01293 if (rc) rpmlog(RPMLOG_WARNING, "cget(%s) sql_step rc %d\n", dbi->dbi_subfile, rc); 01294 01295 rc = sqlite3_reset(scp->pStmt); 01296 if (rc) rpmlog(RPMLOG_WARNING, "reset %d\n", rc); 01297 01298 /* 1 key should return 0 or 1 row/value */ 01299 assert(scp->nr < 2); 01300 01301 if (scp->nr == 0 && scp->all == 0) 01302 rc = DB_NOTFOUND; /* No data for that key found! */ 01303 01304 if (rc != 0) 01305 goto exit; 01306 01307 /* If we're looking at the whole db, return the key */ 01308 if (scp->all) { 01309 01310 /* To get this far there has to be _1_ key returned! (protect against dup keys) */ 01311 assert(scp->nr == 1); 01312 01313 if ( scp->lkey ) { 01314 scp->lkey = _free(scp->lkey); 01315 } 01316 01317 key->size = scp->keys[scp->rx]->size; 01318 key->data = xmalloc(key->size); 01319 if (! (key->flags & DB_DBT_MALLOC)) 01320 scp->lkey = key->data; 01321 01322 (void) memcpy(key->data, scp->keys[scp->rx]->data, key->size); 01323 } 01324 01325 /* Construct and return the data element (element 0 is "value", 1 is _THE_ value)*/ 01326 switch (dbi->dbi_rpmtag) { 01327 default: 01328 if ( scp->ldata ) { 01329 scp->ldata = _free(scp->ldata); 01330 } 01331 01332 data->size = (UINT32_T) scp->avlen[1]; 01333 data->data = xmalloc(data->size); 01334 if (! (data->flags & DB_DBT_MALLOC) ) 01335 scp->ldata = data->data; 01336 01337 (void) memcpy(data->data, scp->av[1], data->size); 01338 } 01339 01340 scp->rx++; 01341 01342 /* XXX FIXME: ptr alignment is fubar here. */ 01343 if (_debug) 01344 fprintf(stderr, "\tcget(%s) found key 0x%x (%d)\n", dbi->dbi_subfile, 01345 key->data == NULL ? 0 : *(unsigned int *)key->data, key->size); 01346 if (_debug) 01347 fprintf(stderr, "\tcget(%s) found data 0x%x (%d)\n", dbi->dbi_subfile, 01348 key->data == NULL ? 0 : *(unsigned int *)data->data, data->size); 01349 01350 exit: 01351 if (rc == DB_NOTFOUND) { 01352 if (_debug) 01353 fprintf(stderr, "\tcget(%s) not found\n", dbi->dbi_subfile); 01354 } 01355 01356 leaveChroot(dbi); 01357 01358 return rc; 01359 } 01360 01370 static int sql_cput (dbiIndex dbi, /*@null@*/ DBC * dbcursor, DBT * key, 01371 DBT * data, unsigned int flags) 01372 /*@globals fileSystem, internalState @*/ 01373 /*@modifies dbi, *dbcursor, fileSystem, internalState @*/ 01374 { 01375 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 01376 SCP_t scp = scpNew(dbi->dbi_db); 01377 int rc = 0; 01378 01379 dbg_keyval("sql_cput", dbi, dbcursor, key, data, flags); 01380 01381 enterChroot(dbi); 01382 01383 switch (dbi->dbi_rpmtag) { 01384 default: 01385 scp->cmd = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' VALUES(?, ?);", 01386 dbi->dbi_subfile); 01387 rc = sqlite3_prepare(sqldb->db, scp->cmd, (int)strlen(scp->cmd), &scp->pStmt, &scp->pzErrmsg); 01388 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) prepare %s (%d)\n",dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01389 rc = sql_bind_key(dbi, scp, 1, key); 01390 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) key bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01391 rc = sql_bind_data(dbi, scp, 2, data); 01392 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) data bind %s (%d)\n", dbi->dbi_subfile, sqlite3_errmsg(sqldb->db), rc); 01393 01394 rc = sql_step(dbi, scp); 01395 if (rc) rpmlog(RPMLOG_WARNING, "cput(%s) sql_step rc %d\n", dbi->dbi_subfile, rc); 01396 01397 break; 01398 } 01399 01400 scp = scpFree(scp); 01401 01402 leaveChroot(dbi); 01403 01404 return rc; 01405 } 01406 01412 static int sql_byteswapped (dbiIndex dbi) 01413 /*@globals fileSystem, internalState @*/ 01414 /*@modifies fileSystem, internalState @*/ 01415 { 01416 SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 01417 SCP_t scp = scpNew(dbi->dbi_db); 01418 int sql_rc, rc = 0; 01419 union _dbswap db_endian; 01420 01421 enterChroot(dbi); 01422 01423 /*@-nullstate@*/ 01424 sql_rc = sqlite3_get_table(sqldb->db, "SELECT endian FROM 'db_info';", 01425 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg); 01426 /*@=nullstate@*/ 01427 01428 if (sql_rc == 0 && scp->nr > 0) { 01429 assert(scp->av != NULL); 01430 db_endian.uc[0] = (unsigned char) strtol(scp->av[1], NULL, 10); 01431 01432 if ( db_endian.uc[0] == ((union _dbswap *)&endian)->uc[0] ) 01433 rc = 0; /* Native endian */ 01434 else 01435 rc = 1; /* swapped */ 01436 01437 } else { 01438 if ( sql_rc ) { 01439 rpmlog(RPMLOG_DEBUG, D_("db_info failed %s (%d)\n"), 01440 scp->pzErrmsg, sql_rc); 01441 } 01442 rpmlog(RPMLOG_WARNING, "Unable to determine DB endian.\n"); 01443 } 01444 01445 scp = scpFree(scp); 01446 01447 leaveChroot(dbi); 01448 01449 return rc; 01450 } 01451 01452 /************************************************** 01453 * 01454 * All of the following are not implemented! 01455 * they are not used by the rest of the system 01456 * 01457 **************************************************/ 01458 01467 static int sql_associate (/*@unused@*/ dbiIndex dbi, 01468 /*@unused@*/ dbiIndex dbisecondary, 01469 /*@unused@*/int (*callback) (DB *, const DBT *, const DBT *, DBT *), 01470 /*@unused@*/ unsigned int flags) 01471 /*@*/ 01472 { 01473 if (_debug) 01474 fprintf(stderr, "*** sql_associate:\n"); 01475 return EINVAL; 01476 } 01477 01486 static int sql_associate_foreign (/*@unused@*/ dbiIndex dbi, 01487 /*@unused@*/ dbiIndex dbisecondary, 01488 /*@unused@*/int (*callback) (DB *, const DBT *, DBT *, const DBT *, int *), 01489 /*@unused@*/ unsigned int flags) 01490 /*@*/ 01491 { 01492 if (_debug) 01493 fprintf(stderr, "*** sql_associate_foreign:\n"); 01494 return EINVAL; 01495 } 01496 01505 static int sql_join (/*@unused@*/ dbiIndex dbi, 01506 /*@unused@*/ DBC ** curslist, 01507 /*@unused@*/ /*@out@*/ DBC ** dbcp, 01508 /*@unused@*/ unsigned int flags) 01509 /*@globals fileSystem @*/ 01510 /*@modifies dbi, *dbcp, fileSystem @*/ 01511 { 01512 if (_debug) 01513 fprintf(stderr, "*** sql_join:\n"); 01514 return EINVAL; 01515 } 01516 01525 static int sql_cdup (/*@unused@*/ dbiIndex dbi, 01526 /*@unused@*/ DBC * dbcursor, 01527 /*@unused@*/ /*@out@*/ DBC ** dbcp, 01528 /*@unused@*/ unsigned int flags) 01529 /*@globals fileSystem @*/ 01530 /*@modifies dbi, *dbcp, fileSystem @*/ 01531 { 01532 if (_debug) 01533 fprintf(stderr, "*** sql_cdup:\n"); 01534 return EINVAL; 01535 } 01536 01547 static int sql_cpget (/*@unused@*/ dbiIndex dbi, 01548 /*@unused@*/ /*@null@*/ DBC * dbcursor, 01549 /*@unused@*/ DBT * key, 01550 /*@unused@*/ DBT * pkey, 01551 /*@unused@*/ DBT * data, 01552 /*@unused@*/ unsigned int flags) 01553 /*@globals fileSystem @*/ 01554 /*@modifies *dbcursor, *key, *pkey, *data, fileSystem @*/ 01555 { 01556 if (_debug) 01557 fprintf(stderr, "*** sql_cpget:\n"); 01558 return EINVAL; 01559 } 01560 01569 static int sql_ccount (/*@unused@*/ dbiIndex dbi, 01570 /*@unused@*/ DBC * dbcursor, 01571 /*@unused@*/ /*@out@*/ unsigned int * countp, 01572 /*@unused@*/ unsigned int flags) 01573 /*@globals fileSystem @*/ 01574 /*@modifies *dbcursor, fileSystem @*/ 01575 { 01576 if (_debug) 01577 fprintf(stderr, "*** sql_ccount:\n"); 01578 return EINVAL; 01579 } 01580 01587 static int sql_stat (dbiIndex dbi, /*@unused@*/ unsigned int flags) 01588 /*@globals fileSystem, internalState @*/ 01589 /*@modifies dbi, fileSystem, internalState @*/ 01590 { 01591 /*@i@*/ SQL_DB * sqldb = (SQL_DB *) dbi->dbi_db; 01592 SCP_t scp = scpNew(dbi->dbi_db); 01593 int rc = 0; 01594 long nkeys = -1; 01595 01596 enterChroot(dbi); 01597 01598 dbi->dbi_stats = _free(dbi->dbi_stats); 01599 01600 /*@-sizeoftype@*/ 01601 dbi->dbi_stats = xcalloc(1, sizeof(DB_HASH_STAT)); 01602 /*@=sizeoftype@*/ 01603 01604 scp->cmd = sqlite3_mprintf("SELECT COUNT('key') FROM '%q';", dbi->dbi_subfile); 01605 /*@-nullstate@*/ 01606 rc = sqlite3_get_table(sqldb->db, scp->cmd, 01607 &scp->av, &scp->nr, &scp->nc, (char **)&scp->pzErrmsg); 01608 /*@=nullstate@*/ 01609 01610 if ( rc == 0 && scp->nr > 0) { 01611 assert(scp->av != NULL); 01612 nkeys = strtol(scp->av[1], NULL, 10); 01613 01614 rpmlog(RPMLOG_DEBUG, D_(" stat on %s nkeys %ld\n"), 01615 dbi->dbi_subfile, nkeys); 01616 } else { 01617 if ( rc ) { 01618 rpmlog(RPMLOG_DEBUG, D_("stat failed %s (%d)\n"), 01619 scp->pzErrmsg, rc); 01620 } 01621 } 01622 01623 if (nkeys < 0) 01624 nkeys = 4096; /* Good high value */ 01625 01626 ((DB_HASH_STAT *)(dbi->dbi_stats))->hash_nkeys = nkeys; 01627 01628 scp = scpFree(scp); 01629 01630 leaveChroot(dbi); 01631 01632 return rc; 01633 } 01634 01635 /* Major, minor, patch version of DB.. we're not using db.. so set to 0 */ 01636 /* open, close, sync, associate, asociate_foreign, join */ 01637 /* cursor_open, cursor_close, cursor_dup, cursor_delete, cursor_get, */ 01638 /* cursor_pget?, cursor_put, cursor_count */ 01639 /* db_bytewapped, stat */ 01640 /*@observer@*/ /*@unchecked@*/ 01641 struct _dbiVec sqlitevec = { 01642 "Sqlite " SQLITE_VERSION, 01643 ((SQLITE_VERSION_NUMBER / (1000 * 1000)) % 1000), 01644 ((SQLITE_VERSION_NUMBER / ( 1000)) % 1000), 01645 ((SQLITE_VERSION_NUMBER ) % 1000), 01646 sql_open, 01647 sql_close, 01648 sql_sync, 01649 sql_associate, 01650 sql_associate_foreign, 01651 sql_join, 01652 sql_exists, 01653 sql_seqno, 01654 sql_copen, 01655 sql_cclose, 01656 sql_cdup, 01657 sql_cdel, 01658 sql_cget, 01659 sql_cpget, 01660 sql_cput, 01661 sql_ccount, 01662 sql_byteswapped, 01663 sql_stat 01664 }; 01665 01666 /*@=evalorderuncon@*/ 01667 /*@=modfilesystem@*/ 01668 /*@=compmempass@*/ 01669 /*@=compdef@*/ 01670 /*@=moduncon@*/ 01671 /*@=noeffectuncon@*/ 01672 /*@=globuse@*/ 01673 /*@=paramuse@*/ 01674 /*@=mustmod@*/