diff --git a/HACKERS b/HACKERS index 3e3c3ba..487db23 100644 --- a/HACKERS +++ b/HACKERS @@ -93,8 +93,8 @@ Column Definition ----------------- The second and third bytes of each catalog entry store a 16 bit page pointer to -a column definition, including name, type, size and possibly more. I haven't -fully figured this out so what follows is rough. +a column definition, including name, type, size, number of datarows, a pointer +to the first data page, and possibly more. I haven't fully figured this out so what follows is rough. The header to table definition pages start look something like this: @@ -103,13 +103,27 @@ The header to table definition pages start look something like this: | 0x01 | 1 byte | Unknown | | 'VC' | 2 bytes | ??? | | 0x00 | 4 bytes | Unknown | -| ???? | 2 bytes | appears to be a length of the data | -| 0x00 |10 bytes | ??? | +| ???? | 4 bytes | appears to be a length of the data | +| ???? | 4 bytes | number of rows of data in this table | +| 0x00 | 4 bytes | ??? | | 0x4e | 1 byte | ??? | -| ???? | 2 bytes | ranges from 1 to 3ish | -| ???? | 2 bytes | ranges from 1 to 3ish | -| ???? | 1 byte | number of columns in table | +| ???? | 2 bytes | generally same as # of cols but not always | +| ???? | 2 bytes | ??? | +| ???? | 2 bytes | number of columns in table | +| ???? | 4 bytes | number of data pages in table | +| ???? | 4 bytes | number of data pages in table (repeat) | +| 0x00 | 1 byte | ??? | +| ???? | 2 bytes | page number of first datapage for table | +| ???? | 2 bytes | ??? | +| ???? | 2 bytes | page number of first datapage for table | +| 0x00 | 1 byte | ??? | +-------------------------------------------------------------------------+ +| Iterate for the 2 x number of datapages | ++-------------------------------------------------------------------------+ +| ???? | 4 bytes | number of rows in table | +| ???? | 4 bytes | ??? | ++-------------------------------------------------------------------------+ + The next few bytes are somewhat of a mystery right now, but around 0x2B from the start of the page (though not always) begins a series of 18 byte records one for each column present. It's format is as follows: diff --git a/src/include/mdbtools.h b/src/include/mdbtools.h index cce87d5..e3ff108 100644 --- a/src/include/mdbtools.h +++ b/src/include/mdbtools.h @@ -47,6 +47,13 @@ enum { MDB_UNKNOWN_0A, MDB_UNKNOWN_0B }; +enum { + MDB_INT = 0x03, + MDB_LONGINT = 0x04, + MDB_SDATETIME = 0x08, + MDB_TEXT = 0x0a, + MDB_HYPERLINK = 0x0c +}; typedef struct { int fd; diff --git a/src/libmdb/Makefile b/src/libmdb/Makefile index 159cae3..1499fe2 100644 --- a/src/libmdb/Makefile +++ b/src/libmdb/Makefile @@ -2,7 +2,7 @@ CC = gcc INC = -I ../include `glib-config --cflags` -OBJS = catalog.o mem.o file.o kkd.o +OBJS = catalog.o mem.o file.o kkd.o table.o all: libmdb diff --git a/src/libmdb/table.c b/src/libmdb/table.c new file mode 100644 index 0000000..cae5c63 --- /dev/null +++ b/src/libmdb/table.c @@ -0,0 +1,109 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + + +char *mdb_get_coltype_string(int col_type) +{ + +/* +** need to do this is a way that will allow multiple outputs for different +** backend servers...these are MS SQL/Sybase specific +*/ +static char *type_name[] = {"Unknown 0x00", + "Unknown 0x01", + "Unknown 0x02", + "smallint", + "int", + "Unknown 0x05", + "Unknown 0x06", + "Unknown 0x07", + "smalldatetime", + "Unknown 0x09", + "varchar", + "Unknown 0x0b" + "hyperlink -- fixme" + }; + + if (col_type > 11) { + return NULL; + } else { + return type_name[col_type]; + } +} + +unsigned char mdb_col_needs_size(int col_type) +{ + if (col_type == MDB_TEXT) { + return TRUE; + } else { + return FALSE; + } +} + +/* +** +*/ + +void mdb_table_dump(MdbCatalogEntry *entry) +{ +int num_cols, num_rows, data_pgs, first_dpg; +int len, i; +int cur_col, cur_name; +int col_type, col_size; +int col_start, name_start; +char name[MDB_MAX_OBJ_NAME+1]; +int name_sz; +MdbHandle *mdb = entry->mdb; + + mdb_read_pg(mdb, entry->table_pg); + len = mdb_get_int16(mdb,8); + num_rows = mdb_get_int32(mdb,12); + num_cols = mdb_get_int16(mdb,25); + data_pgs = mdb_get_int32(mdb,27); + first_dpg = mdb_get_int16(mdb,36); + fprintf(stdout,"number of datarows = %d\n",num_rows); + fprintf(stdout,"number of columns = %d\n",num_cols); + fprintf(stdout,"number of datapages = %d\n",data_pgs); + fprintf(stdout,"first data page = %d\n",first_dpg); + + col_start = 43 + (data_pgs * 8); + name_start = col_start + (num_cols * 18); + + cur_col = col_start; + cur_name = name_start; + + for (i=0;ipg_buf[cur_col]; + col_size = mdb_get_int16(mdb,cur_col+16); + + /* get the name */ + name_sz = mdb->pg_buf[cur_name]; + memcpy(name,&mdb->pg_buf[cur_name+1],name_sz); + name[name_sz]='\0'; + fprintf(stdout,"column %2d %s\n",i,name); + fprintf(stdout,"column type %s\n",mdb_get_coltype_string(col_type)); + fprintf(stdout,"column size %d\n",col_size); + + cur_col += 18; + cur_name += name_sz + 1; + } +} + diff --git a/src/util/Makefile b/src/util/Makefile index 99c4845..4132f10 100644 --- a/src/util/Makefile +++ b/src/util/Makefile @@ -3,8 +3,9 @@ CC = gcc INC = -I ../include `glib-config --cflags` LIBS = -L ../libmdb -lmdb `glib-config --libs` -PROGS = prcat prtable +PROGS = prcat prkkd prtable PRCATOBJS = prcat.o +PRKKDOBJS = prkkd.o PRTABLEOBJS = prtable.o all: $(PROGS) @@ -12,6 +13,9 @@ all: $(PROGS) prcat: $(PRCATOBJS) $(CC) -g -o $@ $(PRCATOBJS) $(LIBS) +prkkd: $(PRKKDOBJS) + $(CC) -g -o $@ $(PRKKDOBJS) $(LIBS) + prtable: $(PRTABLEOBJS) $(CC) -g -o $@ $(PRTABLEOBJS) $(LIBS) diff --git a/src/util/prtable.c b/src/util/prtable.c new file mode 100644 index 0000000..826e921 --- /dev/null +++ b/src/util/prtable.c @@ -0,0 +1,51 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000 Brian Bruns + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mdbtools.h" + +main(int argc, char **argv) +{ +int rows; +int i; +unsigned char buf[2048]; +MdbHandle *mdb; +MdbCatalogEntry entry; + + + if (argc<2) { + fprintf(stderr,"Usage: prtable \n"); + exit(1); + } + + mdb = mdb_open(argv[1]); + + mdb_read_pg(mdb, MDB_CATALOG_PG); + rows = mdb_catalog_rows(mdb); + + for (i=0;i