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]); |