mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-04-05 18:39:35 +08:00
more gmdb2 work, reorged mdbhandle
This commit is contained in:
parent
3c0d61076d
commit
cc362c42e9
7
HACKING
7
HACKING
@ -193,13 +193,14 @@ with the next_pg pointer.
|
||||
| ???? | 1 byte | col_name_len| len of the name of the column |
|
||||
| ???? | n bytes | col_name | Name of the column |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Iterate for the number of num_real_idx (30+5 = 35 bytes) |
|
||||
| Iterate for the number of num_real_idx (30+9 = 39 bytes) |
|
||||
+-------------------------------------------------------------------------+
|
||||
| Iterate 10 times for 10 possible columns (10*3 = 30 bytes) |
|
||||
+-------------------------------------------------------------------------+
|
||||
| ???? | 2 bytes | col_num | number of a column (0xFFFF= none) |
|
||||
| ???? | 1 byte | col_order | 0x01 = ascendency order |
|
||||
+-------------------------------------------------------------------------+
|
||||
| ???? | 4 bytes | unknown | |
|
||||
| ???? | 4 bytes | first_dp | Data pointer of the index page |
|
||||
| ???? | 1 byte | flags | See flags table for indexes |
|
||||
+-------------------------------------------------------------------------+
|
||||
@ -362,6 +363,10 @@ Note: For boolean fixed columns, the values are in null_table[]:
|
||||
0 indicates a false value
|
||||
1 indicates a true value
|
||||
|
||||
An 0xFF stored in the var_table indicates that this column has been deleted.
|
||||
|
||||
Note: A row will always have the number of fixed columns as specified in the table definition, but may have less variable columns, as rows are not updated when columns are added.
|
||||
|
||||
In Access 2000 (JET4) data rows are like this
|
||||
|
||||
+------+---------+----------------------------------------------------------+
|
||||
|
@ -92,6 +92,15 @@ enum {
|
||||
MDB_DESC
|
||||
};
|
||||
|
||||
enum {
|
||||
MDB_IDX_UNIQUE = 0x01,
|
||||
MDB_IDX_IGNORENULLS = 0x02,
|
||||
MDB_IDX_REQUIRED = 0x08
|
||||
};
|
||||
|
||||
#define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4)
|
||||
#define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3)
|
||||
|
||||
/* hash to store registered backends */
|
||||
GHashTable *mdb_backends;
|
||||
|
||||
@ -101,24 +110,19 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
gboolean writable;
|
||||
char *filename;
|
||||
guint16 cur_pg;
|
||||
guint16 row_num;
|
||||
unsigned int cur_pos;
|
||||
unsigned char pg_buf[MDB_PGSIZE];
|
||||
unsigned char alt_pg_buf[MDB_PGSIZE];
|
||||
int num_catalog;
|
||||
GPtrArray *catalog;
|
||||
int pg_size;
|
||||
guint32 jet_version;
|
||||
guint32 db_key;
|
||||
char db_passwd[14];
|
||||
MdbBackend *default_backend;
|
||||
char *backend_name;
|
||||
/* free map */
|
||||
int map_sz;
|
||||
unsigned char *free_map;
|
||||
/* offset to row count on data pages...version dependant */
|
||||
} MdbFile;
|
||||
|
||||
/* offset to row count on data pages...version dependant */
|
||||
typedef struct {
|
||||
int pg_size;
|
||||
guint16 row_count_offset;
|
||||
guint16 tab_num_rows_offset;
|
||||
guint16 tab_num_cols_offset;
|
||||
@ -129,9 +133,23 @@ typedef struct {
|
||||
guint16 tab_cols_start_offset;
|
||||
guint16 tab_ridx_entry_size;
|
||||
guint16 col_fixed_offset;
|
||||
guint16 col_num_offset;
|
||||
guint16 col_size_offset;
|
||||
guint16 col_num_offset;
|
||||
guint16 tab_col_entry_size;
|
||||
} MdbFormatConstants;
|
||||
|
||||
typedef struct {
|
||||
MdbFile *f;
|
||||
guint16 cur_pg;
|
||||
guint16 row_num;
|
||||
unsigned int cur_pos;
|
||||
unsigned char pg_buf[MDB_PGSIZE];
|
||||
unsigned char alt_pg_buf[MDB_PGSIZE];
|
||||
int num_catalog;
|
||||
GPtrArray *catalog;
|
||||
MdbBackend *default_backend;
|
||||
char *backend_name;
|
||||
MdbFormatConstants *fmt;
|
||||
} MdbHandle;
|
||||
|
||||
typedef struct {
|
||||
@ -166,6 +184,9 @@ typedef struct {
|
||||
int map_sz;
|
||||
unsigned char *usage_map;
|
||||
/* */
|
||||
int idxmap_base_pg;
|
||||
int idxmap_sz;
|
||||
unsigned char *idx_usage_map;
|
||||
} MdbTableDef;
|
||||
|
||||
typedef struct {
|
||||
@ -177,6 +198,7 @@ typedef struct {
|
||||
int num_keys;
|
||||
short key_col_num[MDB_MAX_IDX_COLS];
|
||||
unsigned char key_col_order[MDB_MAX_IDX_COLS];
|
||||
unsigned char flags;
|
||||
} MdbIndex;
|
||||
|
||||
typedef struct {
|
||||
@ -213,6 +235,7 @@ typedef struct {
|
||||
MdbAny value;
|
||||
} MdbSarg;
|
||||
|
||||
|
||||
/* mem.c */
|
||||
extern void mdb_init();
|
||||
extern void mdb_exit();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user