|
|
2ff057 |
/** \ingroup rpmdep
|
|
|
2ff057 |
* \file lib/rpmts.c
|
|
|
2ff057 |
* Routine(s) to handle a "rpmts" transaction sets.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
#include "system.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <inttypes.h>
|
|
|
2ff057 |
#include <libgen.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmtypes.h>
|
|
|
2ff057 |
#include <rpm/rpmlib.h> /* rpmReadPackage etc */
|
|
|
2ff057 |
#include <rpm/rpmmacro.h>
|
|
|
2ff057 |
#include <rpm/rpmfileutil.h> /* rpmtsOpenDB() needs rpmGetPath */
|
|
|
2ff057 |
#include <rpm/rpmstring.h>
|
|
|
2ff057 |
#include <rpm/rpmkeyring.h>
|
|
|
2ff057 |
#include <rpm/rpmbase64.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include <rpm/rpmdb.h>
|
|
|
2ff057 |
#include <rpm/rpmds.h>
|
|
|
2ff057 |
#include <rpm/rpmfi.h>
|
|
|
2ff057 |
#include <rpm/rpmlog.h>
|
|
|
2ff057 |
#include <rpm/rpmsq.h>
|
|
|
2ff057 |
#include <rpm/rpmte.h>
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "rpmio/digest.h"
|
|
|
2ff057 |
#include "lib/rpmal.h"
|
|
|
2ff057 |
#include "lib/rpmchroot.h"
|
|
|
2ff057 |
#include "lib/rpmplugins.h"
|
|
|
2ff057 |
#include "lib/rpmts_internal.h"
|
|
|
2ff057 |
#include "lib/rpmte_internal.h"
|
|
|
2ff057 |
#include "lib/misc.h"
|
|
|
2ff057 |
#include "lib/rpmtriggers.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
#include "debug.h"
|
|
|
2ff057 |
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* Iterator across transaction elements, forward on install, backward on erase.
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
struct rpmtsi_s {
|
|
|
2ff057 |
rpmts ts; /*!< transaction set. */
|
|
|
2ff057 |
int oc; /*!< iterator index. */
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
struct rpmtxn_s {
|
|
|
2ff057 |
rpmlock lock; /* transaction lock */
|
|
|
2ff057 |
rpmtxnFlags flags; /* transaction flags */
|
|
|
2ff057 |
rpmts ts; /* parent transaction set reference */
|
|
|
2ff057 |
};
|
|
|
2ff057 |
|
|
|
2ff057 |
static void loadKeyring(rpmts ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
int _rpmts_stats = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
static rpmts rpmtsUnlink(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ts)
|
|
|
2ff057 |
ts->nrefs--;
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmts rpmtsLink(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ts)
|
|
|
2ff057 |
ts->nrefs++;
|
|
|
2ff057 |
return ts;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsCloseDB(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->rdb != NULL) {
|
|
|
2ff057 |
(void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBGET),
|
|
|
2ff057 |
rpmdbOp(ts->rdb, RPMDB_OP_DBGET));
|
|
|
2ff057 |
(void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBPUT),
|
|
|
2ff057 |
rpmdbOp(ts->rdb, RPMDB_OP_DBPUT));
|
|
|
2ff057 |
(void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DBDEL),
|
|
|
2ff057 |
rpmdbOp(ts->rdb, RPMDB_OP_DBDEL));
|
|
|
2ff057 |
rc = rpmdbClose(ts->rdb);
|
|
|
2ff057 |
ts->rdb = NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsOpenDB(rpmts ts, int dbmode)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->rdb != NULL && ts->dbmode == dbmode)
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
(void) rpmtsCloseDB(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX there's a potential db lock race here. */
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->dbmode = dbmode;
|
|
|
2ff057 |
rc = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
|
|
|
2ff057 |
if (rc) {
|
|
|
2ff057 |
char * dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("cannot open Packages database in %s\n"), dn);
|
|
|
2ff057 |
free(dn);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsInitDB(rpmts ts, int dbmode)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_WRITE);
|
|
|
2ff057 |
int rc = -1;
|
|
|
2ff057 |
if (txn)
|
|
|
2ff057 |
rc = rpmdbInit(ts->rootDir, dbmode);
|
|
|
2ff057 |
rpmtxnEnd(txn);
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsGetDBMode(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
assert(ts != NULL);
|
|
|
2ff057 |
return (ts->dbmode);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetDBMode(rpmts ts, int dbmode)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 1;
|
|
|
2ff057 |
/* mode setting only permitted on non-open db */
|
|
|
2ff057 |
if (ts != NULL && rpmtsGetRdb(ts) == NULL) {
|
|
|
2ff057 |
ts->dbmode = dbmode;
|
|
|
2ff057 |
rc = 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsRebuildDB(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = -1;
|
|
|
2ff057 |
rpmtxn txn = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Cannot do this on a populated transaction set */
|
|
|
2ff057 |
if (rpmtsNElements(ts) > 0)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
txn = rpmtxnBegin(ts, RPMTXN_WRITE);
|
|
|
2ff057 |
if (txn) {
|
|
|
2ff057 |
if (!(ts->vsflags & RPMVSF_NOHDRCHK))
|
|
|
2ff057 |
rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
|
|
|
2ff057 |
else
|
|
|
2ff057 |
rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
|
|
|
2ff057 |
rpmtxnEnd(txn);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsVerifyDB(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = -1;
|
|
|
2ff057 |
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_READ);
|
|
|
2ff057 |
if (txn) {
|
|
|
2ff057 |
rc = rpmdbVerify(ts->rootDir);
|
|
|
2ff057 |
rpmtxnEnd(txn);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* keyp might no be defined. */
|
|
|
2ff057 |
rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmDbiTagVal rpmtag,
|
|
|
2ff057 |
const void * keyp, size_t keylen)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmdbMatchIterator mi = NULL;
|
|
|
2ff057 |
char *tmp = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts && ts->keyring == NULL)
|
|
|
2ff057 |
loadKeyring(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Parse out "N(EVR)" tokens from a label key if present */
|
|
|
2ff057 |
if (rpmtag == RPMDBI_LABEL && keyp != NULL && strchr(keyp, '(')) {
|
|
|
2ff057 |
const char *se, *s = keyp;
|
|
|
2ff057 |
char *t;
|
|
|
2ff057 |
size_t slen = strlen(s);
|
|
|
2ff057 |
int level = 0;
|
|
|
2ff057 |
int c;
|
|
|
2ff057 |
|
|
|
2ff057 |
tmp = xmalloc(slen+1);
|
|
|
2ff057 |
keyp = t = tmp;
|
|
|
2ff057 |
while ((c = *s++) != '\0') {
|
|
|
2ff057 |
switch (c) {
|
|
|
2ff057 |
default:
|
|
|
2ff057 |
*t++ = c;
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case '(':
|
|
|
2ff057 |
/* XXX Fail if nested parens. */
|
|
|
2ff057 |
if (level++ != 0) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("extra '(' in package label: %s\n"), (const char*)keyp);
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* Parse explicit epoch. */
|
|
|
2ff057 |
for (se = s; *se && risdigit(*se); se++)
|
|
|
2ff057 |
{};
|
|
|
2ff057 |
if (*se == ':') {
|
|
|
2ff057 |
/* XXX skip explicit epoch's (for now) */
|
|
|
2ff057 |
*t++ = '-';
|
|
|
2ff057 |
s = se + 1;
|
|
|
2ff057 |
} else {
|
|
|
2ff057 |
/* No Epoch: found. Convert '(' to '-' and chug. */
|
|
|
2ff057 |
*t++ = '-';
|
|
|
2ff057 |
}
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
case ')':
|
|
|
2ff057 |
/* XXX Fail if nested parens. */
|
|
|
2ff057 |
if (--level != 0) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("missing '(' in package label: %s\n"), (const char*)keyp);
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
/* Don't copy trailing ')' */
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (level) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("missing ')' in package label: %s\n"), (const char*)keyp);
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
*t = '\0';
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
mi = rpmdbInitIterator(ts->rdb, rpmtag, keyp, keylen);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Verify header signature/digest during retrieve (if not disabled). */
|
|
|
2ff057 |
if (mi && !(ts->vsflags & RPMVSF_NOHDRCHK))
|
|
|
2ff057 |
(void) rpmdbSetHdrChk(mi, ts, headerCheck);
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
free(tmp);
|
|
|
2ff057 |
|
|
|
2ff057 |
return mi;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmKeyring rpmtsGetKeyring(rpmts ts, int autoload)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmKeyring keyring = NULL;
|
|
|
2ff057 |
if (ts) {
|
|
|
2ff057 |
if (ts->keyring == NULL && autoload) {
|
|
|
2ff057 |
loadKeyring(ts);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
keyring = rpmKeyringLink(ts->keyring);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return keyring;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetKeyring(rpmts ts, rpmKeyring keyring)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmKeyringFree(ts->keyring);
|
|
|
2ff057 |
ts->keyring = rpmKeyringLink(keyring);
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int loadKeyringFromFiles(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
ARGV_t files = NULL;
|
|
|
2ff057 |
/* XXX TODO: deal with chroot path issues */
|
|
|
2ff057 |
char *pkpath = rpmGetPath(ts->rootDir, "%{_keyringpath}/*.key", NULL);
|
|
|
2ff057 |
int nkeys = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "loading keyring from pubkeys in %s\n", pkpath);
|
|
|
2ff057 |
if (rpmGlob(pkpath, NULL, &files)) {
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "couldn't find any keys in %s\n", pkpath);
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
for (char **f = files; *f; f++) {
|
|
|
2ff057 |
int subkeysCount, i;
|
|
|
2ff057 |
rpmPubkey *subkeys;
|
|
|
2ff057 |
rpmPubkey key = rpmPubkeyRead(*f);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (!key) {
|
|
|
2ff057 |
rpmlog(RPMLOG_ERR, _("%s: reading of public key failed.\n"), *f);
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (rpmKeyringAddKey(ts->keyring, key) == 0) {
|
|
|
2ff057 |
nkeys++;
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", *f);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
subkeys = rpmGetSubkeys(key, &subkeysCount);
|
|
|
2ff057 |
rpmPubkeyFree(key);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < subkeysCount; i++) {
|
|
|
2ff057 |
rpmPubkey subkey = subkeys[i];
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmKeyringAddKey(ts->keyring, subkey) == 0) {
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG,
|
|
|
2ff057 |
"added subkey %d of main key %s to keyring\n",
|
|
|
2ff057 |
i, *f);
|
|
|
2ff057 |
|
|
|
2ff057 |
nkeys++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmPubkeyFree(subkey);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(subkeys);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
free(pkpath);
|
|
|
2ff057 |
argvFree(files);
|
|
|
2ff057 |
return nkeys;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int loadKeyringFromDB(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
Header h;
|
|
|
2ff057 |
rpmdbMatchIterator mi;
|
|
|
2ff057 |
int nkeys = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "loading keyring from rpmdb\n");
|
|
|
2ff057 |
mi = rpmtsInitIterator(ts, RPMDBI_NAME, "gpg-pubkey", 0);
|
|
|
2ff057 |
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
|
|
2ff057 |
struct rpmtd_s pubkeys;
|
|
|
2ff057 |
const char *key;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (!headerGet(h, RPMTAG_PUBKEYS, &pubkeys, HEADERGET_MINMEM))
|
|
|
2ff057 |
continue;
|
|
|
2ff057 |
|
|
|
2ff057 |
while ((key = rpmtdNextString(&pubkeys))) {
|
|
|
2ff057 |
uint8_t *pkt;
|
|
|
2ff057 |
size_t pktlen;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmBase64Decode(key, (void **) &pkt, &pktlen) == 0) {
|
|
|
2ff057 |
rpmPubkey key = rpmPubkeyNew(pkt, pktlen);
|
|
|
2ff057 |
int subkeysCount, i;
|
|
|
2ff057 |
rpmPubkey *subkeys = rpmGetSubkeys(key, &subkeysCount);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmKeyringAddKey(ts->keyring, key) == 0) {
|
|
|
2ff057 |
char *nvr = headerGetAsString(h, RPMTAG_NVR);
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", nvr);
|
|
|
2ff057 |
free(nvr);
|
|
|
2ff057 |
nkeys++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmPubkeyFree(key);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < subkeysCount; i++) {
|
|
|
2ff057 |
rpmPubkey subkey = subkeys[i];
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmKeyringAddKey(ts->keyring, subkey) == 0) {
|
|
|
2ff057 |
char *nvr = headerGetAsString(h, RPMTAG_NVR);
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG,
|
|
|
2ff057 |
"added subkey %d of main key %s to keyring\n",
|
|
|
2ff057 |
i, nvr);
|
|
|
2ff057 |
|
|
|
2ff057 |
free(nvr);
|
|
|
2ff057 |
nkeys++;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmPubkeyFree(subkey);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(subkeys);
|
|
|
2ff057 |
free(pkt);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmtdFreeData(&pubkeys);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmdbFreeIterator(mi);
|
|
|
2ff057 |
|
|
|
2ff057 |
return nkeys;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static void loadKeyring(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
/* Never load the keyring if signature checking is disabled */
|
|
|
2ff057 |
if ((rpmtsVSFlags(ts) & RPMVSF_MASK_NOSIGNATURES) !=
|
|
|
2ff057 |
RPMVSF_MASK_NOSIGNATURES) {
|
|
|
2ff057 |
ts->keyring = rpmKeyringNew();
|
|
|
2ff057 |
if (loadKeyringFromFiles(ts) == 0) {
|
|
|
2ff057 |
if (loadKeyringFromDB(ts) > 0) {
|
|
|
2ff057 |
/* XXX make this a warning someday... */
|
|
|
2ff057 |
rpmlog(RPMLOG_DEBUG, "Using legacy gpg-pubkey(s) from rpmdb\n");
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Build pubkey header. */
|
|
|
2ff057 |
static int makePubkeyHeader(rpmts ts, rpmPubkey key, rpmPubkey *subkeys,
|
|
|
2ff057 |
int subkeysCount, Header * hdrp)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
Header h = headerNew();
|
|
|
2ff057 |
const char * afmt = "%{pubkeys:armor}";
|
|
|
2ff057 |
const char * group = "Public Keys";
|
|
|
2ff057 |
const char * license = "pubkey";
|
|
|
2ff057 |
const char * buildhost = "localhost";
|
|
|
2ff057 |
const char * userid;
|
|
|
2ff057 |
rpmsenseFlags pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
|
|
|
2ff057 |
uint32_t zero = 0;
|
|
|
2ff057 |
uint32_t keytime = 0;
|
|
|
2ff057 |
pgpDig dig = NULL;
|
|
|
2ff057 |
pgpDigParams pubp = NULL;
|
|
|
2ff057 |
char * d = NULL;
|
|
|
2ff057 |
char * enc = NULL;
|
|
|
2ff057 |
char * n = NULL;
|
|
|
2ff057 |
char * u = NULL;
|
|
|
2ff057 |
char * v = NULL;
|
|
|
2ff057 |
char * r = NULL;
|
|
|
2ff057 |
char * evr = NULL;
|
|
|
2ff057 |
int rc = -1;
|
|
|
2ff057 |
int i;
|
|
|
2ff057 |
|
|
|
2ff057 |
if ((enc = rpmPubkeyBase64(key)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
if ((dig = rpmPubkeyDig(key)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
if ((pubp = pgpDigGetParams(dig, PGPTAG_PUBLIC_KEY)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Build header elements. */
|
|
|
2ff057 |
v = pgpHexStr(pubp->signid, sizeof(pubp->signid));
|
|
|
2ff057 |
userid = pubp->userid ? pubp->userid : "none";
|
|
|
2ff057 |
keytime = pubp->time;
|
|
|
2ff057 |
|
|
|
2ff057 |
rasprintf(&n, "gpg(%s)", v+8);
|
|
|
2ff057 |
rasprintf(&u, "gpg(%s)", userid);
|
|
|
2ff057 |
rasprintf(&r, "%x", keytime);
|
|
|
2ff057 |
rasprintf(&evr, "%d:%s-%s", pubp->version, v, r);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PUBKEYS, enc);
|
|
|
2ff057 |
|
|
|
2ff057 |
if ((d = headerFormat(h, afmt, NULL)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_NAME, "gpg-pubkey");
|
|
|
2ff057 |
headerPutString(h, RPMTAG_VERSION, v+8);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_RELEASE, r);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_DESCRIPTION, d);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_GROUP, group);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_LICENSE, license);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_SUMMARY, u);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PACKAGER, userid);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_SIZE, &zero, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDENAME, u);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDENAME, n);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_RPMVERSION, RPMVERSION);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_BUILDHOST, buildhost);
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_BUILDTIME, &keytime, 1);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_SOURCERPM, "(none)");
|
|
|
2ff057 |
|
|
|
2ff057 |
for (i = 0; i < subkeysCount; i++) {
|
|
|
2ff057 |
char *v, *r, *n, *evr;
|
|
|
2ff057 |
pgpDigParams pgpkey;
|
|
|
2ff057 |
|
|
|
2ff057 |
pgpkey = rpmPubkeyPgpDigParams(subkeys[i]);
|
|
|
2ff057 |
v = pgpHexStr(pgpkey->signid, sizeof(pgpkey->signid));
|
|
|
2ff057 |
|
|
|
2ff057 |
rasprintf(&n, "gpg(%s)", v+8);
|
|
|
2ff057 |
rasprintf(&r, "%x", pgpkey->time);
|
|
|
2ff057 |
rasprintf(&evr, "%d:%s-%s", pubp->version, v, r);
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDENAME, n);
|
|
|
2ff057 |
headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
free(v);
|
|
|
2ff057 |
free(r);
|
|
|
2ff057 |
free(n);
|
|
|
2ff057 |
free(evr);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Reload the lot to immutable region and stomp sha1 digest on it */
|
|
|
2ff057 |
h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
|
|
|
2ff057 |
if (h != NULL) {
|
|
|
2ff057 |
char *sha1 = NULL;
|
|
|
2ff057 |
unsigned int blen = 0;
|
|
|
2ff057 |
void *blob = headerExport(h, &blen);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX FIXME: bah, this code is repeated in way too many places */
|
|
|
2ff057 |
DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
|
|
|
2ff057 |
rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
|
|
|
2ff057 |
rpmDigestUpdate(ctx, blob, blen);
|
|
|
2ff057 |
rpmDigestFinal(ctx, (void **)&sha1, NULL, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (sha1) {
|
|
|
2ff057 |
headerPutString(h, RPMTAG_SHA1HEADER, sha1);
|
|
|
2ff057 |
*hdrp = headerLink(h);
|
|
|
2ff057 |
rc = 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(sha1);
|
|
|
2ff057 |
free(blob);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
headerFree(h);
|
|
|
2ff057 |
pgpFreeDig(dig);
|
|
|
2ff057 |
free(n);
|
|
|
2ff057 |
free(u);
|
|
|
2ff057 |
free(v);
|
|
|
2ff057 |
free(r);
|
|
|
2ff057 |
free(evr);
|
|
|
2ff057 |
free(enc);
|
|
|
2ff057 |
free(d);
|
|
|
2ff057 |
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmtsImportHeader(rpmtxn txn, Header h, rpmFlags flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmRC rc = RPMRC_FAIL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (txn && h && rpmtsOpenDB(txn->ts, (O_RDWR|O_CREAT)) == 0) {
|
|
|
2ff057 |
if (rpmdbAdd(rpmtsGetRdb(txn->ts), h) == 0) {
|
|
|
2ff057 |
rc = RPMRC_OK;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmRC rpmtsImportPubkey(const rpmts ts, const unsigned char * pkt, size_t pktlen)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
Header h = NULL;
|
|
|
2ff057 |
rpmRC rc = RPMRC_FAIL; /* assume failure */
|
|
|
2ff057 |
rpmPubkey pubkey = NULL;
|
|
|
2ff057 |
rpmPubkey *subkeys = NULL;
|
|
|
2ff057 |
int subkeysCount = 0;
|
|
|
2ff057 |
rpmVSFlags oflags = rpmtsVSFlags(ts);
|
|
|
2ff057 |
rpmKeyring keyring;
|
|
|
2ff057 |
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_WRITE);
|
|
|
2ff057 |
int krc, i;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (txn == NULL)
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* XXX keyring wont load if sigcheck disabled, force it temporarily */
|
|
|
2ff057 |
rpmtsSetVSFlags(ts, (oflags & ~RPMVSF_MASK_NOSIGNATURES));
|
|
|
2ff057 |
keyring = rpmtsGetKeyring(ts, 1);
|
|
|
2ff057 |
rpmtsSetVSFlags(ts, oflags);
|
|
|
2ff057 |
|
|
|
2ff057 |
if ((pubkey = rpmPubkeyNew(pkt, pktlen)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
if ((subkeys = rpmGetSubkeys(pubkey, &subkeysCount)) == NULL)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
krc = rpmKeyringAddKey(keyring, pubkey);
|
|
|
2ff057 |
if (krc < 0)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* If we dont already have the key, make a persistent record of it */
|
|
|
2ff057 |
if (krc == 0) {
|
|
|
2ff057 |
rpm_tid_t tid = rpmtsGetTid(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (makePubkeyHeader(ts, pubkey, subkeys, subkeysCount, &h) != 0)
|
|
|
2ff057 |
goto exit;
|
|
|
2ff057 |
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_INSTALLTIME, &tid, 1);
|
|
|
2ff057 |
headerPutUint32(h, RPMTAG_INSTALLTID, &tid, 1);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Add header to database. */
|
|
|
2ff057 |
if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
|
|
|
2ff057 |
rc = rpmtsImportHeader(txn, h, 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rc = RPMRC_OK;
|
|
|
2ff057 |
|
|
|
2ff057 |
exit:
|
|
|
2ff057 |
/* Clean up. */
|
|
|
2ff057 |
headerFree(h);
|
|
|
2ff057 |
rpmPubkeyFree(pubkey);
|
|
|
2ff057 |
for (i = 0; i < subkeysCount; i++)
|
|
|
2ff057 |
rpmPubkeyFree(subkeys[i]);
|
|
|
2ff057 |
free(subkeys);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmKeyringFree(keyring);
|
|
|
2ff057 |
rpmtxnEnd(txn);
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetSolveCallback(rpmts ts,
|
|
|
2ff057 |
int (*solve) (rpmts ts, rpmds key, const void * data),
|
|
|
2ff057 |
const void * solveData)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts) {
|
|
|
2ff057 |
ts->solve = solve;
|
|
|
2ff057 |
ts->solveData = solveData;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSolve(rpmts ts, rpmds key)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int rc = 1; /* assume not found */
|
|
|
2ff057 |
if (ts && ts->solve) {
|
|
|
2ff057 |
rc = (*ts->solve)(ts, key, ts->solveData);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rc;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmps rpmtsProblems(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmps ps = rpmpsCreate();
|
|
|
2ff057 |
rpmtsi pi = rpmtsiInit(ts);
|
|
|
2ff057 |
rpmte p;
|
|
|
2ff057 |
|
|
|
2ff057 |
while ((p = rpmtsiNext(pi, 0)) != NULL) {
|
|
|
2ff057 |
rpmps teprobs = rpmteProblems(p);
|
|
|
2ff057 |
rpmpsMerge(ps, teprobs);
|
|
|
2ff057 |
rpmpsFree(teprobs);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
rpmtsiFree(pi);
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Return NULL on no problems instead of an empty set */
|
|
|
2ff057 |
if (rpmpsNumProblems(ps) == 0) {
|
|
|
2ff057 |
ps = rpmpsFree(ps);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return ps;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmtsCleanProblems(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmte p;
|
|
|
2ff057 |
rpmtsi pi = rpmtsiInit(ts);
|
|
|
2ff057 |
while ((p = rpmtsiNext(pi, 0)) != NULL)
|
|
|
2ff057 |
rpmteCleanProblems(p);
|
|
|
2ff057 |
rpmtsiFree(pi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmtsClean(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmtsi pi; rpmte p;
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
|
|
|
2ff057 |
/* Clean up after dependency checks. */
|
|
|
2ff057 |
pi = rpmtsiInit(ts);
|
|
|
2ff057 |
while ((p = rpmtsiNext(pi, 0)) != NULL)
|
|
|
2ff057 |
rpmteCleanDS(p);
|
|
|
2ff057 |
rpmtsiFree(pi);
|
|
|
2ff057 |
|
|
|
2ff057 |
tsmem->addedPackages = rpmalFree(tsmem->addedPackages);
|
|
|
2ff057 |
tsmem->rpmlib = rpmdsFree(tsmem->rpmlib);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsCleanProblems(ts);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* hash comparison function */
|
|
|
2ff057 |
static int uintCmp(unsigned int a, unsigned int b)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (a != b);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/* "hash"function*/
|
|
|
2ff057 |
static unsigned int uintId(unsigned int a)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return a;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmtsEmpty(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsClean(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
for (int oc = 0; oc < tsmem->orderCount; oc++) {
|
|
|
2ff057 |
tsmem->order[oc] = rpmteFree(tsmem->order[oc]);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
tsmem->orderCount = 0;
|
|
|
2ff057 |
/* The pool cannot be emptied, there might be references to its contents */
|
|
|
2ff057 |
tsmem->pool = rpmstrPoolFree(tsmem->pool);
|
|
|
2ff057 |
packageHashEmpty(tsmem->removedPackages);
|
|
|
2ff057 |
return;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static void rpmtsPrintStat(const char * name, struct rpmop_s * op)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
static const unsigned int scale = (1000 * 1000);
|
|
|
2ff057 |
if (op != NULL && op->count > 0)
|
|
|
2ff057 |
fprintf(stderr, " %s %6d %6lu.%06lu MB %6lu.%06lu secs\n",
|
|
|
2ff057 |
name, op->count,
|
|
|
2ff057 |
(unsigned long)op->bytes/scale, (unsigned long)op->bytes%scale,
|
|
|
2ff057 |
op->usecs/scale, op->usecs%scale);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static void rpmtsPrintStats(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
(void) rpmswExit(rpmtsOp(ts, RPMTS_OP_TOTAL), 0);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsPrintStat("total: ", rpmtsOp(ts, RPMTS_OP_TOTAL));
|
|
|
2ff057 |
rpmtsPrintStat("check: ", rpmtsOp(ts, RPMTS_OP_CHECK));
|
|
|
2ff057 |
rpmtsPrintStat("order: ", rpmtsOp(ts, RPMTS_OP_ORDER));
|
|
|
2ff057 |
rpmtsPrintStat("verify: ", rpmtsOp(ts, RPMTS_OP_VERIFY));
|
|
|
2ff057 |
rpmtsPrintStat("fingerprint: ", rpmtsOp(ts, RPMTS_OP_FINGERPRINT));
|
|
|
2ff057 |
rpmtsPrintStat("install: ", rpmtsOp(ts, RPMTS_OP_INSTALL));
|
|
|
2ff057 |
rpmtsPrintStat("erase: ", rpmtsOp(ts, RPMTS_OP_ERASE));
|
|
|
2ff057 |
rpmtsPrintStat("scriptlets: ", rpmtsOp(ts, RPMTS_OP_SCRIPTLETS));
|
|
|
2ff057 |
rpmtsPrintStat("compress: ", rpmtsOp(ts, RPMTS_OP_COMPRESS));
|
|
|
2ff057 |
rpmtsPrintStat("uncompress: ", rpmtsOp(ts, RPMTS_OP_UNCOMPRESS));
|
|
|
2ff057 |
rpmtsPrintStat("digest: ", rpmtsOp(ts, RPMTS_OP_DIGEST));
|
|
|
2ff057 |
rpmtsPrintStat("signature: ", rpmtsOp(ts, RPMTS_OP_SIGNATURE));
|
|
|
2ff057 |
rpmtsPrintStat("dbadd: ", rpmtsOp(ts, RPMTS_OP_DBADD));
|
|
|
2ff057 |
rpmtsPrintStat("dbremove: ", rpmtsOp(ts, RPMTS_OP_DBREMOVE));
|
|
|
2ff057 |
rpmtsPrintStat("dbget: ", rpmtsOp(ts, RPMTS_OP_DBGET));
|
|
|
2ff057 |
rpmtsPrintStat("dbput: ", rpmtsOp(ts, RPMTS_OP_DBPUT));
|
|
|
2ff057 |
rpmtsPrintStat("dbdel: ", rpmtsOp(ts, RPMTS_OP_DBDEL));
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmts rpmtsFree(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->nrefs > 1)
|
|
|
2ff057 |
return rpmtsUnlink(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsEmpty(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
(void) rpmtsCloseDB(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
tsmem->removedPackages = packageHashFree(tsmem->removedPackages);
|
|
|
2ff057 |
tsmem->installedPackages = packageHashFree(tsmem->installedPackages);
|
|
|
2ff057 |
tsmem->order = _free(tsmem->order);
|
|
|
2ff057 |
ts->members = _free(ts->members);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->dsi = _free(ts->dsi);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->scriptFd != NULL) {
|
|
|
2ff057 |
ts->scriptFd = fdFree(ts->scriptFd);
|
|
|
2ff057 |
ts->scriptFd = NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ts->rootDir = _free(ts->rootDir);
|
|
|
2ff057 |
ts->lockPath = _free(ts->lockPath);
|
|
|
2ff057 |
ts->lock = rpmlockFree(ts->lock);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->keyring = rpmKeyringFree(ts->keyring);
|
|
|
2ff057 |
ts->netsharedPaths = argvFree(ts->netsharedPaths);
|
|
|
2ff057 |
ts->installLangs = argvFree(ts->installLangs);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->plugins = rpmpluginsFree(ts->plugins);
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtriggersFree(ts->trigs2run);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (_rpmts_stats)
|
|
|
2ff057 |
rpmtsPrintStats(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
(void) rpmtsUnlink(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts = _free(ts);
|
|
|
2ff057 |
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmVSFlags rpmtsVSFlags(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmVSFlags vsflags = 0;
|
|
|
2ff057 |
if (ts != NULL)
|
|
|
2ff057 |
vsflags = ts->vsflags;
|
|
|
2ff057 |
return vsflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmVSFlags ovsflags = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ovsflags = ts->vsflags;
|
|
|
2ff057 |
ts->vsflags = vsflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ovsflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmVSFlags rpmtsVfyFlags(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmVSFlags vfyflags = 0;
|
|
|
2ff057 |
if (ts != NULL)
|
|
|
2ff057 |
vfyflags = ts->vfyflags;
|
|
|
2ff057 |
return vfyflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmVSFlags rpmtsSetVfyFlags(rpmts ts, rpmVSFlags vfyflags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmVSFlags ovfyflags = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ovfyflags = ts->vfyflags;
|
|
|
2ff057 |
ts->vfyflags = vfyflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ovfyflags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsVfyLevel(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int vfylevel = 0;
|
|
|
2ff057 |
if (ts != NULL)
|
|
|
2ff057 |
vfylevel = ts->vfylevel;
|
|
|
2ff057 |
return vfylevel;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetVfyLevel(rpmts ts, int vfylevel)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int ovfylevel = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ovfylevel = ts->vfylevel;
|
|
|
2ff057 |
ts->vfylevel = vfylevel;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ovfylevel;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
const char * rpmtsRootDir(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return ts ? ts->rootDir : NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetRootDir(rpmts ts, const char * rootDir)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ts == NULL || (rootDir && rootDir[0] != '/')) {
|
|
|
2ff057 |
return -1;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->rootDir = _free(ts->rootDir);
|
|
|
2ff057 |
/* Ensure clean path with a trailing slash */
|
|
|
2ff057 |
ts->rootDir = rootDir ? rpmGetPath(rootDir, NULL) : xstrdup("/");
|
|
|
2ff057 |
if (!rstreq(ts->rootDir, "/")) {
|
|
|
2ff057 |
rstrcat(&ts->rootDir, "/");
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
FD_t rpmtsScriptFd(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
FD_t scriptFd = NULL;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
scriptFd = ts->scriptFd;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return scriptFd;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void rpmtsSetScriptFd(rpmts ts, FD_t scriptFd)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
if (ts->scriptFd != NULL) {
|
|
|
2ff057 |
ts->scriptFd = fdFree(ts->scriptFd);
|
|
|
2ff057 |
ts->scriptFd = NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
if (scriptFd != NULL)
|
|
|
2ff057 |
ts->scriptFd = fdLink(scriptFd);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_tid_t rpmtsGetTid(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_tid_t tid = (rpm_tid_t)-1; /* XXX -1 is time(2) error return. */
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
tid = ts->tid;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tid;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_tid_t rpmtsSetTid(rpmts ts, rpm_tid_t tid)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_tid_t otid = (rpm_tid_t)-1; /* XXX -1 is time(2) error return. */
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
otid = ts->tid;
|
|
|
2ff057 |
ts->tid = tid;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return otid;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmdb rpmtsGetRdb(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmdb rdb = NULL;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
rdb = ts->rdb;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return rdb;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
void * rpmtsNotify(rpmts ts, rpmte te,
|
|
|
2ff057 |
rpmCallbackType what, rpm_loff_t amount, rpm_loff_t total)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
void * ptr = NULL;
|
|
|
2ff057 |
if (ts && ts->notify) {
|
|
|
2ff057 |
Header h = NULL;
|
|
|
2ff057 |
fnpyKey cbkey = NULL;
|
|
|
2ff057 |
if (te) {
|
|
|
2ff057 |
h = rpmteHeader(te);
|
|
|
2ff057 |
cbkey = rpmteKey(te);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ptr = ts->notify(h, what, amount, total, cbkey, ts->notifyData);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (h) {
|
|
|
2ff057 |
headerFree(h); /* undo rpmteHeader() ref */
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ptr;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsNElements(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int nelements = 0;
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
if (tsmem != NULL && tsmem->order != NULL) {
|
|
|
2ff057 |
nelements = tsmem->orderCount;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return nelements;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmte rpmtsElement(rpmts ts, int ix)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmte te = NULL;
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
if (tsmem != NULL && tsmem->order != NULL) {
|
|
|
2ff057 |
if (ix >= 0 && ix < tsmem->orderCount)
|
|
|
2ff057 |
te = tsmem->order[ix];
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return te;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmprobFilterFlags rpmtsFilterFlags(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ts != NULL ? ts->ignoreSet : 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtransFlags rpmtsFlags(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ts != NULL ? ts->transFlags : 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmtransFlags otransFlags = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
otransFlags = ts->transFlags;
|
|
|
2ff057 |
ts->transFlags = transFlags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return otransFlags;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmtsColor(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ts != NULL ? ts->color : 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmtsSetColor(rpmts ts, rpm_color_t color)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_color_t ocolor = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ocolor = ts->color;
|
|
|
2ff057 |
ts->color = color;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ocolor;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmtsPrefColor(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ts != NULL ? ts->prefcolor : 0);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpm_color_t rpmtsSetPrefColor(rpmts ts, rpm_color_t color)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpm_color_t ocolor = 0;
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ocolor = ts->prefcolor;
|
|
|
2ff057 |
ts->prefcolor = color;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return ocolor;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmop op = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts != NULL && opx >= 0 && opx < RPMTS_OP_MAX)
|
|
|
2ff057 |
op = ts->ops + opx;
|
|
|
2ff057 |
return op;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmPlugins rpmtsPlugins(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmPlugins plugins = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
if (ts->plugins == NULL)
|
|
|
2ff057 |
ts->plugins = rpmpluginsNew(ts);
|
|
|
2ff057 |
plugins = ts->plugins;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return plugins;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
int rpmtsSetNotifyCallback(rpmts ts,
|
|
|
2ff057 |
rpmCallbackFunction notify, rpmCallbackData notifyData)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (ts != NULL) {
|
|
|
2ff057 |
ts->notify = notify;
|
|
|
2ff057 |
ts->notifyData = notifyData;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return 0;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
tsMembers rpmtsMembers(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
return (ts != NULL) ? ts->members : NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmstrPool rpmtsPool(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
tsMembers tsmem = rpmtsMembers(ts);
|
|
|
2ff057 |
rpmstrPool tspool = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tsmem) {
|
|
|
2ff057 |
if (tsmem->pool == NULL)
|
|
|
2ff057 |
tsmem->pool = rpmstrPoolCreate();
|
|
|
2ff057 |
tspool = tsmem->pool;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return tspool;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
static int vfylevel_init(void)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
int vfylevel = -1;
|
|
|
2ff057 |
char *val = rpmExpand("%{?_pkgverify_level}", NULL);
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rstreq(val, "all"))
|
|
|
2ff057 |
vfylevel = RPMSIG_SIGNATURE_TYPE|RPMSIG_DIGEST_TYPE;
|
|
|
2ff057 |
else if (rstreq(val, "signature"))
|
|
|
2ff057 |
vfylevel = RPMSIG_SIGNATURE_TYPE;
|
|
|
2ff057 |
else if (rstreq(val, "digest"))
|
|
|
2ff057 |
vfylevel = RPMSIG_DIGEST_TYPE;
|
|
|
2ff057 |
else if (rstreq(val, "none"))
|
|
|
2ff057 |
vfylevel = 0;
|
|
|
2ff057 |
else if (!rstreq(val, ""))
|
|
|
2ff057 |
rpmlog(RPMLOG_WARNING, _("invalid package verify level %s\n"), val);
|
|
|
2ff057 |
|
|
|
2ff057 |
free(val);
|
|
|
2ff057 |
return vfylevel;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmts rpmtsCreate(void)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmts ts;
|
|
|
2ff057 |
tsMembers tsmem;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts = xcalloc(1, sizeof(*ts));
|
|
|
2ff057 |
memset(&ts->ops, 0, sizeof(ts->ops));
|
|
|
2ff057 |
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_TOTAL), -1);
|
|
|
2ff057 |
ts->dsi = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->solve = NULL;
|
|
|
2ff057 |
ts->solveData = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->rdb = NULL;
|
|
|
2ff057 |
ts->dbmode = O_RDONLY;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->scriptFd = NULL;
|
|
|
2ff057 |
ts->tid = (rpm_tid_t) time(NULL);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->color = rpmExpandNumeric("%{?_transaction_color}");
|
|
|
2ff057 |
ts->prefcolor = rpmExpandNumeric("%{?_prefer_color}")?:2;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->netsharedPaths = NULL;
|
|
|
2ff057 |
ts->installLangs = NULL;
|
|
|
2ff057 |
{ char *tmp = rpmExpand("%{_netsharedpath}", NULL);
|
|
|
2ff057 |
if (tmp && *tmp != '%') {
|
|
|
2ff057 |
argvSplit(&ts->netsharedPaths, tmp, ":");
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(tmp);
|
|
|
2ff057 |
|
|
|
2ff057 |
tmp = rpmExpand("%{_install_langs}", NULL);
|
|
|
2ff057 |
if (tmp && *tmp != '%') {
|
|
|
2ff057 |
ARGV_t langs = NULL;
|
|
|
2ff057 |
argvSplit(&langs, tmp, ":");
|
|
|
2ff057 |
/* If we'll be installing all languages anyway, don't bother */
|
|
|
2ff057 |
for (ARGV_t l = langs; *l; l++) {
|
|
|
2ff057 |
if (rstreq(*l, "all")) {
|
|
|
2ff057 |
langs = argvFree(langs);
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ts->installLangs = langs;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
free(tmp);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
tsmem = xcalloc(1, sizeof(*ts->members));
|
|
|
2ff057 |
tsmem->pool = NULL;
|
|
|
2ff057 |
tsmem->delta = 5;
|
|
|
2ff057 |
tsmem->addedPackages = NULL;
|
|
|
2ff057 |
tsmem->removedPackages = packageHashCreate(128, uintId, uintCmp, NULL, NULL);
|
|
|
2ff057 |
tsmem->installedPackages = packageHashCreate(128, uintId, uintCmp, NULL, NULL);
|
|
|
2ff057 |
tsmem->orderAlloced = 0;
|
|
|
2ff057 |
tsmem->orderCount = 0;
|
|
|
2ff057 |
tsmem->order = NULL;
|
|
|
2ff057 |
ts->members = tsmem;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->rootDir = NULL;
|
|
|
2ff057 |
ts->keyring = NULL;
|
|
|
2ff057 |
ts->vfyflags = rpmExpandNumeric("%{?_pkgverify_flags}");
|
|
|
2ff057 |
ts->vfylevel = vfylevel_init();
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->nrefs = 0;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->plugins = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->trigs2run = rpmtriggersCreate(10);
|
|
|
2ff057 |
|
|
|
2ff057 |
ts->min_writes = rpmExpandNumeric("%{_minimize_writes}");
|
|
|
2ff057 |
|
|
|
2ff057 |
return rpmtsLink(ts);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsi rpmtsiFree(rpmtsi tsi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
/* XXX watchout: a funky recursion segfaults here iff nrefs is wrong. */
|
|
|
2ff057 |
if (tsi) {
|
|
|
2ff057 |
tsi->ts = rpmtsFree(tsi->ts);
|
|
|
2ff057 |
_free(tsi);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtsi rpmtsiInit(rpmts ts)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmtsi tsi = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
tsi = xcalloc(1, sizeof(*tsi));
|
|
|
2ff057 |
tsi->ts = rpmtsLink(ts);
|
|
|
2ff057 |
tsi->oc = 0;
|
|
|
2ff057 |
return tsi;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
/**
|
|
|
2ff057 |
* Return next transaction element.
|
|
|
2ff057 |
* @param tsi transaction element iterator
|
|
|
2ff057 |
* @return transaction element, NULL on termination
|
|
|
2ff057 |
*/
|
|
|
2ff057 |
static
|
|
|
2ff057 |
rpmte rpmtsiNextElement(rpmtsi tsi)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmte te = NULL;
|
|
|
2ff057 |
int oc = -1;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tsi == NULL || tsi->ts == NULL || rpmtsNElements(tsi->ts) <= 0)
|
|
|
2ff057 |
return te;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (tsi->oc < rpmtsNElements(tsi->ts)) oc = tsi->oc++;
|
|
|
2ff057 |
if (oc != -1)
|
|
|
2ff057 |
te = rpmtsElement(tsi->ts, oc);
|
|
|
2ff057 |
return te;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmte rpmtsiNext(rpmtsi tsi, rpmElementTypes types)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
rpmte te;
|
|
|
2ff057 |
|
|
|
2ff057 |
while ((te = rpmtsiNextElement(tsi)) != NULL) {
|
|
|
2ff057 |
if (types == 0 || (rpmteType(te) & types) != 0)
|
|
|
2ff057 |
break;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return te;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
#define RPMLOCK_PATH LOCALSTATEDIR "/rpm/.rpm.lock"
|
|
|
2ff057 |
rpmtxn rpmtxnBegin(rpmts ts, rpmtxnFlags flags)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
static const char * const rpmlock_path_default = "%{?_rpmlock_path}";
|
|
|
2ff057 |
rpmtxn txn = NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts == NULL)
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->lockPath == NULL) {
|
|
|
2ff057 |
const char *rootDir = rpmtsRootDir(ts);
|
|
|
2ff057 |
char *t;
|
|
|
2ff057 |
|
|
|
2ff057 |
if (!rootDir || rpmChrootDone())
|
|
|
2ff057 |
rootDir = "/";
|
|
|
2ff057 |
|
|
|
2ff057 |
t = rpmGenPath(rootDir, rpmlock_path_default, NULL);
|
|
|
2ff057 |
if (t == NULL || *t == '\0' || *t == '%') {
|
|
|
2ff057 |
free(t);
|
|
|
2ff057 |
t = xstrdup(RPMLOCK_PATH);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
ts->lockPath = xstrdup(t);
|
|
|
2ff057 |
(void) rpmioMkpath(dirname(t), 0755, getuid(), getgid());
|
|
|
2ff057 |
free(t);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
if (ts->lock == NULL)
|
|
|
2ff057 |
ts->lock = rpmlockNew(ts->lockPath, _("transaction"));
|
|
|
2ff057 |
|
|
|
2ff057 |
if (rpmlockAcquire(ts->lock)) {
|
|
|
2ff057 |
txn = xcalloc(1, sizeof(*txn));
|
|
|
2ff057 |
txn->lock = ts->lock;
|
|
|
2ff057 |
txn->flags = flags;
|
|
|
2ff057 |
txn->ts = rpmtsLink(ts);
|
|
|
2ff057 |
if (txn->flags & RPMTXN_WRITE)
|
|
|
2ff057 |
rpmsqBlock(SIG_BLOCK);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
return txn;
|
|
|
2ff057 |
}
|
|
|
2ff057 |
|
|
|
2ff057 |
rpmtxn rpmtxnEnd(rpmtxn txn)
|
|
|
2ff057 |
{
|
|
|
2ff057 |
if (txn) {
|
|
|
2ff057 |
rpmlockRelease(txn->lock);
|
|
|
2ff057 |
if (txn->flags & RPMTXN_WRITE)
|
|
|
2ff057 |
rpmsqBlock(SIG_UNBLOCK);
|
|
|
2ff057 |
rpmtsFree(txn->ts);
|
|
|
2ff057 |
free(txn);
|
|
|
2ff057 |
}
|
|
|
2ff057 |
return NULL;
|
|
|
2ff057 |
}
|