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

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>
extern GtkWidget *app;
@@ -131,6 +148,7 @@ GtkTextBuffer *buffer;
GtkTextIter iter;
GtkWidget *entry;
GtkTextView *textview;
gchar *s;
if (!mdb) return;
@@ -138,21 +156,33 @@ GtkTextView *textview;
entry = glade_xml_get_widget (xml, "debug_entry");
textview = glade_xml_get_widget (xml, "debug_textview");
page = atol(gtk_entry_get_text(GTK_ENTRY(entry)));
s = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
if (!strncmp(s,"0x",2)) {
page = 0;
for (i=2;i<strlen(s);i++) {
page *= 16;
if (isupper(s[i]))
s[i] -= 0x20;
page += s[i] > '9' ? s[i] - 'a' + 10 : s[i] - '0';
}
} else {
page = atol(gtk_entry_get_text(GTK_ENTRY(entry)));
}
if (page>gmdb_get_max_page(mdb) || page<0) {
gmdb_info_msg("Page entered is outside valid page range.");
}
gmdb_debug_clear(xml);
pos = lseek(mdb->fd, 0, SEEK_CUR);
lseek(mdb->fd, page * mdb->pg_size, SEEK_SET);
pos = lseek(mdb->f->fd, 0, SEEK_CUR);
lseek(mdb->f->fd, page * mdb->fmt->pg_size, SEEK_SET);
fbuf = (unsigned char *) malloc(mdb->pg_size);
tbuf = (unsigned char *) malloc( (mdb->pg_size / 16) * 80);
memset(tbuf, 0, (mdb->pg_size / 16) * 80);
length = read(mdb->fd, fbuf, mdb->pg_size);
if (length<mdb->pg_size) {
fbuf = (unsigned char *) malloc(mdb->fmt->pg_size);
tbuf = (unsigned char *) malloc( (mdb->fmt->pg_size / 16) * 80);
memset(tbuf, 0, (mdb->fmt->pg_size / 16) * 80);
length = read(mdb->f->fd, fbuf, mdb->fmt->pg_size);
if (length<mdb->fmt->pg_size) {
}
i = 0;
while (i<length) {
@@ -191,8 +221,8 @@ gmdb_get_max_page(MdbHandle *mdb)
{
struct stat st;
assert( fstat(mdb->fd, &st)!=-1 );
return st.st_size/mdb->pg_size;
assert( fstat(mdb->f->fd, &st)!=-1 );
return st.st_size/mdb->fmt->pg_size;
}
gchar *
gmdb_val_to_str(GMdbValStr *valstr, gint val)
@@ -293,10 +323,99 @@ GtkTreeIter *node;
gmdb_debug_add_item(store, node, str, offset+1, offset+3);
}
void
gmdb_debug_dissect_row(GtkTreeStore *store, GtkTreeIter *parent, char *fbuf, int offset, int end)
{
gchar str[100];
int bitmask_sz;
int num_cols, var_cols, var_cols_loc, fixed_end, eod_ptr;
int i;
num_cols = fbuf[offset];
snprintf(str, 100, "Num columns: %u", num_cols);
gmdb_debug_add_item(store, parent, str, offset, offset);
bitmask_sz = ((num_cols-1) / 8) + 1;
var_cols_loc = end - bitmask_sz;
var_cols = fbuf[var_cols_loc];
fixed_end = offset + fbuf[var_cols_loc - 1] - 1; /* work even if 0 b/c of EOD */
snprintf(str, 100, "Fixed columns");
gmdb_debug_add_item(store, parent, str, offset + 1, fixed_end);
for (i=0;i<var_cols;i++) {
}
eod_ptr = var_cols_loc - var_cols - 1;
for (i=0;i<var_cols;i++) {
snprintf(str, 100, "Var col %d", var_cols-i);
gmdb_debug_add_item(store, parent, str, offset + fbuf[var_cols_loc - i - 1], offset + fbuf[var_cols_loc - i - 2] - 1);
}
snprintf(str, 100, "End of data (EOD): 0x%02x (%u)", fbuf[eod_ptr], fbuf[eod_ptr]);
gmdb_debug_add_item(store, parent, str, eod_ptr, eod_ptr);
for (i=0;i<var_cols;i++) {
snprintf(str, 100, "Var col %d offset: 0x%02x (%u)", var_cols-i,fbuf[eod_ptr+i+1], fbuf[eod_ptr+i+1]);
gmdb_debug_add_item(store, parent, str, eod_ptr + i + 1, eod_ptr + i + 1);
}
snprintf(str, 100, "Num var cols: %u", var_cols);
gmdb_debug_add_item(store, parent, str, var_cols_loc, var_cols_loc);
snprintf(str, 100, "Null mask");
gmdb_debug_add_item(store, parent, str, var_cols_loc + 1, end);
}
void
gmdb_debug_dissect_leaf_pg(GtkTreeStore *store, char *fbuf, int offset, int len)
{
gchar str[100];
guint32 tdef;
tdef = get_uint32(&fbuf[offset+4]);
snprintf(str, 100, "Parents TDEF page: 0x%06x (%lu)", tdef,tdef);
gmdb_debug_add_item(store, NULL, str, offset+4, offset+7);
snprintf(str, 100, "Previous leaf page: 0x%06x (%lu)", get_uint32(&fbuf[offset+8]),get_uint32(&fbuf[offset+8]));
gmdb_debug_add_item(store, NULL, str, offset+8, offset+11);
snprintf(str, 100, "Next leaf page: 0x%06x (%lu)", get_uint32(&fbuf[offset+12]),get_uint32(&fbuf[offset+12]));
gmdb_debug_add_item(store, NULL, str, offset+12, offset+15);
}
void
gmdb_debug_dissect_data_pg(GtkTreeStore *store, char *fbuf, int offset, int len)
{
gchar str[100];
int num_rows, i, row_start, row_end;
guint32 tdef;
GtkTreeIter *container;
snprintf(str, 100, "Page free space: %u",
get_uint16(&fbuf[offset+2]));
gmdb_debug_add_item(store, NULL, str, offset+2, offset+3);
tdef = get_uint32(&fbuf[offset+4]);
snprintf(str, 100, "Parents TDEF page: 0x%06x (%lu)", tdef,tdef);
gmdb_debug_add_item(store, NULL, str, offset+4, offset+7);
num_rows = get_uint16(&fbuf[offset+8]);
snprintf(str, 100, "Num rows: %u", num_rows);
gmdb_debug_add_item(store, NULL, str, offset+8, offset+9);
for (i=0;i<num_rows;i++) {
row_start = get_uint16(&fbuf[offset+10+(2*i)]);
snprintf(str, 100, "Row %d offset: 0x%02x (%u)",
i+1, row_start, row_start) ;
gmdb_debug_add_item(store, NULL, str, offset+10+(2*i),
offset+10+(2*i)+1);
}
for (i=0;i<num_rows;i++) {
row_start = get_uint16(&fbuf[offset+10+(2*i)]);
if (i==0)
row_end = mdb->fmt->pg_size - 1;
else
row_end = get_uint16(&fbuf[offset+10+(i-1)*2])
& 0x0FFF - 1;
snprintf(str, 100, "Row %d", i+1);
container = gmdb_debug_add_item(store, NULL, str, row_start, row_end);
/* usage pages have parent id of 0 (database) and do not
* follow normal row format */
if (tdef)
gmdb_debug_dissect_row(store, container, fbuf, row_start, row_end);
}
}
void
gmdb_debug_dissect_tabledef_pg(GtkTreeStore *store, char *fbuf, int offset, int len)
{
gchar str[100];
guint32 i, num_idx, num_cols;
guint32 i, num_idx, num_cols, idx_entries;
int newbase;
GtkTreeIter *node, *container;
@@ -321,8 +440,8 @@ GtkTreeIter *node, *container;
snprintf(str, 100, "# of Columns: %u",
get_uint16(&fbuf[offset+25]));
gmdb_debug_add_item(store, NULL, str, offset+25, offset+26);
snprintf(str, 100, "# of Index Entries: %lu",
get_uint32(&fbuf[offset+27]));
idx_entries = get_uint32(&fbuf[offset+27]);
snprintf(str, 100, "# of Index Entries: %lu", idx_entries);
gmdb_debug_add_item(store, NULL, str, offset+27, offset+30);
num_idx = get_uint32(&fbuf[offset+31]);
@@ -361,6 +480,34 @@ GtkTreeIter *node, *container;
node = gmdb_debug_add_item(store, container, str, newbase + 1, newbase + namelen);
newbase += namelen + 1;
}
container = gmdb_debug_add_item(store, NULL, "Index definition 1", -1, -1);
for (i=0;i<num_idx;i++) {
snprintf(str, 100, "Index %d", i+1);
node = gmdb_debug_add_item(store, container, str, newbase+(i*39), newbase+(i*39)+38);
//gmdb_debug_dissect_index2(store, container, fbuf, newbase+(i*39));
}
newbase += num_idx * 39;
container = gmdb_debug_add_item(store, NULL, "Index definition 2", -1, -1);
for (i=0;i<idx_entries;i++) {
snprintf(str, 100, "Index %d", i+1);
node = gmdb_debug_add_item(store, container, str, newbase+(i*20), newbase+(i*20)+19);
}
newbase += idx_entries * 20;
container = gmdb_debug_add_item(store, NULL, "Index Names", -1, -1);
for (i=0;i<idx_entries;i++) {
char *tmpstr;
int namelen;
namelen = fbuf[newbase];
tmpstr = malloc(namelen + 1);
strncpy(tmpstr, &fbuf[newbase+1], namelen);
tmpstr[namelen]=0;
snprintf(str, 100, "Index %d: %s", i+1, tmpstr);
node = gmdb_debug_add_item(store, container, str, newbase+1, newbase+namelen);
free(tmpstr);
newbase += namelen + 1;
}
}
void gmdb_debug_dissect(GtkTreeStore *store, char *fbuf, int offset, int len)
{
@@ -375,7 +522,7 @@ gchar str[100];
//gmdb_debug_dissect_dbpage(store, fbuf, 1, len);
break;
case 0x01:
//gmdb_debug_dissect_dbpage(store, fbuf, 1, len);
gmdb_debug_dissect_data_pg(store, fbuf, 0, len);
break;
case 0x02:
gmdb_debug_dissect_tabledef_pg(store, fbuf, 0, len);
@@ -384,7 +531,7 @@ gchar str[100];
//gmdb_debug_dissect_dbpage(store, fbuf, 1, len);
break;
case 0x04:
//gmdb_debug_dissect_dbpage(store, fbuf, 1, len);
gmdb_debug_dissect_leaf_pg(store, fbuf, 0, len);
break;
}
}

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <mdbtools.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
extern GtkWidget *app;
@@ -26,7 +43,7 @@ struct stat st;
/* connect the signals in the interface */
glade_xml_signal_autoconnect(propswin_xml);
filepath = g_strdup(mdb->filename);
filepath = g_strdup(mdb->f->filename);
for (i=strlen(filepath);i>0 && filepath[i-1]!='/';i--);
filename=&filepath[i];
@@ -38,14 +55,14 @@ struct stat st;
gtk_label_set_text(GTK_LABEL(label), filename);
label = glade_xml_get_widget (propswin_xml, "props_jetver");
gtk_label_set_text(GTK_LABEL(label), mdb->jet_version == MDB_VER_JET3 ? "3 (Access 97)" : "4 (Access 2000/XP)");
gtk_label_set_text(GTK_LABEL(label), mdb->f->jet_version == MDB_VER_JET3 ? "3 (Access 97)" : "4 (Access 2000/XP)");
assert( fstat(mdb->fd, &st)!=-1 );
assert( fstat(mdb->f->fd, &st)!=-1 );
sprintf(tmpstr, "%ld K", st.st_size/1024);
label = glade_xml_get_widget (propswin_xml, "props_filesize");
gtk_label_set_text(GTK_LABEL(label), tmpstr);
sprintf(tmpstr, "%ld", st.st_size / mdb->pg_size);
sprintf(tmpstr, "%ld", st.st_size / mdb->fmt->pg_size);
label = glade_xml_get_widget (propswin_xml, "props_numpages");
gtk_label_set_text(GTK_LABEL(label), tmpstr);

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <gnome.h>
#include <glade/glade.h>
#include <mdbtools.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
extern GtkWidget *app;

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#if SQL

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include <glade/glade.h>

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
extern GtkWidget *app;

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
#include "pk.xpm"

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
extern GtkWidget *app;

