summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2002-03-03 23:09:49 +0000
committerjbj <devnull@localhost>2002-03-03 23:09:49 +0000
commit2e2d1cad39b9bf8af73ec7b2c584236aabcdad14 (patch)
tree29804eebc51fc8e0143e62a7743f1c635b25820e
parent48b19eaedae1d80691073730628c3ef806d6322d (diff)
downloadlibrpm-tizen-2e2d1cad39b9bf8af73ec7b2c584236aabcdad14.tar.gz
librpm-tizen-2e2d1cad39b9bf8af73ec7b2c584236aabcdad14.tar.bz2
librpm-tizen-2e2d1cad39b9bf8af73ec7b2c584236aabcdad14.zip
- add payload uncompressed size to signature to avoid rewriting header.
- drill header sha1 into signature parallel to header+payload md5. - mandatory "most effective" signature check on query/verify/install. - don't bother adding empty filemd's to index. - add Pubkey index, using signer id as binary key. - display pubkeys in hex when debugging db access. - retrieve pubkey(s) from rpmdb, not from detached signature file. - reapply Berkeley DB patch #4491. CVS patchset: 5341 CVS date: 2002/03/03 23:09:49
-rw-r--r--CHANGES8
-rw-r--r--build/pack.c15
-rw-r--r--db/hash/hash_dup.c265
-rw-r--r--db/hash/hash_page.c523
-rw-r--r--lib/package.c151
-rw-r--r--lib/query.c2
-rw-r--r--lib/rpmchecksig.c44
-rw-r--r--lib/rpmlib.h13
-rw-r--r--lib/signature.c328
-rw-r--r--lib/verify.c2
-rw-r--r--rpm.spec12
-rw-r--r--rpm.spec.in8
-rw-r--r--rpmdb/rpmdb.c157
-rw-r--r--rpmdb/rpmdb.h1
-rw-r--r--rpmio/rpmio_internal.h10
15 files changed, 1123 insertions, 416 deletions
diff --git a/CHANGES b/CHANGES
index 88472ad01..b7a5087e7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -81,6 +81,13 @@
- splint fiddles.
- make peace with gcc-3.1, remove compiler cruft.
- make peace with automake et al in 8.0, ugh.
+ - add payload uncompressed size to signature to avoid rewriting header.
+ - drill header sha1 into signature parallel to header+payload md5.
+ - mandatory "most effective" signature check on query/verify/install.
+ - don't bother adding empty filemd's to index.
+ - add Pubkey index, using signer id as binary key.
+ - display pubkeys in hex when debugging db access.
+ - retrieve pubkey(s) from rpmdb, not from detached signature file.
4.0.3 -> 4.0.4:
- solaris: translate i86pc to i386 (#57182).
@@ -127,6 +134,7 @@
- query/verify by install transaction id.
- rpm-4.0.4 release candidate.
- add cpanflute2, another perl.req fiddle.
+ - reapply Berkeley DB patch #4491.
4.0.2 -> 4.0.3:
- update per-interpreter dependency scripts, add sql/tcl (#20295).
diff --git a/build/pack.c b/build/pack.c
index 1f0e98221..33b81e9a8 100644
--- a/build/pack.c
+++ b/build/pack.c
@@ -410,12 +410,14 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
h = headerLink(*hdrp, "writeRPM xfer");
*hdrp = headerFree(*hdrp, "writeRPM xfer");
+#ifdef DYING
if (Fileno(csa->cpioFdIn) < 0) {
csa->cpioArchiveSize = 0;
/* Add a bogus archive size to the Header */
(void) headerAddEntry(h, RPMTAG_ARCHIVESIZE, RPM_INT32_TYPE,
&csa->cpioArchiveSize, 1);
}
+#endif
/* Binary packages now have explicit Provides: name = version-release. */
if (type == RPMLEAD_BINARY)
@@ -480,10 +482,12 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
goto exit;
}
+ fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
rc = RPMERR_NOSPACE;
rpmError(RPMERR_NOSPACE, _("Unable to write temp header\n"));
} else { /* Write the archive and get the size */
+ fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&sha1, NULL, 1);
if (csa->cpioList != NULL) {
rc = cpio_doio(fd, h, csa, rpmio_flags);
} else if (Fileno(csa->cpioFdIn) >= 0) {
@@ -498,6 +502,7 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
if (rc)
goto exit;
+#ifdef DYING
/*
* Set the actual archive size, and rewrite the header.
* This used to be done using headerModifyEntry(), but now that headers
@@ -529,6 +534,7 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
}
(void) Fflush(fd);
fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&sha1, NULL, 1);
+#endif
(void) Fclose(fd);
fd = NULL;
@@ -542,16 +548,22 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
sig = rpmNewSignature();
(void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
(void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
+
if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
rpmMessage(RPMMESS_NORMAL, _("Generating signature: %d\n"), sigtype);
(void) rpmAddSignature(sig, sigtarget, sigtype, passPhrase);
}
if (sha1) {
- (void) headerAddEntry(sig, RPMTAG_SHA1HEADER, RPM_STRING_TYPE, sha1, 1);
+ (void) headerAddEntry(sig, RPMSIGTAG_SHA1, RPM_STRING_TYPE, sha1, 1);
sha1 = _free(sha1);
}
+ { int_32 payloadSize = csa->cpioArchiveSize;
+ (void) headerAddEntry(sig, RPMSIGTAG_PAYLOADSIZE, RPM_INT32_TYPE,
+ &payloadSize, 1);
+ }
+
/* Reallocate the signature into one contiguous region. */
sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
if (sig == NULL) { /* XXX can't happen */
@@ -621,6 +633,7 @@ int writeRPM(Header *hdrp, const char *fileName, int type,
}
/* Add signatures to header, and write header into the package. */
+ /* XXX header+payload digests/signatures might be checked again here. */
{ Header nh = headerRead(ifd, HEADER_MAGIC_YES);
if (nh == NULL) {
diff --git a/db/hash/hash_dup.c b/db/hash/hash_dup.c
index f5fbf4f47..ad06c522c 100644
--- a/db/hash/hash_dup.c
+++ b/db/hash/hash_dup.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2001
* Sleepycat Software. All rights reserved.
*/
/*
@@ -38,7 +38,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_dup.c,v 11.49 2000/12/21 21:54:35 margo Exp $";
+static const char revid[] = "Id: hash_dup.c,v 11.65 2001/08/13 19:11:37 bostic Exp ";
#endif /* not lint */
/*
@@ -66,8 +66,11 @@ static const char revid[] = "$Id: hash_dup.c,v 11.49 2000/12/21 21:54:35 margo E
#include "btree.h"
#include "txn.h"
+static int __ham_c_chgpg __P((DBC *,
+ db_pgno_t, u_int32_t, db_pgno_t, u_int32_t));
static int __ham_check_move __P((DBC *, u_int32_t));
static int __ham_dcursor __P((DBC *, db_pgno_t, u_int32_t));
+static int __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
/*
* Called from hash_access to add a duplicate key. nval is the new
@@ -92,13 +95,15 @@ __ham_add_dup(dbc, nval, flags, pgnop)
db_pgno_t *pgnop;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT pval, tmp_val;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
u_int32_t add_bytes, new_size;
int cmp, ret;
u_int8_t *hk;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
DB_ASSERT(flags != DB_CURRENT);
@@ -148,8 +153,8 @@ __ham_add_dup(dbc, nval, flags, pgnop)
pval.size = LEN_HDATA(hcp->page, dbp->pgsize,
hcp->indx);
if ((ret = __ham_make_dup(dbp->dbenv,
- &pval, &tmp_val, &dbc->rdata.data,
- &dbc->rdata.ulen)) != 0 || (ret =
+ &pval, &tmp_val, &dbc->my_rdata.data,
+ &dbc->my_rdata.ulen)) != 0 || (ret =
__ham_replpair(dbc, &tmp_val, 1)) != 0)
return (ret);
hk = H_PAIRDATA(hcp->page, hcp->indx);
@@ -167,7 +172,7 @@ __ham_add_dup(dbc, nval, flags, pgnop)
/* Now make the new entry a duplicate. */
if ((ret = __ham_make_dup(dbp->dbenv, nval,
- &tmp_val, &dbc->rdata.data, &dbc->rdata.ulen)) != 0)
+ &tmp_val, &dbc->my_rdata.data, &dbc->my_rdata.ulen)) != 0)
return (ret);
tmp_val.dlen = 0;
@@ -176,7 +181,8 @@ __ham_add_dup(dbc, nval, flags, pgnop)
case DB_KEYLAST:
case DB_NODUPDATA:
if (dbp->dup_compare != NULL) {
- __ham_dsearch(dbc, nval, &tmp_val.doff, &cmp);
+ __ham_dsearch(dbc,
+ nval, &tmp_val.doff, &cmp, flags);
/* dup dups are not supported w/ sorted dups */
if (cmp == 0)
@@ -203,8 +209,7 @@ __ham_add_dup(dbc, nval, flags, pgnop)
/* Add the duplicate. */
ret = __ham_replpair(dbc, &tmp_val, 0);
if (ret == 0)
- ret = memp_fset(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
-
+ ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
if (ret != 0)
return (ret);
@@ -245,19 +250,21 @@ int
__ham_dup_convert(dbc)
DBC *dbc;
{
+ BOVERFLOW bo;
DB *dbp;
DBC **hcs;
+ DBT dbt;
DB_LSN lsn;
- PAGE *dp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
- BOVERFLOW bo;
- DBT dbt;
HOFFPAGE ho;
+ PAGE *dp;
db_indx_t i, len, off;
int c, ret, t_ret;
u_int8_t *p, *pend;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
/*
@@ -274,7 +281,7 @@ __ham_dup_convert(dbc)
*/
if ((ret = __ham_get_clist(dbp,
PGNO(hcp->page), (u_int32_t)hcp->indx, &hcs)) != 0)
- return (ret);
+ goto err;
/*
* Now put the duplicates onto the new page.
@@ -301,12 +308,11 @@ __ham_dup_convert(dbc)
dbt.data = &bo;
ret = __db_pitem(dbc, dp, 0, dbt.size, &dbt, NULL);
-
finish: if (ret == 0) {
- memp_fset(dbp->mpf, dp, DB_MPOOL_DIRTY);
- /*
- * Update any other cursors
- */
+ if ((ret = mpf->set(mpf, dp, DB_MPOOL_DIRTY)) != 0)
+ break;
+
+ /* Update any other cursors. */
if (hcs != NULL && DB_LOGGING(dbc)
&& IS_SUBTRANSACTION(dbc->txn)) {
if ((ret = __ham_chgpg_log(dbp->dbenv,
@@ -319,10 +325,8 @@ finish: if (ret == 0) {
if ((ret = __ham_dcursor(hcs[c],
PGNO(dp), 0)) != 0)
break;
-
}
break;
-
case H_DUPLICATE:
p = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx));
pend = p +
@@ -344,39 +348,49 @@ finish: if (ret == 0) {
if ((ret = __db_pitem(dbc, dp,
i, BKEYDATA_SIZE(dbt.size), NULL, &dbt)) != 0)
break;
- /*
- * Update any other cursors
- */
+
+ /* Update any other cursors */
+ if (hcs != NULL && DB_LOGGING(dbc)
+ && IS_SUBTRANSACTION(dbc->txn)) {
+ if ((ret = __ham_chgpg_log(dbp->dbenv,
+ dbc->txn, &lsn, 0, dbp->log_fileid,
+ DB_HAM_DUP, PGNO(hcp->page),
+ PGNO(dp), hcp->indx, i)) != 0)
+ break;
+ }
for (c = 0; hcs != NULL && hcs[c] != NULL; c++)
if (((HASH_CURSOR *)(hcs[c]->internal))->dup_off
== off && (ret = __ham_dcursor(hcs[c],
PGNO(dp), i)) != 0)
- goto out;
+ goto err;
off += len + 2 * sizeof(db_indx_t);
}
-out: break;
-
+ break;
default:
- ret = __db_pgfmt(dbp, (u_long)hcp->pgno);
+ ret = __db_pgfmt(dbp->dbenv, (u_long)hcp->pgno);
break;
}
- if (ret == 0) {
- /*
- * Now attach this to the source page in place of
- * the old duplicate item.
- */
- __ham_move_offpage(dbc, hcp->page,
+
+ /*
+ * Now attach this to the source page in place of the old duplicate
+ * item.
+ */
+ if (ret == 0)
+ ret = __ham_move_offpage(dbc, hcp->page,
(u_int32_t)H_DATAINDEX(hcp->indx), PGNO(dp));
- ret = memp_fset(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
- if ((t_ret = memp_fput(dbp->mpf, dp, DB_MPOOL_DIRTY)) != 0)
- ret = t_ret;
+err: if (ret == 0)
+ ret = mpf->set(mpf, hcp->page, DB_MPOOL_DIRTY);
+
+ if ((t_ret =
+ mpf->put(mpf, dp, ret == 0 ? DB_MPOOL_DIRTY : 0)) != 0 && ret == 0)
+ ret = t_ret;
+
+ if (ret == 0)
hcp->dup_tlen = hcp->dup_off = hcp->dup_len = 0;
- } else
- (void)__db_free(dbc, dp);
if (hcs != NULL)
- __os_free(hcs, 0);
+ __os_free(dbp->dbenv, hcs, 0);
return (ret);
}
@@ -444,9 +458,10 @@ __ham_check_move(dbc, add_len)
u_int32_t add_len;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT k, d;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
PAGE *next_pagep;
db_pgno_t next_pgno;
u_int32_t new_datalen, old_len, rectype;
@@ -454,6 +469,7 @@ __ham_check_move(dbc, add_len)
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
hk = H_PAIRDATA(hcp->page, hcp->indx);
@@ -500,10 +516,10 @@ __ham_check_move(dbc, add_len)
for (next_pgno = NEXT_PGNO(hcp->page); next_pgno != PGNO_INVALID;
next_pgno = NEXT_PGNO(next_pagep)) {
if (next_pagep != NULL &&
- (ret = memp_fput(dbp->mpf, next_pagep, 0)) != 0)
+ (ret = mpf->put(mpf, next_pagep, 0)) != 0)
return (ret);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = mpf->get(mpf,
&next_pgno, DB_MPOOL_CREATE, &next_pagep)) != 0)
return (ret);
@@ -519,7 +535,7 @@ __ham_check_move(dbc, add_len)
/* Add new page at the end of the chain. */
if (P_FREESPACE(next_pagep) < new_datalen && (ret =
__ham_add_ovflpage(dbc, next_pagep, 1, &next_pagep)) != 0) {
- (void)memp_fput(dbp->mpf, next_pagep, 0);
+ (void)mpf->put(mpf, next_pagep, 0);
return (ret);
}
@@ -557,13 +573,14 @@ __ham_check_move(dbc, add_len)
dbp->log_fileid, PGNO(next_pagep),
(u_int32_t)NUM_ENT(next_pagep), &LSN(next_pagep),
&k, &d)) != 0) {
- (void)memp_fput(dbp->mpf, next_pagep, 0);
+ (void)mpf->put(mpf, next_pagep, 0);
return (ret);
}
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(next_pagep) = new_lsn; /* Structure assignment. */
- }
+ /* Move lsn onto page. */
+ LSN(next_pagep) = new_lsn; /* Structure assignment. */
__ham_copy_item(dbp->pgsize,
hcp->page, H_KEYINDEX(hcp->indx), next_pagep);
@@ -581,7 +598,7 @@ __ham_check_move(dbc, add_len)
* Note that __ham_del_pair should dirty the page we're moving
* the items from, so we need only dirty the new page ourselves.
*/
- if ((ret = memp_fset(dbp->mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
+ if ((ret = mpf->set(mpf, next_pagep, DB_MPOOL_DIRTY)) != 0)
goto out;
/* Update all cursors that used to point to this item. */
@@ -596,12 +613,17 @@ __ham_check_move(dbc, add_len)
* __ham_del_pair decremented nelem. This is incorrect; we
* manually copied the element elsewhere, so the total number
* of elements hasn't changed. Increment it again.
+ *
+ * !!!
+ * Note that we still have the metadata page pinned, and
+ * __ham_del_pair dirtied it, so we don't need to set the dirty
+ * flag again.
*/
if (!STD_LOCKING(dbc))
hcp->hdr->nelem++;
out:
- (void)memp_fput(dbp->mpf, hcp->page, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, hcp->page, DB_MPOOL_DIRTY);
hcp->page = next_pagep;
hcp->pgno = PGNO(hcp->page);
hcp->indx = NUM_ENT(hcp->page) - 2;
@@ -620,9 +642,8 @@ out:
* This is really just a special case of __onpage_replace; we should
* probably combine them.
*
- * PUBLIC: void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t));
*/
-void
+static int
__ham_move_offpage(dbc, pagep, ndx, pgno)
DBC *dbc;
PAGE *pagep;
@@ -630,32 +651,34 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
db_pgno_t pgno;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT new_dbt;
DBT old_dbt;
HOFFDUP od;
db_indx_t i;
int32_t shrink;
u_int8_t *src;
+ int ret;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
od.type = H_OFFDUP;
UMRW_SET(od.unused[0]);
UMRW_SET(od.unused[1]);
UMRW_SET(od.unused[2]);
od.pgno = pgno;
+ ret = 0;
if (DB_LOGGING(dbc)) {
new_dbt.data = &od;
new_dbt.size = HOFFDUP_SIZE;
old_dbt.data = P_ENTRY(pagep, ndx);
old_dbt.size = LEN_HITEM(pagep, dbp->pgsize, ndx);
- (void)__ham_replace_log(dbp->dbenv,
+ if ((ret = __ham_replace_log(dbp->dbenv,
dbc->txn, &LSN(pagep), 0, dbp->log_fileid,
PGNO(pagep), (u_int32_t)ndx, &LSN(pagep), -1,
- &old_dbt, &new_dbt, 0);
- }
+ &old_dbt, &new_dbt, 0)) != 0)
+ return (ret);
+ } else
+ LSN_NOT_LOGGED(LSN(pagep));
shrink = LEN_HITEM(pagep, dbp->pgsize, ndx) - HOFFDUP_SIZE;
@@ -672,6 +695,7 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
/* Now copy the offdup entry onto the page. */
memcpy(P_ENTRY(pagep, ndx), &od, HOFFDUP_SIZE);
+ return (ret);
}
/*
@@ -679,13 +703,14 @@ __ham_move_offpage(dbc, pagep, ndx, pgno)
* Locate a particular duplicate in a duplicate set. Make sure that
* we exit with the cursor set appropriately.
*
- * PUBLIC: void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *));
+ * PUBLIC: void __ham_dsearch
+ * PUBLIC: __P((DBC *, DBT *, u_int32_t *, int *, u_int32_t));
*/
void
-__ham_dsearch(dbc, dbt, offp, cmpp)
+__ham_dsearch(dbc, dbt, offp, cmpp, flags)
DBC *dbc;
DBT *dbt;
- u_int32_t *offp;
+ u_int32_t *offp, flags;
int *cmpp;
{
DB *dbp;
@@ -697,10 +722,7 @@ __ham_dsearch(dbc, dbt, offp, cmpp)
dbp = dbc->dbp;
hcp = (HASH_CURSOR *)dbc->internal;
- if (dbp->dup_compare == NULL)
- func = __bam_defcmp;
- else
- func = dbp->dup_compare;
+ func = dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare;
i = F_ISSET(hcp, H_CONTINUE) ? hcp->dup_off: 0;
data = HKEYDATA_DATA(H_PAIRDATA(hcp->page, hcp->indx)) + i;
@@ -710,12 +732,26 @@ __ham_dsearch(dbc, dbt, offp, cmpp)
data += sizeof(db_indx_t);
cur.data = data;
cur.size = (u_int32_t)len;
+
+ /*
+ * If we find an exact match, we're done. If in a sorted
+ * duplicate set and the item is larger than our test item,
+ * we're done. In the latter case, if permitting partial
+ * matches, it's not a failure.
+ */
*cmpp = func(dbp, dbt, &cur);
- if (*cmpp == 0 || (*cmpp < 0 && dbp->dup_compare != NULL))
+ if (*cmpp == 0)
break;
+ if (*cmpp < 0 && dbp->dup_compare != NULL) {
+ if (flags == DB_GET_BOTH_RANGE)
+ *cmpp = 0;
+ break;
+ }
+
i += len + 2 * sizeof(db_indx_t);
data += len + sizeof(db_indx_t);
}
+
*offp = i;
hcp->dup_off = i;
hcp->dup_len = len;
@@ -727,29 +763,22 @@ __ham_dsearch(dbc, dbt, offp, cmpp)
* __ham_cprint --
* Display the current cursor list.
*
- * PUBLIC: int __ham_cprint __P((DB *));
+ * PUBLIC: void __ham_cprint __P((DBC *));
*/
-int
-__ham_cprint(dbp)
- DB *dbp;
+void
+__ham_cprint(dbc)
+ DBC *dbc;
{
HASH_CURSOR *cp;
- DBC *dbc;
- MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
- for (dbc = TAILQ_FIRST(&dbp->active_queue);
- dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
- cp = (HASH_CURSOR *)dbc->internal;
- fprintf(stderr, "%#0lx->%#0lx: page: %lu index: %lu",
- P_TO_ULONG(dbc), P_TO_ULONG(cp), (u_long)cp->pgno,
- (u_long)cp->indx);
- if (F_ISSET(cp, H_DELETED))
- fprintf(stderr, " (deleted)");
- fprintf(stderr, "\n");
- }
- MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
+ cp = (HASH_CURSOR *)dbc->internal;
- return (0);
+ fprintf(stderr, "%#0lx->%#0lx: page: %lu index: %lu",
+ P_TO_ULONG(dbc), P_TO_ULONG(cp), (u_long)cp->pgno,
+ (u_long)cp->indx);
+ if (F_ISSET(cp, H_DELETED))
+ fprintf(stderr, " (deleted)");
+ fprintf(stderr, "\n");
}
#endif /* DEBUG */
@@ -803,3 +832,75 @@ __ham_dcursor(dbc, pgno, indx)
return (0);
}
+
+/*
+ * __ham_c_chgpg --
+ * Adjust the cursors after moving an item to a new page. We only
+ * move cursors that are pointing at this one item and are not
+ * deleted; since we only touch non-deleted cursors, and since
+ * (by definition) no item existed at the pgno/indx we're moving the
+ * item to, we're guaranteed that all the cursors we affect here or
+ * on abort really do refer to this one item.
+ */
+static int
+__ham_c_chgpg(dbc, old_pgno, old_index, new_pgno, new_index)
+ DBC *dbc;
+ db_pgno_t old_pgno, new_pgno;
+ u_int32_t old_index, new_index;
+{
+ DB *dbp, *ldbp;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_TXN *my_txn;
+ DBC *cp;
+ HASH_CURSOR *hcp;
+ int found, ret;
+
+ dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+
+ my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
+ found = 0;
+
+ MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+
+ hcp = (HASH_CURSOR *)cp->internal;
+
+ /*
+ * If a cursor is deleted, it doesn't refer to this
+ * item--it just happens to have the same indx, but
+ * it points to a former neighbor. Don't move it.
+ */
+ if (F_ISSET(hcp, H_DELETED))
+ continue;
+
+ if (hcp->pgno == old_pgno) {
+ if (hcp->indx == old_index) {
+ hcp->pgno = new_pgno;
+ hcp->indx = new_index;
+ } else
+ continue;
+ if (my_txn != NULL && cp->txn != my_txn)
+ found = 1;
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+ if (found != 0 && DB_LOGGING(dbc)) {
+ if ((ret = __ham_chgpg_log(dbenv,
+ my_txn, &lsn, 0, dbp->log_fileid, DB_HAM_CHGPG,
+ old_pgno, new_pgno, old_index, new_index)) != 0)
+ return (ret);
+ }
+ return (0);
+}
diff --git a/db/hash/hash_page.c b/db/hash/hash_page.c
index 64f388532..a7bc1cd1b 100644
--- a/db/hash/hash_page.c
+++ b/db/hash/hash_page.c
@@ -1,7 +1,7 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2001
* Sleepycat Software. All rights reserved.
*/
/*
@@ -43,7 +43,7 @@
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: hash_page.c,v 11.46 2001/01/11 18:19:51 bostic Exp $";
+static const char revid[] = "Id: hash_page.c,v 11.74 2001/10/20 20:10:01 bostic Exp ";
#endif /* not lint */
/*
@@ -75,6 +75,9 @@ static const char revid[] = "$Id: hash_page.c,v 11.46 2001/01/11 18:19:51 bostic
#include "lock.h"
#include "txn.h"
+static int __ham_c_delpg
+ __P((DBC *, db_pgno_t, db_pgno_t, u_int32_t, db_ham_mode, u_int32_t *));
+
/*
* PUBLIC: int __ham_item __P((DBC *, db_lockmode_t, db_pgno_t *));
*/
@@ -153,15 +156,18 @@ int
__ham_item_reset(dbc)
DBC *dbc;
{
- HASH_CURSOR *hcp;
DB *dbp;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
int ret;
- ret = 0;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
+
+ ret = 0;
if (hcp->page != NULL)
- ret = memp_fput(dbp->mpf, hcp->page, 0);
+ ret = mpf->put(mpf, hcp->page, 0);
__ham_item_init(dbc);
return (ret);
@@ -181,8 +187,7 @@ __ham_item_init(dbc)
* If this cursor still holds any locks, we must
* release them if we are not running with transactions.
*/
- if (hcp->lock.off != LOCK_INVALID && dbc->txn == NULL)
- (void)lock_put(dbc->dbp->dbenv, &hcp->lock);
+ (void)__TLPUT(dbc, hcp->lock);
/*
* The following fields must *not* be initialized here
@@ -191,7 +196,7 @@ __ham_item_init(dbc)
*/
hcp->bucket = BUCKET_INVALID;
hcp->lbucket = BUCKET_INVALID;
- hcp->lock.off = LOCK_INVALID;
+ LOCK_INIT(hcp->lock);
hcp->lock_mode = DB_LOCK_NG;
hcp->dup_off = 0;
hcp->dup_len = 0;
@@ -264,13 +269,12 @@ __ham_item_prev(dbc, mode, pgnop)
db_lockmode_t mode;
db_pgno_t *pgnop;
{
- DB *dbp;
HASH_CURSOR *hcp;
db_pgno_t next_pgno;
int ret;
- dbp = dbc->dbp;
hcp = (HASH_CURSOR *)dbc->internal;
+
/*
* There are 5 cases for backing up in a hash file.
* Case 1: In the middle of a page, no duplicates, just dec the index.
@@ -537,25 +541,27 @@ __ham_del_pair(dbc, reclaim_page)
int reclaim_page;
{
DB *dbp;
- HASH_CURSOR *hcp;
DBT data_dbt, key_dbt;
DB_ENV *dbenv;
DB_LSN new_lsn, *n_lsn, tmp_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
PAGE *n_pagep, *nn_pagep, *p, *p_pagep;
+ db_ham_mode op;
db_indx_t ndx;
db_pgno_t chg_pgno, pgno, tmp_pgno;
int ret, t_ret;
+ u_int32_t order;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
-
dbenv = dbp->dbenv;
- ndx = hcp->indx;
-
+ mpf = dbp->mpf;
+ hcp = (HASH_CURSOR *)dbc->internal;
n_pagep = p_pagep = nn_pagep = NULL;
+ ndx = hcp->indx;
- if (hcp->page == NULL && (ret = memp_fget(dbp->mpf,
- &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
+ if (hcp->page == NULL &&
+ (ret = mpf->get(mpf, &hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
p = hcp->page;
@@ -607,10 +613,11 @@ __ham_del_pair(dbc, reclaim_page)
dbp->log_fileid, PGNO(p), (u_int32_t)ndx,
&LSN(p), &key_dbt, &data_dbt)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(p) = new_lsn;
- }
+ /* Move lsn onto page. */
+ LSN(p) = new_lsn;
/* Do the delete. */
__ham_dpair(dbp, p, ndx);
@@ -636,8 +643,11 @@ __ham_del_pair(dbc, reclaim_page)
* XXX
* Perhaps we can retain incremental numbers and apply them later.
*/
- if (!STD_LOCKING(dbc))
+ if (!STD_LOCKING(dbc)) {
--hcp->hdr->nelem;
+ if ((ret = __ham_dirty_meta(dbc)) != 0)
+ return (ret);
+ }
/*
* If we need to reclaim the page, then check if the page is empty.
@@ -650,20 +660,18 @@ __ham_del_pair(dbc, reclaim_page)
if (!reclaim_page ||
NUM_ENT(p) != 0 ||
(PREV_PGNO(p) == PGNO_INVALID && NEXT_PGNO(p) == PGNO_INVALID))
- return (memp_fset(dbp->mpf, p, DB_MPOOL_DIRTY));
+ return (mpf->set(mpf, p, DB_MPOOL_DIRTY));
if (PREV_PGNO(p) == PGNO_INVALID) {
/*
* First page in chain is empty and we know that there
* are more pages in the chain.
*/
- if ((ret =
- memp_fget(dbp->mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
return (ret);
- if (NEXT_PGNO(n_pagep) != PGNO_INVALID &&
- (ret = memp_fget(dbp->mpf, &NEXT_PGNO(n_pagep), 0,
- &nn_pagep)) != 0)
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID && (ret =
+ mpf->get(mpf, &NEXT_PGNO(n_pagep), 0, &nn_pagep)) != 0)
goto err;
if (DB_LOGGING(dbc)) {
@@ -676,17 +684,19 @@ __ham_del_pair(dbc, reclaim_page)
nn_pagep == NULL ? NULL : &LSN(nn_pagep),
&key_dbt)) != 0)
goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ /* Move lsn onto page. */
+ LSN(p) = new_lsn; /* Structure assignment. */
+ LSN(n_pagep) = new_lsn;
+ if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
+ LSN(nn_pagep) = new_lsn;
- /* Move lsn onto page. */
- LSN(p) = new_lsn; /* Structure assignment. */
- LSN(n_pagep) = new_lsn;
- if (NEXT_PGNO(n_pagep) != PGNO_INVALID)
- LSN(nn_pagep) = new_lsn;
- }
if (nn_pagep != NULL) {
PREV_PGNO(nn_pagep) = PGNO(p);
- if ((ret = memp_fput(dbp->mpf,
- nn_pagep, DB_MPOOL_DIRTY)) != 0) {
+ if ((ret =
+ mpf->put(mpf, nn_pagep, DB_MPOOL_DIRTY)) != 0) {
nn_pagep = NULL;
goto err;
}
@@ -703,26 +713,30 @@ __ham_del_pair(dbc, reclaim_page)
* Update cursors to reflect the fact that records
* on the second page have moved to the first page.
*/
- if ((ret = __ham_c_chgpg(dbc,
- PGNO(n_pagep), NDX_INVALID, PGNO(p), NDX_INVALID)) != 0)
- return (ret);
+ if ((ret = __ham_c_delpg(dbc, PGNO(n_pagep),
+ PGNO(p), 0, DB_HAM_DELFIRSTPG, &order)) != 0)
+ goto err;
/*
* Update the cursor to reflect its new position.
*/
hcp->indx = 0;
hcp->pgno = PGNO(p);
- if ((ret = memp_fset(dbp->mpf, p, DB_MPOOL_DIRTY)) != 0 ||
- (ret = __db_free(dbc, n_pagep)) != 0)
- return (ret);
+ hcp->order += order;
+
+ if ((ret = mpf->set(mpf, p, DB_MPOOL_DIRTY)) != 0)
+ goto err;
+ if ((ret = __db_free(dbc, n_pagep)) != 0) {
+ n_pagep = NULL;
+ goto err;
+ }
} else {
- if ((ret =
- memp_fget(dbp->mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &PREV_PGNO(p), 0, &p_pagep)) != 0)
goto err;
if (NEXT_PGNO(p) != PGNO_INVALID) {
- if ((ret = memp_fget(dbp->mpf,
- &NEXT_PGNO(p), 0, &n_pagep)) != 0)
+ if ((ret =
+ mpf->get(mpf, &NEXT_PGNO(p), 0, &n_pagep)) != 0)
goto err;
n_lsn = &LSN(n_pagep);
} else {
@@ -740,26 +754,35 @@ __ham_del_pair(dbc, reclaim_page)
dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep),
PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0)
goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ /* Move lsn onto page. */
+ LSN(p_pagep) = new_lsn; /* Structure assignment. */
+ if (n_pagep)
+ LSN(n_pagep) = new_lsn;
+ LSN(p) = new_lsn;
- /* Move lsn onto page. */
- LSN(p_pagep) = new_lsn; /* Structure assignment. */
- if (n_pagep)
- LSN(n_pagep) = new_lsn;
- LSN(p) = new_lsn;
- }
if (NEXT_PGNO(p) == PGNO_INVALID) {
/*
* There is no next page; put the cursor on the
* previous page as if we'd deleted the last item
- * on that page; index greater than number of
- * valid entries and H_DELETED set.
+ * on that page, with index after the last valid
+ * entry.
+ *
+ * The deleted flag was set up above.
*/
hcp->pgno = PGNO(p_pagep);
hcp->indx = NUM_ENT(p_pagep);
- F_SET(hcp, H_DELETED);
+ op = DB_HAM_DELLASTPG;
} else {
+ /*
+ * There is a next page, so put the cursor at
+ * the beginning of it.
+ */
hcp->pgno = NEXT_PGNO(p);
hcp->indx = 0;
+ op = DB_HAM_DELMIDPG;
}
/*
@@ -770,26 +793,28 @@ __ham_del_pair(dbc, reclaim_page)
hcp->page = NULL;
chg_pgno = PGNO(p);
ret = __db_free(dbc, p);
- if ((t_ret = memp_fput(dbp->mpf, p_pagep, DB_MPOOL_DIRTY)) != 0
- && ret == 0)
+ if ((t_ret =
+ mpf->put(mpf, p_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
- if (n_pagep != NULL && (t_ret = memp_fput(dbp->mpf,
- n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
+ if (n_pagep != NULL && (t_ret =
+ mpf->put(mpf, n_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
- ret = __ham_c_chgpg(dbc,
- chg_pgno, 0, hcp->pgno, hcp->indx);
+ if ((ret = __ham_c_delpg(dbc,
+ chg_pgno, hcp->pgno, hcp->indx, op, &order)) != 0)
+ return (ret);
+ hcp->order += order;
}
return (ret);
err: /* Clean up any pages. */
if (n_pagep != NULL)
- (void)memp_fput(dbp->mpf, n_pagep, 0);
+ (void)mpf->put(mpf, n_pagep, 0);
if (nn_pagep != NULL)
- (void)memp_fput(dbp->mpf, nn_pagep, 0);
+ (void)mpf->put(mpf, nn_pagep, 0);
if (p_pagep != NULL)
- (void)memp_fput(dbp->mpf, p_pagep, 0);
+ (void)mpf->put(mpf, p_pagep, 0);
return (ret);
}
@@ -811,8 +836,8 @@ __ham_replpair(dbc, dbt, make_dup)
DBT old_dbt, tdata, tmp;
DB_LSN new_lsn;
int32_t change; /* XXX: Possible overflow. */
- u_int32_t dup, len, memsize;
- int is_big, ret, type;
+ u_int32_t dup_flag, len, memsize;
+ int beyond_eor, is_big, ret, type;
u_int8_t *beg, *dest, *end, *hk, *src;
void *memp;
@@ -850,10 +875,11 @@ __ham_replpair(dbc, dbt, make_dup)
len = LEN_HKEYDATA(hcp->page,
dbp->pgsize, H_DATAINDEX(hcp->indx));
- if (dbt->doff + dbt->dlen > len)
+ beyond_eor = dbt->doff + dbt->dlen > len;
+ if (beyond_eor)
change += dbt->doff + dbt->dlen - len;
- if (change > (int32_t)P_FREESPACE(hcp->page) || is_big) {
+ if (change > (int32_t)P_FREESPACE(hcp->page) || beyond_eor || is_big) {
/*
* Case 3 -- two subcases.
* A. This is not really a partial operation, but an overwrite.
@@ -868,16 +894,16 @@ __ham_replpair(dbc, dbt, make_dup)
memset(&tmp, 0, sizeof(tmp));
if ((ret =
__db_ret(dbp, hcp->page, H_KEYINDEX(hcp->indx),
- &tmp, &dbc->rkey.data, &dbc->rkey.ulen)) != 0)
+ &tmp, &dbc->rkey->data, &dbc->rkey->ulen)) != 0)
return (ret);
/* Preserve duplicate info. */
- dup = F_ISSET(hcp, H_ISDUP);
+ dup_flag = F_ISSET(hcp, H_ISDUP);
if (dbt->doff == 0 && dbt->dlen == len) {
ret = __ham_del_pair(dbc, 0);
if (ret == 0)
ret = __ham_add_el(dbc,
- &tmp, dbt, dup ? H_DUPLICATE : H_KEYDATA);
+ &tmp, dbt, dup_flag ? H_DUPLICATE : H_KEYDATA);
} else { /* Case B */
type = HPAGE_PTYPE(hk) != H_OFFPAGE ?
HPAGE_PTYPE(hk) : H_KEYDATA;
@@ -891,15 +917,14 @@ __ham_replpair(dbc, dbt, make_dup)
/* Now we can delete the item. */
if ((ret = __ham_del_pair(dbc, 0)) != 0) {
- __os_free(memp, memsize);
+ __os_free(dbp->dbenv, memp, memsize);
goto err;
}
/* Now shift old data around to make room for new. */
if (change > 0) {
if ((ret = __os_realloc(dbp->dbenv,
- tdata.size + change,
- NULL, &tdata.data)) != 0)
+ tdata.size + change, &tdata.data)) != 0)
return (ret);
memp = tdata.data;
memsize = tdata.size + change;
@@ -920,9 +945,9 @@ __ham_replpair(dbc, dbt, make_dup)
/* Now add the pair. */
ret = __ham_add_el(dbc, &tmp, &tdata, type);
- __os_free(memp, memsize);
+ __os_free(dbp->dbenv, memp, memsize);
}
- F_SET(hcp, dup);
+ F_SET(hcp, dup_flag);
err: return (ret);
}
@@ -947,8 +972,10 @@ err: return (ret);
(u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0)
return (ret);
- LSN(hcp->page) = new_lsn; /* Structure assignment. */
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ LSN(hcp->page) = new_lsn; /* Structure assignment. */
__ham_onpage_replace(hcp->page, dbp->pgsize,
(u_int32_t)H_DATAINDEX(hcp->indx), (int32_t)dbt->doff, change, dbt);
@@ -1022,10 +1049,12 @@ __ham_split_page(dbc, obucket, nbucket)
{
DB *dbp;
DBC **carray;
- HASH_CURSOR *hcp, *cp;
DBT key, page_dbt;
DB_ENV *dbenv;
+ DB_LOCK block;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp, *cp;
PAGE **pp, *old_pagep, *temp_pagep, *new_pagep;
db_indx_t n;
db_pgno_t bucket_pgno, npgno, next_pgno;
@@ -1034,22 +1063,24 @@ __ham_split_page(dbc, obucket, nbucket)
void *big_buf;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
dbenv = dbp->dbenv;
+ mpf = dbp->mpf;
+ hcp = (HASH_CURSOR *)dbc->internal;
temp_pagep = old_pagep = new_pagep = NULL;
-
- if ((ret = __ham_get_clist(dbp, obucket, NDX_INVALID, &carray)) != 0)
- return (ret);
+ carray = NULL;
+ LOCK_INIT(block);
bucket_pgno = BUCKET_TO_PAGE(hcp, obucket);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = __db_lget(dbc,
+ 0, bucket_pgno, DB_LOCK_WRITE, 0, &block)) != 0)
+ goto err;
+ if ((ret = mpf->get(mpf,
&bucket_pgno, DB_MPOOL_CREATE, &old_pagep)) != 0)
goto err;
/* Properly initialize the new bucket page. */
npgno = BUCKET_TO_PAGE(hcp, nbucket);
- if ((ret = memp_fget(dbp->mpf,
- &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
+ if ((ret = mpf->get(mpf, &npgno, DB_MPOOL_CREATE, &new_pagep)) != 0)
goto err;
P_INIT(new_pagep,
dbp->pgsize, npgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
@@ -1064,26 +1095,28 @@ __ham_split_page(dbc, obucket, nbucket)
dbc->txn, &new_lsn, 0, dbp->log_fileid, SPLITOLD,
PGNO(old_pagep), &page_dbt, &LSN(old_pagep))) != 0)
goto err;
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+
+ LSN(old_pagep) = new_lsn; /* Structure assignment. */
P_INIT(old_pagep, dbp->pgsize, PGNO(old_pagep), PGNO_INVALID,
PGNO_INVALID, 0, P_HASH);
- if (DB_LOGGING(dbc))
- LSN(old_pagep) = new_lsn; /* Structure assignment. */
-
big_len = 0;
big_buf = NULL;
key.flags = 0;
while (temp_pagep != NULL) {
+ if ((ret = __ham_get_clist(dbp,
+ PGNO(temp_pagep), NDX_INVALID, &carray)) != 0)
+ goto err;
+
for (n = 0; n < (db_indx_t)NUM_ENT(temp_pagep); n += 2) {
- if ((ret =
- __db_ret(dbp, temp_pagep, H_KEYINDEX(n),
- &key, &big_buf, &big_len)) != 0)
+ if ((ret = __db_ret(dbp, temp_pagep,
+ H_KEYINDEX(n), &key, &big_buf, &big_len)) != 0)
goto err;
- if (__ham_call_hash(dbc, key.data, key.size)
- == obucket)
+ if (__ham_call_hash(dbc, key.data, key.size) == obucket)
pp = &old_pagep;
else
pp = &new_pagep;
@@ -1092,7 +1125,6 @@ __ham_split_page(dbc, obucket, nbucket)
* Figure out how many bytes we need on the new
* page to store the key/data pair.
*/
-
len = LEN_HITEM(temp_pagep, dbp->pgsize,
H_DATAINDEX(n)) +
LEN_HITEM(temp_pagep, dbp->pgsize,
@@ -1109,8 +1141,9 @@ __ham_split_page(dbc, obucket, nbucket)
SPLITNEW, PGNO(*pp), &page_dbt,
&LSN(*pp))) != 0)
goto err;
- LSN(*pp) = new_lsn;
- }
+ } else
+ LSN_NOT_LOGGED(new_lsn);
+ LSN(*pp) = new_lsn;
if ((ret =
__ham_add_ovflpage(dbc, *pp, 1, pp)) != 0)
goto err;
@@ -1156,23 +1189,30 @@ __ham_split_page(dbc, obucket, nbucket)
if (next_pgno == PGNO_INVALID)
temp_pagep = NULL;
- else if ((ret = memp_fget(dbp->mpf,
- &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
+ else if ((ret = mpf->get(
+ mpf, &next_pgno, DB_MPOOL_CREATE, &temp_pagep)) != 0)
goto err;
- if (temp_pagep != NULL && DB_LOGGING(dbc)) {
- page_dbt.size = dbp->pgsize;
- page_dbt.data = temp_pagep;
- if ((ret = __ham_splitdata_log(dbenv,
- dbc->txn, &new_lsn, 0, dbp->log_fileid,
- SPLITOLD, PGNO(temp_pagep),
- &page_dbt, &LSN(temp_pagep))) != 0)
- goto err;
+ if (temp_pagep != NULL) {
+ if (DB_LOGGING(dbc)) {
+ page_dbt.size = dbp->pgsize;
+ page_dbt.data = temp_pagep;
+ if ((ret = __ham_splitdata_log(dbenv,
+ dbc->txn, &new_lsn, 0, dbp->log_fileid,
+ SPLITOLD, PGNO(temp_pagep),
+ &page_dbt, &LSN(temp_pagep))) != 0)
+ goto err;
+ } else
+ LSN_NOT_LOGGED(new_lsn);
LSN(temp_pagep) = new_lsn;
}
+
+ if (carray != NULL) /* We never knew its size. */
+ __os_free(dbp->dbenv, carray, 0);
+ carray = NULL;
}
if (big_buf != NULL)
- __os_free(big_buf, big_len);
+ __os_free(dbenv, big_buf, big_len);
/*
* If the original bucket spanned multiple pages, then we've got
@@ -1203,22 +1243,28 @@ __ham_split_page(dbc, obucket, nbucket)
&LSN(new_pagep))) != 0)
goto err;
LSN(new_pagep) = new_lsn;
+ } else {
+ LSN_NOT_LOGGED(LSN(old_pagep));
+ LSN_NOT_LOGGED(LSN(new_pagep));
}
- ret = memp_fput(dbp->mpf, old_pagep, DB_MPOOL_DIRTY);
- if ((t_ret = memp_fput(dbp->mpf, new_pagep, DB_MPOOL_DIRTY)) != 0
- && ret == 0)
+
+ ret = mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
+ if ((t_ret =
+ mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY)) != 0 && ret == 0)
ret = t_ret;
if (0) {
err: if (old_pagep != NULL)
- (void)memp_fput(dbp->mpf, old_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, old_pagep, DB_MPOOL_DIRTY);
if (new_pagep != NULL)
- (void)memp_fput(dbp->mpf, new_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, new_pagep, DB_MPOOL_DIRTY);
if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno)
- (void)memp_fput(dbp->mpf, temp_pagep, DB_MPOOL_DIRTY);
+ (void)mpf->put(mpf, temp_pagep, DB_MPOOL_DIRTY);
}
+ if (LOCK_ISSET(block))
+ __TLPUT(dbc, block);
if (carray != NULL) /* We never knew its size. */
- __os_free(carray, 0);
+ __os_free(dbp->dbenv, carray, 0);
return (ret);
}
@@ -1237,11 +1283,12 @@ __ham_add_el(dbc, key, val, type)
const DBT *key, *val;
int type;
{
- DB *dbp;
- HASH_CURSOR *hcp;
const DBT *pkey, *pdata;
+ DB *dbp;
DBT key_dbt, data_dbt;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
+ HASH_CURSOR *hcp;
HOFFPAGE doff, koff;
db_pgno_t next_pgno, pgno;
u_int32_t data_size, key_size, pairsize, rectype;
@@ -1249,13 +1296,14 @@ __ham_add_el(dbc, key, val, type)
int key_type, data_type;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
do_expand = 0;
- pgno = hcp->seek_found_page != PGNO_INVALID ? hcp->seek_found_page :
- hcp->pgno;
- if (hcp->page == NULL && (ret = memp_fget(dbp->mpf, &pgno,
- DB_MPOOL_CREATE, &hcp->page)) != 0)
+ pgno = hcp->seek_found_page != PGNO_INVALID ?
+ hcp->seek_found_page : hcp->pgno;
+ if (hcp->page == NULL &&
+ (ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
key_size = HKEYDATA_PSIZE(key->size);
@@ -1279,8 +1327,7 @@ __ham_add_el(dbc, key, val, type)
if (P_FREESPACE(hcp->page) >= pairsize)
break;
next_pgno = NEXT_PGNO(hcp->page);
- if ((ret =
- __ham_next_cpage(dbc, next_pgno, 0)) != 0)
+ if ((ret = __ham_next_cpage(dbc, next_pgno, 0)) != 0)
return (ret);
}
@@ -1290,7 +1337,7 @@ __ham_add_el(dbc, key, val, type)
if (P_FREESPACE(hcp->page) < pairsize) {
do_expand = 1;
if ((ret = __ham_add_ovflpage(dbc,
- (PAGE *)hcp->page, 1, (PAGE **)&hcp->page)) != 0)
+ (PAGE *)hcp->page, 1, (PAGE **)&hcp->page)) != 0)
return (ret);
hcp->pgno = PGNO(hcp->page);
}
@@ -1348,10 +1395,11 @@ __ham_add_el(dbc, key, val, type)
(u_int32_t)NUM_ENT(hcp->page), &LSN(hcp->page), pkey,
pdata)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(hcp->page) = new_lsn; /* Structure assignment. */
- }
+ /* Move lsn onto page. */
+ LSN(hcp->page) = new_lsn; /* Structure assignment. */
__ham_putitem(hcp->page, pkey, key_type);
__ham_putitem(hcp->page, pdata, data_type);
@@ -1369,8 +1417,11 @@ __ham_add_el(dbc, key, val, type)
* XXX
* Maybe keep incremental numbers here.
*/
- if (!STD_LOCKING(dbc))
+ if (!STD_LOCKING(dbc)) {
hcp->hdr->nelem++;
+ if ((ret = __ham_dirty_meta(dbc)) != 0)
+ return (ret);
+ }
if (do_expand || (hcp->hdr->ffactor != 0 &&
(u_int32_t)H_NUMPAIRS(hcp->page) > hcp->hdr->ffactor))
@@ -1427,13 +1478,13 @@ __ham_add_ovflpage(dbc, pagep, release, pp)
PAGE **pp;
{
DB *dbp;
- HASH_CURSOR *hcp;
DB_LSN new_lsn;
+ DB_MPOOLFILE *mpf;
PAGE *new_pagep;
int ret;
dbp = dbc->dbp;
- hcp = (HASH_CURSOR *)dbc->internal;
+ mpf = dbp->mpf;
if ((ret = __db_new(dbc, P_HASH, &new_pagep)) != 0)
return (ret);
@@ -1443,15 +1494,17 @@ __ham_add_ovflpage(dbc, pagep, release, pp)
PUTOVFL, dbp->log_fileid, PGNO(pagep), &LSN(pagep),
PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0)
return (ret);
+ } else
+ LSN_NOT_LOGGED(new_lsn);
- /* Move lsn onto page. */
- LSN(pagep) = LSN(new_pagep) = new_lsn;
- }
+ /* Move lsn onto page. */
+ LSN(pagep) = LSN(new_pagep) = new_lsn;
NEXT_PGNO(pagep) = PGNO(new_pagep);
+
PREV_PGNO(new_pagep) = PGNO(pagep);
if (release)
- ret = memp_fput(dbp->mpf, pagep, DB_MPOOL_DIRTY);
+ ret = mpf->put(mpf, pagep, DB_MPOOL_DIRTY);
*pp = new_pagep;
return (ret);
@@ -1467,10 +1520,12 @@ __ham_get_cpage(dbc, mode)
{
DB *dbp;
DB_LOCK tmp_lock;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
ret = 0;
@@ -1485,25 +1540,22 @@ __ham_get_cpage(dbc, mode)
* 4. If there is a lock, but it's for a different bucket, then we need
* to release the existing lock and get a new lock.
*/
- tmp_lock.off = LOCK_INVALID;
+ LOCK_INIT(tmp_lock);
if (STD_LOCKING(dbc)) {
- if (hcp->lock.off != LOCK_INVALID &&
- hcp->lbucket != hcp->bucket) { /* Case 4 */
- if (dbc->txn == NULL &&
- (ret = lock_put(dbp->dbenv, &hcp->lock)) != 0)
- return (ret);
- hcp->lock.off = LOCK_INVALID;
- }
- if ((hcp->lock.off != LOCK_INVALID &&
+ if (hcp->lbucket != hcp->bucket && /* Case 4 */
+ (ret = __TLPUT(dbc, hcp->lock)) != 0)
+ return (ret);
+
+ if ((LOCK_ISSET(hcp->lock) &&
(hcp->lock_mode == DB_LOCK_READ &&
mode == DB_LOCK_WRITE))) {
/* Case 3. */
tmp_lock = hcp->lock;
- hcp->lock.off = LOCK_INVALID;
+ LOCK_INIT(hcp->lock);
}
/* Acquire the lock. */
- if (hcp->lock.off == LOCK_INVALID)
+ if (!LOCK_ISSET(hcp->lock))
/* Cases 1, 3, and 4. */
if ((ret = __ham_lock_bucket(dbc, mode)) != 0)
return (ret);
@@ -1511,17 +1563,18 @@ __ham_get_cpage(dbc, mode)
if (ret == 0) {
hcp->lock_mode = mode;
hcp->lbucket = hcp->bucket;
- if (tmp_lock.off != LOCK_INVALID)
+ if (LOCK_ISSET(tmp_lock))
/* Case 3: release the original lock. */
- ret = lock_put(dbp->dbenv, &tmp_lock);
- } else if (tmp_lock.off != LOCK_INVALID)
+ ret =
+ dbp->dbenv->lock_put(dbp->dbenv, &tmp_lock);
+ } else if (LOCK_ISSET(tmp_lock))
hcp->lock = tmp_lock;
}
if (ret == 0 && hcp->page == NULL) {
if (hcp->pgno == PGNO_INVALID)
hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
- if ((ret = memp_fget(dbp->mpf,
+ if ((ret = mpf->get(mpf,
&hcp->pgno, DB_MPOOL_CREATE, &hcp->page)) != 0)
return (ret);
}
@@ -1543,18 +1596,21 @@ __ham_next_cpage(dbc, pgno, dirty)
int dirty;
{
DB *dbp;
+ DB_MPOOLFILE *mpf;
HASH_CURSOR *hcp;
PAGE *p;
int ret;
dbp = dbc->dbp;
+ mpf = dbp->mpf;
hcp = (HASH_CURSOR *)dbc->internal;
- if (hcp->page != NULL && (ret = memp_fput(dbp->mpf,
- hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
+ if (hcp->page != NULL &&
+ (ret = mpf->put(mpf, hcp->page, dirty ? DB_MPOOL_DIRTY : 0)) != 0)
return (ret);
+ hcp->page = NULL;
- if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
+ if ((ret = mpf->get(mpf, &pgno, DB_MPOOL_CREATE, &p)) != 0)
return (ret);
hcp->page = p;
@@ -1576,7 +1632,7 @@ __ham_lock_bucket(dbc, mode)
db_lockmode_t mode;
{
HASH_CURSOR *hcp;
- u_int32_t flags;
+ db_pgno_t pgno;
int gotmeta, ret;
hcp = (HASH_CURSOR *)dbc->internal;
@@ -1584,17 +1640,12 @@ __ham_lock_bucket(dbc, mode)
if (gotmeta)
if ((ret = __ham_get_meta(dbc)) != 0)
return (ret);
- dbc->lock.pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
+ pgno = BUCKET_TO_PAGE(hcp, hcp->bucket);
if (gotmeta)
if ((ret = __ham_release_meta(dbc)) != 0)
return (ret);
- flags = 0;
- if (DB_NONBLOCK(dbc))
- LF_SET(DB_LOCK_NOWAIT);
-
- ret = lock_get(dbc->dbp->dbenv,
- dbc->locker, flags, &dbc->lock_dbt, mode, &hcp->lock);
+ ret = __db_lget(dbc, 0, pgno, mode, 0, &hcp->lock);
hcp->lock_mode = mode;
return (ret);
@@ -1606,6 +1657,9 @@ __ham_lock_bucket(dbc, mode)
* represents. The caller is responsible for freeing up duplicates
* or offpage entries that might be referenced by this pair.
*
+ * Recovery assumes that this may be called without the metadata
+ * page pinned.
+ *
* PUBLIC: void __ham_dpair __P((DB *, PAGE *, u_int32_t));
*/
void
@@ -1653,3 +1707,152 @@ __ham_dpair(dbp, p, indx)
p->inp[n] = p->inp[n + 2] + delta;
}
+
+/*
+ * __ham_c_delpg --
+ *
+ * Adjust the cursors after we've emptied a page in a bucket, taking
+ * care that when we move cursors pointing to deleted items, their
+ * orders don't collide with the orders of cursors on the page we move
+ * them to (since after this function is called, cursors with the same
+ * index on the two pages will be otherwise indistinguishable--they'll
+ * all have pgno new_pgno). There are three cases:
+ *
+ * 1) The emptied page is the first page in the bucket. In this
+ * case, we've copied all the items from the second page into the
+ * first page, so the first page is new_pgno and the second page is
+ * old_pgno. new_pgno is empty, but can have deleted cursors
+ * pointing at indx 0, so we need to be careful of the orders
+ * there. This is DB_HAM_DELFIRSTPG.
+ *
+ * 2) The page is somewhere in the middle of a bucket. Our caller
+ * can just delete such a page, so it's old_pgno. old_pgno is
+ * empty, but may have deleted cursors pointing at indx 0, so we
+ * need to be careful of indx 0 when we move those cursors to
+ * new_pgno. This is DB_HAM_DELMIDPG.
+ *
+ * 3) The page is the last in a bucket. Again the empty page is
+ * old_pgno, and again it should only have cursors that are deleted
+ * and at indx == 0. This time, though, there's no next page to
+ * move them to, so we set them to indx == num_ent on the previous
+ * page--and indx == num_ent is the index whose cursors we need to
+ * be careful of. This is DB_HAM_DELLASTPG.
+ */
+static int
+__ham_c_delpg(dbc, old_pgno, new_pgno, num_ent, op, orderp)
+ DBC *dbc;
+ db_pgno_t old_pgno, new_pgno;
+ u_int32_t num_ent;
+ db_ham_mode op;
+ u_int32_t *orderp;
+{
+ DB *dbp, *ldbp;
+ DB_ENV *dbenv;
+ DB_LSN lsn;
+ DB_TXN *my_txn;
+ DBC *cp;
+ HASH_CURSOR *hcp;
+ int found, ret;
+ db_indx_t indx;
+ u_int32_t order;
+
+ /* Which is the worrisome index? */
+ indx = (op == DB_HAM_DELLASTPG) ? num_ent : 0;
+
+ dbp = dbc->dbp;
+ dbenv = dbp->dbenv;
+
+ my_txn = IS_SUBTRANSACTION(dbc->txn) ? dbc->txn : NULL;
+ found = 0;
+
+ MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp);
+ /*
+ * Find the highest order of any cursor our movement
+ * may collide with.
+ */
+ order = 1;
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+ hcp = (HASH_CURSOR *)cp->internal;
+ if (hcp->pgno == new_pgno) {
+ if (hcp->indx == indx &&
+ F_ISSET(hcp, H_DELETED) &&
+ hcp->order >= order)
+ order = hcp->order + 1;
+ DB_ASSERT(op != DB_HAM_DELFIRSTPG ||
+ hcp->indx == NDX_INVALID ||
+ (hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED)));
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+
+ for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
+ ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
+ ldbp = LIST_NEXT(ldbp, dblistlinks)) {
+ MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
+ for (cp = TAILQ_FIRST(&ldbp->active_queue); cp != NULL;
+ cp = TAILQ_NEXT(cp, links)) {
+ if (cp == dbc || cp->dbtype != DB_HASH)
+ continue;
+
+ hcp = (HASH_CURSOR *)cp->internal;
+
+ if (hcp->pgno == old_pgno) {
+ switch (op) {
+ case DB_HAM_DELFIRSTPG:
+ /*
+ * We're moving all items,
+ * regardless of index.
+ */
+ hcp->pgno = new_pgno;
+
+ /*
+ * But we have to be careful of
+ * the order values.
+ */
+ if (hcp->indx == indx)
+ hcp->order += order;
+ break;
+ case DB_HAM_DELMIDPG:
+ hcp->pgno = new_pgno;
+ DB_ASSERT(hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED));
+ hcp->order += order;
+ break;
+ case DB_HAM_DELLASTPG:
+ hcp->pgno = new_pgno;
+ DB_ASSERT(hcp->indx == 0 &&
+ F_ISSET(hcp, H_DELETED));
+ hcp->indx = indx;
+ hcp->order += order;
+ break;
+ default:
+ DB_ASSERT(0);
+ return (__db_panic(dbp->dbenv, EINVAL));
+ }
+ if (my_txn != NULL && cp->txn != my_txn)
+ found = 1;
+ }
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
+ }
+ MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp);
+
+ if (found != 0 && DB_LOGGING(dbc)) {
+ if ((ret = __ham_chgpg_log(dbenv,
+ my_txn, &lsn, 0, dbp->log_fileid, op,
+ old_pgno, new_pgno, indx, order)) != 0)
+ return (ret);
+ }
+ *orderp = order;
+ return (0);
+}
+
diff --git a/lib/package.c b/lib/package.c
index 712289b0c..3d79c2b9a 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -39,6 +39,7 @@ void headerMergeLegacySigs(Header h, const Header sig)
ptr = hfd(ptr, type))
{
switch (tag) {
+ /* XXX Translate legacy signature tag values. */
case RPMSIGTAG_SIZE:
tag = RPMTAG_SIGSIZE;
/*@switchbreak@*/ break;
@@ -60,6 +61,11 @@ void headerMergeLegacySigs(Header h, const Header sig)
case RPMSIGTAG_PGP5:
tag = RPMTAG_SIGPGP5;
/*@switchbreak@*/ break;
+ case RPMSIGTAG_PAYLOADSIZE:
+ tag = RPMTAG_ARCHIVESIZE;
+ /*@switchbreak@*/ break;
+ case RPMSIGTAG_SHA1:
+ case RPMSIGTAG_DSA:
default:
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
continue;
@@ -88,6 +94,7 @@ Header headerRegenSigHeader(const Header h)
ptr = hfd(ptr, type))
{
switch (tag) {
+ /* XXX Translate legacy signature tag values. */
case RPMTAG_SIGSIZE:
stag = RPMSIGTAG_SIZE;
/*@switchbreak@*/ break;
@@ -109,6 +116,11 @@ Header headerRegenSigHeader(const Header h)
case RPMTAG_SIGPGP5:
stag = RPMSIGTAG_PGP5;
/*@switchbreak@*/ break;
+ case RPMTAG_ARCHIVESIZE:
+ stag = RPMSIGTAG_PAYLOADSIZE;
+ /*@switchbreak@*/ break;
+ case RPMTAG_SHA1HEADER:
+ case RPMTAG_DSAHEADER:
default:
if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
continue;
@@ -249,6 +261,7 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
/*@notreached@*/ break;
}
+ /* Read the signature header. */
rc = rpmReadSignature(fd, &sig, l->signature_type);
if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) {
rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn);
@@ -260,24 +273,26 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
goto exit;
}
- if (!ts->verify_legacy) /* leave fd ready to install payload */
- ts->sigtag = 0;
- else if (headerIsEntry(sig, RPMSIGTAG_GPG))
+ /* Figger the most effective available signature. */
+ if (headerIsEntry(sig, RPMSIGTAG_DSA))
+ ts->sigtag = RPMSIGTAG_DSA;
+ else if (!ts->verify_legacy) /* leave fd ready to install payload */
+ ts->sigtag = (headerIsEntry(sig, RPMSIGTAG_SHA1)) ? RPMSIGTAG_SHA1 : 0;
+ else if (headerIsEntry(sig, RPMSIGTAG_GPG)) {
ts->sigtag = RPMSIGTAG_GPG;
- else if (headerIsEntry(sig, RPMSIGTAG_PGP))
+ fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
+ } else if (headerIsEntry(sig, RPMSIGTAG_PGP)) {
ts->sigtag = RPMSIGTAG_PGP;
- else if (headerIsEntry(sig, RPMSIGTAG_MD5))
+ fdInitDigest(fd, PGPHASHALGO_MD5, 0);
+ } else if (headerIsEntry(sig, RPMSIGTAG_SHA1)) {
+ ts->sigtag = RPMSIGTAG_SHA1; /* XXX never happens */
+ } else if (headerIsEntry(sig, RPMSIGTAG_MD5)) {
ts->sigtag = RPMSIGTAG_MD5;
- else
- ts->sigtag = 0;
-
- /*@-type@*/ /* FIX: cast? */
- if (ts->sigtag == RPMSIGTAG_GPG)
- fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
- else if (ts->sigtag == RPMSIGTAG_PGP || ts->sigtag == RPMSIGTAG_MD5)
fdInitDigest(fd, PGPHASHALGO_MD5, 0);
- /*@=type@*/
+ } else
+ ts->sigtag = 0; /* XXX never happens */
+ /* Read the metadata, computing digest(s) on the fly. */
hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
h = headerRead(fd, hmagic);
if (h == NULL) {
@@ -293,56 +308,94 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd,
}
ts->dig = pgpNewDig();
- ts->dig->nbytes = headerSizeof(h, hmagic);
-
- /* Read the compressed payload. */
- while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
- ts->dig->nbytes += count;
-
- if (count < 0) {
- rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd));
- rc = RPMRC_FAIL;
+ if (ts->dig == NULL) {
+ rc = RPMRC_OK; /* XXX WRONG */
goto exit;
}
- ts->dig->nbytes += count;
+ ts->dig->nbytes = 0;
+ /* Retrieve the tag parameters from the signature header. */
+ ts->sig = NULL;
xx = headerGetEntry(sig, ts->sigtag, &ts->sigtype,
(void **) &ts->sig, &ts->siglen);
+ if (ts->sig == NULL) {
+ rc = RPMRC_OK; /* XXX WRONG */
+ goto exit;
+ }
- xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
-
- /*@-type@*/ /* FIX: cast? */
- for (i = fd->ndigests - 1; i >= 0; i--) {
- FDDIGEST_t fddig = fd->digests + i;
- if (fddig->hashctx == NULL)
- continue;
- if (fddig->hashalgo == PGPHASHALGO_MD5) {
- /*@-branchstate@*/
- if (ts->dig->md5ctx != NULL)
- (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0);
- /*@=branchstate@*/
- ts->dig->md5ctx = fddig->hashctx;
- fddig->hashctx = NULL;
- continue;
+ switch (ts->sigtag) {
+ case RPMSIGTAG_DSA:
+ /* Parse the parameters from the OpenPGP packets that will be needed. */
+ xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
+ /*@fallthrough@*/
+ case RPMSIGTAG_SHA1:
+ { void * uh = NULL;
+ int_32 uht;
+ int_32 uhc;
+
+ /*@-branchstate@*/
+ if (headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
+ ts->dig->sha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
+ (void) rpmDigestUpdate(ts->dig->sha1ctx, uh, uhc);
+ ts->dig->nbytes += uhc;
+ uh = headerFreeData(uh, uht);
}
- if (fddig->hashalgo == PGPHASHALGO_SHA1) {
- /*@-branchstate@*/
- if (ts->dig->sha1ctx != NULL)
- (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0);
- /*@=branchstate@*/
- ts->dig->sha1ctx = fddig->hashctx;
- fddig->hashctx = NULL;
- continue;
+ /*@=branchstate@*/
+ } break;
+ case RPMSIGTAG_GPG:
+ case RPMSIGTAG_PGP5: /* XXX legacy */
+ case RPMSIGTAG_PGP:
+ /* Parse the parameters from the OpenPGP packets that will be needed. */
+ xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
+ /*@fallthrough@*/
+ case RPMSIGTAG_MD5:
+ /* Legacy signatures need the compressed payload in the digest too. */
+ ts->dig->nbytes += headerSizeof(h, hmagic);
+ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
+ ts->dig->nbytes += count;
+ if (count < 0) {
+ rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
+ fn, Fstrerror(fd));
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+ ts->dig->nbytes += count;
+
+ /* XXX Steal the digest-in-progress from the file handle. */
+ /*@-type@*/ /* FIX: cast? */
+ for (i = fd->ndigests - 1; i >= 0; i--) {
+ FDDIGEST_t fddig = fd->digests + i;
+ if (fddig->hashctx == NULL)
+ continue;
+ if (fddig->hashalgo == PGPHASHALGO_MD5) {
+ /*@-branchstate@*/
+ if (ts->dig->md5ctx != NULL)
+ (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0);
+ /*@=branchstate@*/
+ ts->dig->md5ctx = fddig->hashctx;
+ fddig->hashctx = NULL;
+ continue;
+ }
+ if (fddig->hashalgo == PGPHASHALGO_SHA1) {
+ /*@-branchstate@*/
+ if (ts->dig->sha1ctx != NULL)
+ (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0);
+ /*@=branchstate@*/
+ ts->dig->sha1ctx = fddig->hashctx;
+ fddig->hashctx = NULL;
+ continue;
+ }
}
+ /*@=type@*/
+ break;
}
- /*@=type@*/
/** @todo Implement disable/enable/warn/error/anal policy. */
buf[0] = '\0';
switch (rpmVerifySignature(ts, buf)) {
case RPMSIG_OK: /* Signature is OK. */
- rpmMessage(RPMMESS_VERBOSE, "%s: %s", fn, buf);
+ rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
rc = RPMRC_OK;
break;
case RPMSIG_UNKNOWN: /* Signature is unknown. */
@@ -363,7 +416,7 @@ exit:
/* Convert legacy headers on the fly ... */
legacyRetrofit(h, l);
- /* Append (and remap) signature tags. */
+ /* Append (and remap) signature tags to the metadata. */
headerMergeLegacySigs(h, sig);
/* Bump reference count for return. */
diff --git a/lib/query.c b/lib/query.c
index d08b02ad5..09f0875e9 100644
--- a/lib/query.c
+++ b/lib/query.c
@@ -974,7 +974,9 @@ int rpmcliQuery(rpmTransactionSet ts, QVA_t qva, const char ** argv)
qva->qva_showPackage = showQueryPackage;
switch (qva->qva_source) {
+#ifdef DYING
case RPMQV_RPM:
+#endif
case RPMQV_SPECFILE:
break;
default:
diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c
index 671b3a49a..6bc10328d 100644
--- a/lib/rpmchecksig.c
+++ b/lib/rpmchecksig.c
@@ -21,6 +21,8 @@
/*@access FD_t @*/
/*@access pgpDig @*/
+/**
+ */
static int manageFile(FD_t *fdp, const char **fnp, int flags,
/*@unused@*/ int rc)
/*@globals rpmGlobalMacroContext,
@@ -78,6 +80,7 @@ static int manageFile(FD_t *fdp, const char **fnp, int flags,
}
/**
+ * Copy header+payload, calculating digest(s) on the fly.
*/
static int copyFile(FD_t *sfdp, const char **sfnp,
FD_t *tfdp, const char **tfnp)
@@ -158,11 +161,11 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts,
}
switch (l->major) {
case 1:
- rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1.0 RPM\n"), rpm);
+ rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1 packaging\n"), rpm);
goto exit;
/*@notreached@*/ /*@switchbreak@*/ break;
case 2:
- rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2.0 RPM\n"), rpm);
+ rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2 packaging\n"), rpm);
goto exit;
/*@notreached@*/ /*@switchbreak@*/ break;
default:
@@ -202,18 +205,25 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts,
}
(void) headerRemoveEntry(sig, RPMSIGTAG_SIZE);
- (void) headerRemoveEntry(sig, RPMSIGTAG_MD5);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase);
(void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_1);
(void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_2);
+ (void) headerRemoveEntry(sig, RPMSIGTAG_MD5);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase);
+#ifdef NOTNOW
+ (void) headerRemoveEntry(sig, RPMSIGTAG_SHA1);
+ (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SHA1, qva->passPhrase);
+
(void) headerRemoveEntry(sig, RPMSIGTAG_PGP5);
(void) headerRemoveEntry(sig, RPMSIGTAG_PGP);
(void) headerRemoveEntry(sig, RPMSIGTAG_GPG);
- (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase);
- (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase);
+#endif
}
- if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0)
+ if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
+ (void) headerRemoveEntry(sig, sigtype);
(void) rpmAddSignature(sig, sigtarget, sigtype, qva->passPhrase);
+ }
/* Write the lead/signature of the output rpm */
strcpy(tmprpm, rpm);
@@ -466,7 +476,6 @@ static int readFile(FD_t fd, int_32 sigtag, const char * fn, pgpDig dig)
rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd));
goto exit;
}
- dig->nbytes += count;
/*@-type@*/ /* FIX: cast? */
for (i = fd->ndigests - 1; i >= 0; i--) {
@@ -546,14 +555,20 @@ int rpmVerifySignatures(QVA_t qva, rpmTransactionSet ts, FD_t fd,
}
/* Grab a hint of what needs doing to avoid duplication. */
- if (headerIsEntry(sig, RPMSIGTAG_GPG))
+ if (headerIsEntry(sig, RPMSIGTAG_DSA))
+ sigtag = RPMSIGTAG_DSA;
+ else if (headerIsEntry(sig, RPMSIGTAG_GPG))
sigtag = RPMSIGTAG_GPG;
else if (headerIsEntry(sig, RPMSIGTAG_PGP))
sigtag = RPMSIGTAG_PGP;
else if (headerIsEntry(sig, RPMSIGTAG_MD5))
sigtag = RPMSIGTAG_MD5;
+#ifdef NOTYET
+ else if (headerIsEntry(sig, RPMSIGTAG_SHA1))
+ sigtag = RPMSIGTAG_SHA1; /* XXX never happens */
+#endif
else
- sigtag = 0; /* XXX never happens */
+ sigtag = 0; /* XXX never happens */
ts->dig = pgpNewDig();
@@ -589,6 +604,7 @@ if (rpmIsDebug())
fprintf(stderr, "========================= Package RSA Signature\n");
xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug());
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
if (!(qva->qva_flags & VERIFY_SIGNATURE))
continue;
@@ -603,11 +619,17 @@ fprintf(stderr, "========================= Package DSA Signature\n");
continue;
/*
* Don't bother with md5 if pgp, as RSA/MD5 is more reliable
- * than the legacy -- now unsupported -- legacy md5 breakage.
+ * than the -- now unsupported -- legacy md5 breakage.
*/
if (sigtag == RPMSIGTAG_PGP)
continue;
/*@switchbreak@*/ break;
+ case RPMSIGTAG_SHA1:
+#ifdef NOTYET
+ if (!(qva->qva_flags & VERIFY_DIGEST))
+ continue;
+ /*@switchbreak@*/ break;
+#endif
default:
continue;
/*@notreached@*/ /*@switchbreak@*/ break;
@@ -662,6 +684,7 @@ fprintf(stderr, "========================= Package DSA Signature\n");
/*@innerbreak@*/ break;
}
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
/* Do not consider this a failure */
switch (res3) {
@@ -703,6 +726,7 @@ fprintf(stderr, "========================= Package DSA Signature\n");
case RPMSIGTAG_PGP:
b = stpcpy(b, "pgp ");
/*@switchbreak@*/ break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
b = stpcpy(b, "gpg ");
/*@switchbreak@*/ break;
diff --git a/lib/rpmlib.h b/lib/rpmlib.h
index 4b34fbbe7..1f7310969 100644
--- a/lib/rpmlib.h
+++ b/lib/rpmlib.h
@@ -228,6 +228,7 @@ typedef enum rpmTag_e {
/*@=enummemuse@*/
RPMTAG_SHA1HEADER = RPMTAG_SIG_BASE+9,
RPMTAG_PUBKEYS = RPMTAG_SIG_BASE+10,
+ RPMTAG_DSAHEADER = RPMTAG_SIG_BASE+11,
RPMTAG_NAME = 1000,
RPMTAG_VERSION = 1001,
@@ -773,9 +774,9 @@ typedef /*@abstract@*/ struct _rpmdbMatchIterator * rpmdbMatchIterator;
/*@modifies mi, fileSystem @*/;
/** \ingroup rpmdb
- * Return join key for current position of rpm database iterator.
+ * Return header join key for current position of rpm database iterator.
* @param mi rpm database iterator
- * @return current join key
+ * @return current header join key
*/
unsigned int rpmdbGetIteratorOffset(/*@null@*/ rpmdbMatchIterator mi)
/*@*/;
@@ -1780,12 +1781,16 @@ typedef enum rpmEraseInterfaceFlags_e {
enum rpmtagSignature {
RPMSIGTAG_SIZE = 1000, /*!< Header+Payload size in bytes. */
/* the md5 sum was broken *twice* on big endian machines */
- RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 */
+ RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 @deprecated legacy. */
RPMSIGTAG_PGP = 1002, /*!< PGP 2.6.3 signature. */
- RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 */
+ RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 @deprecated legacy. */
RPMSIGTAG_MD5 = 1004, /*!< MD5 signature. */
RPMSIGTAG_GPG = 1005, /*!< GnuPG signature. */
RPMSIGTAG_PGP5 = 1006, /*!< PGP5 signature @deprecated legacy. */
+ RPMSIGTAG_PAYLOADSIZE = 1007,
+ /*!< uncompressed payload size in bytes. */
+ RPMSIGTAG_SHA1 = RPMTAG_SHA1HEADER, /*!< sha1 header digest. */
+ RPMSIGTAG_DSA = RPMTAG_DSAHEADER, /*!< DSA header signature. */
};
/**
diff --git a/lib/signature.c b/lib/signature.c
index 40ed66cc1..f9a81b2e0 100644
--- a/lib/signature.c
+++ b/lib/signature.c
@@ -7,6 +7,7 @@
#include "rpmio_internal.h"
#include <rpmlib.h>
#include <rpmmacro.h> /* XXX for rpmGetPath() */
+#include "rpmdb.h"
#include "depends.h"
#include "misc.h" /* XXX for dosetenv() and makeTempFile() */
@@ -483,6 +484,10 @@ int rpmAddSignature(Header h, const char * file, int_32 sigTag,
if (ret == 0)
(void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, sig, size);
break;
+ case RPMSIGTAG_DSA: /* XXX UNIMPLEMENTED */
+ break;
+ case RPMSIGTAG_SHA1: /* XXX UNIMPLEMENTED */
+ break;
}
return ret;
@@ -523,6 +528,7 @@ static int checkPassPhrase(const char * passPhrase, const int sigTag)
(void) dup2(passPhrasePipe[0], 3);
switch (sigTag) {
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
{ const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
@@ -597,6 +603,7 @@ char * rpmGetPassPhrase(const char * prompt, const int sigTag)
int aok;
switch (sigTag) {
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
{ const char *name = rpmExpand("%{?_gpg_name}", NULL);
aok = (name && *name != '\0');
@@ -662,21 +669,31 @@ verifySizeSignature(const rpmTransactionSet ts, /*@out@*/ char * t)
*t = '\0';
t = stpcpy(t, _("Header+Payload size: "));
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
memcpy(&size, ts->sig, sizeof(size));
/*@-type@*/
/*@-nullderef@*/ /* FIX: ts->dig can be NULL */
if (size != ts->dig->nbytes) {
res = RPMSIG_BAD;
- sprintf(t, "BAD Expected(%d) != (%d)\n", size, ts->dig->nbytes);
+ t = stpcpy(t, rpmSigString(res));
+ sprintf(t, " Expected(%d) != (%d)\n", size, ts->dig->nbytes);
} else {
res = RPMSIG_OK;
- sprintf(t, "OK (%d)\n", ts->dig->nbytes);
+ t = stpcpy(t, rpmSigString(res));
+ sprintf(t, " (%d)", ts->dig->nbytes);
}
/*@=type@*/
/*@=nullpass =nullderef@*/
+exit:
+ t = stpcpy(t, "\n");
return res;
}
@@ -691,7 +708,13 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
*t = '\0';
t = stpcpy(t, _("MD5 digest: "));
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
/*@-type@*/
(void) rpmDigestFinal(rpmDigestDup(ts->dig->md5ctx),
(void **)&md5sum, &md5len, 0);
@@ -699,21 +722,172 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
if (md5len != ts->siglen || memcmp(md5sum, ts->sig, md5len)) {
res = RPMSIG_BAD;
- t = stpcpy(t, "BAD Expected(");
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " Expected(");
(void) pgpHexCvt(t, ts->sig, ts->siglen);
t += strlen(t);
t = stpcpy(t, ") != (");
} else {
res = RPMSIG_OK;
- t = stpcpy(t, "OK (");
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " (");
}
/*@=nullpass =nullderef@*/
(void) pgpHexCvt(t, md5sum, md5len);
t += strlen(t);
- t = stpcpy(t, ")\n");
+ t = stpcpy(t, ")");
+exit:
md5sum = _free(md5sum);
+ t = stpcpy(t, "\n");
+ return res;
+}
+
+static rpmVerifySignatureReturn
+verifySHA1Signature(const rpmTransactionSet ts, /*@out@*/ char * t)
+ /*@modifies *t @*/
+{
+ rpmVerifySignatureReturn res;
+ const char * sha1 = NULL;
+
+ *t = '\0';
+ t = stpcpy(t, _("SHA1 header digest: "));
+
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ t = stpcpy(t, rpmSigString(res));
+ goto exit;
+ }
+
+ /*@-type@*/
+ (void) rpmDigestFinal(rpmDigestDup(ts->dig->sha1ctx),
+ (void **)&sha1, NULL, 1);
+ /*@=type@*/
+
+ if (sha1 == NULL || strlen(sha1) != strlen(ts->sig)) {
+ res = RPMSIG_BAD;
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " Expected(");
+ t = stpcpy(t, ts->sig);
+ t = stpcpy(t, ") != (");
+ } else {
+ res = RPMSIG_OK;
+ t = stpcpy(t, rpmSigString(res));
+ t = stpcpy(t, " (");
+ }
+ if (sha1)
+ t = stpcpy(t, sha1);
+ t = stpcpy(t, ")");
+
+exit:
+ sha1 = _free(sha1);
+ t = stpcpy(t, "\n");
+ return res;
+}
+
+/**
+ * Retrieve pubkey from rpm database.
+ * @param ts rpm transaction
+ * @return RPMSIG_OK on success, RPMSIG_NOKEY if not found
+ */
+static rpmVerifySignatureReturn
+rpmtsFindPubkey(rpmTransactionSet ts)
+ /*@modifies ts */
+{
+ struct pgpDigParams_s * sigp = NULL;
+ rpmVerifySignatureReturn res;
+ /*@unchecked@*/ /*@only@*/ static const byte * pkpkt = NULL;
+ /*@unchecked@*/ static size_t pkpktlen = 0;
+ /*@unchecked@*/ static byte pksignid[8];
+ int xx;
+
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
+ /*@-globs -internalglobs -mods -modfilesys@*/
+ if (pkpkt == NULL || memcmp(sigp->signid, pksignid, sizeof(pksignid))) {
+ int ix = -1;
+ rpmdbMatchIterator mi;
+ Header h;
+
+ pkpkt = _free(pkpkt);
+ pkpktlen = 0;
+ memset(pksignid, 0, sizeof(pksignid));
+
+ (void) rpmtsOpenDB(ts, ts->dbmode);
+
+ mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
+ while ((h = rpmdbNextIterator(mi)) != NULL) {
+ const char ** pubkeys;
+ int_32 pt, pc;
+
+ if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc))
+ continue;
+ ix = rpmdbGetIteratorFileNum(mi);
+ if (ix >= pc
+ || b64decode(pubkeys[ix], (void **) &pkpkt, &pkpktlen))
+ ix = -1;
+ pubkeys = headerFreeData(pubkeys, pt);
+ break;
+ }
+ mi = rpmdbFreeIterator(mi);
+
+ if (ix < 0 || pkpkt == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+
+ /* Make sure the pkt can be parsed, print info if debugging. */
+ if (pgpPrtPkts(pkpkt, pkpktlen, NULL, 0)) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+
+ /* XXX Verify the pubkey signature. */
+
+ /* Packet looks good, save the signer id. */
+ memcpy(pksignid, sigp->signid, sizeof(pksignid));
+ }
+
+#ifdef NOTNOW
+ {
+ if (pkpkt == NULL) {
+ const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
+ if (pgpReadPkts(pkfn, &pkpkt, &pkpktlen) != PGPARMOR_PUBKEY) {
+ pkfn = _free(pkfn);
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ pkfn = _free(pkfn);
+ }
+ }
+#endif
+
+ rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n",
+ (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" :
+ (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")),
+ pgpHexStr(sigp->signid, sizeof(sigp->signid)));
+
+ /* Retrieve parameters from pubkey packet(s). */
+ xx = pgpPrtPkts(pkpkt, pkpktlen, ts->dig, 0);
+ /*@=globs =internalglobs =mods =modfilesys@*/
+
+ /* Make sure we have the correct public key. */
+ if (ts->dig->signature.pubkey_algo == ts->dig->pubkey.pubkey_algo
+#ifdef NOTYET
+ && ts->dig->signature.hash_algo == ts->dig->pubkey.hash_algo
+#endif
+ && !memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
+ res = RPMSIG_OK;
+ else
+ res = RPMSIG_NOKEY;
+
+ /* XXX Verify the signature signature. */
+exit:
return res;
}
@@ -721,22 +895,33 @@ static rpmVerifySignatureReturn
verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t)
/*@modifies ts, *t */
{
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ struct pgpDigParams_s * sigp = NULL;
rpmVerifySignatureReturn res;
- struct pgpDigParams_s * digp = &ts->dig->signature;
- /*@unchecked@*/ static const byte * pgppk = NULL;
- /*@unchecked@*/ static size_t pgppklen = 0;
int xx;
*t = '\0';
t = stpcpy(t, _("V3 RSA/MD5 signature: "));
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
/* XXX sanity check on ts->sigtag and signature agreement. */
+ if (!(ts->sigtag == RPMSIGTAG_PGP
+ && sigp->pubkey_algo == PGPPUBKEYALGO_RSA
+ && sigp->hash_algo == PGPHASHALGO_MD5))
+ {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
/*@-type@*/ /* FIX: cast? */
{ DIGEST_CTX ctx = rpmDigestDup(ts->dig->md5ctx);
- xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen);
+ if (sigp->hash != NULL)
+ xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
xx = rpmDigestFinal(ctx, (void **)&ts->dig->md5, &ts->dig->md5len, 1);
/* XXX compare leading 16 bits of digest for quick check. */
@@ -763,46 +948,25 @@ verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t)
hexstr = _free(hexstr);
}
- /* XXX retrieve by keyid from signature. */
-
- /*@-globs -internalglobs -mods -modfilesys@*/
- if (pgppk == NULL) {
- const char * pkfn = rpmExpand("%{_pgp_pubkey}", NULL);
- if (pgpReadPkts(pkfn, &pgppk, &pgppklen) != PGPARMOR_PUBKEY) {
- pkfn = _free(pkfn);
- res = RPMSIG_NOKEY;
- goto exit;
- }
- rpmMessage(RPMMESS_DEBUG,
- "========== PGP RSA/MD5 pubkey %s\n", pkfn);
- xx = pgpPrtPkts(pgppk, pgppklen, NULL, rpmIsDebug());
- pkfn = _free(pkfn);
- }
-
- /* Retrieve parameters from pubkey packet(s). */
- xx = pgpPrtPkts(pgppk, pgppklen, ts->dig, 0);
- /*@=globs =internalglobs =mods =modfilesys@*/
-
- /* Make sure we have the correct public key. */
- if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo
- || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
- {
- res = RPMSIG_NOKEY;
+ /* Retrieve the matching public key. */
+ res = rpmtsFindPubkey(ts);
+ if (res != RPMSIG_OK)
goto exit;
- }
/*@-type@*/
- if (!rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c))
- res = RPMSIG_BAD;
- else
+ if (rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c))
res = RPMSIG_OK;
+ else
+ res = RPMSIG_BAD;
/*@=type@*/
-/*@=nullpass =nullderef@*/
exit:
- t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID ");
- (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4);
- t += strlen(t);
+ t = stpcpy(t, rpmSigString(res));
+ if (sigp != NULL) {
+ t = stpcpy(t, ", key ID ");
+ (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
+ t += strlen(t);
+ }
t = stpcpy(t, "\n");
return res;
}
@@ -811,71 +975,61 @@ static rpmVerifySignatureReturn
verifyGPGSignature(rpmTransactionSet ts, /*@out@*/ char * t)
/*@modifies ts, *t @*/
{
-/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */
+ struct pgpDigParams_s * sigp = NULL;
rpmVerifySignatureReturn res;
- struct pgpDigParams_s * digp = &ts->dig->signature;
- /*@unchecked@*/ static const byte * gpgpk = NULL;
- /*@unchecked@*/ static size_t gpgpklen = 0;
int xx;
*t = '\0';
t = stpcpy(t, _("V3 DSA signature: "));
+ if (ts->sig == NULL || ts->dig == NULL) {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
+ sigp = &ts->dig->signature;
+
/* XXX sanity check on ts->sigtag and signature agreement. */
+ if (!((ts->sigtag == RPMSIGTAG_GPG || ts->sigtag == RPMSIGTAG_DSA)
+ && sigp->pubkey_algo == PGPPUBKEYALGO_DSA
+ && sigp->hash_algo == PGPHASHALGO_SHA1))
+ {
+ res = RPMSIG_NOKEY;
+ goto exit;
+ }
/*@-type@*/ /* FIX: cast? */
{ DIGEST_CTX ctx = rpmDigestDup(ts->dig->sha1ctx);
- xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen);
+ if (sigp->hash != NULL)
+ xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen);
xx = rpmDigestFinal(ctx, (void **)&ts->dig->sha1, &ts->dig->sha1len, 1);
+ /* XXX compare leading 16 bits of digest for quick check. */
+
mp32nzero(&ts->dig->hm); mp32nsethex(&ts->dig->hm, ts->dig->sha1);
}
/*@=type@*/
- /* XXX retrieve by keyid from signature. */
-
- /*@-globs -internalglobs -mods -modfilesys@*/
- if (gpgpk == NULL) {
- const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL);
- int printing = 0; /* XXX was rpmIsDebug() */
-
- if (pgpReadPkts(pkfn, &gpgpk, &gpgpklen) != PGPARMOR_PUBKEY) {
- pkfn = _free(pkfn);
- res = RPMSIG_NOKEY;
- goto exit;
- }
- rpmMessage(RPMMESS_DEBUG,
- "========== GPG DSA pubkey %s\n", pkfn);
- xx = pgpPrtPkts(gpgpk, gpgpklen, NULL, printing);
- pkfn = _free(pkfn);
- }
-
- /* Retrieve parameters from pubkey packet(s). */
- xx = pgpPrtPkts(gpgpk, gpgpklen, ts->dig, 0);
- /*@=globs =internalglobs =mods =modfilesys@*/
-
- /* Make sure we have the correct public key. */
- if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo
- || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8))
- {
- res = RPMSIG_NOKEY;
+ /* Retrieve the matching public key. */
+ res = rpmtsFindPubkey(ts);
+ if (res != RPMSIG_OK)
goto exit;
- }
/*@-type@*/
- if (!dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g,
+ if (dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g,
&ts->dig->hm, &ts->dig->y, &ts->dig->r, &ts->dig->s))
- res = RPMSIG_BAD;
- else
res = RPMSIG_OK;
+ else
+ res = RPMSIG_BAD;
/*@=type@*/
-/*@=nullpass =nullderef@*/
exit:
- t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID ");
- (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4);
- t += strlen(t);
+ t = stpcpy(t, rpmSigString(res));
+ if (sigp != NULL) {
+ t = stpcpy(t, ", key ID ");
+ (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4);
+ t += strlen(t);
+ }
t = stpcpy(t, "\n");
return res;
}
@@ -897,10 +1051,14 @@ rpmVerifySignature(const rpmTransactionSet ts, char * result)
case RPMSIGTAG_MD5:
res = verifyMD5Signature(ts, result);
break;
+ case RPMSIGTAG_SHA1:
+ res = verifySHA1Signature(ts, result);
+ break;
case RPMSIGTAG_PGP5: /* XXX legacy */
case RPMSIGTAG_PGP:
res = verifyPGPSignature(ts, result);
break;
+ case RPMSIGTAG_DSA:
case RPMSIGTAG_GPG:
res = verifyGPGSignature(ts, result);
break;
diff --git a/lib/verify.c b/lib/verify.c
index 13a30e3ee..c3f544bf1 100644
--- a/lib/verify.c
+++ b/lib/verify.c
@@ -572,10 +572,12 @@ int rpmcliVerify(rpmTransactionSet ts, QVA_t qva, const char ** argv)
qva->qva_showPackage = showVerifyPackage;
switch (qva->qva_source) {
+#ifdef DYING
case RPMQV_RPM:
if (!(qva->qva_flags & VERIFY_DEPS))
break;
/*@fallthrough@*/
+#endif
default:
if (rpmtsOpenDB(ts, O_RDONLY))
return 1; /* XXX W2DO? */
diff --git a/rpm.spec b/rpm.spec
index df22b86ee..a4d0484cf 100644
--- a/rpm.spec
+++ b/rpm.spec
@@ -2,7 +2,7 @@
%define with_python_version 2.2%{nil}
%define with_perl_subpackage 1
%define with_bzip2 1%{nil}
-%define with_apidocs 1%{nil}
+%define with_apidocs 0%{nil}
%define with_internal_db 1%{nil}
%define strip_binaries 1
@@ -479,7 +479,7 @@ fi
%files devel
%defattr(-,root,root)
%if %{with_apidocs}
-%doc apidocs
+%doc
%endif
%{__prefix}/include/rpm
%{__prefix}/lib/librpm.a
@@ -647,3 +647,11 @@ fi
- add cpanflute2, another perl.req fiddle.
- make peace with gcc-3.1, remove compiler cruft.
- make peace with automake et al in 8.0, ugh.
+- add payload uncompressed size to signature to avoid rewriting header.
+- drill header sha1 into signature parallel to header+payload md5.
+- mandatory "most effective" signature check on query/verify/install.
+- don't bother adding empty filemd's to index.
+- add Pubkey index, using signer id as binary key.
+- display pubkeys in hex when debugging db access.
+- retrieve pubkey(s) from rpmdb, not from detached signature file.
+- reapply Berkeley DB patch #4491.
diff --git a/rpm.spec.in b/rpm.spec.in
index b1898f2dc..f89f7ab82 100644
--- a/rpm.spec.in
+++ b/rpm.spec.in
@@ -647,3 +647,11 @@ fi
- add cpanflute2, another perl.req fiddle.
- make peace with gcc-3.1, remove compiler cruft.
- make peace with automake et al in 8.0, ugh.
+- add payload uncompressed size to signature to avoid rewriting header.
+- drill header sha1 into signature parallel to header+payload md5.
+- mandatory "most effective" signature check on query/verify/install.
+- don't bother adding empty filemd's to index.
+- add Pubkey index, using signer id as binary key.
+- display pubkeys in hex when debugging db access.
+- retrieve pubkey(s) from rpmdb, not from detached signature file.
+- reapply Berkeley DB patch #4491.
diff --git a/rpmdb/rpmdb.c b/rpmdb/rpmdb.c
index 339804bc3..b879142aa 100644
--- a/rpmdb/rpmdb.c
+++ b/rpmdb/rpmdb.c
@@ -33,6 +33,7 @@ extern void regfree (/*@only@*/ regex_t *preg)
#endif
#include <rpmcli.h>
+#include <rpmpgp.h>
#include "rpmdb.h"
#include "fprint.h"
@@ -63,6 +64,38 @@ static int _db_filter_dups = 0;
int dbiTagsMax = 0;
/**
+ * Convert hex to binary nibble.
+ * @param c hex character
+ * @return binary nibble
+ */
+static inline unsigned char nibble(char c)
+ /*@*/
+{
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ if (c >= 'A' && c <= 'F')
+ return (c - 'A') + 10;
+ if (c >= 'a' && c <= 'f')
+ return (c - 'a') + 10;
+ return 0;
+}
+
+/**
+ * Check key for printable characters.
+ * @param ptr key value pointer
+ * @param len key value length
+ * @return 1 if only ASCII, 0 otherwise.
+ */
+static int printable(const void * ptr, size_t len) /*@*/
+{
+ const char * s = ptr;
+ int i;
+ for (i = 0; i < len; i++, s++)
+ if (!(*s >= ' ' && *s <= '~')) return 0;
+ return 1;
+}
+
+/**
* Return dbi index used for rpm tag.
* @param rpmtag rpm header tag
* @return dbi index, -1 on error
@@ -209,15 +242,6 @@ fprintf(stderr, "--- RMW %s\n", tagName(dbi->dbi_rpmtag));
return (*dbi->dbi_vec->cclose) (dbi, dbcursor, flags);
}
-static int printable(const void * ptr, size_t len) /*@*/
-{
- const char * s = ptr;
- int i;
- for (i = 0; i < len; i++, s++)
- if (!(*s >= ' ' && *s <= '~')) return 0;
- return 1;
-}
-
INLINE int dbiDel(dbiIndex dbi, DBC * dbcursor,
const void * keyp, size_t keylen, unsigned int flags)
{
@@ -257,13 +281,24 @@ if (_debug < 0 || dbi->dbi_debug) {
char keyval[64];
keyval[0] = '\0';
if (keypp && *keypp && keylenp) {
- if (*keylenp <= sizeof(int) && !printable(*keypp, *keylenp)) {
+ if (printable(*keypp, *keylenp)) {
+ kvp = *keypp;
+ } else if (*keylenp <= sizeof(int)) {
int keyint = 0;
memcpy(&keyint, *keypp, sizeof(keyint));
sprintf(keyval, "#%d", keyint);
kvp = keyval;
} else {
- kvp = *keypp;
+ static const char hex[] = "0123456789abcdef";
+ const byte * s = *keypp;
+ char * t = keyval;
+ int i;
+ for (i = 0; i < *keylenp && t < (keyval+sizeof(keyval)-2); i++) {
+ *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
+ *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ];
+ }
+ *t = '\0';
+ kvp = keyval;
}
} else
kvp = keyval;
@@ -298,13 +333,24 @@ if (_debug < 0 || dbi->dbi_debug) {
char keyval[64];
keyval[0] = '\0';
if (keyp) {
- if (keylen == sizeof(int) && !printable(keyp, keylen)) {
+ if (printable(keyp, keylen)) {
+ kvp = keyp;
+ } else if (keylen <= sizeof(int)) {
int keyint = 0;
memcpy(&keyint, keyp, sizeof(keyint));
sprintf(keyval, "#%d", keyint);
kvp = keyval;
} else {
- kvp = keyp;
+ static const char hex[] = "0123456789abcdef";
+ const byte * s = keyp;
+ char * t = keyval;
+ int i;
+ for (i = 0; i < keylen && t < (keyval+sizeof(keyval)-2); i++) {
+ *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
+ *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ];
+ }
+ *t = '\0';
+ kvp = keyval;
}
} else
kvp = keyval;
@@ -2457,7 +2503,7 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum)
int rpmcnt = 0;
int rpmtag;
int xx;
- int i;
+ int i, j;
dbi = NULL;
rpmtag = dbiTags[dbix];
@@ -2506,6 +2552,17 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum)
const void * valp;
size_t vallen;
int stringvalued;
+ byte bin[32];
+
+ switch (dbi->dbi_rpmtag) {
+ case RPMTAG_FILEMD5S:
+ /* Filter out empty MD5 strings. */
+ if (!(rpmvals[i] && *rpmvals[i] != '\0'))
+ /*@innercontinue@*/ continue;
+ /*@switchbreak@*/ break;
+ default:
+ /*@switchbreak@*/ break;
+ }
/* Identify value pointer and length. */
stringvalued = 0;
@@ -2533,6 +2590,36 @@ int rpmdbRemove(rpmdb db, /*@unused@*/ int rid, unsigned int hdrNum)
rpmcnt = 1; /* XXX break out of loop. */
/*@fallthrough@*/
case RPM_STRING_ARRAY_TYPE:
+ /* Convert from hex to binary. */
+ if (dbi->dbi_rpmtag == RPMTAG_FILEMD5S) {
+ const char * s;
+ byte * t;
+
+ s = rpmvals[i];
+ t = bin;
+ for (j = 0; j < 16; j++, t++, s += 2)
+ *t = (nibble(s[0]) << 4) | nibble(s[1]);
+ valp = bin;
+ vallen = 16;
+ /*@switchbreak@*/ break;
+ }
+ /* Extract the pubkey id from the base64 blob. */
+ if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) {
+ pgpDig dig = pgpNewDig();
+ const byte * pkt;
+ ssize_t pktlen;
+
+ if (b64decode(rpmvals[i], (void **)&pkt, &pktlen))
+ continue;
+ (void) pgpPrtPkts(pkt, pktlen, dig, 0);
+ memcpy(bin, dig->pubkey.signid, 8);
+ pkt = _free(pkt);
+ dig = _free(dig);
+ valp = bin;
+ vallen = 8;
+ /*@switchbreak@*/ break;
+ }
+ /*@fallthrough@*/
default:
vallen = strlen(rpmvals[i]);
valp = rpmvals[i];
@@ -2812,17 +2899,25 @@ int rpmdbAdd(rpmdb db, int iid, Header h)
const void * valp;
size_t vallen;
int stringvalued;
+ byte bin[32];
/*
* Include the tagNum in all indices. rpm-3.0.4 and earlier
* included the tagNum only for files.
*/
+ rec->tagNum = i;
switch (dbi->dbi_rpmtag) {
+ case RPMTAG_PUBKEYS:
+ /*@switchbreak@*/ break;
+ case RPMTAG_FILEMD5S:
+ /* Filter out empty MD5 strings. */
+ if (!(rpmvals[i] && *rpmvals[i] != '\0'))
+ /*@innercontinue@*/ continue;
+ /*@switchbreak@*/ break;
case RPMTAG_REQUIRENAME:
/* Filter out install prerequisites. */
if (requireFlags && isInstallPreReq(requireFlags[i]))
/*@innercontinue@*/ continue;
- rec->tagNum = i;
/*@switchbreak@*/ break;
case RPMTAG_TRIGGERNAME:
if (i) { /* don't add duplicates */
@@ -2833,10 +2928,8 @@ int rpmdbAdd(rpmdb db, int iid, Header h)
if (j < i)
/*@innercontinue@*/ continue;
}
- rec->tagNum = i;
/*@switchbreak@*/ break;
default:
- rec->tagNum = i;
/*@switchbreak@*/ break;
}
@@ -2866,6 +2959,36 @@ int rpmdbAdd(rpmdb db, int iid, Header h)
rpmcnt = 1; /* XXX break out of loop. */
/*@fallthrough@*/
case RPM_STRING_ARRAY_TYPE:
+ /* Convert from hex to binary. */
+ if (dbi->dbi_rpmtag == RPMTAG_FILEMD5S) {
+ const char * s;
+ byte * t;
+
+ s = rpmvals[i];
+ t = bin;
+ for (j = 0; j < 16; j++, t++, s += 2)
+ *t = (nibble(s[0]) << 4) | nibble(s[1]);
+ valp = bin;
+ vallen = 16;
+ /*@switchbreak@*/ break;
+ }
+ /* Extract the pubkey id from the base64 blob. */
+ if (dbi->dbi_rpmtag == RPMTAG_PUBKEYS) {
+ pgpDig dig = pgpNewDig();
+ const byte * pkt;
+ ssize_t pktlen;
+
+ if (b64decode(rpmvals[i], (void **)&pkt, &pktlen))
+ continue;
+ (void) pgpPrtPkts(pkt, pktlen, dig, 0);
+ memcpy(bin, dig->pubkey.signid, 8);
+ pkt = _free(pkt);
+ dig = _free(dig);
+ valp = bin;
+ vallen = 8;
+ /*@switchbreak@*/ break;
+ }
+ /*@fallthrough@*/
default:
valp = rpmvals[i];
vallen = strlen(rpmvals[i]);
diff --git a/rpmdb/rpmdb.h b/rpmdb/rpmdb.h
index 4dc515010..c0fd4dd79 100644
--- a/rpmdb/rpmdb.h
+++ b/rpmdb/rpmdb.h
@@ -519,7 +519,6 @@ char * db1basename(int rpmtag)
/** \ingroup rpmdb
*/
-/*@unused@*/
unsigned int rpmdbGetIteratorFileNum(rpmdbMatchIterator mi)
/*@*/;
diff --git a/rpmio/rpmio_internal.h b/rpmio/rpmio_internal.h
index 8c645ca14..28eb4036f 100644
--- a/rpmio/rpmio_internal.h
+++ b/rpmio/rpmio_internal.h
@@ -507,11 +507,11 @@ void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo,
if (i < 0) {
if (datap) *datap = NULL;
if (lenp) *lenp = 0;
- return;
- } else if (i == imax)
- fd->ndigests = imax - 1;
- else
- fd->ndigests = imax;
+ }
+
+ fd->ndigests = imax;
+ if (i < imax)
+ fd->ndigests++; /* convert index to count */
}
/*@-shadow@*/