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);