View File

@@ -1,3 +1,20 @@
/* MDB Tools - A library for reading MS Access database file
* Copyright (C) 2000 Brian Bruns
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "gmdb.h"
void gmdb_info_msg(gchar *message) {

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

View File

@@ -50,13 +50,12 @@ int opt;
if (!(mdb = mdb_open(argv[optind]))) {
exit(1);
}
switch (mdb->jet_version) {
case MDB_VER_JET3:
printf("JET3\n");
break;
case MDB_VER_JET4:
printf("JET4\n");
break;
if (IS_JET3(mdb)) {
printf("JET3\n");
} else if (IS_JET4(mdb)) {
printf("JET4\n");
} else {
printf("unknown\n");
}
mdb_free_handle(mdb);

View File

@@ -45,7 +45,7 @@ int len;
}
mdb_init();
mdb = mdb_open(argv[1]);
mdb = _mdb_open(argv[1], TRUE);
tabname = argv[2];
sargname = argv[3];
updstr = strdup(argv[4]);
@@ -64,8 +64,10 @@ int len;
colval = strtok(NULL,"=");
bind_column(table, colname, data, &len);
read_to_row(table, sargname);
mdb_update_row(table);
printf("current value of %s is %s, changing to %s\n", colname, data, colval);
len = strlen(colval);
strcpy(data,colval);
mdb_update_row(table);
}
}