static int db3_dbiClose(dbiIndex dbi, unsigned int flags) { rpmdb rdb = dbi->dbi_rpmdb; const char * dbhome = rpmdbHome(rdb); DB * db = dbi->dbi_db; int _printit; int rc = 0; if (db) { rc = db->close(db, flags); /* XXX ignore not found error messages. */ _printit = (rc == ENOENT ? 0 : _debug); rc = cvtdberr(dbi, "db->close", rc, _printit); db = dbi->dbi_db = NULL; rpmlog(RPMLOG_DEBUG, "closed db index %s/%s\n", dbhome, dbi->dbi_file); } db_fini(rdb, dbhome ? dbhome : ""); dbi->dbi_db = NULL; dbi = dbiFree(dbi); return rc; }
/* return DSI of the device the rpmdb lives on */ static rpmDiskSpaceInfo rpmtsDbDSI(const rpmts ts) { const char *dbhome = rpmdbHome(rpmtsGetRdb(ts)); struct stat sb; int rc; rc = stat(dbhome, &sb); if (rc) { return NULL; } return rpmtsGetDSI(ts, sb.st_dev, dbhome); }
static void dbDetectBackend(rpmdb rdb) { #ifdef ENABLE_NDB const char *dbhome = rpmdbHome(rdb); char *path = rstrscat(NULL, dbhome, "/Packages", NULL); rdb->db_ops = &ndb_dbops; if (access(path, F_OK) == 0) rdb->db_ops = &db3_dbops; free(path); #else rdb->db_ops = &db3_dbops; #endif }
/* * Lock a file using fcntl(2). Traditionally this is Packages, * the file used to store metadata of installed header(s), * as Packages is always opened, and should be opened first, * for any rpmdb access. * * If no DBENV is used, then access is protected with a * shared/exclusive locking scheme, as always. * * With a DBENV, the fcntl(2) lock is necessary only to keep * the riff-raff from playing where they don't belong, as * the DBENV should provide it's own locking scheme. So try to * acquire a lock, but permit failures, as some other * DBENV player may already have acquired the lock. * * With NPTL posix mutexes, revert to fcntl lock on non-functioning * glibc/kernel combinations. */ static int dbiFlock(dbiIndex dbi, int mode) { int fdno = -1; int rc = 0; DB * db = dbi->dbi_db; if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { const char *dbhome = rpmdbHome(dbi->dbi_rpmdb); struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = 0; l.l_start = 0; l.l_len = 0; l.l_type = (mode & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK; l.l_pid = 0; rc = fcntl(fdno, F_SETLK, (void *) &l); if (rc) { uint32_t eflags = db_envflags(db); /* Warning iff using non-private CDB locking. */ rc = (((eflags & DB_INIT_CDB) && !(eflags & DB_PRIVATE)) ? 0 : 1); rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), _("cannot get %s lock on %s/%s\n"), ((mode & O_ACCMODE) == O_RDONLY) ? _("shared") : _("exclusive"), dbhome, dbi->dbi_file); } else { rpmlog(RPMLOG_DEBUG, "locked db index %s/%s\n", dbhome, dbi->dbi_file); } } return rc; }
static int rpmtsPrepare(rpmts ts) { tsMembers tsmem = rpmtsMembers(ts); rpmtsi pi; rpmte p; int rc = 0; uint64_t fileCount = countFiles(ts); const char *dbhome = NULL; struct stat dbstat; fingerPrintCache fpc = fpCacheCreate(fileCount/2 + 10001, rpmtsPool(ts)); rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount); /* Reset actions, set skip for netshared paths and excluded files */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmfiles files = rpmteFiles(p); if (rpmfilesFC(files) > 0) { rpmfs fs = rpmteGetFileStates(p); /* Ensure clean state, this could get called more than once. */ rpmfsResetActions(fs); if (rpmteType(p) == TR_ADDED) { skipInstallFiles(ts, files, fs); } else { skipEraseFiles(ts, files, fs); } } rpmfilesFree(files); } rpmtsiFree(pi); /* Open rpmdb & enter chroot for fingerprinting if necessary */ if (rpmdbOpenAll(ts->rdb) || rpmChrootIn()) { rc = -1; goto exit; } rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, tsmem->orderCount); /* Add fingerprint for each file not skipped. */ fpCachePopulate(fpc, ts, fileCount); /* check against files in the rpmdb */ checkInstalledFiles(ts, fileCount, fpc); dbhome = rpmdbHome(rpmtsGetRdb(ts)); /* If we can't stat, ignore db growth. Probably not right but... */ if (dbhome && stat(dbhome, &dbstat)) dbhome = NULL; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmfiles files = rpmteFiles(p);; if (files == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); /* check files in ts against each other and update disk space needs on each partition for this package. */ handleOverlappedFiles(ts, fpc, p, files); /* Check added package has sufficient space on each partition used. */ if (rpmteType(p) == TR_ADDED) { /* * Try to estimate space needed for rpmdb growth: guess that the * db grows 4 times the header size (indexes and all). */ if (dbhome) { int64_t hsize = rpmteHeaderSize(p) * 4; rpmtsUpdateDSI(ts, dbstat.st_dev, dbhome, hsize, 0, 0, FA_CREATE); } rpmtsCheckDSIProblems(ts, p); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfilesFree(files); } rpmtsiFree(pi); rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, tsmem->orderCount); /* return from chroot if done earlier */ if (rpmChrootOut()) rc = -1; /* On actual transaction, file info sets are not needed after this */ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))) { pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmteCleanFiles(p); } rpmtsiFree(pi); } exit: fpCacheFree(fpc); rpmtsFreeDSI(ts); return rc; }
static int db3_dbiOpen(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags) { const char *dbhome = rpmdbHome(rdb); dbiIndex dbi = NULL; int rc = 0; int retry_open; int verifyonly = (flags & RPMDB_FLAG_VERIFYONLY); DB * db = NULL; DBTYPE dbtype = DB_UNKNOWN; uint32_t oflags; static int _lockdbfd = 0; if (dbip) *dbip = NULL; if ((dbi = dbiNew(rdb, rpmtag)) == NULL) return 1; /* * Parse db configuration parameters. */ dbConfigure(rpmtag, rdb->db_dbenv == NULL ? &rdb->cfg : NULL, &dbi->cfg); /* * Map open mode flags onto configured database/environment flags. */ oflags = dbi->cfg.dbi_oflags; if ((rdb->db_mode & O_ACCMODE) == O_RDONLY) oflags |= DB_RDONLY; rc = db_init(rdb, dbhome); retry_open = (rc == 0) ? 2 : 0; while (retry_open) { rc = db_create(&db, rdb->db_dbenv, 0); rc = cvtdberr(dbi, "db_create", rc, _debug); /* For verify we only want the handle, not an open db */ if (verifyonly) break; if (rc == 0 && db != NULL) { int _printit; char *dbfs = prDbiOpenFlags(oflags, 0); rpmlog(RPMLOG_DEBUG, "opening db index %s/%s %s mode=0x%x\n", dbhome, dbi->dbi_file, dbfs, rdb->db_mode); free(dbfs); rc = (db->open)(db, NULL, dbi->dbi_file, NULL, dbtype, oflags, rdb->db_perms); /* Attempt to create if missing, discarding DB_RDONLY (!) */ if (rc == ENOENT) { oflags |= DB_CREATE; oflags &= ~DB_RDONLY; dbtype = (rpmtag == RPMDBI_PACKAGES) ? DB_HASH : DB_BTREE; retry_open--; } else { retry_open = 0; } /* XXX return rc == errno without printing */ _printit = (rc > 0 ? 0 : _debug); rc = cvtdberr(dbi, "db->open", rc, _printit); /* Validate the index type is something we can support */ if ((rc == 0) && (dbtype == DB_UNKNOWN)) { db->get_type(db, &dbtype); if (dbtype != DB_HASH && dbtype != DB_BTREE) { rpmlog(RPMLOG_ERR, _("invalid index type %x on %s/%s\n"), dbtype, dbhome, dbi->dbi_file); rc = 1; } } if (rc != 0) { db->close(db, 0); db = NULL; } } } dbi->dbi_db = db; dbi->dbi_flags = 0; if (oflags & DB_CREATE) dbi->dbi_flags |= DBI_CREATED; if (oflags & DB_RDONLY) dbi->dbi_flags |= DBI_RDONLY; if (!verifyonly && rc == 0 && dbi->cfg.dbi_lockdbfd && _lockdbfd++ == 0) { rc = dbiFlock(dbi, rdb->db_mode); } if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { *dbip = dbi; } else { (void) dbiClose(dbi, 0); } return rc; }