|
在SQL SERVER2005以上版本中,数据页默认开启checksum,标识为m_flagBits & 0x200 == True,其值m_tornBits位于页头0x3C,4字节。
其算法概述如下:
- 读8KB 进BUF
- 将BUF头部 CHECKSUM的4字节值清0
- uint32 checksum = 0 //初始checksum
- for i in range(0,15):
- //每扇区的初始checksum
- overall = 0;
- for ii in range(0,127):
- //对当前扇区的每个4字节做累加异或
- overall = overall ^ BUF[i][ii];
- //对每扇区的checksum进行移位,方法为向左移位15-i位,
- //左边移出的15-i位补到最低位。
- checksum = checksum ^ rol(overall, 15- i);
- return checksum; //Gets checksum
复制代码
c源码如下:
- //***CODE***//
- #include <stdio.h>
- #include <stdlib.h>
- #define seed 15 //Initial seed(for first sector)
- #define CHAR_BIT 8
- //***PROTOTYPES***//
- unsigned int page_checksum(int page_id, unsigned int *ondisk);
- unsigned int rol(unsigned int value, unsigned int rotation);
- int main(int argc, char *argv[]) {
- unsigned int computed_checksum; //Var to retrieve calculated checksum
- unsigned int ondisk_checksum; //Var to retrieve checksum on disk
- computed_checksum = page_checksum(152, &ondisk_checksum); //page_checksum call to retrieve stored and calculated checksum for page 152
- //***PRINTS***//
- printf("Calculated checksum: 0x%08x\n", computed_checksum);
- printf("On disk checksum: 0x%08x\n", ondisk_checksum);
- }
- unsigned int page_checksum(int page_id, unsigned int *ondisk)
- {
- FILE *fileptr;
- unsigned int i;
- unsigned int j;
- unsigned int checksum;
- unsigned int overall;
- unsigned int *pagebuf[16][128]; //A pointer to describe 2d array [sector][element]
- fileptr = fopen("C:\\Users\\andre\\Desktop\\teste.mdf", "r+b"); //Open dummy data file for binary read
- fseek(fileptr, page_id * 8192, SEEK_SET); //Calculate page address on data file and points to it
- fread(pagebuf, 4, 2048, fileptr); //Read page buffer
- fclose(fileptr);
- checksum = 0;
- overall = 0;
- *ondisk = pagebuf[0][15]; //This means that torn bits is stored on first sector in 15th element, Internals researches understand this
- pagebuf[0][15] = 0x00000000; //Fill checksum field with zeroes (this field will be discarded in algorithm)
- for (i = 0; i < 16; i++) //Loop through sectors
- {
- overall = 0; //Reset overall sum for sectors
- for (j = 0; j < 128; j++) //Loop through elements in sector i
- {
- overall = overall ^ (unsigned int)pagebuf[i][j]; //XOR operation between sector i elements
- }
- checksum = checksum ^ rol(overall, seed - i); //Current checksum is overall for sector i circular shifted by seed (15 - i)
- }
- return checksum; //Gets checksum
- }
- unsigned int rol(unsigned int value, unsigned int rotation)
- {
- return (value) << (rotation) | (value) >> (sizeof(int) * CHAR_BIT - rotation) & ( (1 << rotation) -1);
- }
复制代码 |
|