mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-09-18 18:22:07 +08:00
port of gmdb to gnome2. lots o other stuff
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
lib_LTLIBRARIES = libmdb.la
|
||||
libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c
|
||||
INCLUDES = -I$(top_srcdir)/include `glib-config --cflags`
|
||||
LIBS = `glib-config --libs`
|
||||
libmdb_la_SOURCES= catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c
|
||||
INCLUDES = -I$(top_srcdir)/include $(GLIB_CFLAGS)
|
||||
LIBS = $(GLIB_LIBS)
|
||||
|
@@ -79,13 +79,13 @@ int type;
|
||||
|
||||
while (mdb_fetch_row(table)) {
|
||||
type = atoi(tobjtype);
|
||||
if (type == objtype) {
|
||||
if (objtype==MDB_ANY || type == objtype) {
|
||||
// fprintf(stdout, "parentid: %10ld objtype: %-3d objname: %s\n",
|
||||
// (atol(parentid) & 0x00FFFFFF), type, objname);
|
||||
memset(&entry,0,sizeof(entry));
|
||||
entry.mdb = mdb;
|
||||
strcpy(entry.object_name, objname);
|
||||
entry.object_type = type;
|
||||
entry.object_type = (type & 0x7F);
|
||||
entry.table_pg = atol(parentid) & 0x00FFFFFF;
|
||||
mdb->num_catalog++;
|
||||
data = g_memdup(&entry,sizeof(MdbCatalogEntry));
|
||||
@@ -124,7 +124,7 @@ fprintf(stdout,"\n");
|
||||
*/
|
||||
|
||||
memset(entry, '\0', sizeof(MdbCatalogEntry));
|
||||
entry->object_type = mdb->pg_buf[offset+0x09];
|
||||
entry->object_type = (mdb->pg_buf[offset+0x09] & 0x7F);
|
||||
j=0;
|
||||
entry->mdb = mdb;
|
||||
entry->table_pg = mdb_get_int16(mdb,offset+1);
|
||||
@@ -221,7 +221,7 @@ MdbCatalogEntry *entry;
|
||||
mdb_read_catalog(mdb, obj_type);
|
||||
for (i=0;i<mdb->num_catalog;i++) {
|
||||
entry = g_ptr_array_index(mdb->catalog,i);
|
||||
if (obj_type==-1 || entry->object_type==obj_type) {
|
||||
if (obj_type==MDB_ANY || entry->object_type==obj_type) {
|
||||
fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2d\n",
|
||||
mdb_get_objtype_string(entry->object_type),
|
||||
entry->object_name,
|
||||
|
@@ -21,8 +21,6 @@
|
||||
#include "time.h"
|
||||
#include "math.h"
|
||||
|
||||
//#define FAST_READ 1
|
||||
|
||||
char *mdb_money_to_string(MdbHandle *mdb, int start, char *s);
|
||||
static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
MdbColumn *col, unsigned char isnull, int offset, int len);
|
||||
@@ -77,7 +75,7 @@ int row_end;
|
||||
return row_end;
|
||||
#endif
|
||||
}
|
||||
static int mdb_is_null(unsigned char *null_mask, int col_num)
|
||||
int mdb_is_null(unsigned char *null_mask, int col_num)
|
||||
{
|
||||
int byte_num = (col_num - 1) / 8;
|
||||
int bit_num = (col_num - 1) % 8;
|
||||
@@ -99,6 +97,24 @@ static int mdb_xfer_bound_bool(MdbHandle *mdb, MdbColumn *col, int value)
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int mdb_xfer_bound_ole(MdbHandle *mdb, int start, MdbColumn *col, int len)
|
||||
{
|
||||
int ret;
|
||||
if (len) {
|
||||
col->cur_value_start = start;
|
||||
col->cur_value_len = len;
|
||||
} else {
|
||||
col->cur_value_start = 0;
|
||||
col->cur_value_len = 0;
|
||||
}
|
||||
if (col->bind_ptr || col->len_ptr) {
|
||||
ret = mdb_copy_ole(mdb, col->bind_ptr, start, len);
|
||||
}
|
||||
if (col->len_ptr) {
|
||||
*col->len_ptr = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int mdb_xfer_bound_data(MdbHandle *mdb, int start, MdbColumn *col, int len)
|
||||
{
|
||||
int ret;
|
||||
@@ -329,6 +345,8 @@ static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
{
|
||||
if (col->col_type == MDB_BOOL) {
|
||||
mdb_xfer_bound_bool(mdb, col, isnull);
|
||||
} else if (col->col_type == MDB_OLE) {
|
||||
mdb_xfer_bound_ole(mdb, offset, col, len);
|
||||
} else if (isnull) {
|
||||
mdb_xfer_bound_data(mdb, 0, col, 0);
|
||||
} else {
|
||||
@@ -339,12 +357,11 @@ static int _mdb_attempt_bind(MdbHandle *mdb,
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int mdb_read_next_dpg(MdbTableDef *table)
|
||||
int
|
||||
mdb_read_next_dpg_by_map0(MdbTableDef *table)
|
||||
{
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
|
||||
#if FAST_READ
|
||||
int pgnum, i, bitn;
|
||||
|
||||
pgnum = _mdb_get_int32(table->usage_map,1);
|
||||
@@ -364,14 +381,71 @@ int pgnum, i, bitn;
|
||||
}
|
||||
/* didn't find anything */
|
||||
return 0;
|
||||
#else
|
||||
}
|
||||
int
|
||||
mdb_read_next_dpg_by_map1(MdbTableDef *table)
|
||||
{
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
guint32 pgnum, i, j, bitn, map_pg;
|
||||
unsigned char map_byte;
|
||||
|
||||
pgnum = 0;
|
||||
//printf("map size %ld\n", table->map_sz);
|
||||
for (i=1;i<table->map_sz-1;i+=4) {
|
||||
map_pg = _mdb_get_int32(table->usage_map, i);
|
||||
//printf("loop %d pg %ld %02x%02x%02x%02x\n",i, map_pg,table->usage_map[i],table->usage_map[i+1],table->usage_map[i+2],table->usage_map[i+3]);
|
||||
|
||||
if (!map_pg) continue;
|
||||
|
||||
if(mdb_read_alt_pg(mdb, map_pg) != mdb->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 (bitn=0;bitn<8;bitn++) {
|
||||
if (mdb->alt_pg_buf[j] & 1 << bitn && pgnum > table->cur_phys_pg) {
|
||||
table->cur_phys_pg = pgnum;
|
||||
if (!mdb_read_pg(mdb, pgnum)) {
|
||||
return 0;
|
||||
} else {
|
||||
//printf("page found at %04x %d\n",pgnum, pgnum);
|
||||
return pgnum;
|
||||
}
|
||||
}
|
||||
pgnum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* didn't find anything */
|
||||
//printf("returning 0\n");
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
mdb_read_next_dpg(MdbTableDef *table)
|
||||
{
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
int map_type;
|
||||
|
||||
#ifndef SLOW_READ
|
||||
map_type = table->usage_map[0];
|
||||
if (map_type==0) {
|
||||
return mdb_read_next_dpg_by_map0(table);
|
||||
} else if (map_type==1) {
|
||||
return mdb_read_next_dpg_by_map1(table);
|
||||
} else {
|
||||
fprintf(stderr,"Warning: unrecognized usage map type: %d, defaulting to brute force read\n",table->usage_map[0]);
|
||||
}
|
||||
#endif
|
||||
/* can't do a fast read, go back to the old way */
|
||||
do {
|
||||
if (!mdb_read_pg(mdb, table->cur_phys_pg++))
|
||||
return 0;
|
||||
} while (mdb->pg_buf[0]!=0x01 || mdb_get_int32(mdb, 4)!=entry->table_pg);
|
||||
/* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */
|
||||
return table->cur_phys_pg;
|
||||
#endif
|
||||
}
|
||||
int mdb_rewind_table(MdbTableDef *table)
|
||||
{
|
||||
@@ -453,6 +527,99 @@ int i;
|
||||
|
||||
return text;
|
||||
}
|
||||
int mdb_copy_ole(MdbHandle *mdb, char *dest, int start, int size)
|
||||
{
|
||||
guint16 ole_len;
|
||||
guint16 ole_flags;
|
||||
guint16 row_start, row_stop;
|
||||
guint8 ole_row;
|
||||
guint32 lval_pg;
|
||||
guint16 len, cur;
|
||||
|
||||
if (size<MDB_MEMO_OVERHEAD) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ole_len = mdb_get_int16(mdb, start);
|
||||
ole_flags = mdb_get_int16(mdb, start+2);
|
||||
|
||||
if (ole_flags == 0x8000) {
|
||||
len = size - MDB_MEMO_OVERHEAD;
|
||||
/* inline ole field */
|
||||
if (dest) memcpy(dest, &mdb->pg_buf[start + MDB_MEMO_OVERHEAD],
|
||||
size - MDB_MEMO_OVERHEAD);
|
||||
return len;
|
||||
} else if (ole_flags == 0x4000) {
|
||||
/* The 16 bit integer at offset 0 is the length of the memo field.
|
||||
* The 24 bit integer at offset 5 is the page it is stored on.
|
||||
*/
|
||||
ole_row = mdb->pg_buf[start+4];
|
||||
|
||||
lval_pg = mdb_get_int24(mdb, start+5);
|
||||
#if MDB_DEBUG
|
||||
printf("Reading LVAL page %06x\n", lval_pg);
|
||||
#endif
|
||||
if(mdb_read_alt_pg(mdb, lval_pg) != mdb->pg_size) {
|
||||
/* Failed to read */
|
||||
return 0;
|
||||
}
|
||||
/* swap the alt and regular page buffers, so we can call get_int16 */
|
||||
mdb_swap_pgbuf(mdb);
|
||||
if (ole_row) {
|
||||
row_stop = mdb_get_int16(mdb, 10 + (ole_row - 1) * 2) & 0x0FFF;
|
||||
} else {
|
||||
row_stop = mdb->pg_size - 1;
|
||||
}
|
||||
row_start = mdb_get_int16(mdb, 10 + ole_row * 2);
|
||||
#if MDB_DEBUG
|
||||
printf("row num %d row start %d row stop %d\n", ole_row, row_start, row_stop);
|
||||
#endif
|
||||
len = row_stop - row_start;
|
||||
if (dest) memcpy(dest, &mdb->pg_buf[row_start], len);
|
||||
/* make sure to swap page back */
|
||||
mdb_swap_pgbuf(mdb);
|
||||
return len;
|
||||
} else if (ole_flags == 0x0000) {
|
||||
ole_row = mdb->pg_buf[start+4];
|
||||
lval_pg = mdb_get_int24(mdb, start+5);
|
||||
#if MDB_DEBUG
|
||||
printf("Reading LVAL page %06x\n", lval_pg);
|
||||
#endif
|
||||
/* swap the alt and regular page buffers, so we can call get_int16 */
|
||||
mdb_swap_pgbuf(mdb);
|
||||
cur=0;
|
||||
do {
|
||||
if(mdb_read_pg(mdb, lval_pg) != mdb->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_start = mdb_get_int16(mdb, 10 + ole_row * 2);
|
||||
#if MDB_DEBUG
|
||||
printf("row num %d row start %d row stop %d\n", ole_row, row_start, row_stop);
|
||||
#endif
|
||||
len = row_stop - row_start;
|
||||
if (dest)
|
||||
memcpy(&dest[cur], &mdb->pg_buf[row_start+4],
|
||||
len - 4);
|
||||
cur += len - 4;
|
||||
|
||||
/* find next lval page */
|
||||
ole_row = mdb->pg_buf[row_start];
|
||||
lval_pg = mdb_get_int24(mdb, row_start+1);
|
||||
} while (lval_pg);
|
||||
/* make sure to swap page back */
|
||||
mdb_swap_pgbuf(mdb);
|
||||
return cur;
|
||||
} else {
|
||||
fprintf(stderr,"Unhandled ole field flags = %04x\n", ole_flags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static char *mdb_memo_to_string(MdbHandle *mdb, int start, int size)
|
||||
{
|
||||
guint16 memo_len;
|
||||
|
@@ -19,6 +19,8 @@
|
||||
|
||||
#include "mdbtools.h"
|
||||
|
||||
#define MDB_DEBUG_USAGE 0
|
||||
|
||||
static gint mdb_col_comparer(MdbColumn *a, MdbColumn *b)
|
||||
{
|
||||
if (a->col_num > b->col_num)
|
||||
@@ -61,13 +63,17 @@ int rownum, row_start, row_end;
|
||||
mdb_swap_pgbuf(mdb);
|
||||
row_start = mdb_get_int16(mdb, (mdb->row_count_offset + 2) + (rownum*2));
|
||||
row_end = mdb_find_end_of_row(mdb, rownum);
|
||||
table->map_sz = row_end - row_start;
|
||||
table->map_sz = row_end - row_start + 1;
|
||||
table->usage_map = malloc(table->map_sz);
|
||||
memcpy(table->usage_map, &mdb->pg_buf[row_start], table->map_sz);
|
||||
#if MDB_DEBUG_USAGE
|
||||
buffer_dump(mdb->pg_buf, row_start, row_end);
|
||||
#endif
|
||||
/* 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);
|
||||
#endif
|
||||
|
||||
|
||||
table->first_data_pg = mdb_get_int16(mdb, mdb->tab_first_dpg_offset);
|
||||
|
152
src/libmdb/write.c
Normal file
152
src/libmdb/write.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/* MDB Tools - A library for reading MS Access database file
|
||||
* Copyright (C) 2000 Brian Bruns
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "mdbtools.h"
|
||||
#include "time.h"
|
||||
#include "math.h"
|
||||
|
||||
#define MDB_DEBUG_WRITE 1
|
||||
|
||||
typedef struct {
|
||||
void *value;
|
||||
int siz;
|
||||
unsigned char is_null;
|
||||
unsigned char is_fixed;
|
||||
} MdbField;
|
||||
|
||||
static int
|
||||
mdb_is_col_indexed(MdbTableDef *table, int colnum)
|
||||
{
|
||||
int i, j;
|
||||
MdbIndex *idx;
|
||||
|
||||
for (i=0;i<table->num_idxs;i++) {
|
||||
idx = g_ptr_array_index (table->indices, i);
|
||||
for (j=0;j<idx->num_keys;j++) {
|
||||
if (idx->key_col_num[j]==colnum) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int mdb_is_null(unsigned char *null_mask, int col_num)
|
||||
{
|
||||
int byte_num = (col_num - 1) / 8;
|
||||
int bit_num = (col_num - 1) % 8;
|
||||
|
||||
if ((1 << bit_num) & null_mask[byte_num]) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
int
|
||||
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;
|
||||
unsigned char null_mask[33]; /* 256 columns max / 8 bits per byte */
|
||||
int bitmask_sz;
|
||||
|
||||
printf("field 0 %s\n", fields[0].value);
|
||||
|
||||
if (mdb->jet_version==MDB_VER_JET4) {
|
||||
num_cols = mdb_get_int16(mdb, row_start);
|
||||
} else {
|
||||
num_cols = mdb->pg_buf[row_start];
|
||||
}
|
||||
|
||||
var_cols = 0; /* mdb->pg_buf[row_end-1]; */
|
||||
fixed_cols = 0; /* num_cols - var_cols; */
|
||||
for (i = 0; i < table->num_cols; i++) {
|
||||
col = g_ptr_array_index (table->columns, i);
|
||||
if (mdb_is_fixed_col(col))
|
||||
fixed_cols++;
|
||||
else
|
||||
var_cols++;
|
||||
}
|
||||
|
||||
bitmask_sz = (num_cols - 1) / 8 + 1;
|
||||
|
||||
for (i=0;i<bitmask_sz;i++) {
|
||||
null_mask[i]=mdb->pg_buf[row_end - bitmask_sz + i + 1];
|
||||
}
|
||||
|
||||
return num_cols;
|
||||
|
||||
}
|
||||
int
|
||||
mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, MdbField *fields)
|
||||
{
|
||||
}
|
||||
int
|
||||
mdb_pg_get_freespace(MdbHandle *mdb)
|
||||
{
|
||||
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;
|
||||
#if MDB_DEBUG_WRITE
|
||||
printf("free space left on page = %d\n", free_end - free_start);
|
||||
#endif
|
||||
return (free_end - free_start);
|
||||
}
|
||||
int
|
||||
mdb_update_row(MdbTableDef *table)
|
||||
{
|
||||
int row_start, row_end;
|
||||
int i;
|
||||
MdbColumn *col;
|
||||
MdbCatalogEntry *entry = table->entry;
|
||||
MdbHandle *mdb = entry->mdb;
|
||||
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);
|
||||
old_row_size = row_end - row_start;
|
||||
|
||||
row_start &= 0x0FFF; /* remove flags */
|
||||
|
||||
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)) {
|
||||
fprintf(stderr, "Attempting to update column that is part of an index\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
num_fields = mdb_crack_row(table, row_start, row_end, &fields);
|
||||
|
||||
#if MDB_DEBUG_WRITE
|
||||
for (i=0;i<num_fields;i++) {
|
||||
}
|
||||
#endif
|
||||
|
||||
new_row_size = mdb_pack_row(table, row_buffer, &fields);
|
||||
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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user