/** * Retrieve i18n text. * @param h header * @param tag tag * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int i18nTag(Header h, rpmTag tag, rpmtd td, headerGetFlags hgflags) { int rc; #if defined(ENABLE_NLS) char * dstring = rpmExpand(_macro_i18ndomains, NULL); td->type = RPM_STRING_TYPE; td->data = NULL; td->count = 0; if (dstring && *dstring) { char *domain, *de; const char * langval; char * msgkey; const char * msgid; rasprintf(&msgkey, "%s(%s)", headerGetString(h, RPMTAG_NAME), rpmTagGetName(tag)); /* change to en_US for msgkey -> msgid resolution */ langval = getenv(language); (void) setenv(language, "en_US", 1); ++_nl_msg_cat_cntr; msgid = NULL; for (domain = dstring; domain != NULL; domain = de) { de = strchr(domain, ':'); if (de) *de++ = '\0'; msgid = dgettext(domain, msgkey); if (msgid != msgkey) break; } /* restore previous environment for msgid -> msgstr resolution */ if (langval) (void) setenv(language, langval, 1); else unsetenv(language); ++_nl_msg_cat_cntr; if (domain && msgid) { td->data = dgettext(domain, msgid); td->data = xstrdup(td->data); /* XXX xstrdup has side effects. */ td->count = 1; td->flags = RPMTD_ALLOCED; } dstring = _free(dstring); free(msgkey); if (td->data) return 1; } free(dstring); #endif rc = headerGet(h, tag, td, HEADERGET_ALLOC); return rc; }
dbiIndex dbiNew(rpmdb rdb, rpmDbiTagVal rpmtag) { dbiIndex dbi = xcalloc(1, sizeof(*dbi)); /* FIX: figger lib/dbi refcounts */ dbi->dbi_rpmdb = rdb; dbi->dbi_file = rpmTagGetName(rpmtag); dbi->dbi_type = (rpmtag == RPMDBI_PACKAGES) ? DBI_PRIMARY : DBI_SECONDARY; dbi->dbi_byteswapped = -1; /* -1 unknown, 0 native order, 1 alien order */ return dbi; }
static rpmRC addFileToTag(rpmSpec spec, const char * file, Header h, rpmTagVal tag, int append) { StringBuf sb = NULL; char buf[BUFSIZ]; char * fn; FILE * f; rpmRC rc = RPMRC_FAIL; /* assume failure */ /* no script file is not an error */ if (file == NULL) return RPMRC_OK; fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL); f = fopen(fn, "r"); if (f == NULL) { rpmlog(RPMLOG_ERR,_("Could not open %s file: %s\n"), rpmTagGetName(tag), file); goto exit; } sb = newStringBuf(); if (append) { const char *s = headerGetString(h, tag); if (s) { appendLineStringBuf(sb, s); headerDel(h, tag); } } while (fgets(buf, sizeof(buf), f)) { char *expanded; if (rpmExpandMacros(spec->macros, buf, &expanded, 0) < 0) { rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf); goto exit; } appendStringBuf(sb, expanded); free(expanded); } headerPutString(h, tag, getStringBuf(sb)); rc = RPMRC_OK; exit: if (f) fclose(f); free(fn); freeStringBuf(sb); return rc; }
/** * Check that required tags are present in header. * @param h header * @param NVR package name-version-release * @return RPMRC_OK if OK */ static int checkForRequired(Header h, const char * NVR) { int res = RPMRC_OK; const rpmTagVal * p; for (p = requiredTags; *p != 0; p++) { if (!headerIsEntry(h, *p)) { rpmlog(RPMLOG_ERR, _("%s field must be present in package: %s\n"), rpmTagGetName(*p), NVR); res = RPMRC_FAIL; } } return res; }
/** * Check that no duplicate tags are present in header. * @param h header * @param NVR package name-version-release * @return RPMRC_OK if OK */ static int checkForDuplicates(Header h, const char * NVR) { int res = RPMRC_OK; rpmTagVal tag, lastTag = RPMTAG_NOT_FOUND; HeaderIterator hi = headerInitIterator(h); while ((tag = headerNextTag(hi)) != RPMTAG_NOT_FOUND) { if (tag == lastTag) { rpmlog(RPMLOG_ERR, _("Duplicate %s entries in package: %s\n"), rpmTagGetName(tag), NVR); res = RPMRC_FAIL; } lastTag = tag; } headerFreeIterator(hi); return res; }
int addLangTag(rpmSpec spec, Header h, rpmTagVal tag, const char *field, const char *lang) { int skip = 0; if (haveLangTag(h, tag, lang)) { /* Turn this into an error eventually */ rpmlog(RPMLOG_WARNING, _("line %d: second %s\n"), spec->lineNum, rpmTagGetName(tag)); } if (!*lang) { headerPutString(h, tag, field); } else { skip = ((spec->flags & RPMSPEC_NOLANG) && !rstreq(lang, RPMBUILD_DEFAULT_LANG)); if (skip) return 0; headerAddI18NString(h, tag, field, lang); } return 0; }
rpmRC checkForEncoding(Header h, int addtag) { rpmRC rc = RPMRC_OK; #if HAVE_ICONV const char *encoding = "utf-8"; rpmTagVal tag; iconv_t ic = (iconv_t) -1; char *dest = NULL; size_t destlen = 0; int strict = rpmExpandNumeric("%{_invalid_encoding_terminates_build}"); HeaderIterator hi = headerInitIterator(h); ic = iconv_open(encoding, encoding); if (ic == (iconv_t) -1) { rpmlog(RPMLOG_WARNING, _("encoding %s not supported by system\n"), encoding); goto exit; } while ((tag = headerNextTag(hi)) != RPMTAG_NOT_FOUND) { struct rpmtd_s td; const char *src = NULL; if (rpmTagGetClass(tag) != RPM_STRING_CLASS) continue; headerGet(h, tag, &td, (HEADERGET_RAW|HEADERGET_MINMEM)); while ((src = rpmtdNextString(&td)) != NULL) { size_t srclen = strlen(src); size_t outlen, inlen = srclen; char *out, *in = (char *) src; if (destlen < srclen) { destlen = srclen * 2; dest = xrealloc(dest, destlen); } out = dest; outlen = destlen; /* reset conversion state */ iconv(ic, NULL, &inlen, &out, &outlen); if (iconv(ic, &in, &inlen, &out, &outlen) == (size_t) -1) { rpmlog(strict ? RPMLOG_ERR : RPMLOG_WARNING, _("Package %s: invalid %s encoding in %s: %s - %s\n"), headerGetString(h, RPMTAG_NAME), encoding, rpmTagGetName(tag), src, strerror(errno)); rc = RPMRC_FAIL; } } rpmtdFreeData(&td); } /* Stomp "known good utf" mark in header if requested */ if (rc == RPMRC_OK && addtag) headerPutString(h, RPMTAG_ENCODING, encoding); if (!strict) rc = RPMRC_OK; exit: if (ic != (iconv_t) -1) iconv_close(ic); headerFreeIterator(hi); free(dest); #endif /* HAVE_ICONV */ return rc; }
static void dbConfigure(rpmDbiTagVal rpmtag, struct dbConfig_s *cfg, struct dbiConfig_s *dbicfg) { char *dbOpts; dbOpts = rpmExpand("%{_dbi_config_", rpmTagGetName(rpmtag), "}", NULL); if (!(dbOpts && *dbOpts && *dbOpts != '%')) { dbOpts = _free(dbOpts); dbOpts = rpmExpand("%{_dbi_config}", NULL); if (!(dbOpts && *dbOpts && *dbOpts != '%')) { dbOpts = _free(dbOpts); } } /* Parse the options for the database element(s). */ if (dbOpts && *dbOpts && *dbOpts != '%') { char *o, *oe; char *p, *pe; memset(&staticdbicfg, 0, sizeof(staticdbicfg)); /*=========*/ for (o = dbOpts; o && *o; o = oe) { const struct poptOption *opt; const char * tok; unsigned int argInfo; /* Skip leading white space. */ while (*o && risspace(*o)) o++; /* Find and terminate next key=value pair. Save next start point. */ for (oe = o; oe && *oe; oe++) { if (risspace(*oe)) break; if (oe[0] == ':' && !(oe[1] == '/' && oe[2] == '/')) break; } if (oe && *oe) *oe++ = '\0'; if (*o == '\0') continue; /* Separate key from value, save value start (if any). */ for (pe = o; pe && *pe && *pe != '='; pe++) {}; p = (pe ? *pe++ = '\0', pe : NULL); /* Skip over negation at start of token. */ for (tok = o; *tok == '!'; tok++) {}; /* Find key in option table. */ for (opt = rdbOptions; opt->longName != NULL; opt++) { if (!rstreq(tok, opt->longName)) continue; break; } if (opt->longName == NULL) { rpmlog(RPMLOG_ERR, _("unrecognized db option: \"%s\" ignored.\n"), o); continue; } /* Toggle the flags for negated tokens, if necessary. */ argInfo = opt->argInfo; if (argInfo == POPT_BIT_SET && *o == '!' && ((tok - o) % 2)) argInfo = POPT_BIT_CLR; /* Save value in template as appropriate. */ switch (argInfo & POPT_ARG_MASK) { case POPT_ARG_NONE: (void) poptSaveInt((int *)opt->arg, argInfo, 1L); break; case POPT_ARG_VAL: (void) poptSaveInt((int *)opt->arg, argInfo, (long)opt->val); break; case POPT_ARG_STRING: { char ** t = opt->arg; if (t) { /* FIX: opt->arg annotation in popt.h */ *t = _free(*t); *t = xstrdup( (p ? p : "") ); } } break; case POPT_ARG_INT: case POPT_ARG_LONG: { long aLong = strtol(p, &pe, 0); if (pe) { if (!rstrncasecmp(pe, "Mb", 2)) aLong *= 1024 * 1024; else if (!rstrncasecmp(pe, "Kb", 2)) aLong *= 1024; else if (*pe != '\0') { rpmlog(RPMLOG_ERR, _("%s has invalid numeric value, skipped\n"), opt->longName); continue; } } if ((argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) { if (aLong == LONG_MIN || aLong == LONG_MAX) { rpmlog(RPMLOG_ERR, _("%s has too large or too small long value, skipped\n"), opt->longName); continue; } (void) poptSaveLong((long *)opt->arg, argInfo, aLong); break; } else { if (aLong > INT_MAX || aLong < INT_MIN) { rpmlog(RPMLOG_ERR, _("%s has too large or too small integer value, skipped\n"), opt->longName); continue; } (void) poptSaveInt((int *)opt->arg, argInfo, aLong); } } break; default: break; } } /*=========*/ } dbOpts = _free(dbOpts); if (cfg) { *cfg = staticcfg; /* structure assignment */ /* Throw in some defaults if configuration didn't set any */ if (!cfg->db_mmapsize) cfg->db_mmapsize = 16 * 1024 * 1024; if (!cfg->db_cachesize) cfg->db_cachesize = 8 * 1024 * 1024; } if (dbicfg) { *dbicfg = staticdbicfg; } }
static int db3open(rpmdb rpmdb, rpmTag rpmtag, dbiIndex * dbip) { extern const struct _dbiVec db3vec; const char * root; const char * home; char * dbhome; const char * dbfile; const char * dbsubfile; dbiIndex dbi = NULL; int rc = 0; int xx; DB * db = NULL; DB_ENV * dbenv = NULL; DB_TXN * txnid = NULL; uint32_t oflags; int _printit; if (dbip) *dbip = NULL; /* * Parse db configuration parameters. */ if ((dbi = db3New(rpmdb, rpmtag)) == NULL) return 1; dbi->dbi_api = DB_VERSION_MAJOR; /* * Get the prefix/root component and directory path. */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); dbhome = rpmGenPath(root, home, NULL); if (dbi->dbi_temporary) { dbfile = NULL; dbsubfile = NULL; } else { #ifdef HACK /* XXX necessary to support dbsubfile */ dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename); dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : rpmTagGetName(dbi->dbi_rpmtag)); #else dbfile = (dbi->dbi_file ? dbi->dbi_file : rpmTagGetName(dbi->dbi_rpmtag)); dbsubfile = NULL; #endif } oflags = (dbi->dbi_oeflags | dbi->dbi_oflags); oflags &= ~DB_TRUNCATE; /* XXX this is dangerous */ #if 0 /* XXX rpmdb: illegal flag combination specified to DB->open */ if ( dbi->dbi_mode & O_EXCL) oflags |= DB_EXCL; #endif /* * Map open mode flags onto configured database/environment flags. */ if (dbi->dbi_temporary) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; oflags &= ~DB_RDONLY; dbi->dbi_oflags &= ~DB_RDONLY; } else { if ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) oflags |= DB_RDONLY; if (dbi->dbi_mode & O_CREAT) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; } #ifdef DANGEROUS if ( dbi->dbi_mode & O_TRUNC) oflags |= DB_TRUNCATE; #endif } /* * Create the /var/lib/rpm directory if it doesn't exist (root only). */ (void) rpmioMkpath(dbhome, 0755, getuid(), getgid()); /* * Avoid incompatible DB_CREATE/DB_RDONLY flags on DBENV->open. */ if (dbi->dbi_use_dbenv) { if (access(dbhome, W_OK) == -1) { /* dbhome is unwritable, don't attempt DB_CREATE on DB->open ... */ oflags &= ~DB_CREATE; /* ... but DBENV->open might still need DB_CREATE ... */ if (dbi->dbi_eflags & DB_PRIVATE) { dbi->dbi_eflags &= ~DB_JOINENV; } else { dbi->dbi_eflags |= DB_JOINENV; dbi->dbi_oeflags &= ~DB_CREATE; dbi->dbi_oeflags &= ~DB_THREAD; /* ... but, unless DB_PRIVATE is used, skip DBENV. */ dbi->dbi_use_dbenv = 0; } /* ... DB_RDONLY maps dbhome perms across files ... */ if (dbi->dbi_temporary) { oflags |= DB_CREATE; dbi->dbi_oeflags |= DB_CREATE; oflags &= ~DB_RDONLY; dbi->dbi_oflags &= ~DB_RDONLY; } else { oflags |= DB_RDONLY; /* ... and DB_WRITECURSOR won't be needed ... */ dbi->dbi_oflags |= DB_RDONLY; } } else { /* dbhome is writable, check for persistent dbenv. */ char * dbf = rpmGetPath(dbhome, "/__db.001", NULL); if (access(dbf, F_OK) == -1) { /* ... non-existent (or unwritable) DBENV, will create ... */ dbi->dbi_oeflags |= DB_CREATE; dbi->dbi_eflags &= ~DB_JOINENV; } else { /* ... pre-existent (or bogus) DBENV, will join ... */ if (dbi->dbi_eflags & DB_PRIVATE) { dbi->dbi_eflags &= ~DB_JOINENV; } else { dbi->dbi_eflags |= DB_JOINENV; dbi->dbi_oeflags &= ~DB_CREATE; dbi->dbi_oeflags &= ~DB_THREAD; } } dbf = _free(dbf); } } /* * Avoid incompatible DB_CREATE/DB_RDONLY flags on DB->open. */ if ((oflags & DB_CREATE) && (oflags & DB_RDONLY)) { /* dbhome is writable, and DB->open flags may conflict. */ const char * dbfn = (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag)); char * dbf = rpmGetPath(dbhome, "/", dbfn, NULL); if (access(dbf, F_OK) == -1) { /* File does not exist, DB->open might create ... */ oflags &= ~DB_RDONLY; } else { /* File exists, DB->open need not create ... */ oflags &= ~DB_CREATE; } /* Only writers need DB_WRITECURSOR ... */ if (!(oflags & DB_RDONLY) && access(dbf, W_OK) == 0) { dbi->dbi_oflags &= ~DB_RDONLY; } else { dbi->dbi_oflags |= DB_RDONLY; } dbf = _free(dbf); } /* * Turn off verify-on-close if opening read-only. */ if (oflags & DB_RDONLY) dbi->dbi_verify_on_close = 0; if (dbi->dbi_use_dbenv) { if (rpmdb->db_dbenv == NULL) { rc = db_init(dbi, dbhome, dbfile, dbsubfile, &dbenv); if (rc == 0) { rpmdb->db_dbenv = dbenv; rpmdb->db_opens = 1; } } else { dbenv = rpmdb->db_dbenv; rpmdb->db_opens++; } } { char *dbiflags = prDbiOpenFlags(oflags, 0); rpmlog(RPMLOG_DEBUG, "opening db index %s/%s %s mode=0x%x\n", dbhome, (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag)), dbiflags, dbi->dbi_mode); free(dbiflags); } if (rc == 0) { static int _lockdbfd = 0; rc = db_create(&db, dbenv, dbi->dbi_cflags); rc = cvtdberr(dbi, "db_create", rc, _debug); if (rc == 0 && db != NULL) { if (rc == 0 && rpmdb->db_malloc && rpmdb->db_realloc && rpmdb->db_free) { rc = db->set_alloc(db, rpmdb->db_malloc, rpmdb->db_realloc, rpmdb->db_free); rc = cvtdberr(dbi, "db->set_alloc", rc, _debug); } /* 4.1: db->set_cache_priority(???) */ if (rc == 0 && !dbi->dbi_use_dbenv && dbi->dbi_cachesize) { rc = db->set_cachesize(db, 0, dbi->dbi_cachesize, 0); rc = cvtdberr(dbi, "db->set_cachesize", rc, _debug); } /* 4.1: db->set_encrypt(???) */ /* 4.1: db->set_errcall(dbenv, rpmdb->db_errcall); */ /* 4.1: db->set_errfile(dbenv, rpmdb->db_errfile); */ /* 4.1: db->set_errpfx(dbenv, rpmdb->db_errpfx); */ /* 4.1: db->set_feedback(???) */ if (rc == 0 && dbi->dbi_lorder) { rc = db->set_lorder(db, dbi->dbi_lorder); rc = cvtdberr(dbi, "db->set_lorder", rc, _debug); } if (rc == 0 && dbi->dbi_pagesize) { rc = db->set_pagesize(db, dbi->dbi_pagesize); rc = cvtdberr(dbi, "db->set_pagesize", rc, _debug); } /* 4.1: db->set_paniccall(???) */ if (rc == 0 && oflags & DB_CREATE) { switch(dbi->dbi_type) { default: case DB_HASH: if (dbi->dbi_h_ffactor) { rc = db->set_h_ffactor(db, dbi->dbi_h_ffactor); rc = cvtdberr(dbi, "db->set_h_ffactor", rc, _debug); if (rc) break; } if (dbi->dbi_h_nelem) { rc = db->set_h_nelem(db, dbi->dbi_h_nelem); rc = cvtdberr(dbi, "db->set_h_nelem", rc, _debug); if (rc) break; } if (dbi->dbi_h_flags) { rc = db->set_flags(db, dbi->dbi_h_flags); rc = cvtdberr(dbi, "db->set_h_flags", rc, _debug); if (rc) break; } if (dbi->dbi_h_hash_fcn) { rc = db->set_h_hash(db, dbi->dbi_h_hash_fcn); rc = cvtdberr(dbi, "db->set_h_hash", rc, _debug); if (rc) break; } if (dbi->dbi_h_dup_compare_fcn) { rc = db->set_dup_compare(db, dbi->dbi_h_dup_compare_fcn); rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug); if (rc) break; } break; case DB_BTREE: /* 4.1: db->set_append_recno(???) */ if (dbi->dbi_bt_flags) { rc = db->set_flags(db, dbi->dbi_bt_flags); rc = cvtdberr(dbi, "db->set_bt_flags", rc, _debug); if (rc) break; } if (dbi->dbi_bt_minkey) { rc = db->set_bt_minkey(db, dbi->dbi_bt_minkey); rc = cvtdberr(dbi, "db->set_bt_minkey", rc, _debug); if (rc) break; } if (dbi->dbi_bt_compare_fcn) { rc = db->set_bt_compare(db, dbi->dbi_bt_compare_fcn); rc = cvtdberr(dbi, "db->set_bt_compare", rc, _debug); if (rc) break; } if (dbi->dbi_bt_dup_compare_fcn) { rc = db->set_dup_compare(db, dbi->dbi_bt_dup_compare_fcn); rc = cvtdberr(dbi, "db->set_dup_compare", rc, _debug); if (rc) break; } if (dbi->dbi_bt_prefix_fcn) { rc = db->set_bt_prefix(db, dbi->dbi_bt_prefix_fcn); rc = cvtdberr(dbi, "db->set_bt_prefix", rc, _debug); if (rc) break; } break; case DB_RECNO: if (dbi->dbi_re_delim) { /* 4.1: db->set_append_recno(???) */ rc = db->set_re_delim(db, dbi->dbi_re_delim); rc = cvtdberr(dbi, "db->set_re_selim", rc, _debug); if (rc) break; } if (dbi->dbi_re_len) { rc = db->set_re_len(db, dbi->dbi_re_len); rc = cvtdberr(dbi, "db->set_re_len", rc, _debug); if (rc) break; } if (dbi->dbi_re_pad) { rc = db->set_re_pad(db, dbi->dbi_re_pad); rc = cvtdberr(dbi, "db->set_re_pad", rc, _debug); if (rc) break; } if (dbi->dbi_re_source) { rc = db->set_re_source(db, dbi->dbi_re_source); rc = cvtdberr(dbi, "db->set_re_source", rc, _debug); if (rc) break; } break; case DB_QUEUE: if (dbi->dbi_q_extentsize) { rc = db->set_q_extentsize(db, dbi->dbi_q_extentsize); rc = cvtdberr(dbi, "db->set_q_extentsize", rc, _debug); if (rc) break; } break; } } if (rc == 0) { char * fullpath; const char * dbpath; fullpath = rpmGetPath(dbhome, "/", dbfile ? dbfile : "", NULL); #ifdef HACK /* XXX necessary to support dbsubfile */ dbpath = (!dbi->dbi_use_dbenv && !dbi->dbi_temporary) ? fullpath : dbfile; #else dbpath = (!dbi->dbi_temporary) ? fullpath : dbfile; #endif rc = (db->open)(db, txnid, dbpath, dbsubfile, dbi->dbi_type, oflags, dbi->dbi_perms); if (rc == 0 && dbi->dbi_type == DB_UNKNOWN) { DBTYPE dbi_type = DB_UNKNOWN; xx = db->get_type(db, &dbi_type); if (xx == 0) dbi->dbi_type = dbi_type; } free(fullpath); } /* XXX return rc == errno without printing */ _printit = (rc > 0 ? 0 : _debug); xx = cvtdberr(dbi, "db->open", rc, _printit); dbi->dbi_txnid = NULL; /* * 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. */ if (rc == 0 && dbi->dbi_lockdbfd && !((dbi->dbi_ecflags & DB_CLIENT) && dbi->dbi_host) && (!dbi->dbi_use_dbenv || _lockdbfd++ == 0)) { int fdno = -1; if (!(db->fd(db, &fdno) == 0 && fdno >= 0)) { rc = 1; } else { struct flock l; memset(&l, 0, sizeof(l)); l.l_whence = 0; l.l_start = 0; l.l_len = 0; l.l_type = (dbi->dbi_mode & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK; l.l_pid = 0; rc = fcntl(fdno, F_SETLK, (void *) &l); if (rc) { /* Warning iff using non-private CDB locking. */ rc = ((dbi->dbi_use_dbenv && (dbi->dbi_eflags & DB_INIT_CDB) && !(dbi->dbi_eflags & DB_PRIVATE)) ? 0 : 1); rpmlog( (rc ? RPMLOG_ERR : RPMLOG_WARNING), _("cannot get %s lock on %s/%s\n"), ((dbi->dbi_mode & O_ACCMODE) == O_RDONLY) ? _("shared") : _("exclusive"), dbhome, (dbfile ? dbfile : "")); } else if (dbfile) { rpmlog(RPMLOG_DEBUG, "locked db index %s/%s\n", dbhome, dbfile); } } } } } dbi->dbi_db = db; if (rc == 0 && dbi->dbi_db != NULL && dbip != NULL) { dbi->dbi_vec = &db3vec; *dbip = dbi; } else { dbi->dbi_verify_on_close = 0; (void) db3close(dbi, 0); } free(dbhome); return rc; }
static int db3close(dbiIndex dbi, unsigned int flags) { rpmdb rpmdb = dbi->dbi_rpmdb; const char * root; const char * home; char * dbhome; const char * dbfile; const char * dbsubfile; DB * db = dbi->dbi_db; int _printit; int rc = 0, xx; flags = 0; /* XXX unused */ /* * Get the prefix/root component and directory path. */ root = (dbi->dbi_root ? dbi->dbi_root : rpmdb->db_root); if ((root[0] == '/' && root[1] == '\0') || rpmdb->db_chrootDone) root = NULL; home = (dbi->dbi_home ? dbi->dbi_home : rpmdb->db_home); dbhome = rpmGenPath(root, home, NULL); if (dbi->dbi_temporary) { dbfile = NULL; dbsubfile = NULL; } else { #ifdef HACK /* XXX necessary to support dbsubfile */ dbfile = (dbi->dbi_file ? dbi->dbi_file : db3basename); dbsubfile = (dbi->dbi_subfile ? dbi->dbi_subfile : rpmTagGetName(dbi->dbi_rpmtag)); #else dbfile = (dbi->dbi_file ? dbi->dbi_file : rpmTagGetName(dbi->dbi_rpmtag)); dbsubfile = NULL; #endif } if (db) { rc = db->close(db, 0); /* 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, (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag))); } if (rpmdb->db_dbenv != NULL && dbi->dbi_use_dbenv) { if (rpmdb->db_opens == 1) { xx = db_fini(dbi, (dbhome ? dbhome : ""), dbfile, dbsubfile); rpmdb->db_dbenv = NULL; } rpmdb->db_opens--; } if (dbi->dbi_verify_on_close && !dbi->dbi_temporary) { DB_ENV * dbenv = NULL; rc = db_env_create(&dbenv, 0); rc = cvtdberr(dbi, "db_env_create", rc, _debug); if (rc || dbenv == NULL) goto exit; dbenv->set_errcall(dbenv, (void *) rpmdb->db_errcall); dbenv->set_errfile(dbenv, rpmdb->db_errfile); dbenv->set_errpfx(dbenv, rpmdb->db_errpfx); /* dbenv->set_paniccall(???) */ #if !(DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3) xx = dbenv->set_verbose(dbenv, DB_VERB_CHKPOINT, (dbi->dbi_verbose & DB_VERB_CHKPOINT)); #endif xx = dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, (dbi->dbi_verbose & DB_VERB_DEADLOCK)); xx = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, (dbi->dbi_verbose & DB_VERB_RECOVERY)); xx = dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, (dbi->dbi_verbose & DB_VERB_WAITSFOR)); if (dbi->dbi_tmpdir) { char * tmpdir = rpmGenPath(root, dbi->dbi_tmpdir, NULL); rc = dbenv->set_tmp_dir(dbenv, tmpdir); rc = cvtdberr(dbi, "dbenv->set_tmp_dir", rc, _debug); tmpdir = _free(tmpdir); if (rc) goto exit; } rc = (dbenv->open)(dbenv, dbhome, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0); rc = cvtdberr(dbi, "dbenv->open", rc, _debug); if (rc) goto exit; rc = db_create(&db, dbenv, 0); rc = cvtdberr(dbi, "db_create", rc, _debug); if (db != NULL) { char * dbf = rpmGetPath(dbhome, "/", dbfile, NULL); rc = db->verify(db, dbf, NULL, NULL, flags); rc = cvtdberr(dbi, "db->verify", rc, _debug); rpmlog(RPMLOG_DEBUG, "verified db index %s/%s\n", (dbhome ? dbhome : ""), (dbfile ? dbfile : rpmTagGetName(dbi->dbi_rpmtag))); /* * The DB handle may not be accessed again after * DB->verify is called, regardless of its return. */ db = NULL; dbf = _free(dbf); } xx = dbenv->close(dbenv, 0); xx = cvtdberr(dbi, "dbenv->close", xx, _debug); if (rc == 0 && xx) rc = xx; } exit: dbi->dbi_db = NULL; free(dbhome); dbi = db3Free(dbi); return rc; }
static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag, const char *macro, const char *lang) { char * field = spec->line; char * end; int multiToken = 0; rpmsenseFlags tagflags = RPMSENSE_ANY; rpmRC rc = RPMRC_FAIL; if (field == NULL) /* XXX can't happen */ goto exit; /* Find the start of the "field" and strip trailing space */ while ((*field) && (*field != ':')) field++; if (*field != ':') { rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"), spec->lineNum, spec->line); goto exit; } field++; SKIPSPACE(field); if (!*field) { /* Empty field */ rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"), spec->lineNum, spec->line); goto exit; } end = findLastChar(field); *(end+1) = '\0'; /* See if this is multi-token */ end = field; SKIPNONSPACE(end); if (*end != '\0') multiToken = 1; switch (tag) { case RPMTAG_NAME: SINGLE_TOKEN_ONLY; if (rpmCharCheck(spec, field, WHITELIST_NAME)) goto exit; headerPutString(pkg->header, tag, field); /* Main pkg name is unknown at the start, populate as soon as we can */ if (pkg == spec->packages) pkg->name = rpmstrPoolId(spec->pool, field, 1); break; case RPMTAG_VERSION: case RPMTAG_RELEASE: SINGLE_TOKEN_ONLY; if (rpmCharCheck(spec, field, "._+%{}~")) goto exit; headerPutString(pkg->header, tag, field); break; case RPMTAG_URL: case RPMTAG_DISTTAG: case RPMTAG_BUGURL: /* XXX TODO: validate format somehow */ case RPMTAG_VCS: SINGLE_TOKEN_ONLY; headerPutString(pkg->header, tag, field); break; case RPMTAG_GROUP: case RPMTAG_SUMMARY: case RPMTAG_DISTRIBUTION: case RPMTAG_VENDOR: case RPMTAG_LICENSE: case RPMTAG_PACKAGER: if (addLangTag(spec, pkg->header, tag, field, lang)) goto exit; break; case RPMTAG_BUILDROOT: /* just silently ignore BuildRoot */ macro = NULL; break; case RPMTAG_PREFIXES: { struct rpmtd_s td; const char *str; if (addOrAppendListEntry(pkg->header, tag, field)) goto exit; headerGet(pkg->header, tag, &td, HEADERGET_MINMEM); while ((str = rpmtdNextString(&td))) { size_t len = strlen(str); if (len > 1 && str[len-1] == '/') { rpmlog(RPMLOG_ERR, _("line %d: Prefixes must not end with \"/\": %s\n"), spec->lineNum, spec->line); rpmtdFreeData(&td); goto exit; } } rpmtdFreeData(&td); break; } case RPMTAG_DOCDIR: SINGLE_TOKEN_ONLY; if (field[0] != '/') { rpmlog(RPMLOG_ERR, _("line %d: Docdir must begin with '/': %s\n"), spec->lineNum, spec->line); goto exit; } macro = NULL; rpmPopMacro(NULL, "_docdir"); rpmPushMacro(NULL, "_docdir", NULL, field, RMIL_SPEC); break; case RPMTAG_EPOCH: { SINGLE_TOKEN_ONLY; uint32_t epoch; if (parseUnsignedNum(field, &epoch)) { rpmlog(RPMLOG_ERR, _("line %d: Epoch field must be an unsigned number: %s\n"), spec->lineNum, spec->line); goto exit; } headerPutUint32(pkg->header, tag, &epoch, 1); break; } case RPMTAG_AUTOREQPROV: pkg->autoReq = parseYesNo(field); pkg->autoProv = pkg->autoReq; break; case RPMTAG_AUTOREQ: pkg->autoReq = parseYesNo(field); break; case RPMTAG_AUTOPROV: pkg->autoProv = parseYesNo(field); break; case RPMTAG_SOURCE: case RPMTAG_PATCH: macro = NULL; if (addSource(spec, pkg, field, tag)) goto exit; break; case RPMTAG_ICON: SINGLE_TOKEN_ONLY; if (addSource(spec, pkg, field, tag) || readIcon(pkg->header, field)) goto exit; break; case RPMTAG_NOSOURCE: case RPMTAG_NOPATCH: spec->noSource = 1; if (parseNoSource(spec, field, tag)) goto exit; break; case RPMTAG_ORDERFLAGS: case RPMTAG_REQUIREFLAGS: if (parseBits(lang, installScriptBits, &tagflags)) { rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"), spec->lineNum, rpmTagGetName(tag), spec->line); goto exit; } /* fallthrough */ case RPMTAG_PREREQ: case RPMTAG_RECOMMENDFLAGS: case RPMTAG_SUGGESTFLAGS: case RPMTAG_SUPPLEMENTFLAGS: case RPMTAG_ENHANCEFLAGS: case RPMTAG_CONFLICTFLAGS: case RPMTAG_OBSOLETEFLAGS: case RPMTAG_PROVIDEFLAGS: if (parseRCPOT(spec, pkg, field, tag, 0, tagflags)) goto exit; break; case RPMTAG_BUILDPREREQ: case RPMTAG_BUILDREQUIRES: case RPMTAG_BUILDCONFLICTS: if (parseRCPOT(spec, spec->sourcePackage, field, tag, 0, tagflags)) goto exit; break; case RPMTAG_EXCLUDEARCH: case RPMTAG_EXCLUSIVEARCH: case RPMTAG_EXCLUDEOS: case RPMTAG_EXCLUSIVEOS: if (addOrAppendListEntry(spec->buildRestrictions, tag, field)) goto exit; break; case RPMTAG_BUILDARCHS: { int BACount; const char **BANames = NULL; if (poptParseArgvString(field, &BACount, &BANames)) { rpmlog(RPMLOG_ERR, _("line %d: Bad BuildArchitecture format: %s\n"), spec->lineNum, spec->line); goto exit; } if (spec->packages == pkg) { if (spec->BANames) { rpmlog(RPMLOG_ERR, _("line %d: Duplicate BuildArch entry: %s\n"), spec->lineNum, spec->line); BANames = _free(BANames); goto exit; } spec->BACount = BACount; spec->BANames = BANames; } else { if (BACount != 1 || !rstreq(BANames[0], "noarch")) { rpmlog(RPMLOG_ERR, _("line %d: Only noarch subpackages are supported: %s\n"), spec->lineNum, spec->line); BANames = _free(BANames); goto exit; } headerPutString(pkg->header, RPMTAG_ARCH, "noarch"); } if (!BACount) spec->BANames = _free(spec->BANames); break; } case RPMTAG_REMOVEPATHPOSTFIXES: argvSplit(&pkg->removePostfixes, field, ":"); break; default: rpmlog(RPMLOG_ERR, _("Internal error: Bogus tag %d\n"), tag); goto exit; } if (macro) { rpmPushMacro(spec->macros, macro, NULL, field, RMIL_SPEC); /* Add a separate uppercase macro for tags from the main package */ if (pkg == spec->packages) { char *m = xstrdup(macro); for (char *p = m; *p; ++p) *p = rtoupper(*p); rpmPushMacro(spec->macros, m, NULL, field, RMIL_SPEC); free(m); } } rc = RPMRC_OK; exit: return rc; }