diff --git a/ChangeLog b/ChangeLog index ba478db..8c7d45c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sat Mar 16 21:37:01 EST 2002 Brian Bruns + + * include/mdbtools.h: added oam usage map fields to TableDef + * src/extras/mdb-dump.c: added JET4 support + * src/libmdb/data.c: added code to check for unicode compression + * src/libmdb/mem.c(mdb_free_tabledef): clean up for oam fields + 2002-03-15 Brian Bruns * src/libmdb/money.c: Two's complement fix from diff --git a/HACKING b/HACKING index dd68e3f..53a7740 100644 --- a/HACKING +++ b/HACKING @@ -11,8 +11,9 @@ Pages ----- MDB files are a set of pages. These pages are 2K (2048 bytes) in size, so in a -hex dump of the data they start on adreeses like xxx000 and xxx800. Acess 2000 -has increased the page size to 4K. +hex dump of the data they start on addreeses like xxx000 and xxx800. Access +2000 has increased the page size to 4K and thus pages would appear on hex +addresses ending in xxx000. Each page is known by a page_id of 3 bytes (max value is 0x07FFFF). The start adresse of a page is at page_id * 0x800. @@ -51,7 +52,7 @@ The second byte is always 0x01 as far as I can tell. At some point in the file the page layout is apparently abandoned though the very last 2K in the file again looks like a valid page. The purpose of this -non-paged region is so far unknown. Could be a corrupt db as well. +non-paged region is so far unknown. Could be a corrupt db as well. My current thinking is that this area is unallocated pages based on the GAM (global allocation map stored on page 0x01). Bytes after the first and second seemed to depend on the type of page, although bytes 4-7 seem to indicate a page type of some sort. 02 00 00 00 is found on all catalog pages. @@ -279,7 +280,7 @@ Notes for offset_row: (These flags are delflag and lookupflag in source code) -Each data row looks like this: +Each data row looks like this (JET3): +------+---------+----------------------------------------------------------+ | data | length | name | description | @@ -299,6 +300,22 @@ Note: For boolean fixed columns, the values are in null_table[]: 0 indicates a false value 1 indicates a true value +In Access 2000 (JET4) data rows are like this + ++------+---------+----------------------------------------------------------+ +| data | length | name | description | ++------+---------+----------------------------------------------------------+ +| ???? | 2 bytes | num_cols | Number of columns stored in this row | +| ???? | n bytes | | Fixed length columns | +| ???? | n bytes | | Variable length columns | +| ???? | 2 bytes | fixed_len | length of data from beginning of record | +| ???? | n bytes | var_table[] | offset from start of row for each variable | +| | | | length column. (2 bytes per var column) | +| ???? | 2 bytes | var_len | number of variable length columns | +| ???? | n bytes | null_table[]| Null indicator. size is 1 byte per 8 cols. | +| | | | 0 indicates a null value. | ++------+---------+----------------------------------------------------------+ + Note: it is possible for the offset to the beginning of a variable length column to require more than one byte (if the sum of the lengths of columns is greater than 255). I have no idea how this is represented in the data as I diff --git a/include/mdbtools.h b/include/mdbtools.h index fb328e0..11b6213 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -152,6 +152,11 @@ typedef struct { int cur_phys_pg; int cur_row; int noskip_del; /* don't skip deleted rows */ + /* object allocation map */ + int map_base_pg; + int map_sz; + unsigned char *usage_map; + /* */ } MdbTableDef; typedef struct { diff --git a/src/extras/mdb-dump.c b/src/extras/mdb-dump.c index 13aef2c..7cda5aa 100644 --- a/src/extras/mdb-dump.c +++ b/src/extras/mdb-dump.c @@ -10,6 +10,11 @@ #include #include #include +#include +#include +#include +#include +#include int main(int argc, char **argv) { @@ -20,8 +25,9 @@ int main(int argc, char **argv) int length; int pg=0; char addr[10]; + int jet4 = 0; - if (argc < 2) { + if (argc < 1) { fprintf(stderr, "Usage: mdb-dump \n\n"); exit(1); } @@ -29,9 +35,15 @@ int main(int argc, char **argv) fprintf(stderr, "Couldn't open file %s\n", argv[1]); exit(1); } + fseek(in,0x14,SEEK_SET); + fread(data,1,1,in); + if (data[0]==0x01) { + jet4 = 1; + } + fseek(in,0,SEEK_SET); while (length = fread(data,1,16,in)) { sprintf(addr, "%06x", i); - if (!strcmp(&addr[3],"000") ) { //|| ! strcmp(&addr[3],"800")) { + if (!strcmp(&addr[3],"000") || (!jet4 && !strcmp(&addr[3],"800"))) { fprintf(stdout,"-- Page 0x%04x (%d) --\n", pg, pg); pg++; } diff --git a/src/libmdb/data.c b/src/libmdb/data.c index f1f591f..7588965 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -433,9 +433,22 @@ int i; return ""; } if (mdb->jet_version==MDB_VER_JET4) { - for (i=0;ipg_buf[start + i]; - text[size/2]='\0'; +/* + for (i=0;ipg_buf[start+i], mdb->pg_buf[start+i]); + } + fprintf(stdout, "\n"); +*/ + if (mdb->pg_buf[start]==0xff && + mdb->pg_buf[start+1]==0xfe) { + strncpy(text, &mdb->pg_buf[start+2], size-2); + text[size-2]='\0'; + } else { + /* convert unicode to ascii, rather sloppily */ + for (i=0;ipg_buf[start + i]; + text[size/2]='\0'; + } } else { strncpy(text, &mdb->pg_buf[start], size); text[size]='\0'; diff --git a/src/libmdb/mem.c b/src/libmdb/mem.c index 7648bc5..2fc04e8 100644 --- a/src/libmdb/mem.c +++ b/src/libmdb/mem.c @@ -73,6 +73,7 @@ MdbTableDef *table; } void mdb_free_tabledef(MdbTableDef *table) { + if (table->usage_map) free(table->usage_map); if (table) free(table); } mdb_append_column(GPtrArray *columns, MdbColumn *in_col)