rpm  5.4.14
db3.c
Go to the documentation of this file.
1 /*@-type@*/ /* FIX: annotate db3 methods */
6 /*@unchecked@*/
7 static int _debug = 1; /* XXX if < 0 debugging, > 0 unusual error returns */
8 
9 #include "system.h"
10 
11 #if defined(HAVE_FTOK) && defined(HAVE_SYS_IPC_H)
12 #include <sys/ipc.h>
13 #endif
14 
15 #include <rpmlog.h>
16 #include <rpmmacro.h>
17 #include <rpmbf.h>
18 #include <rpmpgp.h> /* XXX pgpExtractPubkeyFingerprint */
19 #include <rpmurl.h> /* XXX urlPath proto */
20 
21 #define _RPMTAG_INTERNAL
22 #include <rpmtag.h>
23 
24 #define _RPMEVR_INTERNAL /* XXX isInstallPrereq */
25 #include <rpmevr.h>
26 
27 #define _RPMDB_INTERNAL
28 #include <rpmdb.h>
29 
30 #include "debug.h"
31 
32 #ifdef NOTYET /* XXX syscall ACID needs --with-db=internal */
33 extern int logio_dispatch(DB_ENV * dbenv, DBT * dbt, DB_LSN * lsn, db_recops op)
34  /*@*/;
35 #endif
36 
37 #define DBIDEBUG(_dbi, _list) if ((_dbi)->dbi_debug) fprintf _list
38 
39 /*@access rpmdb @*/
40 /*@access dbiIndex @*/
41 /*@access dbiIndexSet @*/
42 
43 /*@-redef@*/
44 union _dbswap {
45  uint64_t ul;
46  uint32_t ui;
47  uint16_t us;
48  uint8_t uc[8];
49 };
50 /*@=redef@*/
51 /*@unchecked@*/
52 static union _dbswap _endian = { .ui = 0x11223344 };
53 
54 static inline uint64_t _ntoh_ul(uint64_t ul)
55  /*@*/
56 {
57  union _dbswap _a;
58  _a.ul = ul;
59  if (_endian.uc[0] == 0x44) {
60  uint8_t _b, *_c = _a.uc; \
61  _b = _c[7]; _c[7] = _c[0]; _c[0] = _b; \
62  _b = _c[6]; _c[6] = _c[1]; _c[1] = _b; \
63  _b = _c[5]; _c[5] = _c[2]; _c[2] = _b; \
64  _b = _c[4]; _c[4] = _c[3]; _c[3] = _b; \
65  }
66  return _a.ul;
67 }
68 static inline uint64_t _hton_ul(uint64_t ul)
69  /*@*/
70 {
71  return _ntoh_ul(ul);
72 }
73 
74 static inline uint32_t _ntoh_ui(uint32_t ui)
75  /*@*/
76 {
77  union _dbswap _a;
78  _a.ui = ui;
79  if (_endian.uc[0] == 0x44) {
80  uint8_t _b, *_c = _a.uc; \
81  _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \
82  _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \
83  }
84  return _a.ui;
85 }
86 static inline uint32_t _hton_ui(uint32_t ui)
87  /*@*/
88 {
89  return _ntoh_ui(ui);
90 }
91 
92 static inline uint16_t _ntoh_us(uint16_t us)
93  /*@*/
94 {
95  union _dbswap _a;
96  _a.us = us;
97  if (_endian.uc[0] == 0x44) {
98  uint8_t _b, *_c = _a.uc; \
99  _b = _c[1]; _c[1] = _c[0]; _c[0] = _b; \
100  }
101  return _a.us;
102 }
103 static inline uint16_t _hton_us(uint16_t us)
104  /*@*/
105 {
106  return _ntoh_us(us);
107 }
108 
109 #ifdef NOTNOW
110 static const char * bfstring(unsigned int x, const char * xbf)
111 {
112  const char * s = xbf;
113  static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
114  static char buf[BUFSIZ];
115  char * t, * te;
116  unsigned radix;
117  unsigned c, i, k;
118 
119  radix = (s != NULL ? *s++ : 16);
120 
121  if (radix <= 1 || radix >= 32)
122  radix = 16;
123 
124  t = buf;
125  switch (radix) {
126  case 8: *t++ = '0'; break;
127  case 16: *t++ = '0'; *t++ = 'x'; break;
128  }
129 
130  i = 0;
131  k = x;
132  do { i++; k /= radix; } while (k);
133 
134  te = t + i;
135 
136  k = x;
137  do { --i; t[i] = digits[k % radix]; k /= radix; } while (k);
138 
139  t = te;
140  i = '<';
141  if (s != NULL)
142  while ((c = *s++) != '\0') {
143  if (c > ' ') continue;
144 
145  k = (1 << (c - 1));
146  if (!(x & k)) continue;
147 
148  if (t == te) *t++ = '=';
149 
150  *t++ = i;
151  i = ',';
152  while (*s > ' ')
153  *t++ = *s++;
154  }
155  if (t > te) *t++ = '>';
156  *t = '\0';
157  return buf;
158 }
159 
160 /* XXX checked with db-4.5.20 */
161 static const char * dbtFlags =
162  "\20\1APPMALLOC\2ISSET\3MALLOC\4PARTIAL\5REALLOC\6USERMEM\7DUPOK";
163 
164 static const char * dbenvOpenFlags =
165  "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CDB\20LOCK\21LOG\22MPOOL\23REP\24TXN\25LOCKDOWN\26PRIVATE\27RECOVER_FATAL\30REGISTER\31SYSTEM_MEM";
166 
167 static const char * dbOpenFlags =
168  "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17EXCL\20FCNTL_LOCKING\21NO_AUTO_COMMIT\22RDWRMASTER\23WRITEOPEN";
169 
170 static const char * dbenvSetFlags =
171  "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CDB_ALLDB\20DIRECT_DB\21DIRECT_LOG\22DSYNC_DB\23DSYNC_LOG\24LOG_AUTOREMOVE\25LOG_INMEMORY\26NOLOCKING\27NOPANIC\30OVERWRITE\31PANIC_ENV\36REGION_INIT\37TIME_NOTGRANTED\40YIELDCPU";
172 
173 static const char * dbSetFlags =
174  "\20\1CREATE\2DURABLE_UNKNOWN\3FORCE\4MULTIVERSION\5NOMMAP\6RDONLY\7RECOVER\10THREAD\11TRUNCATE\12TXN_NOSYNC\13TXN_NOT_DURABLEi\14TXN_WRITE_NOSYNC\15USE_ENVIRON\16USE_ENVIRON_ROOT\17CHKSUM\20DUP\21DUPSORT\22ENCRYPT\23INORDER\24RECNUM\25RENUMBER\26REVSPLITOFF\27SNAPSHOT";
175 
176 static const char * dbiModeFlags =
177  "\20\1WRONLY\2RDWR\7CREAT\10EXCL\11NOCTTY\12TRUNC\13APPEND\14NONBLOCK\15SYNC\16ASYNC\17DIRECT\20LARGEFILE\21DIRECTORY\22NOFOLLOW";
178 #endif /* NOTNOW */
179 
180 /*@-redef@*/
181 typedef struct key_s {
182  uint32_t v;
183 /*@observer@*/
184  const char *n;
185 } KEY;
186 /*@=redef@*/
187 
188 /*@observer@*/
189 static const char * tblName(uint32_t v, KEY * tbl, size_t ntbl)
190  /*@*/
191 {
192  const char * n = NULL;
193  static char buf[32];
194  size_t i;
195 
196  for (i = 0; i < ntbl; i++) {
197  if (v != tbl[i].v)
198  continue;
199  n = tbl[i].n;
200  break;
201  }
202  if (n == NULL) {
203  (void) snprintf(buf, sizeof(buf), "0x%x", (unsigned)v);
204  n = buf;
205  }
206  return n;
207 }
208 
209 static const char * fmtBits(uint32_t flags, KEY tbl[], size_t ntbl, char *t)
210  /*@modifies t @*/
211 {
212  char pre = '<';
213  char * te = t;
214  int i;
215 
216  sprintf(t, "0x%x", (unsigned)flags);
217  te = t;
218  te += strlen(te);
219  for (i = 0; i < 32; i++) {
220  uint32_t mask = (1 << i);
221  const char * name;
222 
223  if (!(flags & mask))
224  continue;
225 
226  name = tblName(mask, tbl, ntbl);
227  *te++ = pre;
228  pre = ',';
229  te = stpcpy(te, name);
230  }
231  if (pre == ',') *te++ = '>';
232  *te = '\0';
233  return t;
234 }
235 
236 #define _ENTRY(_v) { DB_##_v, #_v, }
237 
238 /*@unchecked@*/ /*@observer@*/
239 static KEY DBeflags[] = {
240  _ENTRY(INIT_CDB),
241  _ENTRY(INIT_LOCK),
242  _ENTRY(INIT_LOG),
243  _ENTRY(INIT_MPOOL),
244  _ENTRY(INIT_MUTEX), /* XXX not in DBENV->open() doco */
245  _ENTRY(INIT_REP),
246  _ENTRY(INIT_TXN),
247  _ENTRY(RECOVER),
248  _ENTRY(RECOVER_FATAL),
249  _ENTRY(USE_ENVIRON),
250  _ENTRY(USE_ENVIRON_ROOT),
251  _ENTRY(CREATE),
252  _ENTRY(LOCKDOWN),
253 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8) || (DB_VERSION_MAJOR >= 5)
254  _ENTRY(FAILCHK),
255 #endif
256  _ENTRY(PRIVATE),
257  _ENTRY(REGISTER),
258  _ENTRY(SYSTEM_MEM),
259  _ENTRY(THREAD),
260 };
261 /*@unchecked@*/
262 static size_t nDBeflags = sizeof(DBeflags) / sizeof(DBeflags[0]);
263 /*@observer@*/
264 static const char * fmtDBeflags(uint32_t flags)
265  /*@*/
266 {
267  static char buf[BUFSIZ];
268  char * te = buf;
269  te = stpcpy(te, "\n\tflags: ");
270  (void) fmtBits(flags, DBeflags, nDBeflags, te);
271  return buf;
272 }
273 #define _EFLAGS(_eflags) fmtDBeflags(_eflags)
274 
275 /*@unchecked@*/ /*@observer@*/
276 static KEY DBoflags[] = {
277  _ENTRY(AUTO_COMMIT),
278  _ENTRY(CREATE),
279  _ENTRY(EXCL),
280  _ENTRY(MULTIVERSION),
281  _ENTRY(NOMMAP),
282  _ENTRY(RDONLY),
283  _ENTRY(READ_UNCOMMITTED),
284  _ENTRY(THREAD),
285  _ENTRY(TRUNCATE),
286 };
287 /*@unchecked@*/
288 static size_t nDBoflags = sizeof(DBoflags) / sizeof(DBoflags[0]);
289 /*@observer@*/
290 static const char * fmtDBoflags(uint32_t flags)
291  /*@*/
292 {
293  static char buf[BUFSIZ];
294  char * te = buf;
295  te = stpcpy(te, "\n\tflags: ");
296  (void) fmtBits(flags, DBoflags, nDBoflags, te);
297  return buf;
298 }
299 #define _OFLAGS(_oflags) fmtDBoflags(_oflags)
300 
301 /*@unchecked@*/ /*@observer@*/
302 static KEY DBaflags[] = {
303  _ENTRY(CREATE),
304  _ENTRY(IMMUTABLE_KEY),
305 };
306 /*@unchecked@*/
307 static size_t nDBaflags = sizeof(DBaflags) / sizeof(DBaflags[0]);
308 /*@observer@*/
309 static const char * fmtDBaflags(uint32_t flags)
310  /*@*/
311 {
312  static char buf[BUFSIZ];
313  char * te = buf;
314  te = stpcpy(te, "\n\tflags: ");
315  (void) fmtBits(flags, DBaflags, nDBaflags, te);
316  return buf;
317 }
318 #define _AFLAGS(_aflags) fmtDBaflags(_aflags)
319 
320 /*@unchecked@*/ /*@observer@*/
321 static KEY DBafflags[] = {
322  _ENTRY(FOREIGN_ABORT),
323  _ENTRY(FOREIGN_CASCADE),
324  _ENTRY(FOREIGN_NULLIFY),
325 };
326 /*@unchecked@*/
327 static size_t nDBafflags = sizeof(DBafflags) / sizeof(DBafflags[0]);
328 /*@observer@*/
329 static const char * fmtDBafflags(uint32_t flags)
330  /*@*/
331 {
332  static char buf[BUFSIZ];
333  char * te = buf;
334  te = stpcpy(te, "\n\tflags: ");
335  (void) fmtBits(flags, DBafflags, nDBafflags, te);
336  return buf;
337 }
338 #define _AFFLAGS(_afflags) fmtDBafflags(_afflags)
339 
340 /*@unchecked@*/ /*@observer@*/
341 static KEY DBCoflags[] = {
342  /* XXX DB->cursor() doco for db-5.1.19 lists, undef'd */
343 #if defined(DB_CURSOR_BULK)
344  _ENTRY(CURSOR_BULK),
345 #endif
346  _ENTRY(READ_COMMITTED),
347  _ENTRY(READ_UNCOMMITTED),
348  _ENTRY(WRITECURSOR),
349  _ENTRY(TXN_SNAPSHOT),
350 };
351 /*@unchecked@*/
352 static size_t nDBCoflags = sizeof(DBCoflags) / sizeof(DBCoflags[0]);
353 /*@observer@*/
354 static const char * fmtDBCoflags(uint32_t flags)
355  /*@*/
356 {
357  static char buf[BUFSIZ];
358  char * te = buf;
359  (void) fmtBits(flags, DBCoflags, nDBCoflags, te);
360  return buf;
361 }
362 #define _DBCOFLAGS(_coflags) fmtDBCoflags(_coflags)
363 
364 /*@unchecked@*/ /*@observer@*/
365 static KEY DBCflags[] = {
366  _ENTRY(AFTER), /* Dbc.put */
367  _ENTRY(APPEND), /* Db.put */
368  _ENTRY(BEFORE), /* Dbc.put */
369  _ENTRY(CONSUME), /* Db.get, Dbc.del */
370  _ENTRY(CONSUME_WAIT), /* Db.get */
371  _ENTRY(CURRENT), /* Dbc.get, Dbc.put, DbLogc.get */
372  _ENTRY(FIRST), /* Dbc.get, DbLogc->get */
373  _ENTRY(GET_BOTH), /* Db.get, Dbc.get */
374  _ENTRY(GET_BOTHC), /* Dbc.get (internal) */
375  _ENTRY(GET_BOTH_RANGE), /* Db.get, Dbc.get */
376  _ENTRY(GET_RECNO), /* Dbc.get */
377  _ENTRY(JOIN_ITEM), /* Dbc.get; don't do primary lookup */
378  _ENTRY(KEYFIRST), /* Dbc.put */
379  _ENTRY(KEYLAST), /* Dbc.put */
380  _ENTRY(LAST), /* Dbc.get, DbLogc->get */
381  _ENTRY(NEXT), /* Dbc.get, DbLogc->get */
382  _ENTRY(NEXT_DUP), /* Dbc.get */
383  _ENTRY(NEXT_NODUP), /* Dbc.get */
384  _ENTRY(NODUPDATA), /* Db.put, Dbc.put */
385  _ENTRY(NOOVERWRITE), /* Db.put */
386  _ENTRY(NOSYNC), /* Db.close */
387 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8) || (DB_VERSION_MAJOR >= 5)
388  _ENTRY(OVERWRITE_DUP), /* Dbc.put, Db.put; no DB_KEYEXIST */
389 #endif
390  _ENTRY(POSITION), /* Dbc.dup */
391  _ENTRY(PREV), /* Dbc.get, DbLogc->get */
392  _ENTRY(PREV_DUP), /* Dbc.get */
393  _ENTRY(PREV_NODUP), /* Dbc.get */
394  _ENTRY(SET), /* Dbc.get, DbLogc->get */
395  _ENTRY(SET_RANGE), /* Dbc.get */
396  _ENTRY(SET_RECNO), /* Db.get, Dbc.get */
397  _ENTRY(UPDATE_SECONDARY), /* Dbc.get, Dbc.del (internal) */
398 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8) || (DB_VERSION_MAJOR >= 5)
399  _ENTRY(SET_LTE), /* Dbc.get (internal) */
400  _ENTRY(GET_BOTH_LTE), /* Dbc.get (internal) */
401 #endif
402 
403  _ENTRY(IGNORE_LEASE),
404  _ENTRY(READ_COMMITTED),
405  _ENTRY(READ_UNCOMMITTED),
406  _ENTRY(MULTIPLE),
407  _ENTRY(MULTIPLE_KEY),
408  _ENTRY(RMW),
409 };
410 #undef _ENTRY
411 /*@unchecked@*/
412 static size_t nDBCflags = sizeof(DBCflags) / sizeof(DBCflags[0]);
413 
414 /*@observer@*/
415 static const char * fmtDBCflags(uint32_t flags)
416  /*@*/
417 {
418  static char buf[BUFSIZ];
419  char * te = buf;
420  uint32_t op = (flags & DB_OPFLAGS_MASK);
421  flags &= ~DB_OPFLAGS_MASK;
422 
423  te = stpcpy(te, "\n\tflags: ");
424  if (op) {
425  te = stpcpy( stpcpy(te, "DB_"), tblName(op, DBCflags, nDBCflags));
426  *te++ = ' ';
427  *te = '\0';
428  }
429  if (flags)
430  (void) fmtBits(flags, DBCflags, nDBCflags, te);
431  return buf;
432 }
433 #define _DBCFLAGS(_flags) fmtDBCflags(_flags)
434 
435 #define _DBT_ENTRY(_v) { DB_DBT_##_v, #_v, }
436 /*@unchecked@*/ /*@observer@*/
437 static KEY DBTflags[] = {
438  _DBT_ENTRY(MALLOC),
439  _DBT_ENTRY(REALLOC),
440  _DBT_ENTRY(USERMEM),
441  _DBT_ENTRY(PARTIAL),
442  _DBT_ENTRY(APPMALLOC),
443  _DBT_ENTRY(MULTIPLE),
444 #if defined(DB_DBT_READONLY) /* XXX db-5.2.28 */
445  _DBT_ENTRY(READONLY),
446 #endif
447 #if defined(DB_DBT_ISSET)
448  _DBT_ENTRY(ISSET),
449 #endif
450 #if defined(DB_DBT_USERCOPY)
451  _DBT_ENTRY(USERCOPY),
452 #endif
453 #if defined(DB_DBT_USERMEM)
454  _DBT_ENTRY(USERMEM),
455 #endif
456 #if defined(DB_DBT_BLOB)
457  _DBT_ENTRY(BLOB),
458 #endif
459 #if defined(DB_DBT_BLOB_REC)
460  _DBT_ENTRY(BLOB_REC),
461 #endif
462 #if defined(DB_DBT_STREAMING)
463  _DBT_ENTRY(STREAMING),
464 #endif
465 #if defined(DB_DBT_BULK)
466  _DBT_ENTRY(BULK),
467 #endif
468 #if defined(DB_DBT_DUPOK)
469  _DBT_ENTRY(DUPOK),
470 #endif
471 };
472 #undef _DBT_ENTRY
473 /*@unchecked@*/
474 static size_t nDBTflags = sizeof(DBTflags) / sizeof(DBTflags[0]);
475 
476 /*@observer@*/
477 static char * fmtDBT(const DBT * K, char * te)
478  /*@modifies te @*/
479 {
480  static size_t keymax = 35;
481  int unprintable;
482  uint32_t i;
483 
484  sprintf(te, "%p[%u]\t", K->data, (unsigned)K->size);
485  te += strlen(te);
486  (void) fmtBits(K->flags, DBTflags, nDBTflags, te);
487  te += strlen(te);
488  if (K->data && K->size > 0) {
489  uint8_t * _u;
490  size_t _nu;
491 
492  /* Grab the key data/size. */
493  if (K->flags & DB_DBT_MULTIPLE) {
494  DBT * _K = K->data;
495  _u = _K->data;
496  _nu = _K->size;
497  } else {
498  _u = K->data;
499  _nu = K->size;
500  }
501  /* Verify if data is a string. */
502  unprintable = 0;
503  for (i = 0; i < _nu; i++)
504  unprintable |= !xisprint(_u[i]);
505 
506  /* Display the data. */
507  if (!unprintable) {
508  size_t nb = (_nu < keymax ? _nu : keymax);
509  char * ellipsis = (_nu < keymax ? "" : "...");
510  sprintf(te, "\t\"%.*s%s\"", (int)nb, (char *)_u, ellipsis);
511  } else {
512  switch (_nu) {
513  default: break;
514  case 4: sprintf(te, "\t0x%08x", (unsigned)*(uint32_t *)_u); break;
515  }
516  }
517 
518  te += strlen(te);
519  *te = '\0';
520  }
521  return te;
522 }
523 /*@observer@*/
524 static const char * fmtKDR(const DBT * K, const DBT * P, const DBT * D, const DBT * R)
525  /*@*/
526 {
527  static char buf[BUFSIZ];
528  char * te = buf;
529 
530  if (K) {
531  te = stpcpy(te, "\n\t key: ");
532  te = fmtDBT(K, te);
533  }
534  if (P) {
535  te = stpcpy(te, "\n\t pkey: ");
536  te = fmtDBT(P, te);
537  }
538  if (D) {
539  te = stpcpy(te, "\n\t data: ");
540  te = fmtDBT(D, te);
541  }
542  if (R) {
543  te = stpcpy(te, "\n\t res: ");
544  te = fmtDBT(R, te);
545  }
546  *te = '\0';
547 
548  return buf;
549 }
550 #define _KEYDATA(_K, _P, _D, _R) fmtKDR(_K, _P, _D, _R)
551 
552 /*@-globuse -mustmod @*/ /* FIX: rpmError not annotated yet. */
553 static int Xcvtdberr(/*@unused@*/ dbiIndex dbi, const char * msg,
554  int error, int printit,
555  const char * func, const char * fn, unsigned ln)
556  /*@globals fileSystem @*/
557  /*@modifies fileSystem @*/
558 {
559  int rc = error;
560 
561  if (printit && rc) {
562 /*@-moduncon@*/ /* FIX: annotate db3 methods */
563  rpmlog(RPMLOG_ERR, "%s:%s:%u: %s(%d): %s\n",
564  func, fn, ln, msg, rc, db_strerror(error));
565 /*@=moduncon@*/
566  }
567 
568  return rc;
569 }
570 /*@=globuse =mustmod @*/
571 #define cvtdberr(_dbi, _msg, _error, _printit) \
572  Xcvtdberr(_dbi, _msg, _error, _printit, __FUNCTION__, __FILE__, __LINE__)
573 
580 /*@observer@*/
581 static const char * mapTagName(rpmdb rpmdb, dbiIndex dbi)
582  /*@*/
583 {
584  tagStore_t dbiTags = rpmdb->db_tags;
585  size_t dbix = 0;
586 
587  if (dbiTags != NULL)
588  while (dbix < rpmdb->db_ndbi) {
589  if (dbi->dbi_rpmtag == dbiTags->tag)
590  return dbiTags->str;
591  dbiTags++;
592  dbix++;
593  }
594  /* XXX should never reach here */
595  return tagName(dbi->dbi_rpmtag);
596 }
597 
598 static int db_fini(dbiIndex dbi, const char * dbhome,
599  /*@null@*/ const char * dbfile,
600  /*@unused@*/ /*@null@*/ const char * dbsubfile)
601  /*@globals fileSystem @*/
602  /*@modifies fileSystem @*/
603 {
604  rpmdb rpmdb = dbi->dbi_rpmdb;
605  DB_ENV * dbenv = rpmdb->db_dbenv;
606  int rc;
607 
608 DBIDEBUG(dbi, (stderr, "--> %s(%p,%s,%s,%s)\n", __FUNCTION__, dbi, dbhome, dbfile, dbsubfile));
609 
610  if (dbenv == NULL)
611  return 0;
612 
613  rc = dbenv->close(dbenv, 0);
614  rc = cvtdberr(dbi, "dbenv->close", rc, _debug);
615  rpmdb->db_dbenv = NULL;
616 
617  if (dbfile)
618  rpmlog(RPMLOG_DEBUG, D_("closed db environment %s/%s\n"),
619  dbhome, dbfile);
620 
621  if (rpmdb->db_remove_env) {
622  int xx;
623 
624  /*@-moduncon@*/ /* FIX: annotate db3 methods */
625  xx = db_env_create(&dbenv, 0);
626  /*@=moduncon@*/
627  if (!xx && dbenv != NULL) {
628  xx = cvtdberr(dbi, "db_env_create", xx, _debug);
629  xx = dbenv->remove(dbenv, dbhome, DB_FORCE);
630  xx = cvtdberr(dbi, "dbenv->remove", xx, _debug);
631 
632  if (dbfile)
633  rpmlog(RPMLOG_DEBUG, D_("removed db environment %s/%s\n"),
634  dbhome, dbfile);
635  }
636 
637  }
638  return rc;
639 }
640 
641 static int db3_fsync_disable(/*@unused@*/ int fd)
642  /*@*/
643 {
644  return 0;
645 }
646 
647 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5) || (DB_VERSION_MAJOR >= 5)
648 
656 static int db3is_alive(/*@unused@*/ DB_ENV *dbenv, pid_t pid,
657  /*@unused@*/ db_threadid_t tid,
659  /*@*/
660 {
661  int is_alive = 1; /* assume all processes are alive */
662 
663  switch (flags) {
664  case DB_MUTEX_PROCESS_ONLY:
665  case 0:
666  default:
667  is_alive = (!(kill(pid, 0) < 0 && errno == ESRCH));
668  break;
669  }
670  return is_alive;
671 }
672 #endif
673 
674 /*==============================================================*/
675 
676 /* HAVE_SYS_SYSCTL_H */
677 #if defined(HAVE_PHYSMEM_SYSCTL) || defined(HAVE_NCPU_SYSCTL)
678 #include <sys/sysctl.h>
679 #endif
680 
681 static uint64_t physmem(void)
682  /*@*/
683 {
684  static uint64_t _physmem = 0;
685  static int oneshot = 0;
686 
687  if (!oneshot) {
688 #if defined(HAVE_PHYSMEM_SYSCONF)
689  const long _pagesize = sysconf(_SC_PAGESIZE);
690  const long _pages = sysconf(_SC_PHYS_PAGES);
691  if (_pagesize != -1 || _pages != -1)
692  _physmem = (uint64_t)(_pagesize) * (uint64_t)(_pages);
693 #elif defined(HAVE_PHYSMEM_SYSCTL)
694  int name[2] = { CTL_HW, HW_PHYSMEM };
695  unsigned long mem;
696  size_t mem_ptr_size = sizeof(mem);
697  if (!sysctl(name, 2, &mem, &mem_ptr_size, NULL, 0)) {
698  if (mem_ptr_size != sizeof(mem)) {
699  if (mem_ptr_size == sizeof(unsigned int))
700  _physmem = *(unsigned int *)(&mem);
701  } else {
702  _physmem = mem;
703  }
704  }
705 #endif
706  oneshot++;
707  }
708  return _physmem;
709 }
710 
711 static size_t ncores(void)
712  /*@*/
713 {
714  static size_t _ncores = 1;
715  static int oneshot = 0;
716 
717  if (!oneshot) {
718 #if defined(HAVE_NCPU_SYSCONF)
719  const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
720 #elif defined(HAVE_NCPU_SYSCTL)
721  int name[2] = { CTL_HW, HW_NCPU };
722  int cpus = 0;
723  size_t cpus_size = sizeof(cpus);
724  if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0)
725  || cpus_size != sizeof(cpus))
726  cpus = 0;
727 #endif
728  if (cpus > (int)_ncores)
729  _ncores = (size_t)(cpus);
730  oneshot++;
731  }
732  return _ncores;
733 }
734 
735 /*==============================================================*/
736 #define _TABLE(_v) { #_v, DB_EVENT_##_v }
737 static struct _events_s {
738  const char * n;
739  uint32_t v;
740 } _events[] = {
741 #if (DB_VERSION_MAJOR == 6 && DB_VERSION_MINOR >= 0)
742  _TABLE(PANIC), /* 0 */
743  _TABLE(REG_ALIVE), /* 1 */
744  _TABLE(REG_PANIC), /* 2 */
745  _TABLE(REP_AUTOTAKEOVER_FAILED), /* 3 */
746  _TABLE(REP_CLIENT), /* 4 */
747  _TABLE(REP_CONNECT_BROKEN), /* 5 */
748  _TABLE(REP_CONNECT_ESTD), /* 6 */
749  _TABLE(REP_CONNECT_TRY_FAILED), /* 7 */
750  _TABLE(REP_DUPMASTER), /* 8 */
751  _TABLE(REP_ELECTED), /* 9 */
752  _TABLE(REP_ELECTION_FAILED),/* 10 */
753  _TABLE(REP_INIT_DONE), /* 11 */
754  _TABLE(REP_JOIN_FAILURE), /* 12 */
755  _TABLE(REP_LOCAL_SITE_REMOVED), /* 13 */
756  _TABLE(REP_MASTER), /* 14 */
757  _TABLE(REP_MASTER_FAILURE), /* 15 */
758  _TABLE(REP_NEWMASTER), /* 16 */
759  _TABLE(REP_PERM_FAILED), /* 17 */
760  _TABLE(REP_SITE_ADDED), /* 18 */
761  _TABLE(REP_SITE_REMOVED), /* 19 */
762  _TABLE(REP_STARTUPDONE), /* 20 */
763  _TABLE(REP_WOULD_ROLLBACK), /* 21 */
764  _TABLE(WRITE_FAILED), /* 22 */
765  _TABLE(NO_SUCH_EVENT), /* 23 */
766  _TABLE(NO_SUCH_EVENT), /* 24 */
767  _TABLE(NO_SUCH_EVENT), /* 25 */
768  _TABLE(NO_SUCH_EVENT), /* 26 */
769  _TABLE(NO_SUCH_EVENT), /* 27 */
770  _TABLE(NO_SUCH_EVENT), /* 28 */
771  _TABLE(NO_SUCH_EVENT), /* 29 */
772  _TABLE(NO_SUCH_EVENT), /* 30 */
773  _TABLE(NO_SUCH_EVENT), /* 31 */
774 #elif (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2)
775  _TABLE(PANIC), /* 0 */
776  _TABLE(REG_ALIVE), /* 1 */
777  _TABLE(REG_PANIC), /* 2 */
778  _TABLE(REP_CLIENT), /* 3 */
779  _TABLE(REP_CONNECT_BROKEN), /* 4 */
780  _TABLE(REP_CONNECT_ESTD), /* 5 */
781  _TABLE(REP_CONNECT_TRY_FAILED), /* 6 */
782  _TABLE(REP_DUPMASTER), /* 7 */
783  _TABLE(REP_ELECTED), /* 8 */
784  _TABLE(REP_ELECTION_FAILED),/* 9 */
785  _TABLE(REP_INIT_DONE), /* 10 */
786  _TABLE(REP_JOIN_FAILURE), /* 11 */
787  _TABLE(REP_LOCAL_SITE_REMOVED), /* 12 */
788  _TABLE(REP_MASTER), /* 13 */
789  _TABLE(REP_MASTER_FAILURE), /* 14 */
790  _TABLE(REP_NEWMASTER), /* 15 */
791  _TABLE(REP_PERM_FAILED), /* 16 */
792  _TABLE(REP_SITE_ADDED), /* 17 */
793  _TABLE(REP_SITE_REMOVED), /* 18 */
794  _TABLE(REP_STARTUPDONE), /* 19 */
795  _TABLE(REP_WOULD_ROLLBACK), /* 20 */
796  _TABLE(WRITE_FAILED), /* 21 */
797  _TABLE(NO_SUCH_EVENT), /* 22 */
798  _TABLE(NO_SUCH_EVENT), /* 23 */
799  _TABLE(NO_SUCH_EVENT), /* 24 */
800  _TABLE(NO_SUCH_EVENT), /* 25 */
801  _TABLE(NO_SUCH_EVENT), /* 26 */
802  _TABLE(NO_SUCH_EVENT), /* 27 */
803  _TABLE(NO_SUCH_EVENT), /* 28 */
804  _TABLE(NO_SUCH_EVENT), /* 29 */
805  _TABLE(NO_SUCH_EVENT), /* 30 */
806  _TABLE(NO_SUCH_EVENT), /* 31 */
807 #elif (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR < 2) || (DB_VERSION_MAJOR >= 6)
808  /* XXX numbered from db-5.1.19, older versions are different. */
809  _TABLE(PANIC), /* 0 */
810  _TABLE(REG_ALIVE), /* 1 */
811  _TABLE(REG_PANIC), /* 2 */
812  _TABLE(REP_CLIENT), /* 3 */
813  _TABLE(REP_DUPMASTER), /* 4 */
814  _TABLE(REP_ELECTED), /* 5 */
815  _TABLE(REP_ELECTION_FAILED),/* 6 */
816  _TABLE(REP_JOIN_FAILURE), /* 7 */
817  _TABLE(REP_MASTER), /* 8 */
818  _TABLE(REP_MASTER_FAILURE), /* 9 */
819  _TABLE(REP_NEWMASTER), /* 10 */
820  _TABLE(REP_PERM_FAILED), /* 11 */
821  _TABLE(REP_STARTUPDONE), /* 12 */
822  _TABLE(WRITE_FAILED), /* 13 */
823  _TABLE(NO_SUCH_EVENT), /* 14 */
824  _TABLE(NO_SUCH_EVENT), /* 15 */
825  _TABLE(NO_SUCH_EVENT), /* 16 */
826  _TABLE(NO_SUCH_EVENT), /* 17 */
827  _TABLE(NO_SUCH_EVENT), /* 18 */
828  _TABLE(NO_SUCH_EVENT), /* 19 */
829  _TABLE(NO_SUCH_EVENT), /* 20 */
830  _TABLE(NO_SUCH_EVENT), /* 21 */
831  _TABLE(NO_SUCH_EVENT), /* 22 */
832  _TABLE(NO_SUCH_EVENT), /* 23 */
833  _TABLE(NO_SUCH_EVENT), /* 24 */
834  _TABLE(NO_SUCH_EVENT), /* 25 */
835  _TABLE(NO_SUCH_EVENT), /* 26 */
836  _TABLE(NO_SUCH_EVENT), /* 27 */
837  _TABLE(NO_SUCH_EVENT), /* 28 */
838  _TABLE(NO_SUCH_EVENT), /* 29 */
839  _TABLE(NO_SUCH_EVENT), /* 30 */
840  _TABLE(NO_SUCH_EVENT), /* 31 */
841 #else
842  _TABLE(NO_SUCH_EVENT), /* 0 */
843  _TABLE(PANIC), /* 1 */
844 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8)
845  _TABLE(REG_ALIVE), /* 2 */
846  _TABLE(REG_PANIC), /* 3 */
847 #else
848  _TABLE(NO_SUCH_EVENT), /* 2 */
849  _TABLE(NO_SUCH_EVENT), /* 3 */
850 #endif
851  _TABLE(REP_CLIENT), /* 4 */
852  _TABLE(REP_ELECTED), /* 5 */
853  _TABLE(REP_MASTER), /* 6 */
854  _TABLE(REP_NEWMASTER), /* 7 */
855  _TABLE(REP_PERM_FAILED), /* 8 */
856  _TABLE(REP_STARTUPDONE), /* 9 */
857  _TABLE(WRITE_FAILED), /* 10 */
858  _TABLE(NO_SUCH_EVENT), /* 11 */
859  _TABLE(NO_SUCH_EVENT), /* 12 */
860  _TABLE(NO_SUCH_EVENT), /* 13 */
861  _TABLE(NO_SUCH_EVENT), /* 14 */
862  _TABLE(NO_SUCH_EVENT), /* 15 */
863  _TABLE(NO_SUCH_EVENT), /* 16 */
864  _TABLE(NO_SUCH_EVENT), /* 17 */
865  _TABLE(NO_SUCH_EVENT), /* 18 */
866  _TABLE(NO_SUCH_EVENT), /* 19 */
867  _TABLE(NO_SUCH_EVENT), /* 20 */
868  _TABLE(NO_SUCH_EVENT), /* 21 */
869  _TABLE(NO_SUCH_EVENT), /* 22 */
870  _TABLE(NO_SUCH_EVENT), /* 23 */
871  _TABLE(NO_SUCH_EVENT), /* 24 */
872  _TABLE(NO_SUCH_EVENT), /* 25 */
873  _TABLE(NO_SUCH_EVENT), /* 26 */
874  _TABLE(NO_SUCH_EVENT), /* 27 */
875  _TABLE(NO_SUCH_EVENT), /* 28 */
876  _TABLE(NO_SUCH_EVENT), /* 29 */
877  _TABLE(NO_SUCH_EVENT), /* 30 */
878  _TABLE(NO_SUCH_EVENT), /* 31 */
879 #endif
880 };
881 #undef _TABLE
882 
883 static void
884 rpmdbe_event_notify(DB_ENV * dbenv, u_int32_t event, void * event_info)
885 {
886  void * o = (dbenv ? dbenv->app_private : NULL);
887 fprintf(stderr, "==> %s(%p, %s(%u), %p) app_private %p\n", __FUNCTION__, dbenv, _events[event & 0x1f].n, event, event_info, o);
888 }
889 
890 static void
891 rpmdbe_feedback(DB_ENV * dbenv, int opcode, int percent)
892  /*@*/
893 {
894  dbenv = NULL;
895  dbenv = dbenv;
896  switch (opcode) {
897  case DB_RECOVER:
898  fprintf(stderr, "\rrecovery %d%% complete", percent);
899  (void)fflush(stderr); /* XXX unnecessary? */
900  /*@fallthrough@*/
901  default:
902  break;
903  }
904 }
905 
906 /*@-moduncon@*/ /* FIX: annotate db3 methods */
907 static int db_init(dbiIndex dbi, const char * dbhome,
908  /*@null@*/ const char * dbfile,
909  /*@unused@*/ /*@null@*/ const char * dbsubfile,
910  /*@out@*/ DB_ENV ** dbenvp)
911  /*@globals rpmGlobalMacroContext, h_errno,
912  fileSystem, internalState @*/
913  /*@modifies dbi, *dbenvp, fileSystem, internalState @*/
914 {
915  static int oneshot = 0;
916  uint64_t _physmem = physmem();
917  size_t _ncores = ncores();
918  rpmdb rpmdb = dbi->dbi_rpmdb;
919  DB_ENV *dbenv = NULL;
920  int eflags;
921  int rc;
922  int xx;
923 
924  if (!oneshot) {
925  rpmlog(RPMLOG_DEBUG, D_("rpmdb: cpus %u physmem %uMb\n"),
926  (unsigned)_ncores, (unsigned)(_physmem/(1024 * 1024)));
927  xx = db_env_set_func_open((int (*)(const char *, int, ...))Open);
928  xx = cvtdberr(dbi, "db_env_set_func_open", xx, _debug);
929  oneshot++;
930  }
931 
932  if (dbenvp == NULL)
933  return 1;
934 
935  /* XXX HACK */
936  /*@-assignexpose@*/
937  if (rpmdb->db_errfile == NULL)
938  rpmdb->db_errfile = stderr;
939  /*@=assignexpose@*/
940 
941  eflags = (dbi->dbi_oeflags | dbi->dbi_eflags);
942  /* Try to join, rather than create, the environment. */
943  /* XXX DB_JOINENV is defined to 0 in db-4.5.20 */
944  if (eflags & DB_JOINENV) eflags &= DB_JOINENV;
945  /* XXX DB_RECOVER needs automagic */
946  if (!(eflags & DB_INIT_TXN)) eflags &= ~DB_RECOVER;
947 
948  if (dbfile)
949  rpmlog(RPMLOG_DEBUG, D_("opening db environment %s/%s %s\n"),
950  dbhome, dbfile, prDbiOpenFlags(eflags, 1));
951 
952  /* XXX Can't do RPC w/o host. */
953 #if defined(DB_RPCCLIENT)
954  if (dbi->dbi_host == NULL)
955  dbi->dbi_ecflags &= ~DB_RPCCLIENT;
956 #endif
957 
958  /* XXX DB_THREAD from dbi->dbi_oeflags? */
959  rc = db_env_create(&dbenv, dbi->dbi_ecflags);
960  rc = cvtdberr(dbi, "db_env_create", rc, _debug);
961  if (dbenv == NULL || rc)
962  goto errxit;
963 
964 /*@-noeffectuncon@*/
965 /*@-castfcnptr@*/
966  dbenv->set_errcall(dbenv, (void *)rpmdb->db_errcall);
967 /*@=castfcnptr@*/
968  dbenv->set_errfile(dbenv, rpmdb->db_errfile);
969  dbenv->set_errpfx(dbenv, rpmdb->db_errpfx);
970 /*@=noeffectuncon@*/
971 
972  /* 4.1: dbenv->set_alloc(???) */
973  /* 4.1: dbenv->set_data_dir(???) */
974  /* 4.1: dbenv->set_encrypt(???) */
975 
976  /* 5.3: dbenv->backup() */
977  /* 5.3: dbenv->dbackup() */
978  /* 5.3: dbenv->set_backup_callbacks() */
979  /* 5.3: dbenv->set_backup_config() */
980 
981  /* 5.3: dbenv->set_metadata_dir() */
982 
983  xx = dbenv->set_feedback(dbenv, rpmdbe_feedback);
984  xx = cvtdberr(dbi, "dbenv->set_feedback", xx, _debug);
985  xx = dbenv->set_event_notify(dbenv, rpmdbe_event_notify);
986  xx = cvtdberr(dbi, "dbenv->set_event_notify", xx, _debug);
987 
988  /* 4.1: dbenv->set_flags(???) */
989 
990  /* dbenv->set_paniccall(???) */
991 
992 #if defined(DB_RPCCLIENT)
993  if ((dbi->dbi_ecflags & DB_RPCCLIENT) && dbi->dbi_host) {
994  const char * home;
995  int retry = 0;
996 
997  if ((home = strrchr(dbhome, '/')) != NULL)
998  dbhome = ++home;
999 
1000  while (retry++ < 5) {
1001 /* XXX 3.3.4 change. */
1002  xx = dbenv->set_rpc_server(dbenv, NULL, dbi->dbi_host,
1003  dbi->dbi_cl_timeout, dbi->dbi_sv_timeout, 0);
1004  xx = cvtdberr(dbi, "dbenv->set_server", xx, _debug);
1005  if (!xx)
1006  break;
1007  (void) sleep(15);
1008  }
1009  } else
1010 #endif
1011  {
1012 
1013  { size_t _lo = 16 * 1024 * 1024;
1014  size_t _hi = 512 * 1024 * 1024;
1015  size_t _mp_mmapsize = _physmem; /* XXX default value? */
1016  if (_mp_mmapsize < _lo) _mp_mmapsize = _lo;
1017  if (_mp_mmapsize > _hi) _mp_mmapsize = _hi;
1018  xx = dbenv->set_mp_mmapsize(dbenv, _mp_mmapsize);
1019  xx = cvtdberr(dbi, "dbenv->set_mp_mmapsize", xx, _debug);
1020  }
1021 
1022  if (dbi->dbi_tmpdir) {
1023  const char * root;
1024  const char * tmpdir;
1025 
1026  root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
1027  if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
1028  root = NULL;
1029 /*@-mods@*/
1030  tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL);
1031 /*@=mods@*/
1032  xx = dbenv->set_tmp_dir(dbenv, tmpdir);
1033  xx = cvtdberr(dbi, "dbenv->set_tmp_dir", xx, _debug);
1034  tmpdir = _free(tmpdir);
1035  }
1036  }
1037 
1038 /* ==== Locking: */
1039 #define _RPMDB_NLOCKS 16384
1040  if (eflags & DB_INIT_LOCK) {
1041  uint32_t _lk_max_lockers = _RPMDB_NLOCKS;
1042  uint32_t _lk_max_locks = _RPMDB_NLOCKS;
1043  uint32_t _lk_max_objects = _RPMDB_NLOCKS;
1044 
1045  xx = dbenv->set_lk_max_lockers(dbenv, _lk_max_lockers);
1046  xx = cvtdberr(dbi, "dbenv->set_lk_max_lockers", xx, _debug);
1047  xx = dbenv->set_lk_max_locks(dbenv, _lk_max_locks);
1048  xx = cvtdberr(dbi, "dbenv->set_lk_max_locks", xx, _debug);
1049  xx = dbenv->set_lk_max_objects(dbenv, _lk_max_objects);
1050  xx = cvtdberr(dbi, "dbenv->set_lk_max_objects", xx, _debug);
1051 
1052  { uint32_t _max = 10 * _RPMDB_NLOCKS;
1053  xx = dbenv->mutex_set_max(dbenv, _max);
1054  xx = cvtdberr(dbi, "dbenv->mutex_set_max", xx, _debug);
1055  }
1056 
1057  }
1058 
1059 /* ==== Logging: */
1060  const char *logdir;
1061 
1062  logdir = rpmGetPath(dbhome, "/", "log", NULL);
1063  /*
1064  * Create the /var/lib/rpm/log directory if it doesn't exist (root only).
1065  */
1066  rpmioMkpath(logdir, 0755, getuid(), getgid());
1067 
1068  xx = dbenv->set_lg_dir(dbenv, logdir);
1069  xx = cvtdberr(dbi, "dbenv->set_lg_dir", xx, _debug);
1070 
1071  _free(logdir);
1072 
1073 /* ==== Memory pool: */
1074  if (eflags & DB_INIT_MPOOL) {
1075  uint32_t _lo = 16 * 1024 * 1024;
1076  uint32_t _hi = 512 * 1024 * 1024;
1077  uint32_t _gb = 0;
1078  uint32_t _bytes = _physmem; /* XXX default value? */
1079  int _ncache = 4;
1080  if (_bytes < _lo) _bytes = _lo;
1081  if (_bytes > _hi) _bytes = _hi;
1082  xx = dbenv->set_cache_max(dbenv, _gb, _hi);
1083  xx = cvtdberr(dbi, "dbenv->set_cache_max", xx, _debug);
1084  if (_ncache > 0)
1085  _bytes /= _ncache;
1086  xx = dbenv->set_cachesize(dbenv, _gb, _bytes, _ncache);
1087  xx = cvtdberr(dbi, "dbenv->set_cachesize", xx, _debug);
1088  }
1089 
1090 /* ==== Mutexes: */
1091 /* ==== Replication: */
1092 /* ==== Sequences: */
1093 /* ==== Transactions: */
1094 #ifdef NOTYET /* XXX syscall ACID needs --with-db=internal */
1095  if (eflags & DB_INIT_TXN) {
1096  xx = dbenv->set_app_dispatch(dbenv, logio_dispatch);
1097  xx = cvtdberr(dbi, "dbenv->set_app_dispatch", xx, _debug);
1098  }
1099 #endif
1100 
1101 /* ==== Other: */
1102  if (dbi->dbi_no_fsync) {
1103  xx = db_env_set_func_fsync(db3_fsync_disable);
1104  xx = cvtdberr(dbi, "db_env_set_func_fsync", xx, _debug);
1105  }
1106 
1107  /* XXX Set a default shm_key. */
1108  if ((eflags & DB_SYSTEM_MEM) && dbi->dbi_shmkey == 0) {
1109 #if defined(HAVE_FTOK)
1110  dbi->dbi_shmkey = ftok(dbhome, 0);
1111 #else
1112  dbi->dbi_shmkey = 0x44631380;
1113 #endif
1114  }
1115  if (dbi->dbi_shmkey) {
1116  xx = dbenv->set_shm_key(dbenv, dbi->dbi_shmkey);
1117  xx = cvtdberr(dbi, "dbenv->set_shm_key", xx, _debug);
1118  }
1119 
1120 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5) || (DB_VERSION_MAJOR >= 5)
1121  /* XXX capture dbenv->falchk output on stderr. */
1122 /*@-noeffectuncon@*/
1123  dbenv->set_msgfile(dbenv, rpmdb->db_errfile);
1124 /*@=noeffectuncon@*/
1125  if (dbi->dbi_thread_count >= 8) {
1126  xx = dbenv->set_thread_count(dbenv, dbi->dbi_thread_count);
1127  xx = cvtdberr(dbi, "dbenv->set_thread_count", xx, _debug);
1128  }
1129 #endif
1130 
1131  /* XXX Attempt db_recover -ev (i.e. dbenv w DB_INIT_LOCK) */
1132  if (eflags & DB_RECOVER) {
1133  eflags |= DB_CREATE;
1134  xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
1135  xx = cvtdberr(dbi, "dbenv->set_verbose", xx, _debug);
1136  }
1137 
1138  rc = (dbenv->open)(dbenv, dbhome, eflags, dbi->dbi_perms);
1139  xx = _debug;
1140 #if defined(DB_VERSION_MISMATCH)
1141  if (rc == DB_VERSION_MISMATCH) xx = 0;
1142 #endif
1143  if (rc == EINVAL) xx = 0;
1144  rc = cvtdberr(dbi, "dbenv->open", rc, xx);
1145  if (rc)
1146  goto errxit;
1147 
1148 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5) || (DB_VERSION_MAJOR >= 5)
1149  if (dbi->dbi_thread_count >= 8) {
1150  /* XXX Set pid/tid is_alive probe. */
1151  xx = dbenv->set_isalive(dbenv, db3is_alive);
1152  xx = cvtdberr(dbi, "dbenv->set_isalive", xx, _debug);
1153  /* XXX Clean out stale shared read locks. */
1154  xx = dbenv->failchk(dbenv, 0);
1155  xx = cvtdberr(dbi, "dbenv->failchk", xx, _debug);
1156  if (xx == DB_RUNRECOVERY) {
1157  rc = xx;
1158  goto errxit;
1159  }
1160  }
1161 #endif
1162 
1163  *dbenvp = dbenv;
1164 
1165 DBIDEBUG(dbi, (stderr, "<-- %s(%p(%s),%s,%s,%s,%p) dbenv %p %s\n", __FUNCTION__, dbi, tagName(dbi->dbi_rpmtag), dbhome, dbfile, dbsubfile, dbenvp, dbenv, _EFLAGS(eflags)));
1166 
1167  return 0;
1168 
1169 errxit:
1170  if (dbenv) {
1171  xx = dbenv->close(dbenv, 0);
1172  xx = cvtdberr(dbi, "dbenv->close", xx, _debug);
1173  }
1174  return rc;
1175 }
1176 /*@=moduncon@*/
1177 
1178 #ifdef NOTYET
1179 /*@-mustmod@*/
1180 static int db3remove(dbiIndex dbi, /*@null@*/ const char * dbfile,
1181  /*@unused@*/ /*@null@*/ const char * dbsubfile,
1182  unsigned int flags)
1183  /*@globals fileSystem @*/
1184  /*@modifies dbi, fileSystem @*/
1185 {
1186  DB * db = (DB *) dbi->dbi_db;
1187  int rc;
1188 
1189 assert(db != NULL);
1190  rc = db->remove(db, dbfile, dbsubfile, flags);
1191  rc = cvtdberr(dbi, "db->remove", rc, _debug);
1192 
1193 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%s,%s,0x%x) rc %d\n", __FUNCTION__, dbi, dbfile, dbsubfile, flags, rc));
1194 
1195  return rc;
1196 }
1197 /*@=mustmod@*/
1198 
1199 /*@-mustmod@*/
1200 static int db3rename(dbiIndex dbi, /*@null@*/ const char * dbfile,
1201  /*@unused@*/ /*@null@*/ const char * dbsubfile,
1202  /*@unused@*/ /*@null@*/ const char * newname,
1203  unsigned int flags)
1204  /*@globals fileSystem @*/
1205  /*@modifies dbi, fileSystem @*/
1206 {
1207  DB * db = (DB *) dbi->dbi_db;
1208  int rc;
1209 
1210 assert(db != NULL);
1211  rc = db->rename(db, dbfile, dbsubfile, newname, flags);
1212  rc = cvtdberr(dbi, "db->rename", rc, _debug);
1213 
1214 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%s,%s,%s,0x%x) rc %d %s\n", __FUNCTION__, dbi, dbfile, dbsubfile, newname, flags, rc, _DBCFLAGS(flags)));
1215 
1216  return rc;
1217 }
1218 /*@=mustmod@*/
1219 
1220 /*@-mustmod@*/
1221 static int db3truncate(dbiIndex dbi, unsigned int * countp, unsigned int flags)
1222  /*@globals fileSystem @*/
1223  /*@modifies *countp, fileSystem @*/
1224 {
1225  DB * db = (DB *) dbi->dbi_db;
1226  DB_TXN * _txnid = dbiTxnid(dbi);
1227  int rc;
1228 
1229 assert(db != NULL);
1230  rc = db->truncate(db, _txnid, countp, flags);
1231  rc = cvtdberr(dbi, "db->truncate", rc, _debug);
1232 
1233 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, countp, flags, rc));
1234 
1235  return rc;
1236 }
1237 /*@=mustmod@*/
1238 
1239 /*@-mustmod@*/
1240 static int db3upgrade(dbiIndex dbi, /*@null@*/ const char * dbfile,
1241  unsigned int flags)
1242  /*@globals fileSystem @*/
1243  /*@modifies fileSystem @*/
1244 {
1245  DB * db = (DB *) dbi->dbi_db;
1246  int rc;
1247 
1248 assert(db != NULL);
1249  rc = db->upgrade(db, dbfile, flags);
1250  rc = cvtdberr(dbi, "db->upgrade", rc, _debug);
1251 
1252 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%s,0x%x) rc %d\n", __FUNCTION__, dbi, dbfile, flags, rc));
1253 
1254  return rc;
1255 }
1256 /*@=mustmod@*/
1257 #endif /* NOTYET */
1258 
1259 static int db3sync(dbiIndex dbi, unsigned int flags)
1260  /*@globals fileSystem @*/
1261  /*@modifies fileSystem @*/
1262 {
1263  DB * db = (DB *) dbi->dbi_db;
1264  int rc = 0;
1265  int _printit;
1266 
1267  if (db != NULL)
1268  rc = db->sync(db, flags);
1269  _printit = _debug;
1270  rc = cvtdberr(dbi, "db->sync", rc, _printit);
1271 
1272 DBIDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d\n", __FUNCTION__, dbi, flags, rc));
1273 
1274  return rc;
1275 }
1276 
1277 /*@-mustmod@*/
1278 static int db3exists(dbiIndex dbi, DBT * key, unsigned int flags)
1279  /*@globals fileSystem @*/
1280  /*@modifies fileSystem @*/
1281 {
1282  DB * db = (DB *) dbi->dbi_db;
1283  DB_TXN * _txnid = dbiTxnid(dbi);
1284  int _printit;
1285  int rc;
1286 
1287 assert(db != NULL);
1288  rc = db->exists(db, _txnid, key, flags);
1289  /* XXX DB_NOTFOUND can be returned */
1290  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1291  rc = cvtdberr(dbi, "db->exists", rc, _printit);
1292 
1293 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d %s\n", __FUNCTION__, dbi, key, flags, rc, _KEYDATA(key, NULL, NULL, NULL)));
1294 
1295  return rc;
1296 }
1297 /*@=mustmod@*/
1298 
1299 /*@-mustmod@*/
1300 static int db3seqno(dbiIndex dbi, int64_t * seqnop, unsigned int flags)
1301  /*@globals fileSystem @*/
1302  /*@modifies *seqnop, fileSystem @*/
1303 {
1304  DB * db = (DB *) dbi->dbi_db;
1305  DB_TXN * _txnid = dbiTxnid(dbi);
1306  DB_SEQUENCE * seq = (DB_SEQUENCE *) dbi->dbi_seq;
1307  int32_t _delta = 1;
1308  db_seq_t seqno = 0;
1309  int rc;
1310 
1311 assert(db != NULL);
1312 assert(seq != NULL);
1313 
1314  if (seqnop && *seqnop)
1315  _delta = *seqnop;
1316 
1317  rc = seq->get(seq, _txnid, _delta, &seqno, 0);
1318  rc = cvtdberr(dbi, "seq->get", rc, _debug);
1319  if (rc) goto exit;
1320 
1321  if (seqnop)
1322  *seqnop = seqno;
1323 
1324 exit:
1325 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) seqno %lld rc %d\n", __FUNCTION__, dbi, seqnop, flags, (long long)seqno, rc));
1326 
1327  return rc;
1328 }
1329 /*@=mustmod@*/
1330 
1331 static int db3cdup(dbiIndex dbi, DBC * dbcursor, DBC ** dbcp,
1332  unsigned int flags)
1333  /*@globals fileSystem @*/
1334  /*@modifies *dbcp, fileSystem @*/
1335 {
1336  int rc;
1337 
1338  if (dbcp) *dbcp = NULL;
1339 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1340  rc = dbcursor->dup(dbcursor, dbcp, flags);
1341  rc = cvtdberr(dbi, "dbcursor->dup", rc, _debug);
1342 #else
1343  rc = dbcursor->c_dup(dbcursor, dbcp, flags);
1344  rc = cvtdberr(dbi, "dbcursor->c_dup", rc, _debug);
1345 #endif
1346 
1347 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbcursor, dbcp, flags, rc));
1348 
1349  return rc;
1350 }
1351 
1352 /*@-mustmod@*/
1353 static int db3cclose(dbiIndex dbi, /*@only@*/ /*@null@*/ DBC * dbcursor,
1354  /*@unused@*/ unsigned int flags)
1355  /*@globals fileSystem @*/
1356  /*@modifies dbi, fileSystem @*/
1357 {
1358  int rc = -2;
1359 
1360  /* XXX db3copen error pathways come through here. */
1361  if (dbcursor != NULL) {
1362 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1363  rc = dbcursor->close(dbcursor);
1364  rc = cvtdberr(dbi, "dbcursor->close", rc, _debug);
1365 #else
1366  rc = dbcursor->c_close(dbcursor);
1367  rc = cvtdberr(dbi, "dbcursor->c_close", rc, _debug);
1368 #endif
1369  }
1370 
1371 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,0x%x) rc %d\n", __FUNCTION__, dbi, dbcursor, flags, rc));
1372 
1373  return rc;
1374 }
1375 /*@=mustmod@*/
1376 
1377 static int db3copen(dbiIndex dbi, DB_TXN * txnid,
1378  /*@null@*/ /*@out@*/ DBC ** dbcp, unsigned int dbiflags)
1379  /*@globals fileSystem @*/
1380  /*@modifies dbi, *dbcp, fileSystem @*/
1381 {
1382  DB * db = (DB *) dbi->dbi_db;
1383  DBC * dbcursor = NULL;
1384  int flags;
1385  int rc;
1386 
1387  /* XXX DB_WRITECURSOR cannot be used with sunrpc dbenv. */
1388  assert(db != NULL);
1389  if ((dbiflags & DB_WRITECURSOR) &&
1390  (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_oflags & DB_RDONLY))
1391  {
1392  flags = DB_WRITECURSOR;
1393  } else
1394  flags = 0;
1395 
1396  rc = db->cursor(db, txnid, &dbcursor, flags);
1397  rc = cvtdberr(dbi, "db->cursor", rc, _debug);
1398 
1399  if (dbcp)
1400  *dbcp = dbcursor;
1401  else
1402  (void) db3cclose(dbi, dbcursor, 0);
1403 
1404 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) dbc %p %s rc %d\n", __FUNCTION__, dbi, txnid, dbcp, dbiflags, dbcursor, _DBCOFLAGS(flags), rc));
1405  return rc;
1406 }
1407 
1408 static int db3cput(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
1409  /*@unused@*/ unsigned int flags)
1410  /*@globals fileSystem @*/
1411  /*@modifies fileSystem @*/
1412 {
1413  DB * db = (DB *) dbi->dbi_db;
1414  DB_TXN * _txnid = dbiTxnid(dbi);
1415  int rc;
1416 
1417  assert(db != NULL);
1418  if (dbcursor == NULL) {
1419 flags = 0;
1420  rc = db->put(db, _txnid, key, data, flags);
1421  rc = cvtdberr(dbi, "db->put", rc, _debug);
1422  } else {
1423 flags = DB_KEYLAST;
1424 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1425  rc = dbcursor->put(dbcursor, key, data, flags);
1426  rc = cvtdberr(dbi, "dbcursor->put", rc, _debug);
1427 #else
1428  rc = dbcursor->c_put(dbcursor, key, data, flags);
1429  rc = cvtdberr(dbi, "dbcursor->c_put", rc, _debug);
1430 #endif
1431  }
1432 
1433 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, NULL, data, NULL)));
1434  return rc;
1435 }
1436 
1437 /*@-mustmod@*/
1438 static int db3cget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
1439  unsigned int flags)
1440  /*@globals fileSystem @*/
1441  /*@modifies *dbcursor, *key, *data, fileSystem @*/
1442 {
1443  DB * db = (DB *) dbi->dbi_db;
1444  DB_TXN * _txnid = dbiTxnid(dbi);
1445  int _printit;
1446  int rc;
1447 
1448 assert(db != NULL);
1449  if (dbcursor == NULL) {
1450  /* XXX duplicates require cursors. */
1451  rc = db->get(db, _txnid, key, data, flags);
1452  /* XXX DB_NOTFOUND can be returned */
1453  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1454  rc = cvtdberr(dbi, "db->get", rc, _printit);
1455  } else {
1456 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1457  /* XXX db3 does DB_FIRST on uninitialized cursor */
1458  rc = dbcursor->get(dbcursor, key, data, flags);
1459  /* XXX DB_NOTFOUND can be returned */
1460  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1461  /* XXX Permit DB_BUFFER_SMALL to be returned (more restrictive?) */
1462  _printit = (rc == DB_BUFFER_SMALL ? 0 : _printit);
1463  rc = cvtdberr(dbi, "dbcursor->get", rc, _printit);
1464 #else
1465  /* XXX db3 does DB_FIRST on uninitialized cursor */
1466  rc = dbcursor->c_get(dbcursor, key, data, flags);
1467  /* XXX DB_NOTFOUND can be returned */
1468  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1469  rc = cvtdberr(dbi, "dbcursor->c_get", rc, _printit);
1470 #endif
1471  }
1472 
1473 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, NULL, data, NULL)));
1474  return rc;
1475 }
1476 /*@=mustmod@*/
1477 
1478 /*@-mustmod@*/
1479 static int db3cpget(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * pkey,
1480  DBT * data, unsigned int flags)
1481  /*@globals fileSystem @*/
1482  /*@modifies *dbcursor, *key, *data, fileSystem @*/
1483 {
1484  DB * db = (DB *) dbi->dbi_db;
1485  DB_TXN * _txnid = dbiTxnid(dbi);
1486  int _printit;
1487  int rc;
1488 
1489 assert(db != NULL);
1490  if (dbcursor == NULL) {
1491  /* XXX duplicates require cursors. */
1492  rc = db->pget(db, _txnid, key, pkey, data, flags);
1493  /* XXX DB_NOTFOUND can be returned */
1494  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1495  rc = cvtdberr(dbi, "db->pget", rc, _printit);
1496  } else {
1497 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1498  /* XXX db3 does DB_FIRST on uninitialized cursor */
1499  rc = dbcursor->pget(dbcursor, key, pkey, data, flags);
1500  /* XXX DB_NOTFOUND can be returned */
1501  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1502  rc = cvtdberr(dbi, "dbcursor->pget", rc, _printit);
1503 #else
1504  /* XXX db3 does DB_FIRST on uninitialized cursor */
1505  rc = dbcursor->c_pget(dbcursor, key, pkey, data, flags);
1506  /* XXX DB_NOTFOUND can be returned */
1507  _printit = (rc == DB_NOTFOUND ? 0 : _debug);
1508  rc = cvtdberr(dbi, "dbcursor->c_pget", rc, _printit);
1509 #endif
1510  }
1511 
1512 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, pkey, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, pkey, data, NULL)));
1513  return rc;
1514 }
1515 /*@=mustmod@*/
1516 
1517 /*@-mustmod@*/
1518 static int db3cdel(dbiIndex dbi, DBC * dbcursor, DBT * key, DBT * data,
1519  unsigned int flags)
1520  /*@globals fileSystem @*/
1521  /*@modifies *dbcursor, fileSystem @*/
1522 {
1523  DB * db = (DB *) dbi->dbi_db;
1524  DB_TXN * _txnid = dbiTxnid(dbi);
1525  int rc;
1526 
1527 assert(db != NULL);
1528  if (dbcursor == NULL) {
1529  rc = db->del(db, _txnid, key, flags);
1530  rc = cvtdberr(dbi, "db->del", rc, _debug);
1531  } else {
1532 
1533  /* XXX TODO: insure that cursor is positioned with duplicates */
1534  rc = db3cget(dbi, dbcursor, key, data, DB_SET);
1535 
1536  if (rc == 0) {
1537 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1538  rc = dbcursor->del(dbcursor, flags);
1539  rc = cvtdberr(dbi, "dbcursor->del", rc, _debug);
1540 #else
1541  rc = dbcursor->c_del(dbcursor, flags);
1542  rc = cvtdberr(dbi, "dbcursor->c_del", rc, _debug);
1543 #endif
1544  }
1545  }
1546 
1547 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,%p,0x%x) rc %d %s%s\n", __FUNCTION__, dbi, dbcursor, key, data, flags, rc, _DBCFLAGS(flags), _KEYDATA(key, NULL, data, NULL)));
1548  return rc;
1549 }
1550 /*@=mustmod@*/
1551 
1552 static int db3ccount(dbiIndex dbi, DBC * dbcursor,
1553  /*@null@*/ /*@out@*/ unsigned int * countp,
1554  /*@unused@*/ unsigned int flags)
1555  /*@globals fileSystem @*/
1556  /*@modifies *countp, fileSystem @*/
1557 {
1558  db_recno_t count = 0;
1559  int rc = 0;
1560 
1561  flags = 0;
1562 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 6) || (DB_VERSION_MAJOR >= 5)
1563  rc = dbcursor->count(dbcursor, &count, flags);
1564  rc = cvtdberr(dbi, "dbcursor->count", rc, _debug);
1565 #else
1566  rc = dbcursor->c_count(dbcursor, &count, flags);
1567  rc = cvtdberr(dbi, "dbcursor->c_count", rc, _debug);
1568 #endif
1569  if (countp) *countp = (!rc ? count : 0);
1570 
1571 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p,%p,0x%x) count %d\n", __FUNCTION__, dbi, dbcursor, countp, flags, count));
1572 
1573  return rc;
1574 }
1575 
1576 static int db3byteswapped(dbiIndex dbi) /*@*/
1577 {
1578  DB * db = (DB *) dbi->dbi_db;
1579  int rc = 0;
1580 
1581  if (db != NULL) {
1582  int isswapped = 0;
1583  rc = db->get_byteswapped(db, &isswapped);
1584  if (rc == 0)
1585  rc = isswapped;
1586  }
1587 
1588  return rc;
1589 }
1590 
1591 static int db3stat(dbiIndex dbi, unsigned int flags)
1592  /*@globals fileSystem @*/
1593  /*@modifies dbi, fileSystem @*/
1594 {
1595  DB * db = (DB *) dbi->dbi_db;
1596 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) || (DB_VERSION_MAJOR >= 5)
1597  DB_TXN * _txnid = dbiTxnid(dbi);
1598 #endif
1599  int rc = 0;
1600 
1601  assert(db != NULL);
1602 #if defined(DB_FAST_STAT)
1603  if (flags)
1604  flags = DB_FAST_STAT;
1605  else
1606 #endif
1607  flags = 0;
1608  dbi->dbi_stats = _free(dbi->dbi_stats);
1609 /* XXX 3.3.4 change. */
1610 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) || (DB_VERSION_MAJOR >= 5)
1611  rc = db->stat(db, _txnid, &dbi->dbi_stats, flags);
1612 #else
1613  rc = db->stat(db, &dbi->dbi_stats, flags);
1614 #endif
1615  rc = cvtdberr(dbi, "db->stat", rc, _debug);
1616 
1617 DBIDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d\n", __FUNCTION__, dbi, flags, rc));
1618 
1619  return rc;
1620 }
1621 
1622 /*@-mustmod@*/
1623 static int db3associate(dbiIndex dbi, dbiIndex dbisecondary,
1624  int (*callback)(DB *, const DBT *, const DBT *, DBT *),
1625  unsigned int flags)
1626  /*@globals fileSystem @*/
1627  /*@modifies dbi, fileSystem @*/
1628 {
1629  DB * db = (DB *) dbi->dbi_db;
1630  DB * secondary = (DB *) dbisecondary->dbi_db;
1631  DB_TXN * _txnid = dbiTxnid(dbi);
1632  int rc;
1633 
1634 assert(db != NULL);
1635 
1636 /*@-moduncon@*/ /* FIX: annotate db3 methods */
1637  rc = db->associate(db, _txnid, secondary, callback, flags);
1638 /*@=moduncon@*/
1639  rc = cvtdberr(dbi, "db->associate", rc, _debug);
1640 
1641  if (dbi->dbi_debug || dbisecondary->dbi_debug) {
1642  const char * tag2 = xstrdup(tagName(dbisecondary->dbi_rpmtag));
1643 fprintf(stderr, "<-- %s(%p(%s),%p(%s),%p,0x%x) rc %d %s\n", __FUNCTION__, dbi, tagName(dbi->dbi_rpmtag), dbisecondary, tag2, (void *)callback, flags, rc, _AFLAGS(flags));
1644  tag2 = _free(tag2);
1645  }
1646 
1647  return rc;
1648 }
1649 /*@=mustmod@*/
1650 
1651 /*@-mustmod@*/
1652 static int db3associate_foreign(dbiIndex dbi, dbiIndex dbisecondary,
1653  int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *),
1654  unsigned int flags)
1655  /*@globals fileSystem @*/
1656  /*@modifies dbi, fileSystem @*/
1657 {
1658  int rc = ENOTSUP;;
1659 
1660 #if !defined(__LCLINT__)
1661 /*@-moduncon@*/ /* FIX: annotate db3 methods */
1662 #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 8) || (DB_VERSION_MAJOR >= 5)
1663  DB * db = (DB *) dbi->dbi_db;
1664  DB * secondary = (DB *) dbisecondary->dbi_db;
1665 assert(db != NULL);
1666  rc = db->associate_foreign(db, secondary, callback, flags);
1667 #endif
1668 /*@=moduncon@*/
1669 #endif /* !defined(__LCLINT__) */
1670  rc = cvtdberr(dbi, "db->associate_foreign", rc, _debug);
1671 
1672  if (dbi->dbi_debug || dbisecondary->dbi_debug) {
1673  const char * tag2 = xstrdup(tagName(dbisecondary->dbi_rpmtag));
1674 fprintf(stderr, "<-- %s(%p(%s),%p(%s),%p,0x%x) rc %d %s\n", __FUNCTION__, dbi, tagName(dbi->dbi_rpmtag), dbisecondary, tag2, callback, flags, rc, _AFFLAGS(flags));
1675  tag2 = _free(tag2);
1676  }
1677 
1678  return rc;
1679 }
1680 /*@=mustmod@*/
1681 
1682 /*@-mustmod@*/
1683 static int db3join(dbiIndex dbi, DBC ** curslist, DBC ** dbcp,
1684  unsigned int flags)
1685  /*@globals fileSystem @*/
1686  /*@modifies dbi, fileSystem @*/
1687 {
1688  DB * db = (DB *) dbi->dbi_db;
1689  int rc;
1690 
1691 DBIDEBUG(dbi, (stderr, "--> %s(%p,%p,%p,0x%x)\n", __FUNCTION__, dbi, curslist, dbcp, flags));
1692 assert(db != NULL);
1693 /*@-moduncon@*/ /* FIX: annotate db3 methods */
1694  rc = db->join(db, curslist, dbcp, flags);
1695 /*@=moduncon@*/
1696  rc = cvtdberr(dbi, "db->join", rc, _debug);
1697  return rc;
1698 }
1699 /*@=mustmod@*/
1700 
1701 /*@-moduncon@*/ /* FIX: annotate db3 methods */
1702 static int db3close(/*@only@*/ dbiIndex dbi, /*@unused@*/ unsigned int flags)
1703  /*@globals rpmGlobalMacroContext, h_errno,
1704  fileSystem, internalState @*/
1705  /*@modifies dbi, fileSystem, internalState @*/
1706 {
1707  rpmdb rpmdb = dbi->dbi_rpmdb;
1708  const char * urlfn = NULL;
1709  const char * root;
1710  const char * home;
1711  const char * dbhome;
1712  const char * dbfile;
1713  const char * dbsubfile;
1714  DB * db = (DB *) dbi->dbi_db;
1715  DB_SEQUENCE * seq = (DB_SEQUENCE *) dbi->dbi_seq;
1716  const char * dbiBN = mapTagName(rpmdb, dbi);
1717  int _printit;
1718  int rc = 0, xx;
1719 
1720  flags = 0; /* XXX unused */
1721 
1722  /*
1723  * Get the prefix/root component and directory path.
1724  */
1725  root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
1726  if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
1727  root = NULL;
1728  home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
1729 
1730  /*
1731  * Either the root or directory components may be a URL. Concatenate,
1732  * convert the URL to a path, and add the name of the file.
1733  */
1734  /*@-mods@*/
1735  urlfn = rpmGenPath(root, home, NULL);
1736  /*@=mods@*/
1737  (void) urlPath(urlfn, &dbhome);
1738  if (dbi->dbi_temporary) {
1739  dbfile = NULL;
1740  dbsubfile = NULL;
1741  } else {
1742 #ifdef HACK /* XXX necessary to support dbsubfile */
1743  dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
1744  dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : dbiBN);
1745 #else
1746  dbfile = (dbi->dbi_file ? dbi->dbi_file : dbiBN);
1747  dbsubfile = NULL;
1748 #endif
1749  }
1750 
1751  if (seq) {
1752  rc = seq->close(seq, 0);
1753  rc = cvtdberr(dbi, "seq->close", rc, _debug);
1754  seq = dbi->dbi_seq = NULL;
1755 
1756  rpmlog(RPMLOG_DEBUG, D_("closed db seqno %s/%s\n"),
1757  dbhome, (dbfile ? dbfile : dbiBN));
1758 
1759  }
1760  if (db) {
1761  rc = db->close(db, 0);
1762  /* XXX ignore not found error messages. */
1763  _printit = (rc == ENOENT ? 0 : _debug);
1764  rc = cvtdberr(dbi, "db->close", rc, _printit);
1765  db = dbi->dbi_db = NULL;
1766 
1767  rpmlog(RPMLOG_DEBUG, D_("closed db index %s/%s\n"),
1768  dbhome, (dbfile ? dbfile : dbiBN));
1769 
1770  }
1771 
1772  /* XXX avoid non-root EPERM ACID PANIC with temp Depcache close. */
1773  if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv && !dbi->dbi_temporary) {
1774  if (rpmdb->db_opens == 1) {
1775  /*@-nullstate@*/
1776  xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile);
1777  /*@=nullstate@*/
1778  rpmdb->db_dbenv = NULL;
1779  }
1780  rpmdb->db_opens--;
1781  }
1782 
1783 DBIDEBUG(dbi, (stderr, "<-- %s(%p,0x%x) rc %d\n", __FUNCTION__, dbi, flags, rc));
1784 
1785  dbi->dbi_db = NULL;
1786 
1787  urlfn = _free(urlfn);
1788 
1789  dbi = db3Free(dbi);
1790 
1791  return rc;
1792 }
1793 /*@=moduncon@*/
1794 
1800 static inline unsigned char nibble(char c)
1801  /*@*/
1802 {
1803  if (c >= '0' && c <= '9')
1804  return (unsigned char)(c - '0');
1805  if (c >= 'A' && c <= 'F')
1806  return (unsigned char)((int)(c - 'A') + 10);
1807  if (c >= 'a' && c <= 'f')
1808  return (unsigned char)((int)(c - 'a') + 10);
1809  return '\0';
1810 }
1811 
1812 static int loadDBT(DBT * _r, rpmTag tag, const void * _s, size_t ns)
1813  /*@modifies *_r @*/
1814 {
1815  const char * s = _s;
1816  void * data = NULL;
1817  size_t size = 0;
1818  uint8_t * t = NULL;
1819  uint32_t i;
1820  int xx;
1821 
1822  if (ns == 0) ns = strlen(s);
1823  switch (tag) {
1824  case RPMTAG_FILEDIGESTS:
1825  /* Convert hex to binary, filter out odd hex strings. */
1826  if (ns > 0 && !(ns & 1)) {
1827  ns /= 2;
1828  data = t = xmalloc(ns);
1829  for (i = 0; i < ns; i++, t++, s += 2) {
1830  if (!(isxdigit(s[0]) && isxdigit(s[1])))
1831  /*@loopbreak@*/ break;
1832  *t = (uint8_t) (nibble(s[0]) << 4) | nibble(s[1]);
1833  }
1834  if (i == ns)
1835  size = ns;
1836  else
1837  data = _free(data);
1838  }
1839  break;
1840  case RPMTAG_PUBKEYS:
1841  /* Extract pubkey id from the base64 blob. */
1842  t = xmalloc(32);
1843  if ((xx = pgpExtractPubkeyFingerprint(s, t)) > 0) {
1844  data = t;
1845  size = xx;
1846  } else
1847  t = _free(t);
1848  break;
1849  default:
1850  data = (void *) memcpy(xmalloc(ns), _s, ns);
1851  size = ns;
1852  break;
1853  }
1854  if ((_r->data = data) != NULL) _r->flags |= DB_DBT_APPMALLOC;
1855  return (_r->size = size);
1856 }
1857 
1858 static int uint32Cmp(const void * _a, const void * _b)
1859  /*@*/
1860 {
1861  const uint32_t * a = _a;
1862  const uint32_t * b = _b;
1863  return ((*a < *b) ? -1 :
1864  ((*a > *b) ? 1 : 0));
1865 }
1866 
1867 static int uint64Cmp(const void * _a, const void * _b)
1868  /*@*/
1869 {
1870  const uint64_t * a = _a;
1871  const uint64_t * b = _b;
1872  return ((*a < *b) ? -1 :
1873  ((*a > *b) ? 1 : 0));
1874 }
1875 
1876 static int
1877 db3Acallback(DB * db, const DBT * key, const DBT * data, DBT * _r)
1878  /*@globals internalState @*/
1879  /*@modifies *_r, internalState @*/
1881  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1882  HE_t Fhe = (HE_t) memset(alloca(sizeof(*Fhe)), 0, sizeof(*Fhe));
1883 #ifdef NOTYET
1884  HE_t FMhe = (HE_t) memset(alloca(sizeof(*FMhe)), 0, sizeof(*FMhe));
1885 #endif
1889  uint32_t hdrNum;
1890  DBT * A = NULL;
1891  const char * s = NULL;
1892  size_t ns = 0;
1893  int rc = DB_DONOTINDEX; /* assume no-op */
1894  uint32_t i;
1895  int xx;
1896 
1897 assert(key->size == sizeof(hdrNum));
1898  memcpy(&hdrNum, key->data, key->size);
1899  hdrNum = _ntoh_ui(hdrNum);
1900 
1901  /* XXX Don't index the header instance counter at record 0. */
1902  if (hdrNum == 0)
1903  goto exit;
1904 
1905 assert(dbi);
1906  rpmdb = dbi->dbi_rpmdb;
1907 assert(rpmdb);
1908 
1909  /* XXX Track the maximum primary key value. */
1910  if (hdrNum > rpmdb->db_maxkey)
1911  rpmdb->db_maxkey = hdrNum;
1912 
1913  h = headerLink(rpmdb->db_h);
1914  if (h == NULL) {
1915  /* XXX needs PROT_READ somewhen. */
1916  h = headerLoad(data->data);
1917  if (h == NULL) {
1919  _("db3: header #%u cannot be loaded -- skipping.\n"),
1920  (unsigned)hdrNum);
1921  goto exit;
1922  }
1923  }
1924 
1925  memset(_r, 0, sizeof(*_r));
1926 
1927  he->tag = dbi->dbi_rpmtag;
1928  if (!headerGet(h, he, 0))
1929  goto exit;
1930 
1931  /* XXX catch busted headerGet() rc on RPMTAG_FILEPATHS w empty list. */
1932 assert(he->p.ptr != NULL && he->c > 0);
1933 
1934  /* Retrieve other tags needed for filtering decisions. */
1935  switch (he->tag) {
1936  default:
1937  break;
1938 #ifdef NOTYET
1939  case RPMTAG_BASENAMES:
1940  case RPMTAG_FILEPATHS:
1941  /* XXX Add the pesky trailing '/' to directories. */
1942  FMhe->tag = RPMTAG_FILEMODES;
1943  (void) headerGet(h, FMhe, 0);
1944  break;
1945 #endif
1947  case RPMTAG_REQUIRENAME:
1948  /* The Requires: F is needed to filter install context dependencies. */
1949  Fhe->tag = RPMTAG_REQUIREFLAGS;
1950  (void) headerGet(h, Fhe, 0);
1951  break;
1952  }
1953 
1954  switch (he->t) {
1955  default:
1956 assert(0);
1957  /*@notreached@*/ break;
1958  case RPM_UINT8_TYPE: /* XXX coerce to uint32_t */
1959  { uint8_t * _u = (uint8_t *) he->p.ui8p;
1960  he->p.ui32p = xmalloc(he->c * sizeof(*he->p.ui32p));
1961  for (i = 0; i < he->c; i++)
1962  he->p.ui32p[i] = _u[i];
1963  _u = _free(_u);
1964  goto _ifill;
1965  } /*@notreached@*/ break;
1966  case RPM_UINT16_TYPE: /* XXX coerce to uint32_t */
1967  { uint16_t * _u = (uint16_t *) he->p.ui16p;
1968  he->p.ui32p = xmalloc(he->c * sizeof(*he->p.ui32p));
1969  for (i = 0; i < he->c; i++)
1970  he->p.ui32p[i] = _u[i];
1971  _u = _free(_u);
1972  goto _ifill;
1973  } /*@notreached@*/ break;
1974  case RPM_UINT32_TYPE:
1975 _ifill:
1976  { uint32_t * _u = (uint32_t *) he->p.ui32p;
1977  size_t _ulen = sizeof(*_u);
1978  uint32_t _ube; /* XXX network order integer keys */
1979 
1980  /* Drop the transaction id usecs field (if present) when indexing. */
1981  switch (he->tag) {
1982  case RPMTAG_INSTALLTID:
1983  case RPMTAG_REMOVETID:
1984  he->c = 1;
1985  /*@innerbreak@*/ break;
1986  default:
1987  /*@innerbreak@*/ break;
1988  }
1989  if (he->c == 1) {
1990  _ube = _hton_ui(*_u); /* XXX network order integer keys */
1991  /* XXX is it worth avoiding the realloc here? */
1992  xx = loadDBT(_r, he->tag, &_ube, _ulen);
1993  break;
1994  }
1996  _r->data = A = xcalloc(he->c, sizeof(*A));
1997  _r->size = 0;
1998  if (he->c > 1)
1999  qsort(_u, he->c, _ulen, uint32Cmp);
2000  for (i = 0; i < he->c; i++, _u++) {
2001  /* Don't add identical (key,val) item to secondary. */
2002  if (i > 0 && _u[-1] == _u[0])
2003  continue;
2004  _ube = _hton_ui(*_u); /* XXX network order integer keys */
2005  if (!loadDBT(A, he->tag, &_ube, _ulen))
2006  continue;
2007  A++;
2008  _r->size++;
2009  }
2010  } break;
2011  case RPM_UINT64_TYPE:
2012  { uint64_t * _u = (uint64_t *) he->p.ui64p;
2013  size_t _ulen = sizeof(*_u);
2014  uint64_t _ube; /* XXX network order integer keys */
2015 
2016  if (he->c == 1) {
2017  _ube = _hton_ul(*_u); /* XXX network order integer keys */
2018  /* XXX is it worth avoiding the realloc here? */
2019  xx = loadDBT(_r, he->tag, _u, _ulen);
2020  break;
2021  }
2023  _r->data = A = (DBT *) xcalloc(he->c, sizeof(*A));
2024  _r->size = 0;
2025  if (he->c > 1)
2026  qsort(_u, he->c, _ulen, uint64Cmp);
2027  for (i = 0; i < he->c; i++, _u++) {
2028  /* Don't add identical (key,val) item to secondary. */
2029  if (i > 0 && _u[-1] == _u[0])
2030  continue;
2031  _ube = _hton_ul(*_u); /* XXX network order integer keys */
2032  if (!loadDBT(A, he->tag, &_ube, _ulen))
2033  continue;
2034  A++;
2035  _r->size++;
2036  }
2037  } break;
2038  case RPM_BIN_TYPE:
2039  s = (char *) he->p.ptr; ns = he->c;
2040  /* XXX is it worth avoiding the realloc here? */
2041  if (ns > 0) /* No "" empty keys please. */
2042  xx = loadDBT(_r, he->tag, s, ns);
2043  break;
2044  case RPM_I18NSTRING_TYPE: /* XXX never occurs */
2045  case RPM_STRING_TYPE:
2046  s = he->p.str; ns = strlen(s);
2047  /* XXX is it worth avoiding the realloc here? */
2048  if (ns > 0) /* No "" empty keys please. */
2049  xx = loadDBT(_r, he->tag, s, ns);
2050  break;
2051  case RPM_STRING_ARRAY_TYPE:
2052  if (he->c == 1) {
2053  s = he->p.argv[0]; ns = strlen(s);
2054  if (ns > 0) /* No "" empty keys please. */
2055  xx = loadDBT(_r, he->tag, s, ns);
2056  } else {
2057  static double e = 1.0e-5;
2058  static size_t nmin = 16;
2059  size_t n = 2 * (he->c > nmin ? he->c : nmin);
2060  size_t m = 0;
2061  size_t k = 0;
2062  rpmbf bf;
2063  rpmbfParams(n, e, &m, &k);
2064  bf = rpmbfNew(m, k, 0);
2065 
2067  _r->data = A = (DBT *) xcalloc(he->c, sizeof(*A));
2068  _r->size = 0;
2069  for (i = 0; i < he->c; i++) {
2070  s = he->p.argv[i]; ns = strlen(s);
2071 
2072  /* XXX Skip YAML "- ..." lead-in mark up if present. */
2073  if (s[0] == '-' && s[1] == ' ') {
2074  s += 2, ns -= 2;
2075  }
2076 
2077 #ifdef NOTYET
2078  /* Add the pesky trailing '/' to directories. */
2079  if (FMhe->p.ui16p && !S_ISREG((mode_t)FMhe->p.ui16p[i])) {
2080  continue;
2081  }
2082 #endif
2083 
2084  if (ns == 0) /* No "" empty keys please. */
2085  continue;
2086 
2087  /* Filter install context dependencies. */
2088  if (Fhe->p.ui32p && isInstallPreReq(Fhe->p.ui32p[i]))
2089  continue;
2090 
2091  /* Don't add identical (key,val) item to secondary. */
2092  if (rpmbfChk(bf, s, ns) > 0)
2093  continue;
2094  xx = rpmbfAdd(bf, s, ns);
2095 assert(xx == 0);
2096 
2097  if (!loadDBT(A, he->tag, s, ns))
2098  continue;
2099  A++;
2100  _r->size++;
2101  }
2102  bf = rpmbfFree(bf);
2103  }
2104  break;
2105  }
2106  if (_r->data && _r->size > 0)
2107  rc = 0;
2108  else if (_r->flags & DB_DBT_APPMALLOC) {
2109  _r->data = _free(_r->data);
2110  memset(_r, 0, sizeof(*_r));
2111  }
2112 
2113 exit:
2114  if (!dbi->dbi_no_dbsync && rc != DB_DONOTINDEX)
2115  xx = dbiSync(dbi, 0);
2116 #ifdef NOTYET
2117  FMhe->p.ptr = _free(FMhe->p.ptr);
2118 #endif
2119  Fhe->p.ptr = _free(Fhe->p.ptr);
2120  he->p.ptr = _free(he->p.ptr);
2121  h = headerFree(h);
2122 
2123 DBIDEBUG(dbi, (stderr, "<-- %s(%p, %p, %p, %p) rc %d\n\tdbi %p(%s) rpmdb %p h %p %s\n", __FUNCTION__, db, key, data, _r, rc, dbi, tagName(dbi->dbi_rpmtag), rpmdb, h, _KEYDATA(key, NULL, data, _r)));
2124 
2125  return rc;
2126 }
2127 
2128 static int seqid_init(dbiIndex dbi, const char * keyp, size_t keylen,
2129  DB_SEQUENCE ** seqp)
2130  /*@modifies *seqp @*/
2131 {
2132  DB * db = (DB *) dbi->dbi_db;
2133  DBT k = {0};
2134  DB_TXN * _txnid = dbiTxnid(dbi);
2135  DB_SEQUENCE * seq = NULL;
2136  db_seq_t _rangemin = -922337203685477600LL;
2137  db_seq_t _rangemax = 922337203685477600LL;
2138  db_seq_t _value = 0;
2139  int32_t _cachesize = 0;
2140  uint32_t _flags = DB_SEQ_INC;
2141  uint32_t _oflags = DB_CREATE;
2142  int rc;
2143 
2144 assert(db != NULL);
2145  if (seqp) *seqp = NULL;
2146 
2147 /*@-moduncon@*/
2148  rc = db_sequence_create(&seq, db, 0);
2149 /*@=moduncon@*/
2150  rc = cvtdberr(dbi, "db_sequence_create", rc, _debug);
2151  if (rc) goto exit;
2152 assert(seq != NULL);
2153 
2154  if (dbi->dbi_seq_cachesize) {
2155  _cachesize = dbi->dbi_seq_cachesize;
2156  rc = seq->set_cachesize(seq, _cachesize);
2157  rc = cvtdberr(dbi, "seq->set_cachesize", rc, _debug);
2158  if (rc) goto exit;
2159  }
2160 
2161  if (dbi->dbi_seq_initial)
2162  _value = dbi->dbi_seq_initial;
2163  if (_value <= 0) _value = 1;
2164  rc = seq->initial_value(seq, _value);
2165  rc = cvtdberr(dbi, "seq->initial_value", rc, _debug);
2166  if (rc) goto exit;
2167 
2168  if (dbi->dbi_seq_min)
2169  _rangemin = dbi->dbi_seq_min;
2170  if (dbi->dbi_seq_max)
2171  _rangemax = dbi->dbi_seq_max;
2172  rc = seq->set_range(seq, _rangemin, _rangemax);
2173  rc = cvtdberr(dbi, "seq->set_range", rc, _debug);
2174  if (rc) goto exit;
2175 
2176  if (dbi->dbi_seq_flags)
2177  _flags = dbi->dbi_seq_flags;
2178  rc = seq->set_flags(seq, _flags);
2179  rc = cvtdberr(dbi, "seq->set_flags", rc, _debug);
2180  if (rc) goto exit;
2181 
2182  k.data = (void *)keyp;
2183  k.size = (u_int32_t) (keylen > 0 ? keylen : strlen(keyp));
2184  rc = seq->open(seq, _txnid, &k, _oflags);
2185  rc = cvtdberr(dbi, "seq->open", rc, _debug);
2186  if (rc) goto exit;
2187 
2188 exit:
2189  if (rc == 0 && seqp != NULL)
2190  *seqp = seq;
2191  else {
2192  int xx = seq->close(seq, 0);
2193  xx = cvtdberr(dbi, "seq->close", xx, _debug);
2194  }
2195 
2196 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%p[%u],%p) seq %p rc %d %s\n", __FUNCTION__, dbi, keyp, (unsigned)keylen, seqp, (seqp ? *seqp : NULL), rc, _KEYDATA(&k, NULL, NULL, NULL)));
2197 
2198  return rc;
2199 }
2200 
2208 static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip)
2209  /*@globals rpmGlobalMacroContext, h_errno,
2210  fileSystem, internalState @*/
2211  /*@modifies *dbip, fileSystem, internalState @*/
2212 {
2213  /*@-nestedextern -shadow@*/
2214  extern struct _dbiVec db3vec;
2215  /*@=nestedextern =shadow@*/
2216  const char * urlfn = NULL;
2217  const char * root;
2218  const char * home;
2219  const char * dbhome;
2220  const char * dbfile;
2221  const char * dbsubfile;
2222  const char * dbiBN;
2223  dbiIndex dbi = NULL;
2224  int rc = 0;
2225  int xx;
2226 
2227  DB * db = NULL;
2228  DB_ENV * dbenv = NULL;
2229  DB_TXN * _txnid = NULL;
2230  DBTYPE dbi_type = DB_UNKNOWN;
2231  rpmuint32_t oflags;
2232  int _printit;
2233 
2234  if (dbip)
2235  *dbip = NULL;
2236 
2237  /*
2238  * Parse db configuration parameters.
2239  */
2240  /*@-mods@*/
2241  if ((dbi = db3New(rpmdb, rpmtag)) == NULL)
2242  /*@-nullstate@*/
2243  return 1;
2244  /*@=nullstate@*/
2245  /*@=mods@*/
2246  dbi->dbi_api = DB_VERSION_MAJOR;
2247  dbiBN = mapTagName(rpmdb, dbi);
2248  dbi->dbi_txnid = NULL;
2249  _txnid = NULL;
2250 
2251  /*
2252  * Get the prefix/root component and directory path.
2253  */
2254  root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root);
2255  if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone)
2256  root = NULL;
2257  home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home);
2258 
2259  /*
2260  * Either the root or directory components may be a URL. Concatenate,
2261  * convert the URL to a path, and add the name of the file.
2262  */
2263  /*@-mods@*/
2264  urlfn = rpmGenPath(root, home, NULL);
2265  /*@=mods@*/
2266  (void) urlPath(urlfn, &dbhome);
2267  if (dbi->dbi_temporary) {
2268  dbfile = NULL;
2269  dbsubfile = NULL;
2270  } else {
2271 #ifdef HACK /* XXX necessary to support dbsubfile */
2272  dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename);
2273  dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : dbiBN);
2274 #else
2275  dbfile = (dbi->dbi_file ? dbi->dbi_file : dbiBN);
2276  dbsubfile = NULL;
2277 #endif
2278  }
2279 
2280  oflags = (dbi->dbi_oeflags | dbi->dbi_oflags);
2281  /* XXX permit DB_TRUNCATE iff a secondary index. */
2282  if (dbi->dbi_primary) oflags &= ~DB_TRUNCATE;
2283 
2284 #if 0 /* XXX rpmdb: illegal flag combination specified to DB->open */
2285  if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL;
2286 #endif
2287 
2288  /*
2289  * Map open mode flags onto configured database/environment flags.
2290  */
2291  if (dbi->dbi_temporary) {
2292  oflags |= DB_CREATE;
2293  dbi->dbi_oeflags |= DB_CREATE;
2294  oflags &= ~DB_RDONLY;
2295  dbi->dbi_oflags &= ~DB_RDONLY;
2296  } else {
2297  if (!(dbi->dbi_mode & (O_RDWR|O_WRONLY))) oflags |= DB_RDONLY;
2298  if (dbi->dbi_mode & O_CREAT) {
2299  oflags |= DB_CREATE;
2300  dbi->dbi_oeflags |= DB_CREATE;
2301  }
2302  /* XXX permit DB_TRUNCATE iff a secondary index. */
2303  if (dbi->dbi_primary && (dbi->dbi_mode & O_TRUNC))
2304  oflags |= DB_TRUNCATE;
2305  }
2306 
2307  /*
2308  * Create the /var/lib/rpm directory if it doesn't exist (root only).
2309  */
2310  (void) rpmioMkpath(dbhome, 0755, getuid(), getgid());
2311 
2312  /*
2313  * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open.
2314  */
2315  if (dbi->dbi_use_dbenv) {
2316 
2317  if (access(dbhome, W_OK) == -1) {
2318 
2319  /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */
2320  oflags &= ~DB_CREATE;
2321  oflags &= ~DB_AUTO_COMMIT;
2322 
2323  /* ... but DBENV->open might still need DB_CREATE ... */
2324  if (dbi->dbi_eflags & DB_PRIVATE) {
2325  dbi->dbi_eflags &= ~DB_JOINENV;
2326  } else {
2327  dbi->dbi_eflags |= DB_JOINENV;
2328  dbi->dbi_oeflags &= ~DB_CREATE;
2329 #ifdef DYING
2330  dbi->dbi_oeflags &= ~DB_THREAD;
2331 #endif
2332  /* ... but, unless DB_PRIVATE is used, skip DBENV. */
2333  dbi->dbi_use_dbenv = 0;
2334  }
2335 
2336  /* ... DB_RDONLY maps dbhome perms across files ... */
2337  if (dbi->dbi_temporary) {
2338  oflags |= DB_CREATE;
2339  dbi->dbi_oeflags |= DB_CREATE;
2340  oflags &= ~DB_RDONLY;
2341  dbi->dbi_oflags &= ~DB_RDONLY;
2342  } else {
2343  oflags |= DB_RDONLY;
2344  /* ... and DB_WRITECURSOR won't be needed ... */
2345  dbi->dbi_oflags |= DB_RDONLY;
2346  }
2347 
2348  } else { /* dbhome is writable, check for persistent dbenv. */
2349  /*@-mods@*/
2350  const char * dbf = rpmGetPath(dbhome, "/__db.001", NULL);
2351  /*@=mods@*/
2352 
2353 #if defined(RPM_VENDOR_OPENPKG) /* bdb-allow-zero-sized-files */
2354  /* Make sure RPM passes DB_CREATE to Berkeley-DB also
2355  if file exists, but is (still) zero-sized. */
2356  struct stat sb;
2357  long size = -1;
2358  if (stat(dbf, &sb) == 0)
2359  size = (long)sb.st_size;
2360  if (access(dbf, F_OK) == -1 || size == 0)
2361 #else
2362  if (access(dbf, F_OK) == -1)
2363 #endif
2364  {
2365  /* ... non-existent (or unwritable) DBENV, will create ... */
2366  dbi->dbi_oeflags |= DB_CREATE;
2367  dbi->dbi_eflags &= ~DB_JOINENV;
2368  } else {
2369  /* ... pre-existent (or bogus) DBENV, will join ... */
2370  if (dbi->dbi_eflags & DB_PRIVATE) {
2371  dbi->dbi_eflags &= ~DB_JOINENV;
2372  } else {
2373  dbi->dbi_eflags |= DB_JOINENV;
2374  dbi->dbi_oeflags &= ~DB_CREATE;
2375 #ifdef DYING
2376  dbi->dbi_oeflags &= ~DB_THREAD;
2377 #endif
2378  }
2379  }
2380  /* ... transactionally protected open's need DB_AUTO_COMMIT ... */
2381  if (rpmdb->_dbi[0]
2382  && rpmdb->_dbi[0]->dbi_eflags & DB_INIT_TXN)
2383  oflags |= DB_AUTO_COMMIT;
2384  dbf = _free(dbf);
2385  }
2386  }
2387 
2388  /*
2389  * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open.
2390  */
2391  if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) {
2392  /* dbhome is writable, and DB->open flags may conflict. */
2393  const char * dbfn = (dbfile ? dbfile : dbiBN);
2394  /*@-mods@*/
2395  const char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL);
2396  /*@=mods@*/
2397 
2398  if (access(dbf, F_OK) == -1) {
2399  /* File does not exist, DB->open might create ... */
2400  oflags &= ~DB_RDONLY;
2401  } else {
2402  /* File exists, DB->open need not create ... */
2403  oflags &= ~DB_CREATE;
2404  }
2405 
2406  /* Only writers need DB_WRITECURSOR ... */
2407  if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) {
2408  dbi->dbi_oflags &= ~DB_RDONLY;
2409  } else {
2410  dbi->dbi_oflags |= DB_RDONLY;
2411  }
2412  dbf = _free(dbf);
2413  }
2414 
2415  /*
2416  * Set db type if creating or truncating.
2417  */
2418  if (oflags & (DB_CREATE|DB_TRUNCATE))
2419  dbi_type = (DBTYPE) dbi->dbi_type;
2420 
2421  if (dbi->dbi_use_dbenv) {
2422  /*@-mods@*/
2423  if (rpmdb->db_dbenv == NULL) {
2424  rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
2425  switch (rc) {
2426  default:
2427  break;
2428  case DB_RUNRECOVERY:
2429  if (getuid() != 0)
2430  break;
2431  rpmlog(RPMLOG_NOTICE, _("Re-opening dbenv with DB_RECOVER ...\n"));
2432  /* XXX Attempt db_recover -ev (i.e. dbenv w DB_INIT_LOCK) */
2433  dbi->dbi_eflags |= DB_RECOVER;
2434  rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
2435  dbi->dbi_eflags &= ~DB_RECOVER;
2436  if (rc) {
2437  rpmlog(RPMLOG_NOTICE, _("\nrecovery failed. Exiting ...\n"));
2438  exit(EXIT_FAILURE);
2439  }
2440  rpmlog(RPMLOG_NOTICE, _(".\nrecovery succeeded.\n"));
2441 assert(dbenv);
2442  rpmdb->db_dbenv = dbenv;
2443  rpmdb->db_opens = 1;
2444  break;
2445 
2446 #if defined(DB_VERSION_MISMATCH) /* Nuke __db* files and retry open once. */
2447  case DB_VERSION_MISMATCH:
2448 #endif
2449  case EINVAL:
2450  if (getuid() != 0)
2451  break;
2452  { char * filename = (char *) alloca(BUFSIZ);
2453  struct stat st;
2454  int i;
2455 
2456  for (i = 0; i < 16; i++) {
2457  sprintf(filename, "%s/__db.%03d", dbhome, i);
2458  (void)rpmCleanPath(filename);
2459  if (Stat(filename, &st)
2460  && (errno == ENOENT || errno == EINVAL))
2461  continue;
2462  xx = Unlink(filename);
2463  }
2464  }
2465  dbi->dbi_oeflags |= DB_CREATE;
2466  dbi->dbi_eflags &= ~DB_JOINENV;
2467  rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv);
2468  /* XXX db_init EINVAL was masked. */
2469  rc = cvtdberr(dbi, "dbenv->open", rc, _debug);
2470  if (rc)
2471  break;
2472  /*@fallthrough@*/
2473  case 0:
2474 assert(dbenv);
2475  rpmdb->db_dbenv = dbenv;
2476  rpmdb->db_opens = 1;
2477  break;
2478  }
2479  } else {
2480 assert(rpmdb && rpmdb->db_dbenv);
2481  dbenv = (DB_ENV *) rpmdb->db_dbenv;
2482  rpmdb->db_opens++;
2483  }
2484  /*@=mods@*/
2485  }
2486 
2487  rpmlog(RPMLOG_DEBUG, D_("opening db index %s/%s %s mode=0x%x\n"),
2488  dbhome, (dbfile ? dbfile : dbiBN),
2489  prDbiOpenFlags(oflags, 0), dbi->dbi_mode);
2490 
2491  if (rc == 0) {
2492  static int _lockdbfd = 0;
2493 
2494  /*@-moduncon@*/ /* FIX: annotate db3 methods */
2495  rc = db_create(&db, dbenv, dbi->dbi_cflags);
2496  /*@=moduncon@*/
2497  rc = cvtdberr(dbi, "db_create", rc, _debug);
2498  if (rc == 0 && db != NULL) {
2499 
2500 /* XXX 3.3.4 change. */
2501  if (rc == 0 &&
2502  rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free)
2503  {
2504  rc = db->set_alloc(db,
2505  rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free);
2506  rc = cvtdberr(dbi, "db->set_alloc", rc, _debug);
2507  }
2508 
2509 /* 4.1: db->set_cache_priority(???) */
2510 /* 4.1: db->set_encrypt(???) */
2511 
2512 /* 5.3: db->set_lk_exclusive(???) */
2513 
2514  if (rc == 0 && dbi->dbi_lorder) {
2515  rc = db->set_lorder(db, dbi->dbi_lorder);
2516  rc = cvtdberr(dbi, "db->set_lorder", rc, _debug);
2517  }
2518  if (rc == 0 && dbi->dbi_pagesize) {
2519  rc = db->set_pagesize(db, dbi->dbi_pagesize);
2520  rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug);
2521  }
2522  /* 4.1: db->set_paniccall(???) */
2523  if (rc == 0 && oflags & DB_CREATE) {
2524  switch(dbi->dbi_type) {
2525  default:
2526  case DB_HASH:
2527  if (dbi->dbi_h_ffactor) {
2528  rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor);
2529  rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug);
2530  if (rc) break;
2531  }
2532  if (dbi->dbi_h_nelem) {
2533  rc = db->set_h_nelem(db, dbi->dbi_h_nelem);
2534  rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug);
2535  if (rc) break;
2536  }
2537  if (dbi->dbi_h_flags) {
2538  rc = db->set_flags(db, dbi->dbi_h_flags);
2539  rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug);
2540  if (rc) break;
2541  }
2542  if (dbi->dbi_h_hash_fcn) {
2543  rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn);
2544  rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug);
2545  if (rc) break;
2546  }
2547  if (dbi->dbi_h_dup_compare_fcn) {
2548  rc = db->set_h_compare(db, dbi->dbi_h_dup_compare_fcn);
2549  rc = cvtdberr(dbi, "db->set_h_compare", rc, _debug);
2550  if (rc) break;
2551  }
2552  break;
2553  case DB_BTREE:
2554 /* 4.1: db->set_append_recno(???) */
2555  if (dbi->dbi_bt_flags) {
2556  rc = db->set_flags(db, dbi->dbi_bt_flags);
2557  rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug);
2558  if (rc) break;
2559  }
2560  if (dbi->dbi_bt_minkey) {
2561  rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey);
2562  rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug);
2563  if (rc) break;
2564  }
2565  if (dbi->dbi_bt_compare_fcn) {
2566  rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn);
2567  rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug);
2568  if (rc) break;
2569  }
2570  if (dbi->dbi_bt_dup_compare_fcn) {
2571  rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn);
2572  rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug);
2573  if (rc) break;
2574  }
2575  if (dbi->dbi_bt_prefix_fcn) {
2576  rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn);
2577  rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug);
2578  if (rc) break;
2579  }
2580  break;
2581  case DB_RECNO:
2582 /* 4.1: db->set_append_recno(???) */
2583  if (dbi->dbi_re_delim) {
2584  rc = db->set_re_delim(db, dbi->dbi_re_delim);
2585  rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug);
2586  if (rc) break;
2587  }
2588  if (dbi->dbi_re_len) {
2589  rc = db->set_re_len(db, dbi->dbi_re_len);
2590  rc = cvtdberr(dbi, "db->set_re_len", rc, _debug);
2591  if (rc) break;
2592  }
2593  if (dbi->dbi_re_pad) {
2594  rc = db->set_re_pad(db, dbi->dbi_re_pad);
2595  rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug);
2596  if (rc) break;
2597  }
2598  if (dbi->dbi_re_source) {
2599  rc = db->set_re_source(db, dbi->dbi_re_source);
2600  rc = cvtdberr(dbi, "db->set_re_source", rc, _debug);
2601  if (rc) break;
2602  }
2603  break;
2604  case DB_QUEUE:
2605  if (dbi->dbi_q_extentsize) {
2606  rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize);
2607  rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug);
2608  if (rc) break;
2609  }
2610  break;
2611 #if (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 2) || (DB_VERSION_MAJOR >= 6)
2612  case DB_HEAP:
2613  if (dbi->dbi_heapsize) {
2614  static uint32_t _gbytes = 0;
2615  uint32_t _bytes = dbi->dbi_heapsize;
2616  static uint32_t _flags = 0;
2617 assert(dbi->dbi_heapsize >= (3 * dbi->dbi_pagesize));
2618  rc = db->set_heapsize(db, _gbytes, _bytes, _flags);
2619  rc = cvtdberr(dbi, "db->set_heapsize", rc, _debug);
2620  if (rc) break;
2621  }
2622 #if (DB_VERSION_MAJOR == 5 && DB_VERSION_MINOR >= 3) || (DB_VERSION_MAJOR >= 6)
2623  if (dbi->dbi_heap_regionsize) {
2624  uint32_t _npages = dbi->dbi_heap_regionsize;
2625 /* XXX assert (_npages <= "maximum region size for the database's page size");*/
2626  rc = db->set_heap_regionsize(db, _npages);
2627  rc = cvtdberr(dbi, "db->set_heap_regionsize", rc, _debug);
2628  if (rc) break;
2629  }
2630 #endif
2631  break;
2632 #endif
2633  }
2634  }
2635 
2636  if (rc == 0) {
2637  const char * dbfullpath;
2638  const char * dbpath;
2639  char * t;
2640  int nb;
2641 
2642  nb = strlen(dbhome);
2643  if (dbfile) nb += 1 + strlen(dbfile);
2644  dbfullpath = t = (char *) alloca(nb + 1);
2645 
2646  t = stpcpy(t, dbhome);
2647  if (dbfile)
2648  t = stpcpy( stpcpy( t, "/"), dbfile);
2649 #ifdef HACK /* XXX necessary to support dbsubfile */
2650  dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary)
2651  ? dbfullpath : dbfile;
2652 #else
2653 #ifdef PLD_CHROOT
2654  /* XXX Make dbpath relative. */
2655  dbpath = (!dbi->dbi_use_dbenv)
2656  ? dbfullpath : dbfile;
2657 #else
2658  dbpath = (!dbi->dbi_temporary)
2659  ? dbfullpath : dbfile;
2660 #endif /* PLD_CHROOT */
2661 #endif /* HACK */
2662 
2663  rc = (db->open)(db, _txnid, dbpath, dbsubfile,
2664  dbi_type, oflags, dbi->dbi_perms);
2665 
2666  if (rc == 0 && dbi_type == DB_UNKNOWN) {
2667  xx = db->get_type(db, &dbi_type);
2668  if (xx == 0)
2669  dbi->dbi_type = dbi_type;
2670  }
2671  }
2672 
2673  /* XXX return rc == errno without printing */
2674  _printit = (rc > 0 ? 0 : _debug);
2675  xx = cvtdberr(dbi, "db->open", rc, _printit);
2676 
2677  /*
2678  * Lock a file using fcntl(2). Traditionally this is Packages,
2679  * the file used to store metadata of installed header(s),
2680  * as Packages is always opened, and should be opened first,
2681  * for any rpmdb access.
2682  *
2683  * If no DBENV is used, then access is protected with a
2684  * shared/exclusive locking scheme, as always.
2685  *
2686  * With a DBENV, the fcntl(2) lock is necessary only to keep
2687  * the riff-raff from playing where they don't belong, as
2688  * the DBENV should provide it's own locking scheme. So try to
2689  * acquire a lock, but permit failures, as some other
2690  * DBENV player may already have acquired the lock.
2691  *
2692  * With NPTL posix mutexes, revert to fcntl lock on non-functioning
2693  * glibc/kernel combinations.
2694  */
2695  if (rc == 0 && dbi->dbi_lockdbfd &&
2696 #if defined(DB_RPCCLIENT)
2697  !((dbi->dbi_ecflags & DB_RPCCLIENT) && dbi->dbi_host) &&
2698 #endif
2699  (!dbi->dbi_use_dbenv || _lockdbfd++ == 0))
2700  {
2701  int fdno = -1;
2702 
2703  if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) {
2704  rc = 1;
2705  } else {
2706  struct flock l;
2707  memset(&l, 0, sizeof(l));
2708  l.l_whence = 0;
2709  l.l_start = 0;
2710  l.l_len = 0;
2711  l.l_type = (dbi->dbi_mode & (O_RDWR|O_WRONLY))
2712  ? F_WRLCK : F_RDLCK;
2713  l.l_pid = 0;
2714 
2715  rc = fcntl(fdno, F_SETLK, (void *) &l);
2716  if (rc) {
2717  /* Warning iff using non-private CDB locking. */
2718  rc = ((dbi->dbi_use_dbenv &&
2719  (dbi->dbi_eflags & DB_INIT_CDB) &&
2720  !(dbi->dbi_eflags & DB_PRIVATE))
2721  ? 0 : 1);
2722  rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING),
2723  _("cannot get %s lock on %s/%s\n"),
2724  ((dbi->dbi_mode & (O_RDWR|O_WRONLY))
2725  ? _("exclusive") : _("shared")),
2726  dbhome, (dbfile ? dbfile : ""));
2727  } else if (dbfile) {
2729  D_("locked db index %s/%s\n"),
2730  dbhome, dbfile);
2731  }
2732  }
2733  }
2734  }
2735  }
2736 
2737  dbi->dbi_db = (void *) db;
2738  if (db)
2739  db->app_private = dbi;
2740 
2741 DBIDEBUG(dbi, (stderr, "<-- %s(%p,%s,%p) dbi %p rc %d %s\n", __FUNCTION__, rpmdb, tagName(rpmtag), dbip, dbi, rc, _OFLAGS(dbi->dbi_oflags)));
2742 
2743  if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) {
2744  dbi->dbi_vec = &db3vec;
2745  *dbip = dbi;
2746  if (dbi->dbi_primary) {
2747  rpmTag Ptag = tagValue(dbi->dbi_primary);
2748  dbiIndex Pdbi = NULL;
2749  int (*_callback)(DB *, const DBT *, const DBT *, DBT *)
2750  = db3Acallback;
2751 #ifdef NOTYET /* XXX KISS for now */
2752  int _flags = DB_IMMUTABLE_KEY;
2753 #else
2754  int _flags = 0;
2755 #endif
2756 assert(Ptag == RPMDBI_PACKAGES && Ptag != rpmtag);
2757  Pdbi = dbiOpen(rpmdb, Ptag, 0);
2758 assert(Pdbi != NULL);
2759  if (oflags & (DB_CREATE|DB_TRUNCATE)) _flags |= DB_CREATE;
2760  xx = db3associate(Pdbi, dbi, _callback, _flags);
2761  }
2762  if (dbi->dbi_seq_id && !(oflags & DB_RDONLY)) {
2763  char * end = NULL;
2764  uint32_t u = (uint32_t) strtoll(dbi->dbi_seq_id, &end, 0);
2765 
2766  /* Reset the Seqno counter to the next primary key */
2767  if (oflags & (DB_CREATE|DB_TRUNCATE))
2768  dbi->dbi_seq_initial = rpmdb->db_maxkey + 1;
2769 
2770  if (*end == '\0')
2771  xx = seqid_init(dbi,(const char *)&u, sizeof(u), (DB_SEQUENCE **) &dbi->dbi_seq);
2772  else
2773  xx = seqid_init(dbi, dbi->dbi_seq_id, 0, (DB_SEQUENCE **) &dbi->dbi_seq);
2774  if (xx) {
2775  (void) db3close(dbi, 0);
2776  dbi = NULL;
2777  if (dbip) *dbip = dbi;
2778  }
2779  }
2780  } else {
2781  (void) db3close(dbi, 0);
2782  dbi = NULL;
2783  if (dbip) *dbip = dbi;
2784  }
2785 
2786  urlfn = _free(urlfn);
2787 
2788  /*@-nullstate -compmempass@*/
2789  return rc;
2790  /*@=nullstate =compmempass@*/
2791 }
2792 
2795 /*@-exportheadervar@*/
2796 /*@observer@*/ /*@unchecked@*/
2797 struct _dbiVec db3vec = {
2798  DB_VERSION_STRING, DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
2803 };
2804 /*@=exportheadervar@*/
2805 /*@=type@*/
uint32_t v
Definition: db3.c:739
void * app_private
Definition: db_emu.h:18
static int uint32Cmp(const void *_a, const void *_b)
Definition: db3.c:1858
rpmTagType t
Definition: rpmtag.h:502
#define ISSET(opt)
Definition: fts.c:196
qsort(mc->macroTable, mc->firstFree, sizeof(mc->macroTable[0]), compareMacroName)
const char * str
Definition: rpmtag.h:73
ellipsis
Definition: macro.c:553
int xx
Definition: spec.c:744
rpmTag tag
Definition: rpmtag.h:501
static const char * fmtKDR(const DBT *K, const DBT *P, const DBT *D, const DBT *R)
Definition: db3.c:524
const char ** argv
Definition: rpmtag.h:75
static int db3associate(dbiIndex dbi, dbiIndex dbisecondary, int(*callback)(DB *, const DBT *, const DBT *, DBT *), unsigned int flags)
Definition: db3.c:1623
static uint64_t _ntoh_ul(uint64_t ul)
Definition: db3.c:54
#define headerFree(_h)
Definition: rpmtag.h:870
struct rpmdb_s * rpmdb
Database of headers and tag value indices.
Definition: rpmtypes.h:43
rpmlog(RPMLOG_ERR,"%s\n", buf)
static int db3cpget(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *pkey, DBT *data, unsigned int flags)
Definition: db3.c:1479
DBT * A
Definition: db3.c:1890
uint64_t ul
Definition: db3.c:45
#define DB_THREAD
Definition: db_emu.h:119
int pgpExtractPubkeyFingerprint(const char *b64pkt, rpmuint8_t *keyid)
Extract OpenPGP public key fingerprint from base64 encoded packet.
Definition: rpmpgp.c:1028
#define cvtdberr(_dbi, _msg, _error, _printit)
Definition: db3.c:571
OpenPGP constants and structures from RFC-2440.
#define DB_VERSION_PATCH
Definition: db_emu.h:102
static int loadDBT(DBT *_r, rpmTag tag, const void *_s, size_t ns)
Definition: db3.c:1812
static int db3join(dbiIndex dbi, DBC **curslist, DBC **dbcp, unsigned int flags)
Definition: db3.c:1683
#define EXIT_FAILURE
static const char * fmtDBCoflags(uint32_t flags)
Definition: db3.c:354
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
char * rpmCleanPath(char *path)
Canonicalize file path.
Definition: macro.c:3279
static const char * fmtDBeflags(uint32_t flags)
Definition: db3.c:264
rpmuint32_t * ui32p
Definition: rpmtag.h:70
static KEY DBoflags[]
Definition: db3.c:276
Definition: db3.c:181
char * rpmGetPath(const char *path,...)
Return (malloc&#39;ed) expanded, canonicalized, file path.
Definition: macro.c:3371
static uint32_t _hton_ui(uint32_t ui)
Definition: db3.c:86
static char *size_t nb
fgets(3) analogue that reads \ continuations.
Definition: macro.c:409
uint8_t uc[8]
Definition: db3.c:48
static uint16_t _ntoh_us(uint16_t us)
Definition: db3.c:92
int rc
Definition: poptALL.c:670
static int db3ccount(dbiIndex dbi, DBC *dbcursor, unsigned int *countp, unsigned int flags)
Definition: db3.c:1552
The Header data structure.
int rpmioMkpath(const char *path, mode_t mode, uid_t uid, gid_t gid)
Insure that directories in path exist, creating as needed.
Definition: rpmio.c:3015
#define DB_SET
Definition: db_emu.h:88
static unsigned char nibble(char c)
Convert hex to binary nibble.
Definition: db3.c:1800
void * app_private
Definition: db_emu.h:47
rpmuint16_t * ui16p
Definition: rpmtag.h:69
static size_t nDBCflags
Definition: db3.c:412
static const char * fmtDBaflags(uint32_t flags)
Definition: db3.c:309
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
int Open(const char *path, int flags, mode_t mode)
open(2) clone.
Definition: rpmrpc.c:219
#define DB_DBT_MULTIPLE
Definition: db_emu.h:36
static void rpmdbe_event_notify(DB_ENV *dbenv, u_int32_t event, void *event_info)
Definition: db3.c:884
fts m
Definition: rpmmtree.c:3827
pid_t pid
Definition: rpmsq.c:736
enum rpmTag_e rpmTag
Definition: rpmtag.h:468
#define _RPMDB_NLOCKS
static int db3_fsync_disable(int fd)
Definition: db3.c:641
int errno
#define DB_VERSION_MINOR
Definition: db_emu.h:101
static size_t ncores(void)
Definition: db3.c:711
#define _AFLAGS(_aflags)
Definition: db3.c:318
static const char * mapTagName(rpmdb rpmdb, dbiIndex dbi)
Return (possibly renamed) tagName.
Definition: db3.c:581
static size_t nDBTflags
Definition: db3.c:474
#define _DBCFLAGS(_flags)
Definition: db3.c:433
#define DB_CREATE
Definition: db_emu.h:113
#define DB_KEYLAST
Definition: db_emu.h:85
static int Xcvtdberr(dbiIndex dbi, const char *msg, int error, int printit, const char *func, const char *fn, unsigned ln)
Definition: db3.c:553
static int db3exists(dbiIndex dbi, DBT *key, unsigned int flags)
Definition: db3.c:1278
Definition: db3.c:737
static struct _events_s _events[]
Header headerLink(Header h)
Reference a header instance.
Header h
Definition: spec.c:739
#define DB_NOTFOUND
Definition: db_emu.h:94
static int db3stat(dbiIndex dbi, unsigned int flags)
Definition: db3.c:1591
static const char * fmtDBoflags(uint32_t flags)
Definition: db3.c:290
static int db3cget(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Definition: db3.c:1438
rpmTag tagValue(const char *tagstr)
Return tag value from name.
Definition: tagname.c:446
static int db3cclose(dbiIndex dbi, DBC *dbcursor, unsigned int flags)
Definition: db3.c:1353
static int db3associate_foreign(dbiIndex dbi, dbiIndex dbisecondary, int(*callback)(DB *, const DBT *, DBT *, const DBT *, int *), unsigned int flags)
Definition: db3.c:1652
sprintf(t," (%u)",(unsigned) dig->nbytes)
#define DBIDEBUG(_dbi, _list)
Definition: db3.c:37
static uint64_t physmem(void)
Definition: db3.c:681
char * alloca()
static const char * fmtBits(uint32_t flags, KEY tbl[], size_t ntbl, char *t)
Definition: db3.c:209
Yet Another syslog(3) API clone.
goto exit
Definition: db3.c:1903
memset(_r, 0, sizeof(*_r))
size_t ns
Definition: db3.c:1892
int count
Definition: rpmdb-py.c:157
static int xisprint(int c)
Definition: rpmiotypes.h:455
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
HE_t Fhe
Definition: db3.c:1882
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
assert(key->size==sizeof(hdrNum))
goto errxit
Definition: rpmgrep.c:1527
void * data
Definition: db_emu.h:22
void * ptr
Definition: rpmtag.h:67
#define DB_INIT_TXN
Definition: db_emu.h:117
static size_t nDBafflags
Definition: db3.c:327
rpmuint32_t size
Definition: signature.c:585
DBTYPE
Definition: db_emu.h:105
static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex *dbip)
Return handle for an index database.
Definition: db3.c:2208
static const char * tblName(uint32_t v, KEY *tbl, size_t ntbl)
Definition: db3.c:189
fprintf(stderr,"--> %s(%p,%p,%p) sig %p sigp %p\n", __FUNCTION__, dig, t, rsactx, sig, sigp)
uint32_t hdrNum
Definition: db3.c:1889
#define DB_WRITECURSOR
Definition: db_emu.h:91
static void
Definition: db3.c:893
static int db3byteswapped(dbiIndex dbi)
Definition: db3.c:1576
static const char * fmtDBafflags(uint32_t flags)
Definition: db3.c:329
he tag
Definition: db3.c:1927
rpmTagData p
Definition: rpmtag.h:504
static int db_fini(dbiIndex dbi, const char *dbhome, const char *dbfile, const char *dbsubfile)
Definition: db3.c:598
static int uint64Cmp(const void *_a, const void *_b)
Definition: db3.c:1867
uint32_t v
Definition: db3.c:182
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
static KEY DBeflags[]
Definition: db3.c:239
struct _HE_s * HE_t
Destroy an extension cache.
Definition: rpmtag.h:59
uint16_t us
Definition: db3.c:47
key
Definition: macro.c:383
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2230
Header headerLoad(void *uh)
Convert header to in-memory representation.
Definition: header.c:970
char * o
Definition: macro.c:745
dbenv
Definition: db3.c:895
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3417
#define _ENTRY(_v)
Definition: db3.c:236
rpmTagCount c
Definition: rpmtag.h:505
struct tagStore_s * tagStore_t
Definition: rpmtag.h:519
static int _debug
Definition: db3.c:7
#define DB_INIT_LOCK
Definition: db_emu.h:114
static union _dbswap _endian
Definition: db3.c:52
static uint64_t _hton_ul(uint64_t ul)
Definition: db3.c:68
static int db3close(dbiIndex dbi, unsigned int flags)
Definition: db3.c:1702
#define DB_VERSION_MAJOR
Definition: db_emu.h:100
static unsigned
Definition: rpmmtree.c:386
rpmuint8_t * ui8p
Definition: rpmtag.h:68
Encapsulation of a &quot;value&quot;.
Definition: expression.c:36
* op
Definition: rpmps-py.c:266
static size_t nDBCoflags
Definition: db3.c:352
node fd
Definition: rpmfd-py.c:124
#define _EFLAGS(_eflags)
Definition: db3.c:273
uint32_t size
Definition: db_emu.h:23
uint32_t flags
Definition: db_emu.h:43
struct __db_sequence DB_SEQUENCE
Definition: db_emu.h:14
char * n
Definition: macro.c:744
static KEY DBTflags[]
Definition: db3.c:437
struct _dbiVec db3vec
Definition: db3.c:2797
static const char *char c
Return text between pl and matching pr characters.
Definition: macro.c:470
#define DB_BUFFER_SMALL
Definition: db_emu.h:93
fts u
Definition: rpmmtree.c:3828
static uint16_t _hton_us(uint16_t us)
Definition: db3.c:103
static KEY DBCoflags[]
Definition: db3.c:341
Definition: rpmtag.h:500
#define _DBCOFLAGS(_coflags)
Definition: db3.c:362
#define _DBT_ENTRY(_v)
Definition: db3.c:435
static KEY DBafflags[]
Definition: db3.c:321
static PyObject *rpmds P
Definition: rpmds-py.c:435
const char * s
Definition: poptALL.c:734
#define DB_PRIVATE
Definition: db_emu.h:98
static int db3cput(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Definition: db3.c:1408
char * t
Definition: rpmds.c:2716
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
struct key_s KEY
static size_t nDBaflags
Definition: db3.c:307
dbiIndex dbiOpen(rpmdb db, rpmTag tag, unsigned int flags)
Definition: rpmdb.c:223
Definition: db_emu.h:72
static int db3cdel(dbiIndex dbi, DBC *dbcursor, DBT *key, DBT *data, unsigned int flags)
Definition: db3.c:1518
#define DB_EXCL
Definition: db_emu.h:97
char * stpcpy(char *dest, const char *src)
if(__progname==NULL)
Definition: poptALL.c:683
te
Definition: macro.c:552
#define DB_INIT_MPOOL
Definition: db_emu.h:116
dbiIndex dbi
Definition: db3.c:1886
static const char * fmtDBCflags(uint32_t flags)
Definition: db3.c:415
int flags
Definition: fnmatch.c:282
static size_t nDBeflags
Definition: db3.c:262
#define _AFFLAGS(_afflags)
Definition: db3.c:338
const char * msg
Definition: rpmts-py.c:976
#define F_OK
Definition: system.h:231
static size_t nDBoflags
Definition: db3.c:288
static int db_init(dbiIndex dbi, const char *dbhome, const char *dbfile, const char *dbsubfile, DB_ENV **dbenvp)
Definition: db3.c:907
#define _OFLAGS(_oflags)
Definition: db3.c:299
return NULL
Definition: poptALL.c:613
#define DB_AUTO_COMMIT
Definition: db_emu.h:118
static int seqid_init(dbiIndex dbi, const char *keyp, size_t keylen, DB_SEQUENCE **seqp)
Definition: db3.c:2128
static int db3seqno(dbiIndex dbi, int64_t *seqnop, unsigned int flags)
Definition: db3.c:1300
uint32_t ui
Definition: db3.c:46
Definition: db_emu.h:17
k
Definition: rpmmtree.c:394
return
Definition: spec.c:747
#define INIT_LOCK()
Definition: rpmsq.c:250
static const char * name
#define _TABLE(_v)
Definition: db3.c:736
char * buf
Parse (and execute) macro undefinition.
Definition: macro.c:703
#define _(Text)
Definition: system.h:29
char * b
Definition: macro.c:746
int
Save source and expand field into target.
Definition: rpmds.c:2709
#define xmalloc
Definition: system.h:32
#define _KEYDATA(_K, _P, _D, _R)
Definition: db3.c:550
static KEY DBaflags[]
Definition: db3.c:302
Access RPM indices using Berkeley DB interface(s).
#define DB_DBT_APPMALLOC
Definition: db_emu.h:31
#define D_(Text)
Definition: system.h:526
static int db3copen(dbiIndex dbi, DB_TXN *txnid, DBC **dbcp, unsigned int dbiflags)
Definition: db3.c:1377
static uint32_t _ntoh_ui(uint32_t ui)
Definition: db3.c:74
int fdno
Definition: rpmts-py.c:923
Definition: db3.c:44
const char * n
Definition: db3.c:184
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
static int db3cdup(dbiIndex dbi, DBC *dbcursor, DBC **dbcp, unsigned int flags)
Definition: db3.c:1331
int i
Definition: spec.c:743
#define RPMDBI_PACKAGES
Pseudo-tags used by the rpmdb and rpmgi iterator API&#39;s.
Definition: rpmtag.h:477
#define SET(opt)
Definition: fts.c:197
const char * n
Definition: db3.c:738
size_t fn
Definition: macro.c:1698
static KEY DBCflags[]
Definition: db3.c:365
#define W_OK
Definition: system.h:233
static char * fmtDBT(const DBT *K, char *te)
Definition: db3.c:477
struct _dbiIndex * dbiIndex
Definition: rpmdb.h:59
static int db3sync(dbiIndex dbi, unsigned int flags)
Definition: db3.c:1259
rpmuint64_t * ui64p
Definition: rpmtag.h:71
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397