more gmdb2 work, reorged mdbhandle

This commit is contained in:
brianb
2003-01-01 22:29:39 +00:00
parent 3c0d61076d
commit cc362c42e9
28 changed files with 893 additions and 181 deletions

View File

@@ -111,7 +111,7 @@ int i,j;
if (rowid < 0 || rowid > rows) return NULL;
offset = mdb_get_int16(mdb, (mdb->row_count_offset + 2) + 2 * rowid);
if (mdb->jet_version==MDB_VER_JET4) offset++;
if (IS_JET4(mdb)) offset++;
/*
** ??? this happens, don't know what it means
*/
@@ -132,7 +132,7 @@ fprintf(stdout,"\n");
if (j<=MDB_MAX_OBJ_NAME) {
entry->object_name[j++]=mdb->pg_buf[i];
}
if (mdb->jet_version==MDB_VER_JET4) i++;
if (IS_JET4(mdb)) i++;
}
//fprintf(stderr,"name: %s type: %d\n",entry->object_name, entry->object_type);
//fprintf(stderr,"cur page: %d row; %d\n", entry->table_pg, rowid);

View File

@@ -46,6 +46,7 @@ MdbColumn *col;
}
int mdb_find_end_of_row(MdbHandle *mdb, int row)
{
MdbFormatConstants *fmt = mdb->fmt;
int row_end;
/* Search the previous "row start" values for the first non-deleted one.
@@ -53,14 +54,14 @@ int row_end;
*/
#if 1
if (row==0) {
row_end = mdb->pg_size - 1;
row_end = fmt->pg_size - 1;
} else {
row_end = (mdb_get_int16(mdb, ((mdb->row_count_offset + 2) + (row - 1) * 2)) & 0x0FFF) - 1;
row_end = (mdb_get_int16(mdb, ((fmt->row_count_offset + 2) + (row - 1) * 2)) & 0x0FFF) - 1;
}
return row_end;
#else
for (i = row - 1; i >= 0; i--) {
row_start = mdb_get_int16(mdb, ((mdb->row_count_offset + 2) + i * 2));
row_start = mdb_get_int16(mdb, ((fmt->row_count_offset + 2) + i * 2));
if (!(row_start & 0x8000)) {
break;
}
@@ -68,7 +69,7 @@ int row_end;
row_start &= 0x0FFF;
if (i == -1) {
row_end = mdb->pg_size - 1;
row_end = fmt->pg_size - 1;
} else {
row_end = row_start - 1;
}
@@ -152,6 +153,7 @@ int ret;
int mdb_read_row(MdbTableDef *table, int row)
{
MdbHandle *mdb = table->entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
MdbColumn *col;
int i, j, rc;
int num_cols, var_cols, fixed_cols;
@@ -166,7 +168,7 @@ int col_ptr, deleted_columns=0;
unsigned char null_mask[33]; /* 256 columns max / 8 bits per byte */
unsigned char isnull;
row_start = mdb_get_int16(mdb, (mdb->row_count_offset + 2) + (row*2));
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (row*2));
row_end = mdb_find_end_of_row(mdb, row);
delflag = lookupflag = 0;
@@ -190,7 +192,7 @@ unsigned char isnull;
#endif
/* find out all the important stuff about the row */
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
num_cols = mdb_get_int16(mdb, row_start);
} else {
num_cols = mdb->pg_buf[row_start];
@@ -205,7 +207,7 @@ unsigned char isnull;
var_cols++;
}
bitmask_sz = (num_cols - 1) / 8 + 1;
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
eod = mdb_get_int16(mdb, row_end - 3 - var_cols*2 - bitmask_sz);
} else {
eod = mdb->pg_buf[row_end-1-var_cols-bitmask_sz];
@@ -219,7 +221,7 @@ unsigned char isnull;
num_cols, var_cols, eod);
#endif
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
col_start = 2;
} else {
/* data starts at 1 */
@@ -247,6 +249,7 @@ unsigned char isnull;
}
}
/* if fixed columns add up to more than 256, we need a jump */
if (col_start >= 256) {
num_of_jumps++;
jumps_used++;
@@ -254,11 +257,12 @@ unsigned char isnull;
}
col_start = row_start;
/* */
while (col_start+256 < row_end-bitmask_sz-1-var_cols-num_of_jumps){
col_start += 256;
num_of_jumps++;
}
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
col_ptr = row_end - 2 - bitmask_sz - 1;
eod = mdb_get_int16(mdb, col_ptr - var_cols*2);
col_start = mdb_get_int16(mdb, col_ptr);
@@ -298,7 +302,7 @@ unsigned char isnull;
if (var_cols_found==var_cols) {
len=eod - col_start;
} else {
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
//next_col = mdb_get_int16(mdb, row_end - bitmask_sz - var_cols_found * 2 - 2 - 1) ;
next_col = mdb->pg_buf[row_end - bitmask_sz - var_cols_found * 2 - 2] * 256 +
mdb->pg_buf[row_end - bitmask_sz - var_cols_found * 2 - 2 - 1] ;
@@ -398,12 +402,12 @@ unsigned char map_byte;
if (!map_pg) continue;
if(mdb_read_alt_pg(mdb, map_pg) != mdb->pg_size) {
if(mdb_read_alt_pg(mdb, map_pg) != mdb->fmt->pg_size) {
fprintf(stderr, "Oops! didn't get a full page at %d\n", map_pg);
exit(1);
}
//printf("reading page %ld\n",map_pg);
for (j=4;j<mdb->pg_size;j++) {
for (j=4;j<mdb->fmt->pg_size;j++) {
for (bitn=0;bitn<8;bitn++) {
if (mdb->alt_pg_buf[j] & 1 << bitn && pgnum > table->cur_phys_pg) {
table->cur_phys_pg = pgnum;
@@ -458,6 +462,7 @@ int mdb_rewind_table(MdbTableDef *table)
int mdb_fetch_row(MdbTableDef *table)
{
MdbHandle *mdb = table->entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
int rows;
int rc;
@@ -472,7 +477,7 @@ int rc;
}
do {
rows = mdb_get_int16(mdb,mdb->row_count_offset);
rows = mdb_get_int16(mdb,fmt->row_count_offset);
/* if at end of page, find a new page */
if (table->cur_row >= rows) {
@@ -559,7 +564,7 @@ guint16 len, cur;
#if MDB_DEBUG
printf("Reading LVAL page %06x\n", lval_pg);
#endif
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->pg_size) {
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->fmt->pg_size) {
/* Failed to read */
return 0;
}
@@ -568,7 +573,7 @@ guint16 len, cur;
if (ole_row) {
row_stop = mdb_get_int16(mdb, 10 + (ole_row - 1) * 2) & 0x0FFF;
} else {
row_stop = mdb->pg_size - 1;
row_stop = mdb->fmt->pg_size - 1;
}
row_start = mdb_get_int16(mdb, 10 + ole_row * 2);
#if MDB_DEBUG
@@ -589,14 +594,14 @@ guint16 len, cur;
mdb_swap_pgbuf(mdb);
cur=0;
do {
if(mdb_read_pg(mdb, lval_pg) != mdb->pg_size) {
if(mdb_read_pg(mdb, lval_pg) != mdb->fmt->pg_size) {
/* Failed to read */
return 0;
}
if (ole_row) {
row_stop = mdb_get_int16(mdb, 10 + (ole_row - 1) * 2) & 0x0FFF;
} else {
row_stop = mdb->pg_size - 1;
row_stop = mdb->fmt->pg_size - 1;
}
row_start = mdb_get_int16(mdb, 10 + ole_row * 2);
#if MDB_DEBUG
@@ -622,6 +627,7 @@ guint16 len, cur;
}
static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
{
MdbFormatConstants *fmt = mdb->fmt;
guint16 memo_len;
static char text[MDB_BIND_SIZE];
guint16 memo_flags;
@@ -658,24 +664,24 @@ int i;
#if MDB_DEBUG
printf("Reading LVAL page %06x\n", lval_pg);
#endif
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->pg_size) {
if(mdb_read_alt_pg(mdb, lval_pg) != fmt->pg_size) {
/* Failed to read */
return "";
}
/* swap the alt and regular page buffers, so we can call get_int16 */
mdb_swap_pgbuf(mdb);
if (memo_row) {
row_stop = mdb_get_int16(mdb, mdb->row_count_offset + 2 + (memo_row - 1) * 2) & 0x0FFF;
row_stop = mdb_get_int16(mdb, fmt->row_count_offset + 2 + (memo_row - 1) * 2) & 0x0FFF;
} else {
row_stop = mdb->pg_size - 1;
row_stop = fmt->pg_size - 1;
}
row_start = mdb_get_int16(mdb, mdb->row_count_offset + 2 + memo_row * 2);
row_start = mdb_get_int16(mdb, fmt->row_count_offset + 2 + memo_row * 2);
#if MDB_DEBUG
printf("row num %d row start %d row stop %d\n", memo_row, row_start, row_stop);
buffer_dump(mdb->pg_buf,row_start, row_start + len);
#endif
len = row_stop - row_start;
if (mdb->jet_version==MDB_VER_JET3) {
if (IS_JET3(mdb)) {
strncpy(text, &mdb->pg_buf[row_start], len);
text[len]='\0';
} else {
@@ -703,14 +709,14 @@ int i;
mdb_swap_pgbuf(mdb);
text[0]='\0';
do {
if(mdb_read_pg(mdb, lval_pg) != mdb->pg_size) {
if(mdb_read_pg(mdb, lval_pg) != fmt->pg_size) {
/* Failed to read */
return "";
}
if (memo_row) {
row_stop = mdb_get_int16(mdb, 10 + (memo_row - 1) * 2) & 0x0FFF;
} else {
row_stop = mdb->pg_size - 1;
row_stop = fmt->pg_size - 1;
}
row_start = mdb_get_int16(mdb, 10 + memo_row * 2);
#if MDB_DEBUG
@@ -812,7 +818,7 @@ int i,j;
if (size<0) {
return "";
}
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
/*
for (i=0;i<size;i++) {
fprintf(stdout, "%c %02x ", mdb->pg_buf[start+i], mdb->pg_buf[start+i]);

View File

@@ -19,20 +19,35 @@
#include "mdbtools.h"
MdbFormatConstants MdbJet4Constants = {
4096, 0x0c, 12, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25
};
MdbFormatConstants MdbJet3Constants = {
2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18
};
static size_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg);
MdbHandle *mdb_open(char *filename)
MdbHandle *_mdb_open(char *filename, gboolean writable)
{
MdbHandle *mdb;
int key[] = {0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e, 0x28, 0xe6, 0x13, 0xb6};
int j,pos;
mdb = mdb_alloc_handle();
mdb->filename = (char *) malloc(strlen(filename)+1);
strcpy(mdb->filename, filename);
mdb->fd = open(filename,O_RDONLY);
/* need something to bootstrap with, reassign after page 0 is read */
mdb->fmt = &MdbJet3Constants;
mdb->f = mdb_alloc_file();
mdb->f->filename = (char *) malloc(strlen(filename)+1);
strcpy(mdb->f->filename, filename);
if (writable) {
mdb->f->writable = TRUE;
mdb->f->fd = open(filename,O_RDWR);
} else {
mdb->f->fd = open(filename,O_RDONLY);
}
if (mdb->fd==-1) {
if (mdb->f->fd==-1) {
/* fprintf(stderr,"Couldn't open file %s\n",filename); */
return NULL;
}
@@ -40,42 +55,16 @@ int j,pos;
fprintf(stderr,"Couldn't read first page.\n");
return NULL;
}
mdb->jet_version = mdb_get_int32(mdb, 0x14);
if (mdb->jet_version == MDB_VER_JET4) {
mdb->pg_size = 4096;
mdb->row_count_offset = 0x0c;
mdb->tab_num_rows_offset = 12;
mdb->tab_num_cols_offset = 45;
mdb->tab_num_idxs_offset = 47;
mdb->tab_num_ridxs_offset = 51;
mdb->tab_usage_map_offset = 55;
mdb->tab_first_dpg_offset = 56;
mdb->tab_cols_start_offset = 63;
mdb->tab_ridx_entry_size = 12;
mdb->col_fixed_offset = 15;
mdb->col_size_offset = 23;
mdb->col_num_offset = 5;
mdb->tab_col_entry_size = 25;
mdb->f->jet_version = mdb_get_int32(mdb, 0x14);
if (IS_JET4(mdb)) {
mdb->fmt = &MdbJet4Constants;
} else {
mdb->pg_size = 2048;
mdb->row_count_offset = 0x08;
mdb->tab_num_rows_offset = 12;
mdb->tab_num_cols_offset = 25;
mdb->tab_num_idxs_offset = 27;
mdb->tab_num_ridxs_offset = 31;
mdb->tab_usage_map_offset = 35;
mdb->tab_first_dpg_offset = 36;
mdb->tab_cols_start_offset = 43;
mdb->tab_ridx_entry_size = 8;
mdb->col_fixed_offset = 13;
mdb->col_size_offset = 16;
mdb->col_num_offset = 1;
mdb->tab_col_entry_size = 18;
mdb->fmt = &MdbJet3Constants;
}
/* get the db encryption key and xor it back to clear text */
mdb->db_key = mdb_get_int32(mdb, 0x3e);
mdb->db_key ^= 0xe15e01b9;
mdb->f->db_key = mdb_get_int32(mdb, 0x3e);
mdb->f->db_key ^= 0xe15e01b9;
/* get the db password located at 0x42 bytes into the file */
@@ -83,22 +72,22 @@ int j,pos;
j = mdb_get_int32(mdb,0x42+pos);
j ^= key[pos];
if ( j != 0)
mdb->db_passwd[pos] = j;
mdb->f->db_passwd[pos] = j;
else
mdb->db_passwd[pos] = '\0';
mdb->f->db_passwd[pos] = '\0';
}
return mdb;
}
MdbHandle *mdb_open(char *filename)
{
return _mdb_open(filename, FALSE);
}
void mdb_close(MdbHandle *mdb)
{
if (mdb->fd > 0) {
close(mdb->fd);
if (mdb->filename) {
free(mdb->filename);
mdb->filename = NULL;
}
if (mdb->f) {
mdb_free_file(mdb->f);
}
}
@@ -125,21 +114,21 @@ static size_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long
{
size_t len;
struct stat status;
off_t offset = pg * mdb->pg_size;
off_t offset = pg * mdb->fmt->pg_size;
fstat(mdb->fd, &status);
fstat(mdb->f->fd, &status);
if (status.st_size < offset) {
fprintf(stderr,"offset %lu is beyond EOF\n",offset);
return 0;
}
lseek(mdb->fd, offset, SEEK_SET);
len = read(mdb->fd,pg_buf,mdb->pg_size);
lseek(mdb->f->fd, offset, SEEK_SET);
len = read(mdb->f->fd,pg_buf,mdb->fmt->pg_size);
if (len==-1) {
perror("read");
return 0;
}
else if (len<mdb->pg_size) {
/* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->pg_size); */
else if (len<mdb->fmt->pg_size) {
/* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->fmt->pg_size); */
return 0;
}
return len;
@@ -160,14 +149,18 @@ unsigned char c;
mdb->cur_pos++;
return c;
}
int _mdb_get_int16(unsigned char *buf, int offset)
{
return buf[offset+1]*256+buf[offset];
}
int mdb_get_int16(MdbHandle *mdb, int offset)
{
unsigned char *c;
int i;
if (offset < 0 || offset+2 > mdb->pg_size) return -1;
c = &mdb->pg_buf[offset];
i = c[1]*256+c[0];
if (offset < 0 || offset+2 > mdb->fmt->pg_size) return -1;
i = _mdb_get_int16(mdb->pg_buf, offset);
mdb->cur_pos+=2;
return i;
@@ -178,7 +171,7 @@ gint32 mdb_get_int24(MdbHandle *mdb, int offset)
gint32 l;
unsigned char *c;
if (offset <0 || offset+3 > mdb->pg_size) return -1;
if (offset <0 || offset+3 > mdb->fmt->pg_size) return -1;
c = &mdb->pg_buf[offset];
l =c[2]; l<<=8;
l+=c[1]; l<<=8;
@@ -204,7 +197,7 @@ long mdb_get_int32(MdbHandle *mdb, int offset)
{
long l;
if (offset <0 || offset+4 > mdb->pg_size) return -1;
if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1;
l = _mdb_get_int32(mdb->pg_buf, offset);
mdb->cur_pos+=4;
@@ -216,7 +209,7 @@ float f, f2;
unsigned char *c;
int i;
if (offset <0 || offset+4 > mdb->pg_size) return -1;
if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1;
memcpy(&f, &mdb->pg_buf[offset], 4);
@@ -237,7 +230,7 @@ double d, d2;
unsigned char *c;
int i;
if (offset <0 || offset+4 > mdb->pg_size) return -1;
if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1;
memcpy(&d, &mdb->pg_buf[offset], 8);
@@ -254,7 +247,7 @@ int i;
}
int mdb_set_pos(MdbHandle *mdb, int pos)
{
if (pos<0 || pos >= mdb->pg_size) return 0;
if (pos<0 || pos >= mdb->fmt->pg_size) return 0;
mdb->cur_pos=pos;
return pos;

View File

@@ -106,7 +106,8 @@ int name_sz;
pidx->num_keys = key_num;
cur_pos += 4;
pidx->first_pg = mdb_get_int32(mdb, cur_pos);
cur_pos += 5;
cur_pos += 4;
pidx->flags = mdb->pg_buf[cur_pos++];
}
}
void mdb_index_walk(MdbTableDef *table, MdbIndex *idx)
@@ -140,10 +141,11 @@ MdbColumn *col;
if (idx->index_type==1) fprintf(stdout,"index is a primary key\n");
for (i=0;i<idx->num_keys;i++) {
col=g_ptr_array_index(table->columns,idx->key_col_num[i]-1);
fprintf(stdout,"Column %s(%d) Sorted %s\n",
fprintf(stdout,"Column %s(%d) Sorted %s Unique: %s\n",
col->name,
idx->key_col_num[i],
idx->key_col_order[i]==MDB_ASC ? "ascending" : "descending"
idx->key_col_order[i]==MDB_ASC ? "ascending" : "descending",
idx->flags & MDB_IDX_UNIQUE ? "Yes" : "No"
);
}
mdb_index_walk(table, idx);

View File

@@ -116,10 +116,10 @@ int rowid = entry->kkd_rowid;
fprintf(stdout,"number of rows = %d\n",rows);
kkd_start = mdb_get_int16(mdb,10+rowid*2);
fprintf(stdout,"kkd start = %d %04x\n",kkd_start,kkd_start);
kkd_end = mdb->pg_size;
kkd_end = mdb->fmt->pg_size;
for (i=0;i<rows;i++) {
tmp = mdb_get_int16(mdb, 10+i*2);
if (tmp < mdb->pg_size &&
if (tmp < mdb->fmt->pg_size &&
tmp > kkd_start &&
tmp < kkd_end) {
kkd_end = tmp;

View File

@@ -30,13 +30,28 @@ void mdb_exit()
g_hash_table_destroy(mdb_backends);
}
MdbFile *mdb_alloc_file()
{
MdbHandle *f;
f = (MdbFile *) malloc(sizeof(MdbFile));
memset(f, '\0', sizeof(MdbFile));
return f;
}
void mdb_free_file(MdbFile *f)
{
if (!f) return;
if (f->fd) close(f->fd);
if (f->filename) free(f->filename);
free(f);
}
MdbHandle *mdb_alloc_handle()
{
MdbHandle *mdb;
mdb = (MdbHandle *) malloc(sizeof(MdbHandle));
memset(mdb, '\0', sizeof(MdbHandle));
mdb->pg_size = MDB_PGSIZE;
mdb_set_default_backend(mdb, "access");
return mdb;
@@ -45,8 +60,8 @@ void mdb_free_handle(MdbHandle *mdb)
{
if (!mdb) return;
if (mdb->filename) free(mdb->filename);
if (mdb->catalog) mdb_free_catalog(mdb);
if (mdb->f) mdb_free_file(mdb->f);
if (mdb->backend_name) free(mdb->backend_name);
free(mdb);
}

View File

@@ -44,6 +44,7 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
{
MdbTableDef *table;
MdbHandle *mdb = entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
int len, i;
int rownum, row_start, row_end;
@@ -52,16 +53,16 @@ int rownum, row_start, row_end;
mdb_read_pg(mdb, entry->table_pg);
len = mdb_get_int16(mdb,8);
table->num_rows = mdb_get_int32(mdb, mdb->tab_num_rows_offset);
table->num_cols = mdb_get_int16(mdb, mdb->tab_num_cols_offset);
table->num_idxs = mdb_get_int32(mdb, mdb->tab_num_idxs_offset);
table->num_real_idxs = mdb_get_int32(mdb, mdb->tab_num_ridxs_offset);
table->num_rows = mdb_get_int32(mdb, fmt->tab_num_rows_offset);
table->num_cols = mdb_get_int16(mdb, fmt->tab_num_cols_offset);
table->num_idxs = mdb_get_int32(mdb, fmt->tab_num_idxs_offset);
table->num_real_idxs = mdb_get_int32(mdb, fmt->tab_num_ridxs_offset);
/* grab a copy of the usage map */
rownum = mdb->pg_buf[mdb->tab_usage_map_offset];
mdb_read_alt_pg(mdb, mdb_get_int24(mdb, mdb->tab_usage_map_offset + 1));
rownum = mdb->pg_buf[fmt->tab_usage_map_offset];
mdb_read_alt_pg(mdb, mdb_get_int24(mdb, fmt->tab_usage_map_offset + 1));
mdb_swap_pgbuf(mdb);
row_start = mdb_get_int16(mdb, (mdb->row_count_offset + 2) + (rownum*2));
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (rownum*2));
row_end = mdb_find_end_of_row(mdb, rownum);
table->map_sz = row_end - row_start + 1;
table->usage_map = malloc(table->map_sz);
@@ -72,11 +73,11 @@ int rownum, row_start, row_end;
/* swap back */
mdb_swap_pgbuf(mdb);
#if MDB_DEBUG_USAGE
printf ("usage map found on page %ld start %d end %d\n", mdb_get_int24(mdb, mdb->tab_usage_map_offset + 1), row_start, row_end);
printf ("usage map found on page %ld start %d end %d\n", mdb_get_int24(mdb, fmt->tab_usage_map_offset + 1), row_start, row_end);
#endif
table->first_data_pg = mdb_get_int16(mdb, mdb->tab_first_dpg_offset);
table->first_data_pg = mdb_get_int16(mdb, fmt->tab_first_dpg_offset);
return table;
}
@@ -87,9 +88,9 @@ int rownum, row_start, row_end;
*/
static int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset)
{
if (*cur_pos + offset >= mdb->pg_size) {
if (*cur_pos + offset >= mdb->fmt->pg_size) {
mdb_read_pg(mdb, mdb_get_int32(mdb,4));
*cur_pos = 8 - (mdb->pg_size - (*cur_pos));
*cur_pos = 8 - (mdb->fmt->pg_size - (*cur_pos));
return 1;
}
return 0;
@@ -98,6 +99,7 @@ static int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset)
GPtrArray *mdb_read_columns(MdbTableDef *table)
{
MdbHandle *mdb = table->entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
MdbColumn col, *pcol;
int len, i,j;
unsigned char low_byte, high_byte;
@@ -109,8 +111,8 @@ GSList *slist = NULL;
table->columns = g_ptr_array_new();
cur_col = mdb->tab_cols_start_offset +
(table->num_real_idxs * mdb->tab_ridx_entry_size);
cur_col = fmt->tab_cols_start_offset +
(table->num_real_idxs * fmt->tab_ridx_entry_size);
/* new code based on patch submitted by Tim Nelson 2000.09.27 */
@@ -123,7 +125,7 @@ GSList *slist = NULL;
buffer_dump(mdb->pg_buf, cur_col ,cur_col + 18); */
#endif
memset(&col, 0, sizeof(col));
col.col_num = mdb->pg_buf[cur_col + mdb->col_num_offset];
col.col_num = mdb->pg_buf[cur_col + fmt->col_num_offset];
read_pg_if(mdb, &cur_col, 0);
col.col_type = mdb->pg_buf[cur_col];
@@ -134,20 +136,20 @@ GSList *slist = NULL;
}
read_pg_if(mdb, &cur_col, 13);
col.is_fixed = mdb->pg_buf[cur_col + mdb->col_fixed_offset] &
col.is_fixed = mdb->pg_buf[cur_col + fmt->col_fixed_offset] &
0x01 ? 1 : 0;
if (col.col_type != MDB_BOOL) {
read_pg_if(mdb, &cur_col, 17);
low_byte = mdb->pg_buf[cur_col + mdb->col_size_offset];
low_byte = mdb->pg_buf[cur_col + fmt->col_size_offset];
read_pg_if(mdb, &cur_col, 18);
high_byte = mdb->pg_buf[cur_col + mdb->col_size_offset + 1];
high_byte = mdb->pg_buf[cur_col + fmt->col_size_offset + 1];
col.col_size += high_byte * 256 + low_byte;
} else
col.col_size=0;
pcol = g_memdup(&col, sizeof(MdbColumn));
slist = g_slist_insert_sorted(slist,pcol,(GCompareFunc)mdb_col_comparer);
cur_col += mdb->tab_col_entry_size;
cur_col += fmt->tab_col_entry_size;
}
cur_name = cur_col;
@@ -163,12 +165,12 @@ GSList *slist = NULL;
read_pg_if(mdb, &cur_name, 0);
name_sz = mdb->pg_buf[cur_name];
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
/* FIX ME - for now just skip the high order byte */
cur_name += 2;
/* determine amount of name on this page */
len = ((cur_name + name_sz) > mdb->pg_size) ?
mdb->pg_size - cur_name :
len = ((cur_name + name_sz) > fmt->pg_size) ?
fmt->pg_size - cur_name :
name_sz;
/* strip high order (second) byte from unicode string */
@@ -179,7 +181,7 @@ GSList *slist = NULL;
if (len < name_sz) {
/* read the next pg */
mdb_read_pg(mdb, mdb_get_int32(mdb,4));
cur_name = 8 - (mdb->pg_size - cur_name);
cur_name = 8 - (fmt->pg_size - cur_name);
if (len % 2) cur_name++;
/* get the rest of the name */
for (j=0;j<len;j+=2) {
@@ -189,10 +191,10 @@ GSList *slist = NULL;
pcol->name[name_sz]='\0';
cur_name += name_sz;
} else if (mdb->jet_version==MDB_VER_JET3) {
} else if (IS_JET3(mdb)) {
/* determine amount of name on this page */
len = ((cur_name + name_sz) > mdb->pg_size) ?
mdb->pg_size - cur_name :
len = ((cur_name + name_sz) > fmt->pg_size) ?
fmt->pg_size - cur_name :
name_sz;
if (len) {
@@ -202,7 +204,7 @@ GSList *slist = NULL;
if (len < name_sz) {
/* read the next pg */
mdb_read_pg(mdb, mdb_get_int32(mdb,4));
cur_name = 8 - (mdb->pg_size - cur_name);
cur_name = 8 - (fmt->pg_size - cur_name);
/* get the rest of the name */
memcpy(&pcol->name[len], &mdb->pg_buf[cur_name], name_sz - len);
}
@@ -229,6 +231,7 @@ void mdb_table_dump(MdbCatalogEntry *entry)
{
MdbTableDef *table;
MdbColumn *col;
int coln;
MdbIndex *idx;
MdbHandle *mdb = entry->mdb;
int i,bitn;
@@ -258,12 +261,20 @@ int pgnum;
mdb_index_dump(table, idx);
}
if (table->usage_map) {
printf("pages reserved by this object\n",pgnum);
pgnum = _mdb_get_int32(table->usage_map,1);
/* the first 5 bytes of the usage map mean something */
coln = 0;
for (i=5;i<table->map_sz;i++) {
for (bitn=0;bitn<8;bitn++) {
if (table->usage_map[i] & 1 << bitn)
printf("page %ld is reserved by this object\n",pgnum);
if (table->usage_map[i] & 1 << bitn) {
coln++;
printf("%6ld ",pgnum);
if (coln==10) {
printf("\n");
coln = 0;
}
}
pgnum++;
}
}

View File

@@ -26,11 +26,57 @@
typedef struct {
void *value;
int siz;
int start;
unsigned char is_null;
unsigned char is_fixed;
int colnum;
int offset;
} MdbField;
void
_mdb_put_int16(unsigned char *buf, guint32 offset, guint32 value)
{
buf[offset] = value % 256;
value /= 256;
buf[offset+1] = value % 256;
}
void
_mdb_put_int32(unsigned char *buf, guint32 offset, guint32 value)
{
buf[offset] = value % 256;
value /= 256;
buf[offset+1] = value % 256;
value /= 256;
buf[offset+2] = value % 256;
value /= 256;
buf[offset+3] = value % 256;
}
size_t
mdb_write_pg(MdbHandle *mdb, unsigned long pg)
{
size_t len;
struct stat status;
off_t offset = pg * mdb->fmt->pg_size;
fstat(mdb->f->fd, &status);
/* is page beyond current size + 1 ? */
if (status.st_size < offset + mdb->fmt->pg_size) {
fprintf(stderr,"offset %lu is beyond EOF\n",offset);
return 0;
}
lseek(mdb->f->fd, offset, SEEK_SET);
len = write(mdb->f->fd,mdb->pg_buf,mdb->fmt->pg_size);
if (len==-1) {
perror("write");
return 0;
} else if (len<mdb->fmt->pg_size) {
/* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->pg_size); */
return 0;
}
mdb->cur_pos = 0;
return len;
}
static int
mdb_is_col_indexed(MdbTableDef *table, int colnum)
{
@@ -51,15 +97,16 @@ mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields)
MdbCatalogEntry *entry = table->entry;
MdbHandle *mdb = entry->mdb;
MdbColumn *col;
int var_cols, fixed_cols, num_cols, i, totcols;
int i, j;
int var_cols, fixed_cols, num_cols, totcols;
int var_cols_found, fixed_cols_found, var_entry_pos;
int col_start, next_col;
unsigned char *nullmask;
int bitmask_sz;
int byte_num, bit_num;
int eod, len; /* end of data */
printf("field 0 %s\n", fields[0].value);
if (mdb->jet_version==MDB_VER_JET4) {
if (IS_JET4(mdb)) {
num_cols = mdb_get_int16(mdb, row_start);
} else {
num_cols = mdb->pg_buf[row_start];
@@ -72,17 +119,17 @@ int byte_num, bit_num;
col = g_ptr_array_index (table->columns, i);
if (mdb_is_fixed_col(col)) {
fixed_cols++;
fields[totcols++].colnum = i;
fields[totcols].colnum = i;
fields[totcols].siz = col->col_size;
fields[totcols].is_fixed = 1;
fields[totcols++].is_fixed = 1;
}
}
for (i = 0; i < table->num_cols; i++) {
col = g_ptr_array_index (table->columns, i);
if (!mdb_is_fixed_col(col)) {
var_cols++;
fields[totcols++].colnum = i;
fields[totcols].is_fixed = 0;
fields[totcols].colnum = i;
fields[totcols++].is_fixed = 0;
}
}
@@ -97,25 +144,142 @@ int byte_num, bit_num;
printf("col %d is %s\n", i, fields[i].is_null ? "null" : "not null");
}
/* find the end of data pointer */
if (IS_JET4(mdb)) {
eod = mdb_get_int16(mdb, row_end - 3 - var_cols*2 - bitmask_sz);
} else {
eod = mdb->pg_buf[row_end-1-var_cols-bitmask_sz];
}
printf("eod is %d\n", eod);
if (IS_JET4(mdb)) {
col_start = 2;
} else {
/* data starts at 1 */
col_start = 1;
}
/* actual cols on this row */
fixed_cols_found = 0;
var_cols_found = 0;
totcols = 0;
/* loop through fixed columns and add values to fields[] */
for (j=0;j<table->num_cols;j++) {
col = g_ptr_array_index(table->columns,j);
if (mdb_is_fixed_col(col) && ++fixed_cols_found <= fixed_cols) {
fields[totcols].start = row_start + col_start;
fields[totcols++].value = &mdb->pg_buf[row_start + col_start];
if (col->col_type != MDB_BOOL)
col_start += col->col_size;
}
}
for (j=0;j<table->num_cols;j++) {
col = g_ptr_array_index(table->columns,j);
if (!mdb_is_fixed_col(col) && ++var_cols_found <= var_cols) {
if (var_cols_found==var_cols) {
len=eod - col_start;
printf("len = %d eod %d col_start %d\n",len, eod, col_start);
} else {
if (IS_JET4(mdb)) {
/* position of the var table
* entry for this column */
var_entry_pos =
row_end -
bitmask_sz -
var_cols_found * 2 - 2 - 1;
next_col = mdb_get_int16(mdb, var_entry_pos);
len = next_col - col_start;
} else {
var_entry_pos =
row_end -
bitmask_sz -
var_cols_found - 1;
len=mdb->pg_buf[var_entry_pos] - mdb->pg_buf[var_entry_pos+1];
printf("%d %d %d %d\n", mdb->pg_buf[var_entry_pos-1],mdb->pg_buf[var_entry_pos],len, col_start);
}
} /* if found==var_cols */
if (len<0) len+=256;
fields[totcols].start = row_start + col_start;
fields[totcols].value = &mdb->pg_buf[row_start +col_start];
fields[totcols++].siz = len;
col_start += len;
} /* if !fixed */
} /* for */
return num_cols;
}
/* fields must be ordered with fixed columns first, then vars, subsorted by
* column number */
int
mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, MdbField *fields)
mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, int num_fields, MdbField *fields)
{
int pos = 0;
int var_cols = 0;
unsigned char bit, byte;
int i;
row_buffer[pos++] = num_fields;
for (i=0;i<num_fields;i++) {
if (fields[i].is_fixed) {
fields[i].offset = pos;
memcpy(&row_buffer[pos], fields[i].value, fields[i].siz);
pos += fields[i].siz;
}
}
for (i=0;i<num_fields;i++) {
if (!fields[i].is_fixed) {
var_cols++;
fields[i].offset = pos;
memcpy(&row_buffer[pos], fields[i].value, fields[i].siz);
pos += fields[i].siz;
}
}
/* EOD */
row_buffer[pos++] = pos;
for (i=num_fields-1;i>=num_fields - var_cols;i--) {
row_buffer[pos++] = fields[i].offset % 256;
}
row_buffer[pos++] = var_cols;
byte = 0;
bit = 0;
for (i=0;i<num_fields;i++) {
/* column is null is bit is clear (0) */
if (!fields[i].is_null) {
byte |= 1 << bit;
printf("%d %d %d %d\n", i, bit, 1 << bit, byte);
}
bit++;
if (bit==8) {
row_buffer[pos++] = byte;
bit=0;
byte = 0;
}
}
/* if we've written any bits to the current byte, flush it*/
if (bit)
row_buffer[pos++] = byte;
return pos;
}
int
mdb_pg_get_freespace(MdbHandle *mdb)
{
MdbFormatConstants *fmt = mdb->fmt;
int rows, free_start, free_end;
rows = mdb_get_int16(mdb, mdb->row_count_offset);
free_start = mdb->row_count_offset + 2 + (rows * 2);
free_end = mdb_get_int16(mdb, (mdb->row_count_offset + rows * 2)) -1;
rows = mdb_get_int16(mdb, fmt->row_count_offset);
free_start = fmt->row_count_offset + 2 + (rows * 2);
free_end = mdb_get_int16(mdb, (fmt->row_count_offset + rows * 2)) -1;
#if MDB_DEBUG_WRITE
printf("free space left on page = %d\n", free_end - free_start);
#endif
return (free_end - free_start);
return (free_end - free_start + 1);
}
int
mdb_update_row(MdbTableDef *table)
@@ -125,18 +289,26 @@ int i;
MdbColumn *col;
MdbCatalogEntry *entry = table->entry;
MdbHandle *mdb = entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
MdbField fields[256];
unsigned char row_buffer[4096];
int old_row_size, new_row_size, delta, num_fields;
fields[0].value = "hello";
row_start = mdb_get_int16(mdb, (mdb->row_count_offset + 2) + (table->cur_row*2));
row_end = mdb_find_end_of_row(mdb, table->cur_row);
if (!mdb->f->writable) {
fprintf(stderr, "File is not open for writing\n");
return 0;
}
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + ((table->cur_row-1)*2));
row_end = mdb_find_end_of_row(mdb, table->cur_row-1);
old_row_size = row_end - row_start;
row_start &= 0x0FFF; /* remove flags */
#if MDB_DEBUG_WRITE
printf("page %lu row %d start %d end %d\n", table->cur_phys_pg, table->cur_row-1, row_start, row_end);
buffer_dump(mdb->pg_buf, row_start, row_end);
#endif
for (i=0;i<table->num_cols;i++) {
col = g_ptr_array_index(table->columns,i);
if (col->bind_ptr && mdb_is_col_indexed(table,i)) {
@@ -148,13 +320,95 @@ int old_row_size, new_row_size, delta, num_fields;
#if MDB_DEBUG_WRITE
for (i=0;i<num_fields;i++) {
printf("col %d %d start %d siz %d\n", i, fields[i].colnum, fields[i].start, fields[i].siz);
}
#endif
for (i=0;i<table->num_cols;i++) {
col = g_ptr_array_index(table->columns,i);
if (col->bind_ptr) {
printf("yes\n");
fields[i].value = col->bind_ptr;
fields[i].siz = *(col->len_ptr);
}
}
new_row_size = mdb_pack_row(table, row_buffer, &fields);
new_row_size = mdb_pack_row(table, row_buffer, num_fields, &fields);
#if MDB_DEBUG_WRITE
buffer_dump(row_buffer, 0, new_row_size-1);
#endif
delta = new_row_size - old_row_size;
if ((mdb_pg_get_freespace(mdb) - delta) < 0) {
fprintf(stderr, "No space left on this page, update will not occur\n");
return 0;
}
/* do it! */
mdb_replace_row(table, table->cur_row-1, row_buffer, new_row_size);
}
int
mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size)
{
MdbCatalogEntry *entry = table->entry;
MdbHandle *mdb = entry->mdb;
MdbFormatConstants *fmt = mdb->fmt;
unsigned char *new_pg;
guint16 num_rows;
int row_start, row_end, row_size;
int i, pos;
#if MDB_DEBUG_WRITE
buffer_dump(mdb->pg_buf, 0, 39);
buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1);
printf("updating row %d on page %lu\n", row, table->cur_phys_pg);
#endif
new_pg = (unsigned char *) g_malloc0(fmt->pg_size);
g_free(new_pg);
new_pg[0]=0x01;
new_pg[1]=0x01;
_mdb_put_int32(new_pg, 4, entry->table_pg);
num_rows = mdb_get_int16(mdb, fmt->row_count_offset);
_mdb_put_int16(new_pg, fmt->row_count_offset, num_rows);
pos = mdb->fmt->pg_size;
/* rows before */
for (i=0;i<row;i++) {
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (i*2));
row_end = mdb_find_end_of_row(mdb, i);
row_size = row_end - row_start + 1;
pos -= row_size;
memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size);
_mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos);
}
/* our row */
pos -= new_row_size;
memcpy(&new_pg[pos], new_row, new_row_size);
_mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (row*2), pos);
/* rows after */
for (i=row+1;i<num_rows;i++) {
row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (i*2));
row_end = mdb_find_end_of_row(mdb, i);
row_size = row_end - row_start + 1;
pos -= row_size;
memcpy(&new_pg[pos], &mdb->pg_buf[row_start], row_size);
_mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos);
}
/* almost done, copy page over current */
memcpy(mdb->pg_buf, new_pg, fmt->pg_size);
_mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb));
#if MDB_DEBUG_WRITE
buffer_dump(mdb->pg_buf, 0, 39);
buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1);
#endif
/* drum roll, please */
if (!mdb_write_pg(mdb, table->cur_phys_pg)) {
fprintf(stderr, "write failed! exiting...\n");
exit(1);
}
}