| Index: third_party/sqlite/ext/recover.c
|
| diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/ext/recover.c
|
| similarity index 94%
|
| rename from third_party/sqlite/src/src/recover.c
|
| rename to third_party/sqlite/ext/recover.c
|
| index 5ff6f78c90065131eaa6135c15687d14877ea9d8..c34256130cace3b73ee0b49469bdebd6d9f85874 100644
|
| --- a/third_party/sqlite/src/src/recover.c
|
| +++ b/third_party/sqlite/ext/recover.c
|
| @@ -210,20 +210,213 @@
|
|
|
| #include <assert.h>
|
| #include <ctype.h>
|
| +#include <stdint.h>
|
| #include <stdio.h>
|
| +#include <stdlib.h>
|
| #include <string.h>
|
|
|
| -/* Internal SQLite things that are used:
|
| - * u32, u64, i64 types.
|
| - * Btree, Pager, and DbPage structs.
|
| - * DbPage.pData, .pPager, and .pgno
|
| - * sqlite3 struct.
|
| - * sqlite3BtreePager() and sqlite3BtreeGetPageSize()
|
| - * sqlite3BtreeGetOptimalReserve()
|
| - * sqlite3PagerGet() and sqlite3PagerUnref()
|
| - * getVarint().
|
| - */
|
| +#if defined(SQLITE_CORE) && !defined(SQLITE_CORE_NOT_REALLY)
|
| +
|
| +/* Compiling as part of SQLite core, pull in internal APIs. */
|
| #include "sqliteInt.h"
|
| +#define recoverGetVarint(p, v) sqlite3GetVarint(p, v)
|
| +
|
| +#else
|
| +
|
| +/* Compiling as a module outside of SQLite. Define local versions of some types
|
| +** and functions. These are copied and modestly adapted from SQLite source
|
| +** code.
|
| +*/
|
| +#include "sqlite3.h"
|
| +
|
| +/* Copied from SQLite internals. */
|
| +typedef uint8_t u8;
|
| +typedef uint32_t u32;
|
| +typedef uint64_t u64;
|
| +typedef int64_t i64;
|
| +
|
| +/*
|
| +** A convenience macro that returns the number of elements in
|
| +** an array.
|
| +*/
|
| +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
|
| +
|
| +/*
|
| +** Bitmasks used by sqlite3GetVarint(). These precomputed constants
|
| +** are defined here rather than simply putting the constant expressions
|
| +** inline in order to work around bugs in the RVT compiler.
|
| +**
|
| +** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
|
| +**
|
| +** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
|
| +*/
|
| +#define SLOT_2_0 0x001fc07f
|
| +#define SLOT_4_2_0 0xf01fc07f
|
| +
|
| +/*
|
| +** Read a 64-bit variable-length integer from memory starting at p[0].
|
| +** Return the number of bytes read. The value is stored in *v.
|
| +*/
|
| +static unsigned char recoverGetVarint(const unsigned char *p, u64 *v){
|
| + u32 a,b,s;
|
| +
|
| + a = *p;
|
| + /* a: p0 (unmasked) */
|
| + if (!(a&0x80))
|
| + {
|
| + *v = a;
|
| + return 1;
|
| + }
|
| +
|
| + p++;
|
| + b = *p;
|
| + /* b: p1 (unmasked) */
|
| + if (!(b&0x80))
|
| + {
|
| + a &= 0x7f;
|
| + a = a<<7;
|
| + a |= b;
|
| + *v = a;
|
| + return 2;
|
| + }
|
| +
|
| + /* Verify that constants are precomputed correctly */
|
| + assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
|
| + assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
|
| +
|
| + p++;
|
| + a = a<<14;
|
| + a |= *p;
|
| + /* a: p0<<14 | p2 (unmasked) */
|
| + if (!(a&0x80))
|
| + {
|
| + a &= SLOT_2_0;
|
| + b &= 0x7f;
|
| + b = b<<7;
|
| + a |= b;
|
| + *v = a;
|
| + return 3;
|
| + }
|
| +
|
| + /* CSE1 from below */
|
| + a &= SLOT_2_0;
|
| + p++;
|
| + b = b<<14;
|
| + b |= *p;
|
| + /* b: p1<<14 | p3 (unmasked) */
|
| + if (!(b&0x80))
|
| + {
|
| + b &= SLOT_2_0;
|
| + /* moved CSE1 up */
|
| + /* a &= (0x7f<<14)|(0x7f); */
|
| + a = a<<7;
|
| + a |= b;
|
| + *v = a;
|
| + return 4;
|
| + }
|
| +
|
| + /* a: p0<<14 | p2 (masked) */
|
| + /* b: p1<<14 | p3 (unmasked) */
|
| + /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
| + /* moved CSE1 up */
|
| + /* a &= (0x7f<<14)|(0x7f); */
|
| + b &= SLOT_2_0;
|
| + s = a;
|
| + /* s: p0<<14 | p2 (masked) */
|
| +
|
| + p++;
|
| + a = a<<14;
|
| + a |= *p;
|
| + /* a: p0<<28 | p2<<14 | p4 (unmasked) */
|
| + if (!(a&0x80))
|
| + {
|
| + /* we can skip these cause they were (effectively) done above
|
| + ** while calculating s */
|
| + /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
|
| + /* b &= (0x7f<<14)|(0x7f); */
|
| + b = b<<7;
|
| + a |= b;
|
| + s = s>>18;
|
| + *v = ((u64)s)<<32 | a;
|
| + return 5;
|
| + }
|
| +
|
| + /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
| + s = s<<7;
|
| + s |= b;
|
| + /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
| +
|
| + p++;
|
| + b = b<<14;
|
| + b |= *p;
|
| + /* b: p1<<28 | p3<<14 | p5 (unmasked) */
|
| + if (!(b&0x80))
|
| + {
|
| + /* we can skip this cause it was (effectively) done above in calc'ing s */
|
| + /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
|
| + a &= SLOT_2_0;
|
| + a = a<<7;
|
| + a |= b;
|
| + s = s>>18;
|
| + *v = ((u64)s)<<32 | a;
|
| + return 6;
|
| + }
|
| +
|
| + p++;
|
| + a = a<<14;
|
| + a |= *p;
|
| + /* a: p2<<28 | p4<<14 | p6 (unmasked) */
|
| + if (!(a&0x80))
|
| + {
|
| + a &= SLOT_4_2_0;
|
| + b &= SLOT_2_0;
|
| + b = b<<7;
|
| + a |= b;
|
| + s = s>>11;
|
| + *v = ((u64)s)<<32 | a;
|
| + return 7;
|
| + }
|
| +
|
| + /* CSE2 from below */
|
| + a &= SLOT_2_0;
|
| + p++;
|
| + b = b<<14;
|
| + b |= *p;
|
| + /* b: p3<<28 | p5<<14 | p7 (unmasked) */
|
| + if (!(b&0x80))
|
| + {
|
| + b &= SLOT_4_2_0;
|
| + /* moved CSE2 up */
|
| + /* a &= (0x7f<<14)|(0x7f); */
|
| + a = a<<7;
|
| + a |= b;
|
| + s = s>>4;
|
| + *v = ((u64)s)<<32 | a;
|
| + return 8;
|
| + }
|
| +
|
| + p++;
|
| + a = a<<15;
|
| + a |= *p;
|
| + /* a: p4<<29 | p6<<15 | p8 (unmasked) */
|
| +
|
| + /* moved CSE2 up */
|
| + /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
|
| + b &= SLOT_2_0;
|
| + b = b<<8;
|
| + a |= b;
|
| +
|
| + s = s<<4;
|
| + b = p[-4];
|
| + b &= 0x7f;
|
| + b = b>>3;
|
| + s |= b;
|
| +
|
| + *v = ((u64)s)<<32 | a;
|
| +
|
| + return 9;
|
| +}
|
| +#endif
|
|
|
| /* For debugging. */
|
| #if 0
|
| @@ -241,17 +434,14 @@ static const unsigned char kTableInteriorPage = 0x05;
|
| static const unsigned kiHeaderPageSizeOffset = 16;
|
| static const unsigned kiHeaderReservedSizeOffset = 20;
|
| static const unsigned kiHeaderEncodingOffset = 56;
|
| -/* TODO(shess) |static const unsigned| fails creating the header in GetPager()
|
| -** because |knHeaderSize| isn't |constexpr|. But this isn't C++, either.
|
| -*/
|
| -enum { knHeaderSize = 100};
|
| +static const unsigned knHeaderSize = 100;
|
|
|
| /* From section 1.5. */
|
| static const unsigned kiPageTypeOffset = 0;
|
| -static const unsigned kiPageFreeBlockOffset = 1;
|
| +/*static const unsigned kiPageFreeBlockOffset = 1;*/
|
| static const unsigned kiPageCellCountOffset = 3;
|
| -static const unsigned kiPageCellContentOffset = 5;
|
| -static const unsigned kiPageFragmentedBytesOffset = 7;
|
| +/*static const unsigned kiPageCellContentOffset = 5;*/
|
| +/*static const unsigned kiPageFragmentedBytesOffset = 7;*/
|
| static const unsigned knPageLeafHeaderBytes = 8;
|
| /* Interior pages contain an additional field. */
|
| static const unsigned kiPageRightChildOffset = 8;
|
| @@ -420,7 +610,7 @@ static int pagerCreate(sqlite3_file *pSqliteFile, u32 nPageSize,
|
| const int kExcessSpace = 128;
|
| typedef struct RecoverPage RecoverPage;
|
| struct RecoverPage {
|
| - Pgno pgno; /* Page number for this page */
|
| + u32 pgno; /* Page number for this page */
|
| void *pData; /* Page data for pgno */
|
| RecoverPager *pPager; /* The pager this page is part of */
|
| };
|
| @@ -497,7 +687,7 @@ static const unsigned char *PageHeader(RecoverPage *pPage){
|
| static int GetPager(sqlite3 *db, const char *zName,
|
| RecoverPager **ppPager, unsigned *pnPageSize,
|
| int *piEncoding){
|
| - int rc, iEncoding;
|
| + int i, rc, iEncoding;
|
| unsigned nPageSize, nReservedSize;
|
| unsigned char header[knHeaderSize];
|
| sqlite3_file *pFile = NULL;
|
| @@ -535,7 +725,7 @@ static int GetPager(sqlite3 *db, const char *zName,
|
| nPageSize = decodeUnsigned16(header + kiHeaderPageSizeOffset);
|
| if( (nPageSize&(nPageSize-1)) || nPageSize>32768 || nPageSize<512 ){
|
| pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE);
|
| - return rc;
|
| + return SQLITE_CORRUPT;
|
| }
|
|
|
| /* Space reserved a the end of the page for extensions. Usually 0. */
|
| @@ -553,6 +743,7 @@ static int GetPager(sqlite3 *db, const char *zName,
|
| /* This case should not be possible. */
|
| *piEncoding = SQLITE_UTF8;
|
| }
|
| + /*assert( iEncoding==1 || iEncoding==2 || iEncoding==3 );*/
|
|
|
| rc = pagerCreate(pFile, nPageSize, &pPager);
|
| if( rc!=SQLITE_OK ){
|
| @@ -835,6 +1026,7 @@ static unsigned interiorCursorChildPage(RecoverInteriorCursor *pCursor){
|
| return 0;
|
| }
|
|
|
| +#if 0
|
| static int interiorCursorEOF(RecoverInteriorCursor *pCursor){
|
| /* Find a parent with remaining children. EOF if none found. */
|
| while( pCursor && pCursor->iChild>=pCursor->nChildren ){
|
| @@ -842,6 +1034,7 @@ static int interiorCursorEOF(RecoverInteriorCursor *pCursor){
|
| }
|
| return pCursor==NULL;
|
| }
|
| +#endif
|
|
|
| /* Internal helper. Used to detect if iPage would cause a loop. */
|
| static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor,
|
| @@ -1458,11 +1651,11 @@ static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
|
| return ValidateError();
|
| }
|
|
|
| - nRead = getVarint(pCell, &nRecordBytes);
|
| + nRead = recoverGetVarint(pCell, &nRecordBytes);
|
| assert( iCellOffset+nRead<=pCursor->nPageSize );
|
| pCursor->nRecordBytes = nRecordBytes;
|
|
|
| - nRead += getVarint(pCell + nRead, &iRowid);
|
| + nRead += recoverGetVarint(pCell + nRead, &iRowid);
|
| assert( iCellOffset+nRead<=pCursor->nPageSize );
|
| pCursor->iRowid = (i64)iRowid;
|
|
|
| @@ -1488,7 +1681,7 @@ static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
|
| }
|
| }
|
|
|
| - nRecordHeaderRead = getVarint(pCell + nRead, &nRecordHeaderBytes);
|
| + nRecordHeaderRead = recoverGetVarint(pCell + nRead, &nRecordHeaderBytes);
|
| assert( nRecordHeaderBytes<=nRecordBytes );
|
| pCursor->nRecordHeaderBytes = nRecordHeaderBytes;
|
|
|
| @@ -1510,8 +1703,9 @@ static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
|
| nRecordHeaderBytes - nRecordHeaderRead) ){
|
| return ValidateError();
|
| }
|
| - nRecordHeaderRead += getVarint(pCursor->pRecordHeader + nRecordHeaderRead,
|
| - &iSerialType);
|
| + nRecordHeaderRead +=
|
| + recoverGetVarint(pCursor->pRecordHeader + nRecordHeaderRead,
|
| + &iSerialType);
|
| if( iSerialType==10 || iSerialType==11 ){
|
| return ValidateError();
|
| }
|
| @@ -1577,7 +1771,7 @@ static int leafCursorCellColInfo(RecoverLeafCursor *pCursor,
|
| /* Rather than caching the header size and how many bytes it took,
|
| * decode it every time.
|
| */
|
| - nRead = getVarint(pRecordHeader, &nRecordHeaderBytes);
|
| + nRead = recoverGetVarint(pRecordHeader, &nRecordHeaderBytes);
|
| assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes );
|
|
|
| /* Scan forward to the indicated column. Scans to _after_ column
|
| @@ -1596,7 +1790,7 @@ static int leafCursorCellColInfo(RecoverLeafCursor *pCursor,
|
| if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){
|
| return SQLITE_CORRUPT;
|
| }
|
| - nRead += getVarint(pRecordHeader + nRead, &iSerialType);
|
| + nRead += recoverGetVarint(pRecordHeader + nRead, &iSerialType);
|
| iColEndOffset += SerialTypeLength(iSerialType);
|
| nColsSkipped++;
|
| }
|
| @@ -1991,7 +2185,7 @@ static sqlite3_module recoverModule = {
|
| 0, /* xRename - rename the table */
|
| };
|
|
|
| -CHROMIUM_SQLITE_API
|
| +SQLITE_API
|
| int recoverVtableInit(sqlite3 *db){
|
| return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0);
|
| }
|
| @@ -2229,7 +2423,7 @@ static int recoverInit(
|
| /* Parse out db.table, assuming main if no dot. */
|
| zDot = strchr(argv[3], '.');
|
| if( !zDot ){
|
| - pRecover->zDb = sqlite3_strdup(db->aDb[0].zName);
|
| + pRecover->zDb = sqlite3_strdup("main");
|
| pRecover->zTable = sqlite3_strdup(argv[3]);
|
| }else if( zDot>argv[3] && zDot[1]!='\0' ){
|
| pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]);
|
|
|