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