db_conv.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:12k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. /*
  8.  * Copyright (c) 1990, 1993, 1994, 1995, 1996
  9.  * Keith Bostic.  All rights reserved.
  10.  */
  11. /*
  12.  * Copyright (c) 1990, 1993, 1994, 1995
  13.  * The Regents of the University of California.  All rights reserved.
  14.  *
  15.  * Redistribution and use in source and binary forms, with or without
  16.  * modification, are permitted provided that the following conditions
  17.  * are met:
  18.  * 1. Redistributions of source code must retain the above copyright
  19.  *    notice, this list of conditions and the following disclaimer.
  20.  * 2. Redistributions in binary form must reproduce the above copyright
  21.  *    notice, this list of conditions and the following disclaimer in the
  22.  *    documentation and/or other materials provided with the distribution.
  23.  * 3. Neither the name of the University nor the names of its contributors
  24.  *    may be used to endorse or promote products derived from this software
  25.  *    without specific prior written permission.
  26.  *
  27.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37.  * SUCH DAMAGE.
  38.  */
  39. #include "db_config.h"
  40. #ifndef lint
  41. static const char revid[] = "$Id: db_conv.c,v 11.38 2002/08/15 03:00:13 bostic Exp $";
  42. #endif /* not lint */
  43. #ifndef NO_SYSTEM_INCLUDES
  44. #include <sys/types.h>
  45. #include <string.h>
  46. #endif
  47. #include "db_int.h"
  48. #include "dbinc/crypto.h"
  49. #include "dbinc/hmac.h"
  50. #include "dbinc/db_page.h"
  51. #include "dbinc/db_swap.h"
  52. #include "dbinc/btree.h"
  53. #include "dbinc/hash.h"
  54. #include "dbinc/log.h"
  55. #include "dbinc/qam.h"
  56. /*
  57.  * __db_pgin --
  58.  * Primary page-swap routine.
  59.  *
  60.  * PUBLIC: int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
  61.  */
  62. int
  63. __db_pgin(dbenv, pg, pp, cookie)
  64. DB_ENV *dbenv;
  65. db_pgno_t pg;
  66. void *pp;
  67. DBT *cookie;
  68. {
  69. DB dummydb, *dbp;
  70. DB_PGINFO *pginfo;
  71. DB_CIPHER *db_cipher;
  72. DB_LSN not_used;
  73. PAGE *pagep;
  74. size_t pg_off, pg_len, sum_len;
  75. int is_hmac, ret;
  76. u_int8_t *chksum, *iv;
  77. pginfo = (DB_PGINFO *)cookie->data;
  78. pagep = (PAGE *)pp;
  79. ret = is_hmac = 0;
  80. chksum = iv = NULL;
  81. memset(&dummydb, 0, sizeof(DB));
  82. dbp = &dummydb;
  83. dummydb.flags = pginfo->flags;
  84. db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
  85. switch (pagep->type) {
  86. case P_HASHMETA:
  87. case P_BTREEMETA:
  88. case P_QAMMETA:
  89. /*
  90.  * If checksumming is set on the meta-page, we must set
  91.  * it in the dbp.
  92.  */
  93. if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
  94. F_SET(dbp, DB_AM_CHKSUM);
  95. if (((DBMETA *)pp)->encrypt_alg != 0 ||
  96.     F_ISSET(dbp, DB_AM_ENCRYPT))
  97. is_hmac = 1;
  98. /*
  99.  * !!!
  100.  * For all meta pages it is required that the chksum
  101.  * be at the same location.  Use BTMETA to get to it
  102.  * for any meta type.
  103.  */
  104. chksum = ((BTMETA *)pp)->chksum;
  105. sum_len = DBMETASIZE;
  106. break;
  107. case P_INVALID:
  108. /*
  109.  * We assume that we've read a file hole if we have
  110.  * a zero LSN, zero page number and P_INVALID.  Otherwise
  111.  * we have an invalid page that might contain real data.
  112.  */
  113. if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) {
  114. sum_len = 0;
  115. break;
  116. }
  117. /* FALLTHROUGH */
  118. default:
  119. chksum = P_CHKSUM(dbp, pagep);
  120. sum_len = pginfo->db_pagesize;
  121. /*
  122.  * If we are reading in a non-meta page, then if we have
  123.  * a db_cipher then we are using hmac.
  124.  */
  125. is_hmac = CRYPTO_ON(dbenv) ? 1 : 0;
  126. break;
  127. }
  128. /*
  129.  * We expect a checksum error if there was a configuration problem.
  130.  * If there is no configuration problem and we don't get a match,
  131.  * it's fatal: panic the system.
  132.  */
  133. if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0)
  134. switch (ret = __db_check_chksum(
  135.     dbenv, db_cipher, chksum, pp, sum_len, is_hmac)) {
  136. case 0:
  137. break;
  138. case -1:
  139. if (DBENV_LOGGING(dbenv))
  140. __db_cksum_log(
  141.     dbenv, NULL, &not_used, DB_FLUSH);
  142. __db_err(dbenv,
  143.     "checksum error: catastrophic recovery required");
  144. return (__db_panic(dbenv, DB_RUNRECOVERY));
  145. default:
  146. return (ret);
  147. }
  148. if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
  149. DB_ASSERT(db_cipher != NULL);
  150. DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
  151. pg_off = P_OVERHEAD(dbp);
  152. DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
  153. switch (pagep->type) {
  154. case P_HASHMETA:
  155. case P_BTREEMETA:
  156. case P_QAMMETA:
  157. /*
  158.  * !!!
  159.  * For all meta pages it is required that the iv
  160.  * be at the same location.  Use BTMETA to get to it
  161.  * for any meta type.
  162.  */
  163. iv = ((BTMETA *)pp)->iv;
  164. pg_len = DBMETASIZE;
  165. break;
  166. case P_INVALID:
  167. if (IS_ZERO_LSN(LSN(pagep)) &&
  168.     pagep->pgno == PGNO_INVALID) {
  169. pg_len = 0;
  170. break;
  171. }
  172. /* FALLTHROUGH */
  173. default:
  174. iv = P_IV(dbp, pagep);
  175. pg_len = pginfo->db_pagesize;
  176. break;
  177. }
  178. if (pg_len != 0 && (ret = db_cipher->decrypt(dbenv,
  179.     db_cipher->data, iv, ((u_int8_t *)pagep) + pg_off,
  180.     pg_len - pg_off)) != 0)
  181. return (ret);
  182. }
  183. switch (pagep->type) {
  184. case P_INVALID:
  185. if (pginfo->type == DB_QUEUE)
  186. return (__qam_pgin_out(dbenv, pg, pp, cookie));
  187. else
  188. return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
  189. case P_HASH:
  190. case P_HASHMETA:
  191. return (__ham_pgin(dbenv, dbp, pg, pp, cookie));
  192. case P_BTREEMETA:
  193. case P_IBTREE:
  194. case P_IRECNO:
  195. case P_LBTREE:
  196. case P_LDUP:
  197. case P_LRECNO:
  198. case P_OVERFLOW:
  199. return (__bam_pgin(dbenv, dbp, pg, pp, cookie));
  200. case P_QAMMETA:
  201. case P_QAMDATA:
  202. return (__qam_pgin_out(dbenv, pg, pp, cookie));
  203. default:
  204. break;
  205. }
  206. return (__db_pgfmt(dbenv, pg));
  207. }
  208. /*
  209.  * __db_pgout --
  210.  * Primary page-swap routine.
  211.  *
  212.  * PUBLIC: int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
  213.  */
  214. int
  215. __db_pgout(dbenv, pg, pp, cookie)
  216. DB_ENV *dbenv;
  217. db_pgno_t pg;
  218. void *pp;
  219. DBT *cookie;
  220. {
  221. DB dummydb, *dbp;
  222. DB_CIPHER *db_cipher;
  223. DB_PGINFO *pginfo;
  224. PAGE *pagep;
  225. size_t pg_off, pg_len, sum_len;
  226. int ret;
  227. u_int8_t *chksum, *iv, *key;
  228. pginfo = (DB_PGINFO *)cookie->data;
  229. pagep = (PAGE *)pp;
  230. chksum = iv = key = NULL;
  231. memset(&dummydb, 0, sizeof(DB));
  232. dbp = &dummydb;
  233. dummydb.flags = pginfo->flags;
  234. ret = 0;
  235. switch (pagep->type) {
  236. case P_INVALID:
  237. if (pginfo->type == DB_QUEUE)
  238. ret = __qam_pgin_out(dbenv, pg, pp, cookie);
  239. else
  240. ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
  241. break;
  242. case P_HASH:
  243. case P_HASHMETA:
  244. ret = __ham_pgout(dbenv, dbp, pg, pp, cookie);
  245. break;
  246. case P_BTREEMETA:
  247. case P_IBTREE:
  248. case P_IRECNO:
  249. case P_LBTREE:
  250. case P_LDUP:
  251. case P_LRECNO:
  252. case P_OVERFLOW:
  253. ret = __bam_pgout(dbenv, dbp, pg, pp, cookie);
  254. break;
  255. case P_QAMMETA:
  256. case P_QAMDATA:
  257. ret = __qam_pgin_out(dbenv, pg, pp, cookie);
  258. break;
  259. default:
  260. return (__db_pgfmt(dbenv, pg));
  261. }
  262. if (ret)
  263. return (ret);
  264. db_cipher = (DB_CIPHER *)dbenv->crypto_handle;
  265. if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
  266. DB_ASSERT(db_cipher != NULL);
  267. DB_ASSERT(F_ISSET(dbp, DB_AM_CHKSUM));
  268. pg_off = P_OVERHEAD(dbp);
  269. DB_ASSERT(db_cipher->adj_size(pg_off) == 0);
  270. key = db_cipher->mac_key;
  271. switch (pagep->type) {
  272. case P_HASHMETA:
  273. case P_BTREEMETA:
  274. case P_QAMMETA:
  275. /*
  276.  * !!!
  277.  * For all meta pages it is required that the iv
  278.  * be at the same location.  Use BTMETA to get to it
  279.  * for any meta type.
  280.  */
  281. iv = ((BTMETA *)pp)->iv;
  282. pg_len = DBMETASIZE;
  283. break;
  284. default:
  285. iv = P_IV(dbp, pagep);
  286. pg_len = pginfo->db_pagesize;
  287. break;
  288. }
  289. if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,
  290.     iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0)
  291. return (ret);
  292. }
  293. if (F_ISSET(dbp, DB_AM_CHKSUM)) {
  294. switch (pagep->type) {
  295. case P_HASHMETA:
  296. case P_BTREEMETA:
  297. case P_QAMMETA:
  298. /*
  299.  * !!!
  300.  * For all meta pages it is required that the chksum
  301.  * be at the same location.  Use BTMETA to get to it
  302.  * for any meta type.
  303.  */
  304. chksum = ((BTMETA *)pp)->chksum;
  305. sum_len = DBMETASIZE;
  306. break;
  307. default:
  308. chksum = P_CHKSUM(dbp, pagep);
  309. sum_len = pginfo->db_pagesize;
  310. break;
  311. }
  312. __db_chksum(pp, sum_len, key, chksum);
  313. }
  314. return (0);
  315. }
  316. /*
  317.  * __db_metaswap --
  318.  * Byteswap the common part of the meta-data page.
  319.  *
  320.  * PUBLIC: void __db_metaswap __P((PAGE *));
  321.  */
  322. void
  323. __db_metaswap(pg)
  324. PAGE *pg;
  325. {
  326. u_int8_t *p;
  327. p = (u_int8_t *)pg;
  328. /* Swap the meta-data information. */
  329. SWAP32(p); /* lsn.file */
  330. SWAP32(p); /* lsn.offset */
  331. SWAP32(p); /* pgno */
  332. SWAP32(p); /* magic */
  333. SWAP32(p); /* version */
  334. SWAP32(p); /* pagesize */
  335. p += 4; /* unused, page type, unused, unused */
  336. SWAP32(p); /* free */
  337. SWAP32(p); /* alloc_lsn part 1 */
  338. SWAP32(p); /* alloc_lsn part 2 */
  339. SWAP32(p); /* cached key count */
  340. SWAP32(p); /* cached record count */
  341. SWAP32(p); /* flags */
  342. }
  343. /*
  344.  * __db_byteswap --
  345.  * Byteswap a page.
  346.  *
  347.  * PUBLIC: int __db_byteswap
  348.  * PUBLIC:         __P((DB_ENV *, DB *, db_pgno_t, PAGE *, size_t, int));
  349.  */
  350. int
  351. __db_byteswap(dbenv, dbp, pg, h, pagesize, pgin)
  352. DB_ENV *dbenv;
  353. DB *dbp;
  354. db_pgno_t pg;
  355. PAGE *h;
  356. size_t pagesize;
  357. int pgin;
  358. {
  359. BINTERNAL *bi;
  360. BKEYDATA *bk;
  361. BOVERFLOW *bo;
  362. RINTERNAL *ri;
  363. db_indx_t i, *inp, len, tmp;
  364. u_int8_t *p, *end;
  365. COMPQUIET(pg, 0);
  366. inp = P_INP(dbp, h);
  367. if (pgin) {
  368. M_32_SWAP(h->lsn.file);
  369. M_32_SWAP(h->lsn.offset);
  370. M_32_SWAP(h->pgno);
  371. M_32_SWAP(h->prev_pgno);
  372. M_32_SWAP(h->next_pgno);
  373. M_16_SWAP(h->entries);
  374. M_16_SWAP(h->hf_offset);
  375. }
  376. switch (h->type) {
  377. case P_HASH:
  378. for (i = 0; i < NUM_ENT(h); i++) {
  379. if (pgin)
  380. M_16_SWAP(inp[i]);
  381. switch (HPAGE_TYPE(dbp, h, i)) {
  382. case H_KEYDATA:
  383. break;
  384. case H_DUPLICATE:
  385. len = LEN_HKEYDATA(dbp, h, pagesize, i);
  386. p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
  387. for (end = p + len; p < end;) {
  388. if (pgin) {
  389. P_16_SWAP(p);
  390. memcpy(&tmp,
  391.     p, sizeof(db_indx_t));
  392. p += sizeof(db_indx_t);
  393. } else {
  394. memcpy(&tmp,
  395.     p, sizeof(db_indx_t));
  396. SWAP16(p);
  397. }
  398. p += tmp;
  399. SWAP16(p);
  400. }
  401. break;
  402. case H_OFFDUP:
  403. p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
  404. SWAP32(p); /* pgno */
  405. break;
  406. case H_OFFPAGE:
  407. p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
  408. SWAP32(p); /* pgno */
  409. SWAP32(p); /* tlen */
  410. break;
  411. }
  412. }
  413. /*
  414.  * The offsets in the inp array are used to determine
  415.  * the size of entries on a page; therefore they
  416.  * cannot be converted until we've done all the
  417.  * entries.
  418.  */
  419. if (!pgin)
  420. for (i = 0; i < NUM_ENT(h); i++)
  421. M_16_SWAP(inp[i]);
  422. break;
  423. case P_LBTREE:
  424. case P_LDUP:
  425. case P_LRECNO:
  426. for (i = 0; i < NUM_ENT(h); i++) {
  427. if (pgin)
  428. M_16_SWAP(inp[i]);
  429. /*
  430.  * In the case of on-page duplicates, key information
  431.  * should only be swapped once.
  432.  */
  433. if (h->type == P_LBTREE && i > 1) {
  434. if (pgin) {
  435. if (inp[i] == inp[i - 2])
  436. continue;
  437. } else {
  438. M_16_SWAP(inp[i]);
  439. if (inp[i] == inp[i - 2])
  440. continue;
  441. M_16_SWAP(inp[i]);
  442. }
  443. }
  444. bk = GET_BKEYDATA(dbp, h, i);
  445. switch (B_TYPE(bk->type)) {
  446. case B_KEYDATA:
  447. M_16_SWAP(bk->len);
  448. break;
  449. case B_DUPLICATE:
  450. case B_OVERFLOW:
  451. bo = (BOVERFLOW *)bk;
  452. M_32_SWAP(bo->pgno);
  453. M_32_SWAP(bo->tlen);
  454. break;
  455. }
  456. if (!pgin)
  457. M_16_SWAP(inp[i]);
  458. }
  459. break;
  460. case P_IBTREE:
  461. for (i = 0; i < NUM_ENT(h); i++) {
  462. if (pgin)
  463. M_16_SWAP(inp[i]);
  464. bi = GET_BINTERNAL(dbp, h, i);
  465. M_16_SWAP(bi->len);
  466. M_32_SWAP(bi->pgno);
  467. M_32_SWAP(bi->nrecs);
  468. switch (B_TYPE(bi->type)) {
  469. case B_KEYDATA:
  470. break;
  471. case B_DUPLICATE:
  472. case B_OVERFLOW:
  473. bo = (BOVERFLOW *)bi->data;
  474. M_32_SWAP(bo->pgno);
  475. M_32_SWAP(bo->tlen);
  476. break;
  477. }
  478. if (!pgin)
  479. M_16_SWAP(inp[i]);
  480. }
  481. break;
  482. case P_IRECNO:
  483. for (i = 0; i < NUM_ENT(h); i++) {
  484. if (pgin)
  485. M_16_SWAP(inp[i]);
  486. ri = GET_RINTERNAL(dbp, h, i);
  487. M_32_SWAP(ri->pgno);
  488. M_32_SWAP(ri->nrecs);
  489. if (!pgin)
  490. M_16_SWAP(inp[i]);
  491. }
  492. break;
  493. case P_OVERFLOW:
  494. case P_INVALID:
  495. /* Nothing to do. */
  496. break;
  497. default:
  498. return (__db_pgfmt(dbenv, pg));
  499. }
  500. if (!pgin) {
  501. /* Swap the header information. */
  502. M_32_SWAP(h->lsn.file);
  503. M_32_SWAP(h->lsn.offset);
  504. M_32_SWAP(h->pgno);
  505. M_32_SWAP(h->prev_pgno);
  506. M_32_SWAP(h->next_pgno);
  507. M_16_SWAP(h->entries);
  508. M_16_SWAP(h->hf_offset);
  509. }
  510. return (0);
  511. }