diff options
Diffstat (limited to 'src/db/db_open.c')
-rw-r--r-- | src/db/db_open.c | 142 |
1 files changed, 70 insertions, 72 deletions
diff --git a/src/db/db_open.c b/src/db/db_open.c index fefda48f..21074b15 100644 --- a/src/db/db_open.c +++ b/src/db/db_open.c @@ -1,7 +1,7 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2015 Oracle and/or its affiliates. All rights reserved. * * $Id$ */ @@ -119,6 +119,15 @@ __db_open(dbp, ip, txn, fname, dname, type, flags, mode, meta_pgno) goto err; /* + * Silently disabled blobs in databases that cannot support them. + * Most illegal configurations will have already been caught, this + * is to allow a user to set an environment wide blob threshold, but + * not have to explicitly turn it off for in-memory or queue databases. + */ + if (!__db_blobs_enabled(dbp)) + dbp->blob_threshold = 0; + + /* * If both fname and subname are NULL, it's always a create, so make * sure that we have both DB_CREATE and a type specified. It would * be nice if this checking were done in __db_open where most of the @@ -259,6 +268,11 @@ __db_open(dbp, ip, txn, fname, dname, type, flags, mode, meta_pgno) if (ret != 0) goto err; + if (dbp->blob_file_id != 0) + if ((ret = __blob_make_sub_dir(env, &dbp->blob_sub_dir, + dbp->blob_file_id, dbp->blob_sdb_id)) != 0) + goto err; + #ifdef HAVE_PARTITION if (dbp->p_internal != NULL && (ret = __partition_open(dbp, ip, txn, fname, type, flags, mode, 1)) != 0) @@ -432,8 +446,10 @@ err: return (ret); /* * __db_chk_meta -- - * Take a buffer containing a meta-data page and check it for a valid LSN, - * checksum (and verify the checksum if necessary) and possibly decrypt it. + * Validate a buffer containing a possible meta-data page. It is + * byte-swapped as necessary and checked for having a valid magic number. + * If it does, then it can validate the LSN, checksum (if necessary), + * and possibly decrypt it. * * Return 0 on success, >0 (errno). * @@ -447,44 +463,64 @@ __db_chk_meta(env, dbp, meta, flags) u_int32_t flags; { DB_LSN swap_lsn; - int is_hmac, ret, swapped; - u_int32_t magic, orig_chk; + int is_hmac, needs_swap, ret; + u_int32_t magic; u_int8_t *chksum; ret = 0; - swapped = 0; + needs_swap = 0; + /* + * We can verify that this is some kind of db now, before any potential + * decryption, because the first P_OVERHEAD() bytes of most pages are + * cleartext. This gets called both before and after swapping, so we + * need to check for byte swapping ourselves. + */ + magic = meta->magic; +magic_retry: + switch (magic) { + case DB_BTREEMAGIC: + case DB_HASHMAGIC: + case DB_HEAPMAGIC: + case DB_QAMMAGIC: + case DB_RENAMEMAGIC: + break; + default: + if (needs_swap) + /* It's already been swapped, so it isn't a BDB file. */ + return (EINVAL); + M_32_SWAP(magic); + needs_swap = 1; + goto magic_retry; + } + + if (LOGGING_ON(env) && !LF_ISSET(DB_CHK_NOLSN)) { + swap_lsn = meta->lsn; + if (needs_swap) { + M_32_SWAP(swap_lsn.file); + M_32_SWAP(swap_lsn.offset); + } + if (!IS_REP_CLIENT(env) && !IS_NOT_LOGGED_LSN(swap_lsn) && + !IS_ZERO_LSN(swap_lsn) && (ret = + __log_check_page_lsn(env, dbp, &swap_lsn)) != 0) + return (ret); + } if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) { if (dbp != NULL) F_SET(dbp, DB_AM_CHKSUM); - - is_hmac = meta->encrypt_alg == 0 ? 0 : 1; - chksum = ((BTMETA *)meta)->chksum; - - /* - * If we need to swap, the checksum function overwrites the - * original checksum with 0, so we need to save a copy of the - * original for swapping later. - */ - orig_chk = *(u_int32_t *)chksum; - /* * We cannot add this to __db_metaswap because that gets done * later after we've verified the checksum or decrypted. */ if (LF_ISSET(DB_CHK_META)) { - swapped = 0; -chk_retry: if ((ret = + is_hmac = meta->encrypt_alg != 0; + chksum = ((BTMETA *)meta)->chksum; + if (needs_swap && !is_hmac) + M_32_SWAP(*(u_int32_t *)chksum); + if ((ret = __db_check_chksum(env, NULL, env->crypto_handle, - chksum, meta, DBMETASIZE, is_hmac)) != 0) { - if (is_hmac || swapped) - return (DB_CHKSUM_FAIL); - - M_32_SWAP(orig_chk); - swapped = 1; - *(u_int32_t *)chksum = orig_chk; - goto chk_retry; - } + chksum, meta, DBMETASIZE, is_hmac)) != 0) + return (DB_CHKSUM_FAIL); } } else if (dbp != NULL) F_CLR(dbp, DB_AM_CHKSUM); @@ -492,44 +528,8 @@ chk_retry: if ((ret = #ifdef HAVE_CRYPTO if (__crypto_decrypt_meta(env, dbp, (u_int8_t *)meta, LF_ISSET(DB_CHK_META)) != 0) - ret = DB_CHKSUM_FAIL; - else + ret = DB_CHKSUM_FAIL; #endif - - /* Now that we're decrypted, we can check LSN. */ - if (LOGGING_ON(env) && !LF_ISSET(DB_CHK_NOLSN)) { - /* - * This gets called both before and after swapping, so we - * need to check ourselves. If we already swapped it above, - * we'll know that here. - */ - - swap_lsn = meta->lsn; - magic = meta->magic; -lsn_retry: - if (swapped) { - M_32_SWAP(swap_lsn.file); - M_32_SWAP(swap_lsn.offset); - M_32_SWAP(magic); - } - switch (magic) { - case DB_BTREEMAGIC: - case DB_HASHMAGIC: - case DB_HEAPMAGIC: - case DB_QAMMAGIC: - case DB_RENAMEMAGIC: - break; - default: - if (swapped) - return (EINVAL); - swapped = 1; - goto lsn_retry; - } - if (!IS_REP_CLIENT(env) && - !IS_NOT_LOGGED_LSN(swap_lsn) && !IS_ZERO_LSN(swap_lsn)) - /* Need to do check. */ - ret = __log_check_page_lsn(env, dbp, &swap_lsn); - } return (ret); } @@ -598,7 +598,6 @@ swap_retry: } /* - * We can only check the meta page if we are sure we have a meta page. * If it is random data, then this check can fail. So only now can we * checksum and decrypt. Don't distinguish between configuration and * checksum match errors here, because we haven't opened the database @@ -606,9 +605,9 @@ swap_retry: * If DB_SKIP_CHK is set, it means the checksum was already checked * and the page was already decrypted. */ - if (!LF_ISSET(DB_SKIP_CHK) && + if (!LF_ISSET(DB_SKIP_CHK) && (ret = __db_chk_meta(env, dbp, meta, flags)) != 0) { - if (ret == DB_CHKSUM_FAIL) + if (ret == DB_CHKSUM_FAIL) __db_errx(env, DB_STR_A("0640", "%s: metadata page checksum error", "%s"), name); goto bad_format; @@ -669,10 +668,9 @@ swap_retry: } if (FLD_ISSET(meta->metaflags, - DBMETA_PART_RANGE | DBMETA_PART_CALLBACK)) - if ((ret = - __partition_init(dbp, meta->metaflags)) != 0) - return (ret); + DBMETA_PART_RANGE | DBMETA_PART_CALLBACK) && + (ret = __partition_init(dbp, meta->metaflags)) != 0) + return (ret); return (0); bad_format: |