1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 */ 6/* 7 * Copyright (c) 1990, 1993, 1994, 1995, 1996 8 * Keith Bostic. All rights reserved. 9 */ 10/* 11 * Copyright (c) 1990, 1993, 1994, 1995 12 * The Regents of the University of California. All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id: db_conv.c,v 12.27 2008/04/19 15:30:35 mjc Exp $ 39 */ 40 41#include "db_config.h" 42 43#include "db_int.h" 44#include "dbinc/crypto.h" 45#include "dbinc/hmac.h" 46#include "dbinc/db_page.h" 47#include "dbinc/db_swap.h" 48#include "dbinc/btree.h" 49#include "dbinc/hash.h" 50#include "dbinc/log.h" 51#include "dbinc/qam.h" 52 53/* 54 * __db_pgin -- 55 * Primary page-swap routine. 56 * 57 * PUBLIC: int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *)); 58 */ 59int 60__db_pgin(dbenv, pg, pp, cookie) 61 DB_ENV *dbenv; 62 db_pgno_t pg; 63 void *pp; 64 DBT *cookie; 65{ 66 DB dummydb, *dbp; 67 DB_CIPHER *db_cipher; 68 DB_LSN not_used; 69 DB_PGINFO *pginfo; 70 ENV *env; 71 PAGE *pagep; 72 size_t sum_len; 73 int is_hmac, ret; 74 u_int8_t *chksum; 75 76 pginfo = (DB_PGINFO *)cookie->data; 77 env = dbenv->env; 78 pagep = (PAGE *)pp; 79 80 ret = is_hmac = 0; 81 chksum = NULL; 82 memset(&dummydb, 0, sizeof(DB)); 83 dbp = &dummydb; 84 dbp->dbenv = dbenv; 85 dbp->env = env; 86 dbp->flags = pginfo->flags; 87 dbp->pgsize = pginfo->db_pagesize; 88 db_cipher = env->crypto_handle; 89 switch (pagep->type) { 90 case P_HASHMETA: 91 case P_BTREEMETA: 92 case P_QAMMETA: 93 /* 94 * If checksumming is set on the meta-page, we must set 95 * it in the dbp. 96 */ 97 if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM)) 98 F_SET(dbp, DB_AM_CHKSUM); 99 else 100 F_CLR(dbp, DB_AM_CHKSUM); 101 if (((DBMETA *)pp)->encrypt_alg != 0 || 102 F_ISSET(dbp, DB_AM_ENCRYPT)) 103 is_hmac = 1; 104 /* 105 * !!! 106 * For all meta pages it is required that the chksum 107 * be at the same location. Use BTMETA to get to it 108 * for any meta type. 109 */ 110 chksum = ((BTMETA *)pp)->chksum; 111 sum_len = DBMETASIZE; 112 break; 113 case P_INVALID: 114 /* 115 * We assume that we've read a file hole if we have 116 * a zero LSN, zero page number and P_INVALID. Otherwise 117 * we have an invalid page that might contain real data. 118 */ 119 if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) { 120 sum_len = 0; 121 break; 122 } 123 /* FALLTHROUGH */ 124 default: 125 chksum = P_CHKSUM(dbp, pagep); 126 sum_len = pginfo->db_pagesize; 127 /* 128 * If we are reading in a non-meta page, then if we have 129 * a db_cipher then we are using hmac. 130 */ 131 is_hmac = CRYPTO_ON(env) ? 1 : 0; 132 break; 133 } 134 135 /* 136 * We expect a checksum error if there was a configuration problem. 137 * If there is no configuration problem and we don't get a match, 138 * it's fatal: panic the system. 139 */ 140 if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) { 141 if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0) 142 P_32_SWAP(chksum); 143 switch (ret = __db_check_chksum( 144 env, NULL, db_cipher, chksum, pp, sum_len, is_hmac)) { 145 case 0: 146 break; 147 case -1: 148 if (DBENV_LOGGING(env)) 149 (void)__db_cksum_log( 150 env, NULL, ¬_used, DB_FLUSH); 151 __db_errx(env, 152 "checksum error: page %lu: catastrophic recovery required", 153 (u_long)pg); 154 return (__env_panic(env, DB_RUNRECOVERY)); 155 default: 156 return (ret); 157 } 158 } 159 if ((ret = __db_decrypt_pg(env, dbp, pagep)) != 0) 160 return (ret); 161 switch (pagep->type) { 162 case P_INVALID: 163 if (pginfo->type == DB_QUEUE) 164 return (__qam_pgin_out(env, pg, pp, cookie)); 165 else 166 return (__ham_pgin(dbp, pg, pp, cookie)); 167 case P_HASH_UNSORTED: 168 case P_HASH: 169 case P_HASHMETA: 170 return (__ham_pgin(dbp, pg, pp, cookie)); 171 case P_BTREEMETA: 172 case P_IBTREE: 173 case P_IRECNO: 174 case P_LBTREE: 175 case P_LDUP: 176 case P_LRECNO: 177 case P_OVERFLOW: 178 return (__bam_pgin(dbp, pg, pp, cookie)); 179 case P_QAMMETA: 180 case P_QAMDATA: 181 return (__qam_pgin_out(env, pg, pp, cookie)); 182 default: 183 break; 184 } 185 return (__db_pgfmt(env, pg)); 186} 187 188/* 189 * __db_pgout -- 190 * Primary page-swap routine. 191 * 192 * PUBLIC: int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *)); 193 */ 194int 195__db_pgout(dbenv, pg, pp, cookie) 196 DB_ENV *dbenv; 197 db_pgno_t pg; 198 void *pp; 199 DBT *cookie; 200{ 201 DB dummydb, *dbp; 202 DB_PGINFO *pginfo; 203 ENV *env; 204 PAGE *pagep; 205 int ret; 206 207 pginfo = (DB_PGINFO *)cookie->data; 208 env = dbenv->env; 209 pagep = (PAGE *)pp; 210 211 memset(&dummydb, 0, sizeof(DB)); 212 dbp = &dummydb; 213 dbp->dbenv = dbenv; 214 dbp->env = env; 215 dbp->flags = pginfo->flags; 216 dbp->pgsize = pginfo->db_pagesize; 217 ret = 0; 218 switch (pagep->type) { 219 case P_INVALID: 220 if (pginfo->type == DB_QUEUE) 221 ret = __qam_pgin_out(env, pg, pp, cookie); 222 else 223 ret = __ham_pgout(dbp, pg, pp, cookie); 224 break; 225 case P_HASH: 226 case P_HASH_UNSORTED: 227 /* 228 * Support pgout of unsorted hash pages - since online 229 * replication upgrade can cause pages of this type to be 230 * written out. 231 * 232 * FALLTHROUGH 233 */ 234 case P_HASHMETA: 235 ret = __ham_pgout(dbp, pg, pp, cookie); 236 break; 237 case P_BTREEMETA: 238 case P_IBTREE: 239 case P_IRECNO: 240 case P_LBTREE: 241 case P_LDUP: 242 case P_LRECNO: 243 case P_OVERFLOW: 244 ret = __bam_pgout(dbp, pg, pp, cookie); 245 break; 246 case P_QAMMETA: 247 case P_QAMDATA: 248 ret = __qam_pgin_out(env, pg, pp, cookie); 249 break; 250 default: 251 return (__db_pgfmt(env, pg)); 252 } 253 if (ret) 254 return (ret); 255 256 return (__db_encrypt_and_checksum_pg(env, dbp, pagep)); 257} 258 259/* 260 * __db_decrypt_pg -- 261 * Utility function to decrypt a db page. 262 * 263 * PUBLIC: int __db_decrypt_pg __P((ENV *, DB *, PAGE *)); 264 */ 265int 266__db_decrypt_pg (env, dbp, pagep) 267 ENV *env; 268 DB *dbp; 269 PAGE *pagep; 270{ 271 DB_CIPHER *db_cipher; 272 size_t pg_len, pg_off; 273 u_int8_t *iv; 274 int ret; 275 276 db_cipher = env->crypto_handle; 277 ret = 0; 278 iv = NULL; 279 if (F_ISSET(dbp, DB_AM_ENCRYPT)) { 280 DB_ASSERT(env, db_cipher != NULL); 281 DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM)); 282 283 pg_off = P_OVERHEAD(dbp); 284 DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0); 285 286 switch (pagep->type) { 287 case P_HASHMETA: 288 case P_BTREEMETA: 289 case P_QAMMETA: 290 /* 291 * !!! 292 * For all meta pages it is required that the iv 293 * be at the same location. Use BTMETA to get to it 294 * for any meta type. 295 */ 296 iv = ((BTMETA *)pagep)->iv; 297 pg_len = DBMETASIZE; 298 break; 299 case P_INVALID: 300 if (IS_ZERO_LSN(LSN(pagep)) && 301 pagep->pgno == PGNO_INVALID) { 302 pg_len = 0; 303 break; 304 } 305 /* FALLTHROUGH */ 306 default: 307 iv = P_IV(dbp, pagep); 308 pg_len = dbp->pgsize; 309 break; 310 } 311 if (pg_len != 0) 312 ret = db_cipher->decrypt(env, db_cipher->data, 313 iv, ((u_int8_t *)pagep) + pg_off, 314 pg_len - pg_off); 315 } 316 return (ret); 317} 318 319/* 320 * __db_encrypt_and_checksum_pg -- 321 * Utility function to encrypt and checksum a db page. 322 * 323 * PUBLIC: int __db_encrypt_and_checksum_pg 324 * PUBLIC: __P((ENV *, DB *, PAGE *)); 325 */ 326int 327__db_encrypt_and_checksum_pg (env, dbp, pagep) 328 ENV *env; 329 DB *dbp; 330 PAGE *pagep; 331{ 332 DB_CIPHER *db_cipher; 333 int ret; 334 size_t pg_off, pg_len, sum_len; 335 u_int8_t *chksum, *iv, *key; 336 337 chksum = iv = key = NULL; 338 db_cipher = env->crypto_handle; 339 340 if (F_ISSET(dbp, DB_AM_ENCRYPT)) { 341 DB_ASSERT(env, db_cipher != NULL); 342 DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM)); 343 344 pg_off = P_OVERHEAD(dbp); 345 DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0); 346 347 key = db_cipher->mac_key; 348 349 switch (pagep->type) { 350 case P_HASHMETA: 351 case P_BTREEMETA: 352 case P_QAMMETA: 353 /* 354 * !!! 355 * For all meta pages it is required that the iv 356 * be at the same location. Use BTMETA to get to it 357 * for any meta type. 358 */ 359 iv = ((BTMETA *)pagep)->iv; 360 pg_len = DBMETASIZE; 361 break; 362 default: 363 iv = P_IV(dbp, pagep); 364 pg_len = dbp->pgsize; 365 break; 366 } 367 if ((ret = db_cipher->encrypt(env, db_cipher->data, 368 iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0) 369 return (ret); 370 } 371 if (F_ISSET(dbp, DB_AM_CHKSUM)) { 372 switch (pagep->type) { 373 case P_HASHMETA: 374 case P_BTREEMETA: 375 case P_QAMMETA: 376 /* 377 * !!! 378 * For all meta pages it is required that the chksum 379 * be at the same location. Use BTMETA to get to it 380 * for any meta type. 381 */ 382 chksum = ((BTMETA *)pagep)->chksum; 383 sum_len = DBMETASIZE; 384 break; 385 default: 386 chksum = P_CHKSUM(dbp, pagep); 387 sum_len = dbp->pgsize; 388 break; 389 } 390 __db_chksum(NULL, (u_int8_t *)pagep, sum_len, key, chksum); 391 if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT)) 392 P_32_SWAP(chksum); 393 } 394 return (0); 395} 396 397/* 398 * __db_metaswap -- 399 * Byteswap the common part of the meta-data page. 400 * 401 * PUBLIC: void __db_metaswap __P((PAGE *)); 402 */ 403void 404__db_metaswap(pg) 405 PAGE *pg; 406{ 407 u_int8_t *p; 408 409 p = (u_int8_t *)pg; 410 411 /* Swap the meta-data information. */ 412 SWAP32(p); /* lsn.file */ 413 SWAP32(p); /* lsn.offset */ 414 SWAP32(p); /* pgno */ 415 SWAP32(p); /* magic */ 416 SWAP32(p); /* version */ 417 SWAP32(p); /* pagesize */ 418 p += 4; /* unused, page type, unused, unused */ 419 SWAP32(p); /* free */ 420 SWAP32(p); /* alloc_lsn part 1 */ 421 SWAP32(p); /* alloc_lsn part 2 */ 422 SWAP32(p); /* cached key count */ 423 SWAP32(p); /* cached record count */ 424 SWAP32(p); /* flags */ 425} 426 427/* 428 * __db_byteswap -- 429 * Byteswap an ordinary database page. 430 * 431 * PUBLIC: int __db_byteswap 432 * PUBLIC: __P((DB *, db_pgno_t, PAGE *, size_t, int)); 433 */ 434int 435__db_byteswap(dbp, pg, h, pagesize, pgin) 436 DB *dbp; 437 db_pgno_t pg; 438 PAGE *h; 439 size_t pagesize; 440 int pgin; 441{ 442 ENV *env; 443 BINTERNAL *bi; 444 BKEYDATA *bk; 445 BOVERFLOW *bo; 446 RINTERNAL *ri; 447 db_indx_t i, *inp, len, tmp; 448 u_int8_t *end, *p, *pgend; 449 450 if (pagesize == 0) 451 return (0); 452 453 env = dbp->env; 454 455 if (pgin) { 456 M_32_SWAP(h->lsn.file); 457 M_32_SWAP(h->lsn.offset); 458 M_32_SWAP(h->pgno); 459 M_32_SWAP(h->prev_pgno); 460 M_32_SWAP(h->next_pgno); 461 M_16_SWAP(h->entries); 462 M_16_SWAP(h->hf_offset); 463 } 464 465 pgend = (u_int8_t *)h + pagesize; 466 467 inp = P_INP(dbp, h); 468 if ((u_int8_t *)inp >= pgend) 469 goto out; 470 471 switch (TYPE(h)) { 472 case P_HASH_UNSORTED: 473 case P_HASH: 474 for (i = 0; i < NUM_ENT(h); i++) { 475 if (pgin) 476 M_16_SWAP(inp[i]); 477 478 if (P_ENTRY(dbp, h, i) >= pgend) 479 continue; 480 481 switch (HPAGE_TYPE(dbp, h, i)) { 482 case H_KEYDATA: 483 break; 484 case H_DUPLICATE: 485 len = LEN_HKEYDATA(dbp, h, pagesize, i); 486 p = HKEYDATA_DATA(P_ENTRY(dbp, h, i)); 487 for (end = p + len; p < end;) { 488 if (pgin) { 489 P_16_SWAP(p); 490 memcpy(&tmp, 491 p, sizeof(db_indx_t)); 492 p += sizeof(db_indx_t); 493 } else { 494 memcpy(&tmp, 495 p, sizeof(db_indx_t)); 496 SWAP16(p); 497 } 498 p += tmp; 499 SWAP16(p); 500 } 501 break; 502 case H_OFFDUP: 503 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); 504 SWAP32(p); /* pgno */ 505 break; 506 case H_OFFPAGE: 507 p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); 508 SWAP32(p); /* pgno */ 509 SWAP32(p); /* tlen */ 510 break; 511 default: 512 return (__db_pgfmt(env, pg)); 513 } 514 515 } 516 517 /* 518 * The offsets in the inp array are used to determine 519 * the size of entries on a page; therefore they 520 * cannot be converted until we've done all the 521 * entries. 522 */ 523 if (!pgin) 524 for (i = 0; i < NUM_ENT(h); i++) 525 M_16_SWAP(inp[i]); 526 break; 527 case P_LBTREE: 528 case P_LDUP: 529 case P_LRECNO: 530 for (i = 0; i < NUM_ENT(h); i++) { 531 if (pgin) 532 M_16_SWAP(inp[i]); 533 534 /* 535 * In the case of on-page duplicates, key information 536 * should only be swapped once. 537 */ 538 if (h->type == P_LBTREE && i > 1) { 539 if (pgin) { 540 if (inp[i] == inp[i - 2]) 541 continue; 542 } else { 543 M_16_SWAP(inp[i]); 544 if (inp[i] == inp[i - 2]) 545 continue; 546 M_16_SWAP(inp[i]); 547 } 548 } 549 550 bk = GET_BKEYDATA(dbp, h, i); 551 if ((u_int8_t *)bk >= pgend) 552 continue; 553 switch (B_TYPE(bk->type)) { 554 case B_KEYDATA: 555 M_16_SWAP(bk->len); 556 break; 557 case B_DUPLICATE: 558 case B_OVERFLOW: 559 bo = (BOVERFLOW *)bk; 560 M_32_SWAP(bo->pgno); 561 M_32_SWAP(bo->tlen); 562 break; 563 default: 564 return (__db_pgfmt(env, pg)); 565 } 566 567 if (!pgin) 568 M_16_SWAP(inp[i]); 569 } 570 break; 571 case P_IBTREE: 572 for (i = 0; i < NUM_ENT(h); i++) { 573 if (pgin) 574 M_16_SWAP(inp[i]); 575 576 bi = GET_BINTERNAL(dbp, h, i); 577 if ((u_int8_t *)bi >= pgend) 578 continue; 579 580 M_16_SWAP(bi->len); 581 M_32_SWAP(bi->pgno); 582 M_32_SWAP(bi->nrecs); 583 584 switch (B_TYPE(bi->type)) { 585 case B_KEYDATA: 586 break; 587 case B_DUPLICATE: 588 case B_OVERFLOW: 589 bo = (BOVERFLOW *)bi->data; 590 M_32_SWAP(bo->pgno); 591 M_32_SWAP(bo->tlen); 592 break; 593 default: 594 return (__db_pgfmt(env, pg)); 595 } 596 597 if (!pgin) 598 M_16_SWAP(inp[i]); 599 } 600 break; 601 case P_IRECNO: 602 for (i = 0; i < NUM_ENT(h); i++) { 603 if (pgin) 604 M_16_SWAP(inp[i]); 605 606 ri = GET_RINTERNAL(dbp, h, i); 607 if ((u_int8_t *)ri >= pgend) 608 continue; 609 610 M_32_SWAP(ri->pgno); 611 M_32_SWAP(ri->nrecs); 612 613 if (!pgin) 614 M_16_SWAP(inp[i]); 615 } 616 break; 617 case P_OVERFLOW: 618 case P_INVALID: 619 /* Nothing to do. */ 620 break; 621 default: 622 return (__db_pgfmt(env, pg)); 623 } 624 625out: if (!pgin) { 626 /* Swap the header information. */ 627 M_32_SWAP(h->lsn.file); 628 M_32_SWAP(h->lsn.offset); 629 M_32_SWAP(h->pgno); 630 M_32_SWAP(h->prev_pgno); 631 M_32_SWAP(h->next_pgno); 632 M_16_SWAP(h->entries); 633 M_16_SWAP(h->hf_offset); 634 } 635 return (0); 636} 637 638/* 639 * __db_pageswap -- 640 * Byteswap any database page. Normally, the page to be swapped will be 641 * referenced by the "pp" argument and the pdata argument will be NULL. 642 * This function is also called by automatically generated log functions, 643 * where the page may be split into separate header and data parts. In 644 * that case, pdata is not NULL we reconsitute 645 * 646 * PUBLIC: int __db_pageswap 647 * PUBLIC: __P((DB *, void *, size_t, DBT *, int)); 648 */ 649int 650__db_pageswap(dbp, pp, len, pdata, pgin) 651 DB *dbp; 652 void *pp; 653 size_t len; 654 DBT *pdata; 655 int pgin; 656{ 657 ENV *env; 658 db_pgno_t pg; 659 size_t pgsize; 660 void *pgcopy; 661 int ret; 662 u_int16_t hoffset; 663 664 env = dbp->env; 665 666 switch (TYPE(pp)) { 667 case P_BTREEMETA: 668 return (__bam_mswap(env, pp)); 669 670 case P_HASHMETA: 671 return (__ham_mswap(env, pp)); 672 673 case P_QAMMETA: 674 return (__qam_mswap(env, pp)); 675 676 case P_INVALID: 677 case P_OVERFLOW: 678 /* 679 * We may have been passed an invalid page, or an overflow page 680 * where fields like hoffset have a special meaning. In that 681 * case, no swapping of the page data is required, just the 682 * fields in the page header. 683 */ 684 pdata = NULL; 685 break; 686 687 default: 688 break; 689 } 690 691 if (pgin) { 692 P_32_COPYSWAP(&PGNO(pp), &pg); 693 P_16_COPYSWAP(&HOFFSET(pp), &hoffset); 694 } else { 695 pg = PGNO(pp); 696 hoffset = HOFFSET(pp); 697 } 698 699 if (pdata == NULL) 700 ret = __db_byteswap(dbp, pg, (PAGE *)pp, len, pgin); 701 else { 702 pgsize = hoffset + pdata->size; 703 if ((ret = __os_malloc(env, pgsize, &pgcopy)) != 0) 704 return (ret); 705 memset(pgcopy, 0, pgsize); 706 memcpy(pgcopy, pp, len); 707 memcpy((u_int8_t *)pgcopy + hoffset, pdata->data, pdata->size); 708 709 ret = __db_byteswap(dbp, pg, (PAGE *)pgcopy, pgsize, pgin); 710 memcpy(pp, pgcopy, len); 711 712 /* 713 * If we are swapping data to be written to the log, we can't 714 * overwrite the buffer that was passed in: it may be a pointer 715 * into a page in cache. We set DB_DBT_APPMALLOC here so that 716 * the calling code can free the memory we allocate here. 717 */ 718 if (!pgin) { 719 if ((ret = 720 __os_malloc(env, pdata->size, &pdata->data)) != 0) { 721 __os_free(env, pgcopy); 722 return (ret); 723 } 724 F_SET(pdata, DB_DBT_APPMALLOC); 725 } 726 memcpy(pdata->data, (u_int8_t *)pgcopy + hoffset, pdata->size); 727 __os_free(env, pgcopy); 728 } 729 730 return (ret); 731} 732