** The xRead() method of the wrapper VFS. This is used to intercept calls ** to read page 1 of the input database. */
| 15765 | ** to read page 1 of the input database. |
| 15766 | */ |
| 15767 | static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){ |
| 15768 | int rc = SQLITE_OK; |
| 15769 | if( pFd->pMethods==&recover_methods ){ |
| 15770 | pFd->pMethods = recover_g.pMethods; |
| 15771 | rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff); |
| 15772 | if( nByte==16 ){ |
| 15773 | sqlite3_randomness(16, aBuf); |
| 15774 | }else |
| 15775 | if( rc==SQLITE_OK && iOff==0 && nByte>=108 ){ |
| 15776 | /* Ensure that the database has a valid header file. The only fields |
| 15777 | ** that really matter to recovery are: |
| 15778 | ** |
| 15779 | ** + Database page size (16-bits at offset 16) |
| 15780 | ** + Size of db in pages (32-bits at offset 28) |
| 15781 | ** + Database encoding (32-bits at offset 56) |
| 15782 | ** |
| 15783 | ** Also preserved are: |
| 15784 | ** |
| 15785 | ** + first freelist page (32-bits at offset 32) |
| 15786 | ** + size of freelist (32-bits at offset 36) |
| 15787 | ** + the wal-mode flags (16-bits at offset 18) |
| 15788 | ** |
| 15789 | ** We also try to preserve the auto-vacuum, incr-value, user-version |
| 15790 | ** and application-id fields - all 32 bit quantities at offsets |
| 15791 | ** 52, 60, 64 and 68. All other fields are set to known good values. |
| 15792 | ** |
| 15793 | ** Byte offset 105 should also contain the page-size as a 16-bit |
| 15794 | ** integer. |
| 15795 | */ |
| 15796 | const int aPreserve[] = {32, 36, 52, 60, 64, 68}; |
| 15797 | u8 aHdr[108] = { |
| 15798 | 0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, |
| 15799 | 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00, |
| 15800 | 0xFF, 0xFF, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20, |
| 15801 | 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, |
| 15802 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 15803 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
| 15804 | 0x00, 0x00, 0x10, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, |
| 15805 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 15806 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
| 15807 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 15808 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 15809 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 15810 | 0x00, 0x2e, 0x5b, 0x30, |
| 15811 | |
| 15812 | 0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00 |
| 15813 | }; |
| 15814 | u8 *a = (u8*)aBuf; |
| 15815 | |
| 15816 | u32 pgsz = recoverGetU16(&a[16]); |
| 15817 | u32 nReserve = a[20]; |
| 15818 | u32 enc = recoverGetU32(&a[56]); |
| 15819 | u32 dbsz = 0; |
| 15820 | i64 dbFileSize = 0; |
| 15821 | int ii; |
| 15822 | sqlite3_recover *p = recover_g.p; |
| 15823 | |
| 15824 | if( pgsz==0x01 ) pgsz = 65536; |
nothing calls this directly
no test coverage detected