diff --git a/include/mdbtools.h b/include/mdbtools.h index 439e755..f18df97 100644 --- a/include/mdbtools.h +++ b/include/mdbtools.h @@ -179,6 +179,7 @@ typedef struct { guint16 col_size_offset; guint16 col_num_offset; guint16 tab_col_entry_size; + guint16 tab_free_map_offset; } MdbFormatConstants; typedef struct { diff --git a/src/gmdb2/gladefiles/gmdb-debug.glade b/src/gmdb2/gladefiles/gmdb-debug.glade index a702411..2ac570e 100644 --- a/src/gmdb2/gladefiles/gmdb-debug.glade +++ b/src/gmdb2/gladefiles/gmdb-debug.glade @@ -163,7 +163,6 @@ True - Open a new debug window gtk-new True @@ -173,19 +172,19 @@ True - Back + New File gtk-go-back True - True + True True - Forward + Open File gtk-go-forward True @@ -194,7 +193,6 @@ True - Jump to selected page gtk-jump-to True @@ -203,12 +201,12 @@ True - Close this window + Save File gtk-close True - True + True diff --git a/src/gmdb2/gladefiles/gmdb-sql.glade b/src/gmdb2/gladefiles/gmdb-sql.glade index e9e8069..3ae1199 100644 --- a/src/gmdb2/gladefiles/gmdb-sql.glade +++ b/src/gmdb2/gladefiles/gmdb-sql.glade @@ -246,8 +246,10 @@ Execute query gtk-execute True - True + + True + @@ -266,8 +268,10 @@ Close this window gtk-close True - True + + True + diff --git a/src/gmdb2/gladefiles/gmdb.glade b/src/gmdb2/gladefiles/gmdb.glade index 7146892..9e55ded 100644 --- a/src/gmdb2/gladefiles/gmdb.glade +++ b/src/gmdb2/gladefiles/gmdb.glade @@ -328,9 +328,11 @@ SQL True gtk-execute - True + + True + diff --git a/src/libmdb/Makefile.am b/src/libmdb/Makefile.am index dca669f..40d2b15 100644 --- a/src/libmdb/Makefile.am +++ b/src/libmdb/Makefile.am @@ -1,4 +1,4 @@ lib_LTLIBRARIES = libmdb.la -libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c +libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c INCLUDES = -I$(top_srcdir)/include $(GLIB_CFLAGS) LIBS = $(GLIB_LIBS) diff --git a/src/libmdb/data.c b/src/libmdb/data.c index 47cb36b..e13c6d5 100644 --- a/src/libmdb/data.c +++ b/src/libmdb/data.c @@ -44,6 +44,22 @@ MdbColumn *col; col=g_ptr_array_index(table->columns, col_num - 1); col->bind_ptr = bind_ptr; } +int +mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr) +{ + int i, col_num = -1; + MdbColumn *col; + + for (i=0;inum_cols;i++) { + col=g_ptr_array_index(table->columns,i); + if (!strcmp(col->name,col_name)) + col_num = col->col_num + 1; + } + + mdb_bind_column(table, col_num, bind_ptr); + + return col_num; +} void mdb_bind_len(MdbTableDef *table, int col_num, int *len_ptr) { MdbColumn *col; diff --git a/src/libmdb/file.c b/src/libmdb/file.c index ba127d7..58c50f5 100644 --- a/src/libmdb/file.c +++ b/src/libmdb/file.c @@ -24,10 +24,10 @@ #endif MdbFormatConstants MdbJet4Constants = { - 4096, 0x0c, 12, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25 + 4096, 0x0c, 12, 45, 47, 51, 55, 56, 63, 12, 15, 23, 5, 25, 59 }; MdbFormatConstants MdbJet3Constants = { - 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18 + 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39 }; static size_t _mdb_read_pg(MdbHandle *mdb, unsigned char *pg_buf, unsigned long pg); diff --git a/src/libmdb/map.c b/src/libmdb/map.c new file mode 100644 index 0000000..22b8a30 --- /dev/null +++ b/src/libmdb/map.c @@ -0,0 +1,125 @@ +/* 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" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +guint32 +mdb_map_find_next0(MdbHandle *mdb, unsigned char *map, int map_sz, guint32 start_pg) +{ + int pgnum, i, bitn; + + pgnum = _mdb_get_int32(map,1); + /* the first 5 bytes of the usage map mean something */ + for (i=5;i start_pg) { + return pgnum; + } + pgnum++; + } + } + /* didn't find anything */ + return 0; +} +int +mdb_map_find_next1(MdbHandle *mdb, unsigned char *map, int map_sz, guint32 start_pg) +{ + guint32 pgnum, i, j, bitn, map_pg; + + pgnum = 0; + //printf("map size %ld\n", table->map_sz); + for (i=1;iusage_map[i],table->usage_map[i+1],table->usage_map[i+2],table->usage_map[i+3]); + + if (!map_pg) continue; + + 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;jfmt->pg_size;j++) { + for (bitn=0;bitn<8;bitn++) { + if (mdb->alt_pg_buf[j] & 1 << bitn && pgnum > start_pg) { + return pgnum; + } + pgnum++; + } + } + } + /* didn't find anything */ + //printf("returning 0\n"); + return 0; +} +guint32 +mdb_map_find_next(MdbHandle *mdb, unsigned char *map, int map_sz, guint32 start_pg) +{ + int map_type; + + map_type = map[0]; + if (map_type==0) { + return mdb_map_find_next0(mdb, map, map_sz, start_pg); + } else if (map_type==1) { + return mdb_map_find_next1(mdb, map, map_sz, start_pg); + } else { + fprintf(stderr,"Warning: unrecognized usage map type: %d, defaulting to brute force read\n",map[0]); + } + return 0; +} +guint32 +mdb_alloc_page(MdbTableDef *table) +{ + printf("Allocating new page\n"); + return 0; +} +guint32 +mdb_map_find_next_freepage(MdbTableDef *table, int row_size) +{ + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + guint32 pgnum; + guint32 cur_pg = 0; + int free_space; + + do { + pgnum = mdb_map_find_next(mdb, + table->free_usage_map, + table->freemap_sz, cur_pg); + printf("looking at page %d\n", pgnum); + if (!pgnum) { + /* allocate new page */ + pgnum = mdb_alloc_page(table); + return pgnum; + } + cur_pg = pgnum; + + mdb_read_pg(mdb, pgnum); + free_space = mdb_pg_get_freespace(mdb); + + } while (free_space < row_size); + + printf("page %d has %d bytes left\n", pgnum, free_space); + + return pgnum; +} diff --git a/src/libmdb/mem.c b/src/libmdb/mem.c index 6da7714..6b6ada6 100644 --- a/src/libmdb/mem.c +++ b/src/libmdb/mem.c @@ -108,6 +108,7 @@ void mdb_free_tabledef(MdbTableDef *table) { if (table->usage_map) free(table->usage_map); + if (table->free_usage_map) free(table->free_usage_map); if (table) free(table); } void diff --git a/src/libmdb/table.c b/src/libmdb/table.c index 9788f5f..60724ef 100644 --- a/src/libmdb/table.c +++ b/src/libmdb/table.c @@ -67,7 +67,7 @@ int rownum, row_start, row_end; 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, (fmt->row_count_offset + 2) + (rownum*2)); - row_end = mdb_find_end_of_row(mdb, rownum); + row_end = mdb_find_end_of_row(mdb, rownum); table->map_sz = row_end - row_start + 1; table->usage_map = malloc(table->map_sz); memcpy(table->usage_map, &mdb->pg_buf[row_start], table->map_sz); @@ -81,6 +81,17 @@ int rownum, row_start, row_end; #endif + /* now grab the free space page map */ + mdb_swap_pgbuf(mdb); + rownum = mdb->pg_buf[fmt->tab_free_map_offset]; + mdb_read_alt_pg(mdb, mdb_get_int24(mdb, fmt->tab_free_map_offset + 1)); + mdb_swap_pgbuf(mdb); + row_start = mdb_get_int16(mdb, (fmt->row_count_offset + 2) + (rownum*2)); + row_end = mdb_find_end_of_row(mdb, rownum); + table->freemap_sz = row_end - row_start + 1; + table->free_usage_map = malloc(table->freemap_sz); + memcpy(table->free_usage_map, &mdb->pg_buf[row_start], table->freemap_sz); + table->first_data_pg = mdb_get_int16(mdb, fmt->tab_first_dpg_offset); return table; diff --git a/src/libmdb/write.c b/src/libmdb/write.c index a91b7e1..7fa6a72 100644 --- a/src/libmdb/write.c +++ b/src/libmdb/write.c @@ -276,6 +276,91 @@ int rows, free_start, free_end; #endif return (free_end - free_start + 1); } +unsigned char * +mdb_new_data_pg(MdbCatalogEntry *entry) +{ + MdbHandle *mdb = entry->mdb; + unsigned char *new_pg; + + new_pg = (unsigned char *) g_malloc0(mdb->fmt->pg_size); + + new_pg[0]=0x01; + new_pg[1]=0x01; + _mdb_put_int32(new_pg, 4, entry->table_pg); + + return new_pg; +} + +int +mdb_update_indexes(MdbTableDef *table, int num_fields, MdbField *fields) +{ + int i; + MdbIndex *idx; + + for (i=0;inum_idxs;i++) { + idx = g_ptr_array_index (table->indices, i); +#if MDB_DEBUG_WRITE + fprintf(stderr,"Updating %s (%d).\n", idx->name, idx->index_type); +#endif + } +} + +int +mdb_insert_row(MdbTableDef *table, int num_fields, MdbField *fields) +{ + int new_row_size, num_rows, i, pos, row_start, row_end, row_size; + unsigned char row_buffer[4096]; + MdbCatalogEntry *entry = table->entry; + MdbHandle *mdb = entry->mdb; + MdbFormatConstants *fmt = mdb->fmt; + guint32 pgnum; + unsigned char *new_pg; + + if (!mdb->f->writable) { + fprintf(stderr, "File is not open for writing\n"); + return 0; + } + 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 + pgnum = mdb_map_find_next_freepage(table, new_row_size); + if (!pgnum) { + fprintf(stderr, "Unable to allocate new page.\n"); + return 0; + } + + + new_pg = mdb_new_data_pg(entry); + num_rows = mdb_get_int16(mdb, fmt->row_count_offset); + pos = mdb->fmt->pg_size; + + for (i=0;irow_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); + } + + /* add our new row */ + pos -= new_row_size; + memcpy(&new_pg[pos], row_buffer, new_row_size); + _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); + + num_rows++; + _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + + memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + g_free(new_pg); +#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 + + mdb_update_indexes(table, num_fields, fields); +} int mdb_update_row(MdbTableDef *table) { @@ -356,12 +441,7 @@ int i, pos; buffer_dump(mdb->pg_buf, fmt->pg_size - 160, fmt->pg_size-1); printf("updating row %d on page %lu\n", row, (unsigned long) 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); + new_pg = mdb_new_data_pg(entry); num_rows = mdb_get_int16(mdb, fmt->row_count_offset); _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); @@ -396,6 +476,8 @@ int i, pos; /* almost done, copy page over current */ memcpy(mdb->pg_buf, new_pg, fmt->pg_size); + g_free(new_pg); + _mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); #if MDB_DEBUG_WRITE buffer_dump(mdb->pg_buf, 0, 39);