dissect.database 0.1.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.database.bsd.db import DB
4
+
5
+ __all__ = ["DB"]
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.database.bsd.db import DB
4
+
5
+ __all__ = ["DB"]
@@ -0,0 +1,598 @@
1
+ # References:
2
+ # - libdb
3
+ from __future__ import annotations
4
+
5
+ from dissect.cstruct import cstruct
6
+
7
+ db_def = """
8
+ typedef uint8 u_int8_t;
9
+ typedef uint16 u_int16_t;
10
+ typedef uint32 u_int32_t;
11
+
12
+ typedef u_int32_t db_pgno_t; /* Page number type. */
13
+ typedef u_int16_t db_indx_t; /* Page offset type. */
14
+ #define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */
15
+
16
+ typedef u_int32_t db_recno_t; /* Record number type. */
17
+ #define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */
18
+
19
+ typedef struct _db_lsn {
20
+ uint32 file;
21
+ uint32 offset;
22
+ } DB_LSN;
23
+
24
+ #define DB_FILE_ID_LEN 20 /* Unique file ID length. */
25
+
26
+ /*******************************************************
27
+ * Crypto.
28
+ *******************************************************/
29
+ #define DB_IV_BYTES 16 /* Bytes per IV */
30
+ #define DB_MAC_KEY 20 /* Bytes per MAC checksum */
31
+
32
+ #define DB_RENAMEMAGIC 0x030800 /* File has been renamed. */
33
+
34
+ #define DB_BTREEVERSION 9 /* Current btree version. */
35
+ #define DB_BTREEOLDVER 8 /* Oldest btree version supported. */
36
+ #define DB_BTREEMAGIC 0x053162
37
+
38
+ #define DB_HASHVERSION 9 /* Current hash version. */
39
+ #define DB_HASHOLDVER 7 /* Oldest hash version supported. */
40
+ #define DB_HASHMAGIC 0x061561
41
+
42
+ #define DB_HEAPVERSION 1 /* Current heap version. */
43
+ #define DB_HEAPOLDVER 1 /* Oldest heap version supported. */
44
+ #define DB_HEAPMAGIC 0x074582
45
+
46
+ #define DB_QAMVERSION 4 /* Current queue version. */
47
+ #define DB_QAMOLDVER 3 /* Oldest queue version supported. */
48
+ #define DB_QAMMAGIC 0x042253
49
+
50
+ #define DB_SEQUENCE_VERSION 2 /* Current sequence version. */
51
+ #define DB_SEQUENCE_OLDVER 1 /* Oldest sequence version supported. */
52
+
53
+ #define DB_AM_CHKSUM 0x00000001 /* Checksumming */
54
+ #define DB_AM_COMPENSATE 0x00000002 /* Created by compensating txn */
55
+ #define DB_AM_COMPRESS 0x00000004 /* Compressed BTree */
56
+ #define DB_AM_CREATED 0x00000008 /* Database was created upon open */
57
+ #define DB_AM_CREATED_MSTR 0x00000010 /* Encompassing file was created */
58
+ #define DB_AM_DBM_ERROR 0x00000020 /* Error in DBM/NDBM database */
59
+ #define DB_AM_DELIMITER 0x00000040 /* Variable length delimiter set */
60
+ #define DB_AM_DISCARD 0x00000080 /* Discard any cached pages */
61
+ #define DB_AM_DUP 0x00000100 /* DB_DUP */
62
+ #define DB_AM_DUPSORT 0x00000200 /* DB_DUPSORT */
63
+ #define DB_AM_ENCRYPT 0x00000400 /* Encryption */
64
+ #define DB_AM_FIXEDLEN 0x00000800 /* Fixed-length records */
65
+ #define DB_AM_INMEM 0x00001000 /* In-memory; no sync on close */
66
+ #define DB_AM_INORDER 0x00002000 /* DB_INORDER */
67
+ #define DB_AM_IN_RENAME 0x00004000 /* File is being renamed */
68
+ #define DB_AM_NOT_DURABLE 0x00008000 /* Do not log changes */
69
+ #define DB_AM_OPEN_CALLED 0x00010000 /* DB->open called */
70
+ #define DB_AM_PAD 0x00020000 /* Fixed-length record pad */
71
+ #define DB_AM_PARTDB 0x00040000 /* Handle for a database partition */
72
+ #define DB_AM_PGDEF 0x00080000 /* Page size was defaulted */
73
+ #define DB_AM_RDONLY 0x00100000 /* Database is readonly */
74
+ #define DB_AM_READ_UNCOMMITTED 0x00200000 /* Support degree 1 isolation */
75
+ #define DB_AM_RECNUM 0x00400000 /* DB_RECNUM */
76
+ #define DB_AM_RECOVER 0x00800000 /* DB opened by recovery routine */
77
+ #define DB_AM_RENUMBER 0x01000000 /* DB_RENUMBER */
78
+ #define DB_AM_REVSPLITOFF 0x02000000 /* DB_REVSPLITOFF */
79
+ #define DB_AM_SECONDARY 0x04000000 /* Database is a secondary index */
80
+ #define DB_AM_SNAPSHOT 0x08000000 /* DB_SNAPSHOT */
81
+ #define DB_AM_SUBDB 0x10000000 /* Subdatabases supported */
82
+ #define DB_AM_SWAP 0x20000000 /* Pages need to be byte-swapped */
83
+ #define DB_AM_TXN 0x40000000 /* Opened in a transaction */
84
+ #define DB_AM_VERIFYING 0x80000000 /* DB handle is in the verifier */
85
+
86
+ /*
87
+ * DB page formats.
88
+ *
89
+ * !!!
90
+ * This implementation requires that values within the following structures
91
+ * NOT be padded -- note, ANSI C permits random padding within structures.
92
+ * If your compiler pads randomly you can just forget ever making DB run on
93
+ * your system. In addition, no data type can require larger alignment than
94
+ * its own size, e.g., a 4-byte data element may not require 8-byte alignment.
95
+ *
96
+ * Note that key/data lengths are often stored in db_indx_t's -- this is
97
+ * not accidental, nor does it limit the key/data size. If the key/data
98
+ * item fits on a page, it's guaranteed to be small enough to fit into a
99
+ * db_indx_t, and storing it in one saves space.
100
+ */
101
+
102
+ #define PGNO_INVALID 0 /* Invalid page number in any database. */
103
+ #define PGNO_BASE_MD 0 /* Base database: metadata page number. */
104
+
105
+ /* Page types. */
106
+ #define P_INVALID 0 /* Invalid page type. */
107
+ #define __P_DUPLICATE 1 /* Duplicate. DEPRECATED in 3.1 */
108
+ #define P_HASH_UNSORTED 2 /* Hash pages created pre 4.6. DEPRECATED */
109
+ #define P_IBTREE 3 /* Btree internal. */
110
+ #define P_IRECNO 4 /* Recno internal. */
111
+ #define P_LBTREE 5 /* Btree leaf. */
112
+ #define P_LRECNO 6 /* Recno leaf. */
113
+ #define P_OVERFLOW 7 /* Overflow. */
114
+ #define P_HASHMETA 8 /* Hash metadata page. */
115
+ #define P_BTREEMETA 9 /* Btree metadata page. */
116
+ #define P_QAMMETA 10 /* Queue metadata page. */
117
+ #define P_QAMDATA 11 /* Queue data page. */
118
+ #define P_LDUP 12 /* Off-page duplicate leaf. */
119
+ #define P_HASH 13 /* Sorted hash page. */
120
+ #define P_HEAPMETA 14 /* Heap metadata page. */
121
+ #define P_HEAP 15 /* Heap data page. */
122
+ #define P_IHEAP 16 /* Heap internal. */
123
+ #define P_PAGETYPE_MAX 17
124
+
125
+ /*
126
+ * When we create pages in mpool, we ask mpool to clear some number of bytes
127
+ * in the header. This number must be at least as big as the regular page
128
+ * headers and cover enough of the btree and hash meta-data pages to obliterate
129
+ * the page type.
130
+ */
131
+ #define DB_PAGE_DB_LEN 32
132
+ #define DB_PAGE_QUEUE_LEN 0
133
+
134
+ #define DBMETA_CHKSUM 0x01
135
+ #define DBMETA_PART_RANGE 0x02
136
+ #define DBMETA_PART_CALLBACK 0x04
137
+
138
+ /************************************************************************
139
+ GENERIC METADATA PAGE HEADER
140
+ *
141
+ * !!!
142
+ * The magic and version numbers have to be in the same place in all versions
143
+ * of the metadata page as the application may not have upgraded the database.
144
+ ************************************************************************/
145
+ typedef struct _dbmeta33 {
146
+ DB_LSN lsn; /* 00-07: LSN. */
147
+ db_pgno_t pgno; /* 08-11: Current page number. */
148
+ u_int32_t magic; /* 12-15: Magic number. */
149
+ u_int32_t version; /* 16-19: Version. */
150
+ u_int32_t pagesize; /* 20-23: Pagesize. */
151
+ u_int8_t encrypt_alg; /* 24: Encryption algorithm. */
152
+ u_int8_t type; /* 25: Page type. */
153
+ u_int8_t metaflags; /* 26: Meta-only flags */
154
+ u_int8_t unused1; /* 27: Unused. */
155
+ u_int32_t free; /* 28-31: Free list page number. */
156
+ db_pgno_t last_pgno; /* 32-35: Page number of last page in db. */
157
+ u_int32_t nparts; /* 36-39: Number of partitions. */
158
+ u_int32_t key_count; /* 40-43: Cached key count. */
159
+ u_int32_t record_count; /* 44-47: Cached record count. */
160
+ u_int32_t flags; /* 48-51: Flags: unique to each AM. */
161
+ u_int8_t uid[DB_FILE_ID_LEN]; /* 52-71: Unique file ID. */
162
+ } DBMETA33, DBMETA;
163
+
164
+ /************************************************************************
165
+ BTREE METADATA PAGE LAYOUT
166
+ ************************************************************************/
167
+ #define BTM_DUP 0x001 /* Duplicates. */
168
+ #define BTM_RECNO 0x002 /* Recno tree. */
169
+ #define BTM_RECNUM 0x004 /* Btree: maintain record count. */
170
+ #define BTM_FIXEDLEN 0x008 /* Recno: fixed length records. */
171
+ #define BTM_RENUMBER 0x010 /* Recno: renumber on insert/delete. */
172
+ #define BTM_SUBDB 0x020 /* Subdatabases. */
173
+ #define BTM_DUPSORT 0x040 /* Duplicates are sorted. */
174
+ #define BTM_COMPRESS 0x080 /* Compressed. */
175
+ #define BTM_MASK 0x0ff
176
+
177
+ typedef struct _btmeta33 {
178
+ DBMETA dbmeta; /* 00-71: Generic meta-data header. */
179
+
180
+ u_int32_t unused1; /* 72-75: Unused space. */
181
+ u_int32_t minkey; /* 76-79: Btree: Minkey. */
182
+ u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */
183
+ u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */
184
+ u_int32_t root; /* 88-91: Root page. */
185
+ u_int32_t unused2[92]; /* 92-459: Unused space. */
186
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
187
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
188
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
189
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
190
+
191
+ /*
192
+ * Minimum page size is 512.
193
+ */
194
+ } BTMETA33, BTMETA;
195
+
196
+ /************************************************************************
197
+ HASH METADATA PAGE LAYOUT
198
+ ************************************************************************/
199
+ #define DB_HASH_DUP 0x01 /* Duplicates. */
200
+ #define DB_HASH_SUBDB 0x02 /* Subdatabases. */
201
+ #define DB_HASH_DUPSORT 0x04 /* Duplicates are sorted. */
202
+ #define NCACHED 32 /* number of spare points */
203
+
204
+ typedef struct _hashmeta33 {
205
+ DBMETA dbmeta; /* 00-71: Generic meta-data page header. */
206
+
207
+ u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */
208
+ u_int32_t high_mask; /* 76-79: Modulo mask into table */
209
+ u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */
210
+ u_int32_t ffactor; /* 84-87: Fill factor */
211
+ u_int32_t nelem; /* 88-91: Number of keys in hash table */
212
+ u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */
213
+
214
+ u_int32_t spares[NCACHED]; /* 96-223: Spare pages for overflow */
215
+ u_int32_t unused[59]; /* 224-459: Unused space */
216
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
217
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
218
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
219
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
220
+
221
+ /*
222
+ * Minimum page size is 512.
223
+ */
224
+ } HMETA33, HMETA;
225
+
226
+ /************************************************************************
227
+ HEAP METADATA PAGE LAYOUT
228
+ *************************************************************************/
229
+ /*
230
+ * Heap Meta data page structure
231
+ *
232
+ */
233
+ typedef struct _heapmeta {
234
+ DBMETA dbmeta; /* 00-71: Generic meta-data header. */
235
+
236
+ db_pgno_t curregion; /* 72-75: Current region pgno. */
237
+ u_int32_t nregions; /* 76-79: Number of regions. */
238
+ u_int32_t gbytes; /* 80-83: GBytes for fixed size heap. */
239
+ u_int32_t bytes; /* 84-87: Bytes for fixed size heap. */
240
+ u_int32_t region_size; /* 88-91: Max region size. */
241
+ u_int32_t unused2[92]; /* 92-459: Unused space.*/
242
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
243
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
244
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
245
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
246
+
247
+ /*
248
+ * Minimum page size is 512.
249
+ */
250
+ } HEAPMETA;
251
+
252
+ /************************************************************************
253
+ QUEUE METADATA PAGE LAYOUT
254
+ ************************************************************************/
255
+ /*
256
+ * QAM Meta data page structure
257
+ *
258
+ */
259
+ typedef struct _qmeta33 {
260
+ DBMETA dbmeta; /* 00-71: Generic meta-data header. */
261
+
262
+ u_int32_t first_recno; /* 72-75: First not deleted record. */
263
+ u_int32_t cur_recno; /* 76-79: Next recno to be allocated. */
264
+ u_int32_t re_len; /* 80-83: Fixed-length record length. */
265
+ u_int32_t re_pad; /* 84-87: Fixed-length record pad. */
266
+ u_int32_t rec_page; /* 88-91: Records Per Page. */
267
+ u_int32_t page_ext; /* 92-95: Pages per extent */
268
+
269
+ u_int32_t unused[91]; /* 96-459: Unused space */
270
+ u_int32_t crypto_magic; /* 460-463: Crypto magic number */
271
+ u_int32_t trash[3]; /* 464-475: Trash space - Do not use */
272
+ u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */
273
+ u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */
274
+
275
+ /*
276
+ * Minimum page size is 512.
277
+ */
278
+ } QMETA33, QMETA;
279
+
280
+ /*
281
+ * DBMETASIZE is a constant used by __db_file_setup and DB->verify
282
+ * as a buffer which is guaranteed to be larger than any possible
283
+ * metadata page size and smaller than any disk sector.
284
+ */
285
+ #define DBMETASIZE 512
286
+
287
+ /************************************************************************
288
+ BTREE/HASH MAIN PAGE LAYOUT
289
+ ************************************************************************/
290
+ /*
291
+ * +-----------------------------------+
292
+ * | lsn | pgno | prev pgno |
293
+ * +-----------------------------------+
294
+ * | next pgno | entries | hf offset |
295
+ * +-----------------------------------+
296
+ * | level | type | chksum |
297
+ * +-----------------------------------+
298
+ * | iv | index | free --> |
299
+ * +-----------+-----------------------+
300
+ * | F R E E A R E A |
301
+ * +-----------------------------------+
302
+ * | <-- free | item |
303
+ * +-----------------------------------+
304
+ * | item | item | item |
305
+ * +-----------------------------------+
306
+ *
307
+ * sizeof(PAGE) == 26 bytes + possibly 20 bytes of checksum and possibly
308
+ * 16 bytes of IV (+ 2 bytes for alignment), and the following indices
309
+ * are guaranteed to be two-byte aligned. If we aren't doing crypto or
310
+ * checksumming the bytes are reclaimed for data storage.
311
+ *
312
+ * For hash and btree leaf pages, index items are paired, e.g., inp[0] is the
313
+ * key for inp[1]'s data. All other types of pages only contain single items.
314
+ */
315
+ typedef struct __pg_chksum {
316
+ u_int8_t unused[2]; /* 26-27: For alignment */
317
+ u_int8_t chksum[4]; /* 28-31: Checksum */
318
+ } PG_CHKSUM;
319
+
320
+ typedef struct __pg_crypto {
321
+ u_int8_t unused[2]; /* 26-27: For alignment */
322
+ u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */
323
+ u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */
324
+ /* !!!
325
+ * Must be 16-byte aligned for crypto
326
+ */
327
+ } PG_CRYPTO;
328
+
329
+ #define LEAFLEVEL 1
330
+ #define MAXBTREELEVEL 255
331
+
332
+ typedef struct _db_page {
333
+ DB_LSN lsn; /* 00-07: Log sequence number. */
334
+ db_pgno_t pgno; /* 08-11: Current page number. */
335
+ db_pgno_t prev_pgno; /* 12-15: Previous page number. */
336
+ db_pgno_t next_pgno; /* 16-19: Next page number. */
337
+ db_indx_t entries; /* 20-21: Number of items on the page. */
338
+ db_indx_t hf_offset; /* 22-23: High free byte page offset. */
339
+
340
+ /*
341
+ * The btree levels are numbered from the leaf to the root, starting
342
+ * with 1, so the leaf is level 1, its parent is level 2, and so on.
343
+ * We maintain this level on all btree pages, but the only place that
344
+ * we actually need it is on the root page. It would not be difficult
345
+ * to hide the byte on the root page once it becomes an internal page,
346
+ * so we could get this byte back if we needed it for something else.
347
+ */
348
+ u_int8_t level; /* 24: Btree tree level. */
349
+ u_int8_t type; /* 25: Page type. */
350
+ } PAGE;
351
+
352
+ /*
353
+ * With many compilers sizeof(PAGE) == 28, while SIZEOF_PAGE == 26.
354
+ * We add in other things directly after the page header and need
355
+ * the SIZEOF_PAGE. When giving the sizeof(), many compilers will
356
+ * pad it out to the next 4-byte boundary.
357
+ */
358
+ #define SIZEOF_PAGE 26
359
+
360
+ /************************************************************************
361
+ HEAP PAGE LAYOUT
362
+ ************************************************************************/
363
+ #define HEAPPG_NORMAL 26
364
+ #define HEAPPG_CHKSUM 48
365
+ #define HEAPPG_SEC 64
366
+
367
+ /*
368
+ * +0-----------2------------4-----------6-----------7+
369
+ * | lsn |
370
+ * +-------------------------+------------------------+
371
+ * | pgno | unused0 |
372
+ * +-------------+-----------+-----------+------------+
373
+ * | high_indx | free_indx | entries | hf offset |
374
+ * +-------+-----+-----------+-----------+------------+
375
+ * |unused2|type | unused3 | ...chksum... |
376
+ * +-------+-----+-----------+------------------------+
377
+ * | ...iv... | offset table / free space map |
378
+ * +-------------+------------------------------------+
379
+ * |free-> F R E E A R E A |
380
+ * +--------------------------------------------------+
381
+ * | <-- free | item |
382
+ * +-------------------------+------------------------+
383
+ * | item | item |
384
+ * +-------------------------+------------------------+
385
+ *
386
+ * The page layout of both heap internal and data pages. If not using
387
+ * crypto, iv will be overwritten with data. If not using checksumming,
388
+ * unused3 and chksum will also be overwritten with data and data will start at
389
+ * 26. Note that this layout lets us re-use a lot of the PAGE element macros
390
+ * defined above.
391
+ */
392
+ typedef struct _heappg {
393
+ DB_LSN lsn; /* 00-07: Log sequence number. */
394
+ db_pgno_t pgno; /* 08-11: Current page number. */
395
+ u_int32_t high_pgno; /* 12-15: Highest page in region. */
396
+ u_int16_t high_indx; /* 16-17: Highest index in the offset table. */
397
+ db_indx_t free_indx; /* 18-19: First available index. */
398
+ db_indx_t entries; /* 20-21: Number of items on the page. */
399
+ db_indx_t hf_offset; /* 22-23: High free byte page offset. */
400
+ u_int8_t unused2[1]; /* 24: Unused. */
401
+ u_int8_t type; /* 25: Page type. */
402
+ u_int8_t unused3[2]; /* 26-27: Never used, just checksum alignment. */
403
+ u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */
404
+ u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */
405
+ } HEAPPG;
406
+
407
+ /* Define first possible data page for heap, 0 is metapage, 1 is region page */
408
+ #define FIRST_HEAP_RPAGE 1
409
+ #define FIRST_HEAP_DPAGE 2
410
+
411
+ #define HEAP_RECSPLIT 0x01 /* Heap data record is split */
412
+ #define HEAP_RECFIRST 0x02 /* First piece of a split record */
413
+ #define HEAP_RECLAST 0x04 /* Last piece of a split record */
414
+
415
+ typedef struct __heaphdr {
416
+ u_int8_t flags; /* 00: Flags describing record. */
417
+ u_int8_t unused; /* 01: Padding. */
418
+ u_int16_t size; /* 02-03: The size of the stored data piece. */
419
+ } HEAPHDR;
420
+
421
+ typedef struct __heaphdrsplt {
422
+ HEAPHDR std_hdr; /* 00-03: The standard data header */
423
+ u_int32_t tsize; /* 04-07: Total record size, 1st piece only */
424
+ db_pgno_t nextpg; /* 08-11: RID.pgno of the next record piece */
425
+ db_indx_t nextindx; /* 12-13: RID.indx of the next record piece */
426
+ u_int16_t unused; /* 14-15: Padding. */
427
+ } HEAPSPLITHDR;
428
+
429
+ /************************************************************************
430
+ QUEUE MAIN PAGE LAYOUT
431
+ ************************************************************************/
432
+ /*
433
+ * Sizes of page below. Used to reclaim space if not doing
434
+ * crypto or checksumming. If you change the QPAGE below you
435
+ * MUST adjust this too.
436
+ */
437
+ #define QPAGE_NORMAL 28
438
+ #define QPAGE_CHKSUM 48
439
+ #define QPAGE_SEC 64
440
+
441
+ typedef struct _qpage {
442
+ DB_LSN lsn; /* 00-07: Log sequence number. */
443
+ db_pgno_t pgno; /* 08-11: Current page number. */
444
+ u_int32_t unused0[3]; /* 12-23: Unused. */
445
+ u_int8_t unused1[1]; /* 24: Unused. */
446
+ u_int8_t type; /* 25: Page type. */
447
+ u_int8_t unused2[2]; /* 26-27: Unused. */
448
+ u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */
449
+ u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */
450
+ } QPAGE;
451
+
452
+ /************************************************************************
453
+ OVERFLOW PAGE LAYOUT
454
+ ************************************************************************/
455
+
456
+ /*
457
+ * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which
458
+ * store a page number (the first page of the overflow item) and a length
459
+ * (the total length of the overflow item). The overflow item consists of
460
+ * some number of overflow pages, linked by the next_pgno field of the page.
461
+ * A next_pgno field of PGNO_INVALID flags the end of the overflow item.
462
+ *
463
+ * Overflow page overloads:
464
+ * The amount of overflow data stored on each page is stored in the
465
+ * hf_offset field.
466
+ *
467
+ * The implementation reference counts overflow items as it's possible
468
+ * for them to be promoted onto btree internal pages. The reference
469
+ * count is stored in the entries field.
470
+ */
471
+
472
+ /************************************************************************
473
+ HASH PAGE LAYOUT
474
+ ************************************************************************/
475
+
476
+ /* Each index references a group of bytes on the page. */
477
+ #define H_KEYDATA 1 /* Key/data item. */
478
+ #define H_DUPLICATE 2 /* Duplicate key/data item. */
479
+ #define H_OFFPAGE 3 /* Overflow key/data item. */
480
+ #define H_OFFDUP 4 /* Overflow page of duplicates. */
481
+
482
+ /*
483
+ * The first and second types are H_KEYDATA and H_DUPLICATE, represented
484
+ * by the HKEYDATA structure:
485
+ *
486
+ * +-----------------------------------+
487
+ * | type | key/data ... |
488
+ * +-----------------------------------+
489
+ *
490
+ * For duplicates, the data field encodes duplicate elements in the data
491
+ * field:
492
+ *
493
+ * +---------------------------------------------------------------+
494
+ * | type | len1 | element1 | len1 | len2 | element2 | len2 |
495
+ * +---------------------------------------------------------------+
496
+ *
497
+ * Thus, by keeping track of the offset in the element, we can do both
498
+ * backward and forward traversal.
499
+ */
500
+ typedef struct _hkeydata {
501
+ u_int8_t type; /* 00: Page type. */
502
+ u_int8_t data[0]; /* Variable length key/data item. */
503
+ } HKEYDATA;
504
+
505
+ /*
506
+ * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure:
507
+ */
508
+ typedef struct _hoffpage {
509
+ u_int8_t type; /* 00: Page type and delete flag. */
510
+ u_int8_t unused[3]; /* 01-03: Padding, unused. */
511
+ db_pgno_t pgno; /* 04-07: Offpage page number. */
512
+ u_int32_t tlen; /* 08-11: Total length of item. */
513
+ } HOFFPAGE;
514
+
515
+ /*
516
+ * The fourth type is H_OFFDUP represented by the HOFFDUP structure:
517
+ */
518
+ typedef struct _hoffdup {
519
+ u_int8_t type; /* 00: Page type and delete flag. */
520
+ u_int8_t unused[3]; /* 01-03: Padding, unused. */
521
+ db_pgno_t pgno; /* 04-07: Offpage page number. */
522
+ } HOFFDUP;
523
+
524
+ /************************************************************************
525
+ BTREE PAGE LAYOUT
526
+ ************************************************************************/
527
+
528
+ /* Each index references a group of bytes on the page. */
529
+ #define B_KEYDATA 1 /* Key/data item. */
530
+ #define B_DUPLICATE 2 /* Duplicate key/data item. */
531
+ #define B_OVERFLOW 3 /* Overflow key/data item. */
532
+
533
+ /*
534
+ * We have to store a deleted entry flag in the page. The reason is complex,
535
+ * but the simple version is that we can't delete on-page items referenced by
536
+ * a cursor -- the return order of subsequent insertions might be wrong. The
537
+ * delete flag is an overload of the top bit of the type byte.
538
+ */
539
+ #define B_DELETE (0x80)
540
+
541
+ /*
542
+ * The first type is B_KEYDATA, represented by the BKEYDATA structure:
543
+ */
544
+ typedef struct _bkeydata {
545
+ db_indx_t len; /* 00-01: Key/data item length. */
546
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
547
+ u_int8_t data[0]; /* Variable length key/data item. */
548
+ } BKEYDATA;
549
+
550
+ /*
551
+ * The second and third types are B_DUPLICATE and B_OVERFLOW, represented
552
+ * by the BOVERFLOW structure.
553
+ */
554
+ typedef struct _boverflow {
555
+ db_indx_t unused1; /* 00-01: Padding, unused. */
556
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
557
+ u_int8_t unused2; /* 03: Padding, unused. */
558
+ db_pgno_t pgno; /* 04-07: Next page number. */
559
+ u_int32_t tlen; /* 08-11: Total length of item. */
560
+ } BOVERFLOW;
561
+
562
+ /*
563
+ * Btree leaf and hash page layouts group indices in sets of two, one for the
564
+ * key and one for the data. Everything else does it in sets of one to save
565
+ * space. Use the following macros so that it's real obvious what's going on.
566
+ */
567
+ #define O_INDX 1
568
+ #define P_INDX 2
569
+
570
+ /************************************************************************
571
+ BTREE INTERNAL PAGE LAYOUT
572
+ ************************************************************************/
573
+
574
+ /*
575
+ * Btree internal entry.
576
+ */
577
+ typedef struct _binternal {
578
+ db_indx_t len; /* 00-01: Key/data item length. */
579
+ u_int8_t type; /* 02: Page type AND DELETE FLAG. */
580
+ u_int8_t unused; /* 03: Padding, unused. */
581
+ db_pgno_t pgno; /* 04-07: Page number of referenced page. */
582
+ db_recno_t nrecs; /* 08-11: Subtree record count. */
583
+ u_int8_t data[0]; /* Variable length key item. */
584
+ } BINTERNAL;
585
+
586
+ /************************************************************************
587
+ RECNO INTERNAL PAGE LAYOUT
588
+ ************************************************************************/
589
+
590
+ /*
591
+ * The recno internal entry.
592
+ */
593
+ typedef struct _rinternal {
594
+ db_pgno_t pgno; /* 00-03: Page number of referenced page. */
595
+ db_recno_t nrecs; /* 04-07: Subtree record count. */
596
+ } RINTERNAL;
597
+ """
598
+ c_db = cstruct().load(db_def)