最具挑战性的挑战莫过于提升自我。—— 迈克尔·F·斯特利
前面我们已经知道基本的数据存储格式,要读取数据库中数据文件的数据,我们首先要知道自己要读取的表叫什么名字,数据存储的开始位置,数据存储的分布信息等。Oracle(11g)数据库启动时,首先会去读取0号数据文件(一般都是system01文件)的520号块存储的内容,即表BOOTSTRAP$。BOOTSTRAP$表里面记录了基础数据字典表的创建分布位置:例如CLUSTER C_OBJ#,该簇中分布有核心表tab$和col$;C_OBJ#的开始块为144,即从144块读取,可以读取出核心表tab$和col$表的内容。对于obj$表,其开始块为240,从240块开始,我们可以读取到obj$的内容。
一,表列格式描述
eb4 tab[32] = {
O_NUMBER, O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,
O_NUMBER, O_NUMBER,O_NUMBER,O_VARCHAR2,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,
O_NUMBER, O_NUMBER,O_DATE,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,
O_NUMBER };
eb4 col[24] = {
O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_VARCHAR2,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,
O_NUMBER, O_NUMBER,O_NUMBER,O_LONG,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,O_NUMBER,
O_NUMBER, O_NUMBER,O_NUMBER,O_DATE
};
eb4 obj[] = {
O_NUMBER, O_NUMBER,O_NUMBER,O_VARCHAR2,O_NUMBER,O_VARCHAR2,O_NUMBER,O_DATE,O_DATE,O_DATE,
O_NUMBER, O_VARCHAR2,O_VARCHAR2,O_NUMBER,O_RAW,O_NUMBER,O_NUMBER,O_NUMBER,O_VARCHAR2,O_VARCHAR2,
O_DATE
};
建立了3个数组全局变量,通过里面的值,去匹配tab$,col$和ojb$表每列的类型。
struct sysblock{
struct kcbh v_sb_kcbh;
struct ktech v_sb_ktech;
struct ktemh v_sb_ktemh;
struct ktetb *p_sb_ktetb;
ub4 v_sb_blkid;
ub2 v_sb_fieid;
ub2 sb_ktetb_len;
ub1 v_sb_blktyp;
};
struct datablock{
struct kcbh v_db_kcbh;
struct ktbbh v_db_ktbbh;
struct ktbbhitl *p_db_ktbbhitl;
struct kdbh v_db_kdbh;
struct kdbt *p_db_kdbt;
eb4 v_db_tbnam;
ub4 v_db_blkid;
ub2 v_db_fieid;
ub2 db_ktbbhitl_len;
ub2 db_kdbt_len;
sb2 *p_db_kdbr;
ub2 db_kdbr_len;
ub1 v_db_blktyp;
};
声明两个结构,分别用来读取段头块和数据块的信息。根据段头块信息,可以获取到所有区及数据块的分布信息。根据数据块的信息,可以知道数据块存在几个表,有多少行数据等。
二、核心代码
int main(int argc, char *argv[]){
startReadData();
return 0;
}
void startReadData(){
blkhdr v_blkhdr;
datablk v_datablk;
FILE *fp;
fp = getOracleFile("/opt/oracle/oradata/tpdb/system01.dbf", "r");
if(fp == NULL){
exit(EXIT_FAILURE);
}
v_blkhdr.v_sb_fieid = 1;
v_blkhdr.v_sb_blkid = T_OBJ_BLOCK;
v_datablk.v_db_blktyp = SYS_BLOCK;
v_datablk.v_db_tbnam = O_OBJ;
readBlockData(fp, &v_blkhdr, &v_datablk);
v_blkhdr.v_sb_blkid = C_OBJ_BLOCK;
v_datablk.v_db_blktyp = CLUSTER_BLOCk;
v_datablk.v_db_tbnam = O_TAB;
readBlockData(fp, &v_blkhdr, &v_datablk);
fclose(fp);
}
void readBlockData(FILE *fp, blkhdr *pbh, datablk *pdb){
ub4 extnum;
struct ktetb *pktetb_t;
int i;
pbh = readBlockHeader(fp, pbh);
extnum = pbh->v_sb_ktech.extents_ktech;
pbh->p_sb_ktetb = allocKtetbArray(extnum);
if( pbh->p_sb_ktetb == NULL){
exit(EXIT_FAILURE);
}
pbh->sb_ktetb_len = extnum;
pbh = readKtetbArray(fp , pbh);
pktetb_t = pbh->p_sb_ktetb;
for(i=0; iktetbdba);
pdb->v_db_fieid = ktelocate1.ktefid;
pdb->v_db_blkid = ktelocate1.ktebid;
blknums = pktetb_t->ktetbnbk;
for(j=0; jv_db_kdbh.kdbhntab;
allrows = pdb->v_db_kdbh .kdbhnrow;
if(pdb->v_db_kdbh.kdbhntab <= 0)
continue;
pdb->p_db_kdbt = allocKdbtArray(tabnums);
pdb->db_kdbt_len = tabnums;
pdb = readKdbtArray(fp, pdb);
pdb->p_db_kdbr = (sb2 *)malloc(sizeof(sb2)*allrows);
pdb->db_kdbr_len = allrows;
pdb = readKdbrArray(fp, pdb);
readObjectTab(fp, pdb);
pdb->v_db_blkid += 1;
free(pdb->p_db_kdbr);
free(pdb->p_db_kdbt);
free(pdb->p_db_ktbbhitl);
}
}
free(pbh->p_sb_ktetb);
}
void readRowData(FILE *fp, FILE *write, struct datablock *pdb, const size_t idx, const int *tab){
// sb2 tabnrow = pkdbt[idx]->kdbtnrow;
// sb2 taboffset = pkdbt->kdbtoffs;
// ub4 blkoffset = bid * blocksize;
sb2 tabnrow = (pdb->p_db_kdbt)[idx].kdbtnrow;
sb2 taboffset = (pdb->p_db_kdbt)[idx].kdbtoffs;
ub4 blkoffset = pdb->v_db_blkid * blocksize;
// struct kdtrh kdtrh1;
unsigned char colhdr[4];
int i, j;
ub2 colhdrlen;
ub2 colgap = KCBH_LEN + KTBBH_LEN + (pdb->db_ktbbhitl_len)*KTBBHITL_LEN;
if(pdb->v_db_blktyp == CLUSTER_BLOCk)
colhdrlen = 4;
else
colhdrlen = 3;
unsigned char *collen = NULL;
unsigned char *coldata = NULL;
for(i=0; ip_db_kdbr[taboffset + i];
if(rowoffset == 0xffff || rowoffset < pdb->v_db_kdbh.kdbhtosp){
continue;
}
long col0;
ub4 coloffset;
ub2 truecollen;
printf("the row is %d\n", i);
if(pdb->v_db_blktyp == CLUSTER_BLOCk){
readTabRowHeader(fp, blkoffset + rowoffset + colgap, colhdr, 4);
col0 = readObjectCobj(fp, pdb, colhdr[3]);
printf("the col %2d value is %10ld", 0, col0);
fprintf(write, "the col %2d value is %10ld", 0, col0);
}
else
readTabRowHeader(fp, blkoffset + rowoffset + colgap, colhdr, 3);
if(colhdr[2] == 0){
continue;
}
coloffset = blkoffset + rowoffset + colgap + colhdrlen;
for(j=1; jv_db_tbnam){
//if table name is TAB$
case O_TAB:
tabfp = getOracleFile("/tmp/tab.dat","a+");
readRowData(fp, tabfp, pdb, 1, tab);
break;
case O_COL:
tabfp = getOracleFile("/tmp/col.dat","a+");
readRowData(fp, tabfp, pdb, 5, col);
break;
case O_OBJ:
tabfp = getOracleFile("/tmp/obj.dat", "a+");
readRowData(fp, tabfp, pdb, 0, obj);
break;
default:
break;
}
fclose(tabfp);
}
三,数据展现
tab$数据展现
obj$表数据展现
col$表数据展现