diff options
author | ram@mysql.r18.ru <> | 2002-10-30 15:57:05 +0400 |
---|---|---|
committer | ram@mysql.r18.ru <> | 2002-10-30 15:57:05 +0400 |
commit | 5e09392faa62ea38baa4bd46de5e4183da538e79 (patch) | |
tree | 6881a3cca88bea0bb9eeffd5aae34be437152786 /bdb/db/db_conv.c | |
parent | 1c0f1712ca4869b537ada297930ef01dcb039bb9 (diff) | |
download | mariadb-git-5e09392faa62ea38baa4bd46de5e4183da538e79.tar.gz |
BDB 4.1.24
Diffstat (limited to 'bdb/db/db_conv.c')
-rw-r--r-- | bdb/db/db_conv.c | 290 |
1 files changed, 246 insertions, 44 deletions
diff --git a/bdb/db/db_conv.c b/bdb/db/db_conv.c index df60be06790..f731c82d85e 100644 --- a/bdb/db/db_conv.c +++ b/bdb/db/db_conv.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 1997, 1998, 1999, 2000 + * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. */ /* @@ -40,7 +40,7 @@ #include "db_config.h" #ifndef lint -static const char revid[] = "$Id: db_conv.c,v 11.11 2000/11/30 00:58:31 ubell Exp $"; +static const char revid[] = "$Id: db_conv.c,v 11.38 2002/08/15 03:00:13 bostic Exp $"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -50,12 +50,14 @@ static const char revid[] = "$Id: db_conv.c,v 11.11 2000/11/30 00:58:31 ubell Ex #endif #include "db_int.h" -#include "db_page.h" -#include "db_swap.h" -#include "db_am.h" -#include "btree.h" -#include "hash.h" -#include "qam.h" +#include "dbinc/crypto.h" +#include "dbinc/hmac.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/log.h" +#include "dbinc/qam.h" /* * __db_pgin -- @@ -70,15 +72,135 @@ __db_pgin(dbenv, pg, pp, cookie) void *pp; DBT *cookie; { + DB dummydb, *dbp; DB_PGINFO *pginfo; + DB_CIPHER *db_cipher; + DB_LSN not_used; + PAGE *pagep; + size_t pg_off, pg_len, sum_len; + int is_hmac, ret; + u_int8_t *chksum, *iv; pginfo = (DB_PGINFO *)cookie->data; + pagep = (PAGE *)pp; - switch (((PAGE *)pp)->type) { - case P_HASH: + ret = is_hmac = 0; + chksum = iv = NULL; + memset(&dummydb, 0, sizeof(DB)); + dbp = &dummydb; + dummydb.flags = pginfo->flags; + db_cipher = (DB_CIPHER *)dbenv->crypto_handle; + switch (pagep->type) { case P_HASHMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * If checksumming is set on the meta-page, we must set + * it in the dbp. + */ + if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM)) + F_SET(dbp, DB_AM_CHKSUM); + if (((DBMETA *)pp)->encrypt_alg != 0 || + F_ISSET(dbp, DB_AM_ENCRYPT)) + is_hmac = 1; + /* + * !!! + * For all meta pages it is required that the chksum + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + chksum = ((BTMETA *)pp)->chksum; + sum_len = DBMETASIZE; + break; + case P_INVALID: + /* + * We assume that we've read a file hole if we have + * a zero LSN, zero page number and P_INVALID. Otherwise + * we have an invalid page that might contain real data. + */ + if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) { + sum_len = 0; + break; + } + /* FALLTHROUGH */ + default: + chksum = P_CHKSUM(dbp, pagep); + sum_len = pginfo->db_pagesize; + /* + * If we are reading in a non-meta page, then if we have + * a db_cipher then we are using hmac. + */ + is_hmac = CRYPTO_ON(dbenv) ? 1 : 0; + break; + } + + /* + * We expect a checksum error if there was a configuration problem. + * If there is no configuration problem and we don't get a match, + * it's fatal: panic the system. + */ + if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) + switch (ret = __db_check_chksum( + dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) { + case 0: + break; + case -1: + if (DBENV_LOGGING(dbenv)) + __db_cksum_log( + dbenv, NULL, ¬_used, DB_FLUSH); + __db_err(dbenv, + "checksum error: catastrophic recovery required"); + return (__db_panic(dbenv, DB_RUNRECOVERY)); + default: + return (ret); + } + + if (F_ISSET(dbp, DB_AM_ENCRYPT)) { + DB_ASSERT(db_cipher != NULL); + DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM)); + + pg_off = P_OVERHEAD(dbp); + DB_ASSERT(db_cipher->adj_size(pg_off) == 0); + + switch (pagep->type) { + case P_HASHMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the iv + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + iv = ((BTMETA *)pp)->iv; + pg_len = DBMETASIZE; + break; + case P_INVALID: + if (IS_ZERO_LSN(LSN(pagep)) && + pagep->pgno == PGNO_INVALID) { + pg_len = 0; + break; + } + /* FALLTHROUGH */ + default: + iv = P_IV(dbp, pagep); + pg_len = pginfo->db_pagesize; + break; + } + if (pg_len != 0 && (ret = db_cipher->decrypt(dbenv, + db_cipher->data, iv, ((u_int8_t *)pagep) + pg_off, + pg_len - pg_off)) != 0) + return (ret); + } + switch (pagep->type) { case P_INVALID: - return (__ham_pgin(dbenv, pg, pp, cookie)); + if (pginfo->type == DB_QUEUE) + return (__qam_pgin_out(dbenv, pg, pp, cookie)); + else + return (__ham_pgin(dbenv, dbp, pg, pp, cookie)); + case P_HASH: + case P_HASHMETA: + return (__ham_pgin(dbenv, dbp, pg, pp, cookie)); case P_BTREEMETA: case P_IBTREE: case P_IRECNO: @@ -86,14 +208,14 @@ __db_pgin(dbenv, pg, pp, cookie) case P_LDUP: case P_LRECNO: case P_OVERFLOW: - return (__bam_pgin(dbenv, pg, pp, cookie)); + return (__bam_pgin(dbenv, dbp, pg, pp, cookie)); case P_QAMMETA: case P_QAMDATA: return (__qam_pgin_out(dbenv, pg, pp, cookie)); default: break; } - return (__db_unknown_type(dbenv, "__db_pgin", ((PAGE *)pp)->type)); + return (__db_pgfmt(dbenv, pg)); } /* @@ -109,15 +231,33 @@ __db_pgout(dbenv, pg, pp, cookie) void *pp; DBT *cookie; { + DB dummydb, *dbp; + DB_CIPHER *db_cipher; DB_PGINFO *pginfo; + PAGE *pagep; + size_t pg_off, pg_len, sum_len; + int ret; + u_int8_t *chksum, *iv, *key; pginfo = (DB_PGINFO *)cookie->data; + pagep = (PAGE *)pp; - switch (((PAGE *)pp)->type) { + chksum = iv = key = NULL; + memset(&dummydb, 0, sizeof(DB)); + dbp = &dummydb; + dummydb.flags = pginfo->flags; + ret = 0; + switch (pagep->type) { + case P_INVALID: + if (pginfo->type == DB_QUEUE) + ret = __qam_pgin_out(dbenv, pg, pp, cookie); + else + ret = __ham_pgout(dbenv, dbp, pg, pp, cookie); + break; case P_HASH: case P_HASHMETA: - case P_INVALID: - return (__ham_pgout(dbenv, pg, pp, cookie)); + ret = __ham_pgout(dbenv, dbp, pg, pp, cookie); + break; case P_BTREEMETA: case P_IBTREE: case P_IRECNO: @@ -125,14 +265,73 @@ __db_pgout(dbenv, pg, pp, cookie) case P_LDUP: case P_LRECNO: case P_OVERFLOW: - return (__bam_pgout(dbenv, pg, pp, cookie)); + ret = __bam_pgout(dbenv, dbp, pg, pp, cookie); + break; case P_QAMMETA: case P_QAMDATA: - return (__qam_pgin_out(dbenv, pg, pp, cookie)); - default: + ret = __qam_pgin_out(dbenv, pg, pp, cookie); break; + default: + return (__db_pgfmt(dbenv, pg)); + } + if (ret) + return (ret); + + db_cipher = (DB_CIPHER *)dbenv->crypto_handle; + if (F_ISSET(dbp, DB_AM_ENCRYPT)) { + + DB_ASSERT(db_cipher != NULL); + DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM)); + + pg_off = P_OVERHEAD(dbp); + DB_ASSERT(db_cipher->adj_size(pg_off) == 0); + + key = db_cipher->mac_key; + + switch (pagep->type) { + case P_HASHMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the iv + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + iv = ((BTMETA *)pp)->iv; + pg_len = DBMETASIZE; + break; + default: + iv = P_IV(dbp, pagep); + pg_len = pginfo->db_pagesize; + break; + } + if ((ret = db_cipher->encrypt(dbenv, db_cipher->data, + iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0) + return (ret); + } + if (F_ISSET(dbp, DB_AM_CHKSUM)) { + switch (pagep->type) { + case P_HASHMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the chksum + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + chksum = ((BTMETA *)pp)->chksum; + sum_len = DBMETASIZE; + break; + default: + chksum = P_CHKSUM(dbp, pagep); + sum_len = pginfo->db_pagesize; + break; + } + __db_chksum(pp, sum_len, key, chksum); } - return (__db_unknown_type(dbenv, "__db_pgout", ((PAGE *)pp)->type)); + return (0); } /* @@ -169,11 +368,13 @@ __db_metaswap(pg) * __db_byteswap -- * Byteswap a page. * - * PUBLIC: int __db_byteswap __P((DB_ENV *, db_pgno_t, PAGE *, size_t, int)); + * PUBLIC: int __db_byteswap + * PUBLIC: __P((DB_ENV *, DB *, db_pgno_t, PAGE *, size_t, int)); */ int -__db_byteswap(dbenv, pg, h, pagesize, pgin) +__db_byteswap(dbenv, dbp, pg, h, pagesize, pgin) DB_ENV *dbenv; + DB *dbp; db_pgno_t pg; PAGE *h; size_t pagesize; @@ -183,11 +384,12 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) BKEYDATA *bk; BOVERFLOW *bo; RINTERNAL *ri; - db_indx_t i, len, tmp; + db_indx_t i, *inp, len, tmp; u_int8_t *p, *end; COMPQUIET(pg, 0); + inp = P_INP(dbp, h); if (pgin) { M_32_SWAP(h->lsn.file); M_32_SWAP(h->lsn.offset); @@ -202,14 +404,14 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) case P_HASH: for (i = 0; i < NUM_ENT(h); i++) { if (pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); - switch (HPAGE_TYPE(h, i)) { + switch (HPAGE_TYPE(dbp, h, i)) { case H_KEYDATA: break; case H_DUPLICATE: - len = LEN_HKEYDATA(h, pagesize, i); - p = HKEYDATA_DATA(P_ENTRY(h, i)); + len = LEN_HKEYDATA(dbp, h, pagesize, i); + p = HKEYDATA_DATA(P_ENTRY(dbp, h, i)); for (end = p + len; p < end;) { if (pgin) { P_16_SWAP(p); @@ -226,11 +428,11 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) } break; case H_OFFDUP: - p = HOFFPAGE_PGNO(P_ENTRY(h, i)); + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); SWAP32(p); /* pgno */ break; case H_OFFPAGE: - p = HOFFPAGE_PGNO(P_ENTRY(h, i)); + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); SWAP32(p); /* pgno */ SWAP32(p); /* tlen */ break; @@ -246,14 +448,14 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) */ if (!pgin) for (i = 0; i < NUM_ENT(h); i++) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); break; case P_LBTREE: case P_LDUP: case P_LRECNO: for (i = 0; i < NUM_ENT(h); i++) { if (pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); /* * In the case of on-page duplicates, key information @@ -261,17 +463,17 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) */ if (h->type == P_LBTREE && i > 1) { if (pgin) { - if (h->inp[i] == h->inp[i - 2]) + if (inp[i] == inp[i - 2]) continue; } else { - M_16_SWAP(h->inp[i]); - if (h->inp[i] == h->inp[i - 2]) + M_16_SWAP(inp[i]); + if (inp[i] == inp[i - 2]) continue; - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); } } - bk = GET_BKEYDATA(h, i); + bk = GET_BKEYDATA(dbp, h, i); switch (B_TYPE(bk->type)) { case B_KEYDATA: M_16_SWAP(bk->len); @@ -285,15 +487,15 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) } if (!pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); } break; case P_IBTREE: for (i = 0; i < NUM_ENT(h); i++) { if (pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); - bi = GET_BINTERNAL(h, i); + bi = GET_BINTERNAL(dbp, h, i); M_16_SWAP(bi->len); M_32_SWAP(bi->pgno); M_32_SWAP(bi->nrecs); @@ -310,20 +512,20 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) } if (!pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); } break; case P_IRECNO: for (i = 0; i < NUM_ENT(h); i++) { if (pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); - ri = GET_RINTERNAL(h, i); + ri = GET_RINTERNAL(dbp, h, i); M_32_SWAP(ri->pgno); M_32_SWAP(ri->nrecs); if (!pgin) - M_16_SWAP(h->inp[i]); + M_16_SWAP(inp[i]); } break; case P_OVERFLOW: @@ -331,7 +533,7 @@ __db_byteswap(dbenv, pg, h, pagesize, pgin) /* Nothing to do. */ break; default: - return (__db_unknown_type(dbenv, "__db_byteswap", h->type)); + return (__db_pgfmt(dbenv, pg)); } if (!pgin) { |