From kde-commits Mon Feb 29 23:12:19 2016 From: Jaroslaw Staniek Date: Mon, 29 Feb 2016 23:12:19 +0000 To: kde-commits Subject: [kexi] src/migration/mdb: MDB Import: Update to mdbtools from June 2014 Message-Id: X-MARC-Message: https://marc.info/?l=kde-commits&m=145678884029830 Git commit 5a2ab83ab935d3710ea9daa924427e75a833f247 by Jaroslaw Staniek. Committed on 29/02/2016 at 23:07. Pushed by staniek into branch 'master'. MDB Import: Update to mdbtools from June 2014 BUG:277583 This also fixes primary keys import BUG:336560 FIXED-IN:2.9.11 Test Plan: Northwind database imports properly with keys, try e.g. from htt= p://www.2013.net/courses/access/ Differential Revision: https://phabricator.kde.org/D855 (from calligra.git) M +92 -38 src/migration/mdb/3rdparty/mdbtools/include/mdbtools.h M +53 -18 src/migration/mdb/3rdparty/mdbtools/libmdb/catalog.c M +201 -131 src/migration/mdb/3rdparty/mdbtools/libmdb/data.c M +19 -1 src/migration/mdb/3rdparty/mdbtools/libmdb/dump.c M +132 -12 src/migration/mdb/3rdparty/mdbtools/libmdb/file.c M +41 -21 src/migration/mdb/3rdparty/mdbtools/libmdb/iconv.c M +122 -78 src/migration/mdb/3rdparty/mdbtools/libmdb/index.c M +3 -4 src/migration/mdb/3rdparty/mdbtools/libmdb/like.c M +13 -8 src/migration/mdb/3rdparty/mdbtools/libmdb/map.c M +9 -34 src/migration/mdb/3rdparty/mdbtools/libmdb/mem.c M +53 -24 src/migration/mdb/3rdparty/mdbtools/libmdb/money.c M +22 -22 src/migration/mdb/3rdparty/mdbtools/libmdb/options.c A +215 -0 src/migration/mdb/3rdparty/mdbtools/libmdb/props.c [Lice= nse: LGPL (v2+)] M +53 -8 src/migration/mdb/3rdparty/mdbtools/libmdb/sargs.c A +77 -0 src/migration/mdb/3rdparty/mdbtools/libmdb/stats.c [Lice= nse: LGPL (v2+)] M +86 -39 src/migration/mdb/3rdparty/mdbtools/libmdb/table.c M +3 -3 src/migration/mdb/3rdparty/mdbtools/libmdb/worktable.c M +113 -78 src/migration/mdb/3rdparty/mdbtools/libmdb/write.c D +0 -7 src/migration/mdb/3rdparty/mdbtools/update_diffs.sh M +4 -0 src/migration/mdb/ChangeLog M +6 -1 src/migration/mdb/src/CMakeLists.txt M +6 -21 src/migration/mdb/src/keximdb/mdbmigrate.cpp M +1 -4 src/migration/mdb/src/keximdb/mdbmigrate.h http://commits.kde.org/kexi/5a2ab83ab935d3710ea9daa924427e75a833f247 diff --git a/src/migration/mdb/3rdparty/mdbtools/include/mdbtools.h b/src/m= igration/mdb/3rdparty/mdbtools/include/mdbtools.h index 0c69c18..68b326f 100644 --- a/src/migration/mdb/3rdparty/mdbtools/include/mdbtools.h +++ b/src/migration/mdb/3rdparty/mdbtools/include/mdbtools.h @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ #ifndef _mdbtools_h_ #define _mdbtools_h_ @@ -33,14 +32,18 @@ #include #include = - #ifdef HAVE_ICONV #include #endif = +#ifdef _WIN32 +#include +#endif + #define MDB_DEBUG 0 = #define MDB_PGSIZE 4096 +//#define MDB_MAX_OBJ_NAME (256*3) /* unicode 16 -> utf-8 worst case */ #define MDB_MAX_OBJ_NAME 256 #define MDB_MAX_COLS 256 #define MDB_MAX_IDX_COLS 10 @@ -51,6 +54,11 @@ #define MDB_NO_BACKENDS 1 #define MDB_NO_STATS 1 = +// Theses 2 atrbutes are not supported by all compilers: +// M$VC see http://stackoverflow.com/questions/1113409/attribute-construct= or-equivalent-in-vc +#define MDB_DEPRECATED(type, funcname) type __attribute__((deprecated)) fu= ncname +#define MDB_CONSTRUCTOR(funcname) void __attribute__((constructor)) funcna= me() + enum { MDB_PAGE_DB =3D 0, MDB_PAGE_DATA, @@ -61,7 +69,9 @@ enum { }; enum { MDB_VER_JET3 =3D 0, - MDB_VER_JET4 =3D 1 + MDB_VER_JET4 =3D 1, + MDB_VER_ACCDB_2007 =3D 0x02, + MDB_VER_ACCDB_2010 =3D 0x0103 }; enum { MDB_FORM =3D 0, @@ -74,7 +84,7 @@ enum { MDB_MODULE, MDB_RELATIONSHIP, MDB_UNKNOWN_09, - MDB_UNKNOWN_0A, + MDB_UNKNOWN_0A, /* User access */ MDB_DATABASE_PROPERTY, MDB_ANY =3D -1 }; @@ -86,12 +96,14 @@ enum { MDB_MONEY =3D 0x05, MDB_FLOAT =3D 0x06, MDB_DOUBLE =3D 0x07, - MDB_SDATETIME =3D 0x08, + MDB_DATETIME =3D 0x08, + MDB_BINARY =3D 0x09, MDB_TEXT =3D 0x0a, MDB_OLE =3D 0x0b, MDB_MEMO =3D 0x0c, MDB_REPID =3D 0x0f, - MDB_NUMERIC =3D 0x10 + MDB_NUMERIC =3D 0x10, + MDB_COMPLEX =3D 0x12 }; = /* SARG operators */ @@ -126,8 +138,9 @@ enum { MDB_DEBUG_USAGE =3D 0x0004, MDB_DEBUG_OLE =3D 0x0008, MDB_DEBUG_ROW =3D 0x0010, - MDB_USE_INDEX =3D 0x0020, - MDB_NO_MEMO =3D 0x0040 /* don't follow memo fields */ + MDB_DEBUG_PROPS =3D 0x0020, + MDB_USE_INDEX =3D 0x0040, + MDB_NO_MEMO =3D 0x0080, /* don't follow memo fields */ }; = #define mdb_is_logical_op(x) (x =3D=3D MDB_OR || \ @@ -154,13 +167,27 @@ enum { MDB_IDX_REQUIRED =3D 0x08 }; = -#define IS_JET4(mdb) (mdb->f->jet_version=3D=3DMDB_VER_JET4) -#define IS_JET3(mdb) (mdb->f->jet_version=3D=3DMDB_VER_JET3) +/* export schema options */ +enum { + MDB_SHEXP_DROPTABLE =3D 1<<0, /* issue drop table during export */ + MDB_SHEXP_CST_NOTNULL =3D 1<<1, /* generate NOT NULL constraints */ + MDB_SHEXP_CST_NOTEMPTY =3D 1<<2, /* <>'' constraints */ + MDB_SHEXP_COMMENTS =3D 1<<3, /* export comments on columns & tables */ + MDB_SHEXP_DEFVALUES =3D 1<<4, /* export default values */ + MDB_SHEXP_INDEXES =3D 1<<5, /* export indices */ + MDB_SHEXP_RELATIONS =3D 1<<6 /* export relation (foreign keys) */ +}; +#define MDB_SHEXP_DEFAULT (MDB_SHEXP_CST_NOTNULL | MDB_SHEXP_COMMENTS | MD= B_SHEXP_INDEXES | MDB_SHEXP_RELATIONS) = -#if !MDB_NO_BACKENDS -/* hash to store registered backends */ -extern GHashTable *mdb_backends; -#endif +/* csv export binary options */ +enum { + MDB_BINEXPORT_STRIP, + MDB_BINEXPORT_RAW, + MDB_BINEXPORT_OCTAL +}; + +#define IS_JET4(mdb) (mdb->f->jet_version=3D=3DMDB_VER_JET4) /* obsolete */ +#define IS_JET3(mdb) (mdb->f->jet_version=3D=3DMDB_VER_JET3) = /* forward declarations */ typedef struct mdbindex MdbIndex; @@ -175,7 +202,18 @@ typedef struct { } MdbBackendType; = typedef struct { - MdbBackendType *types_table; + guint32 capabilities; /* see MDB_SHEXP_* */ + MdbBackendType *types_table; + MdbBackendType *type_shortdate; + MdbBackendType *type_autonum; + const char *short_now; + const char *long_now; + const char *charset_statement; + const char *drop_statement; + const char *constaint_not_empty_statement; + const char *column_comment_statement; + const char *table_comment_statement; + gchar* (*quote_schema_name)(const gchar*, const gchar*); } MdbBackend; #endif = @@ -219,7 +257,7 @@ typedef struct { guint16 tab_first_dpg_offset; guint16 tab_cols_start_offset; guint16 tab_ridx_entry_size; - guint16 col_fixed_offset; + guint16 col_flags_offset; guint16 col_size_offset; guint16 col_num_offset; guint16 tab_col_entry_size; @@ -258,10 +296,8 @@ typedef struct { char object_name[MDB_MAX_OBJ_NAME+1]; int object_type; unsigned long table_pg; /* misnomer since object may not be a table */ - unsigned long kkd_pg; - unsigned int kkd_rowid; - int num_props; - GArray *props; + //int num_props; please use props->len + GArray *props; /* GArray of MdbProperties */ GArray *columns; int flags; } MdbCatalogEntry; @@ -277,7 +313,9 @@ typedef union { char s[256]; } MdbAny; = +struct S_MdbTableDef; /* forward definition */ typedef struct { + struct S_MdbTableDef *table; char name[MDB_MAX_OBJ_NAME+1]; int col_type; int col_size; @@ -300,6 +338,8 @@ typedef struct { /* numerics only */ int col_prec; int col_scale; + unsigned char is_long_auto; + unsigned char is_uuid_auto; MdbProperties *props; /* info needed for handling deleted/added columns */ int fixed_offset; @@ -338,7 +378,7 @@ typedef struct { MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; } MdbIndexChain; = -typedef struct { +typedef struct S_MdbTableDef { MdbCatalogEntry *entry; char name[MDB_MAX_OBJ_NAME+1]; unsigned int num_cols; @@ -407,8 +447,8 @@ typedef struct { } MdbSarg; = /* mem.c */ -extern void mdb_init(); -extern void mdb_exit(); +extern MDB_DEPRECATED(void, mdb_init()); +extern MDB_DEPRECATED(void, mdb_exit()); = /* file.c */ extern ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg); @@ -433,8 +473,9 @@ extern void mdb_swap_pgbuf(MdbHandle *mdb); /* catalog.c */ extern void mdb_free_catalog(MdbHandle *mdb); extern GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type); +MdbCatalogEntry *mdb_get_catalogentry_by_name(MdbHandle *mdb, const gchar*= name); extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type); -extern char *mdb_get_objtype_string(int obj_type); +extern const char *mdb_get_objtype_string(int obj_type); = /* table.c */ extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry); @@ -451,10 +492,13 @@ extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur= _pos); extern void *read_pg_if_n(MdbHandle *mdb, void *buf, int *cur_pos, size_t = len); extern int mdb_is_user_table(MdbCatalogEntry *entry); extern int mdb_is_system_table(MdbCatalogEntry *entry); +extern const char *mdb_table_get_prop(const MdbTableDef *table, const gcha= r *key); +extern const char *mdb_col_get_prop(const MdbColumn *col, const gchar *key= ); = /* data.c */ -extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, vo= id *bind_ptr, int *len_ptr); +extern int mdb_bind_column_by_name(MdbTableDef *table, const gchar *col_na= me, void *bind_ptr, int *len_ptr); extern void mdb_data_dump(MdbTableDef *table); +extern void mdb_date_to_tm(double td, struct tm *t); extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_pt= r, int *len_ptr); extern int mdb_rewind_table(MdbTableDef *table); extern int mdb_fetch_row(MdbTableDef *table); @@ -467,21 +511,25 @@ extern int mdb_col_fixed_size(MdbColumn *col); extern int mdb_col_disp_size(MdbColumn *col); extern size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_= ptr); extern size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, = int chunk_size); +extern void* mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *siz= e); extern void mdb_set_date_fmt(const char *); extern int mdb_read_row(MdbTableDef *table, unsigned int row); = /* dump.c */ -extern void buffer_dump(const void *buf, int start, size_t len); +extern void mdb_buffer_dump(const void *buf, int start, size_t len); = #if !MDB_NO_BACKENDS /* backend.c */ -extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); -extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); -extern void mdb_init_backends(); -extern void mdb_register_backend(MdbBackendType *backend, char *backend_na= me); -extern void mdb_remove_backends(); +extern MDB_DEPRECATED(char*, mdb_get_coltype_string(MdbBackend *backend, i= nt col_type)); +extern MDB_DEPRECATED(int, mdb_coltype_takes_length(MdbBackend *backend, i= nt col_type)); +extern const MdbBackendType* mdb_get_colbacktype(const MdbColumn *col); +extern const char* mdb_get_colbacktype_string(const MdbColumn *col); +extern int mdb_colbacktype_takes_length(const MdbColumn *col); +extern MDB_DEPRECATED(void, mdb_init_backends()); +extern void mdb_register_backend(char *backend_name, guint32 capabilities,= MdbBackendType *backend_type, MdbBackendType *type_shortdate, MdbBackendTy= pe *type_autonum, const char *short_now, const char *long_now, const char *= charset_statement, const char *drop_statement, const char *constaint_not_em= pty_statement, const char *column_comment_statement, const char *table_comm= ent_statement, gchar* (*quote_schema_name)(const gchar*, const gchar*)); +extern MDB_DEPRECATED(void, mdb_remove_backends()); extern int mdb_set_default_backend(MdbHandle *mdb, const char *backend_na= me); -extern char *mdb_get_relationships(MdbHandle *mdb); +extern void mdb_print_schema(MdbHandle *mdb, FILE *outfile, char *tabname,= char *dbnamespace, guint32 export_options); #endif = /* sargs.c */ @@ -521,9 +569,13 @@ extern void mdb_dump_stats(MdbHandle *mdb); extern int mdb_like_cmp(char *s, char *r); = /* write.c */ +extern void mdb_put_int16(void *buf, guint32 offset, guint32 value); +extern void mdb_put_int32(void *buf, guint32 offset, guint32 value); +extern void mdb_put_int32_msb(void *buf, guint32 offset, guint32 value); extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, M= dbField *fields); extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_bu= ffer, int new_row_size); extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned in= t num_fields, MdbField *fields, guint32 pgnum, guint16 rownum); +extern int mdb_insert_row(MdbTableDef *table, int num_fields, MdbField *fi= elds); extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, uns= igned int num_fields, MdbField *fields); extern int mdb_replace_row(MdbTableDef *table, int row, void *new_row, int= new_row_size); extern int mdb_pg_get_freespace(MdbHandle *mdb); @@ -532,12 +584,13 @@ extern void *mdb_new_data_pg(MdbCatalogEntry *entry); = /* map.c */ extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size= ); -extern guint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsig= ned int map_sz, guint32 start_pg); +extern gint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsign= ed int map_sz, guint32 start_pg); = /* props.c */ -extern GPtrArray *mdb_read_props_list(gchar *kkd, int len); extern void mdb_free_props(MdbProperties *props); -extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gch= ar *kkd, int len); +extern void mdb_dump_props(MdbProperties *props, FILE *outfile, int show_n= ame); +extern GArray* mdb_kkd_to_props(MdbHandle *mdb, void *kkd, size_t len); + = /* worktable.c */ extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name); @@ -548,13 +601,14 @@ extern void mdb_temp_columns_end(MdbTableDef *table); = /* options.c */ extern int mdb_get_option(unsigned long optnum); -extern void mdb_debug(int klass, char *fmt, ...); +extern void mdb_debug(int klass, const char *fmt, ...); = /* iconv.c */ extern int mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t slen, char = *dest, size_t dlen); extern int mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t slen, char = *dest, size_t dlen); extern void mdb_iconv_init(MdbHandle *mdb); extern void mdb_iconv_close(MdbHandle *mdb); +extern const char* mdb_target_charset(MdbHandle *mdb); = #ifdef __cplusplus } diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/catalog.c b/src/mig= ration/mdb/3rdparty/mdbtools/libmdb/catalog.c index a857ccf..4736652 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/catalog.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/catalog.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include "mdbtools.h" @@ -23,10 +22,10 @@ #include "dmalloc.h" #endif = -char * +const char * mdb_get_objtype_string(int obj_type) { -static char *type_name[] =3D {"Form", +static const char *type_name[] =3D {"Form", "Table", "Macro", "System Table", @@ -36,7 +35,7 @@ static char *type_name[] =3D {"Form", "Module", "Relationship", "Unknown 0x09", - "Unknown 0x0a", + "User Info", "Database" }; = @@ -49,11 +48,21 @@ static char *type_name[] =3D {"Form", = void mdb_free_catalog(MdbHandle *mdb) { - unsigned int i; + unsigned int i, j; + MdbCatalogEntry *entry; = if ((!mdb) || (!mdb->catalog)) return; - for (i=3D0; icatalog->len; i++) - g_free (g_ptr_array_index(mdb->catalog, i)); + for (i=3D0; icatalog->len; i++) { + entry =3D (MdbCatalogEntry *)g_ptr_array_index(mdb->catalog, i); + if (entry) { + if (entry->props) { + for (j=3D0; jprops->len; j++) + mdb_free_props(g_array_index(entry->props, MdbProperties*, j)); + g_array_free(entry->props, TRUE); + } + g_free(entry); + } + } g_ptr_array_free(mdb->catalog, TRUE); mdb->catalog =3D NULL; } @@ -63,10 +72,14 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objtyp= e) MdbCatalogEntry *entry, msysobj; MdbTableDef *table; char obj_id[256]; - char obj_name[256]; + char obj_name[MDB_MAX_OBJ_NAME]; char obj_type[256]; char obj_flags[256]; + char obj_props[MDB_BIND_SIZE]; int type; + unsigned int i; + MdbColumn *col_props; + int kkd_size_ole; = if (!mdb) return NULL; if (mdb->catalog) mdb_free_catalog(mdb); @@ -91,14 +104,16 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objty= pe) mdb_bind_column_by_name(table, "Name", obj_name, NULL); mdb_bind_column_by_name(table, "Type", obj_type, NULL); mdb_bind_column_by_name(table, "Flags", obj_flags, NULL); + i =3D mdb_bind_column_by_name(table, "LvProp", obj_props, &kkd_size_ole); + col_props =3D g_ptr_array_index(table->columns, i-1); = mdb_rewind_table(table); = while (mdb_fetch_row(table)) { type =3D atoi(obj_type); if (objtype=3D=3DMDB_ANY || type =3D=3D objtype) { - - + //fprintf(stderr, "obj_id: %10ld objtype: %-3d (0x%04x) obj_name: %s\n", + // (atol(obj_id) & 0x00FFFFFF), type, type, obj_name); entry =3D (MdbCatalogEntry *) g_malloc0(sizeof(MdbCatalogEntry)); entry->mdb =3D mdb; strcpy(entry->object_name, obj_name); @@ -107,15 +122,37 @@ GPtrArray *mdb_read_catalog (MdbHandle *mdb, int objt= ype) entry->flags =3D atol(obj_flags); mdb->num_catalog++; g_ptr_array_add(mdb->catalog, entry); + if (kkd_size_ole) { + size_t kkd_len; + void *kkd =3D mdb_ole_read_full(mdb, col_props, &kkd_len); + //mdb_buffer_dump(kkd, 0, kkd_len); + entry->props =3D mdb_kkd_to_props(mdb, kkd, kkd_len); + free(kkd); + } } } - + //mdb_dump_catalog(mdb, MDB_TABLE); = mdb_free_tabledef(table); = return mdb->catalog; } = + +MdbCatalogEntry * +mdb_get_catalogentry_by_name(MdbHandle *mdb, const gchar* name) +{ + unsigned int i; + MdbCatalogEntry *entry; + + for (i=3D0; inum_catalog; i++) { + entry =3D g_ptr_array_index(mdb->catalog, i); + if (!strcasecmp(entry->object_name, name)) + return entry; + } + return NULL; +} + void mdb_dump_catalog(MdbHandle *mdb, int obj_type) { @@ -126,14 +163,12 @@ mdb_dump_catalog(MdbHandle *mdb, int obj_type) for (i=3D0;inum_catalog;i++) { entry =3D g_ptr_array_index(mdb->catalog,i); if (obj_type=3D=3DMDB_ANY || entry->object_type=3D=3Dobj_type) { - fprintf(stdout,"Type: %-10s Name: %-18s T pg: %04x KKD pg: %04x row: %2= d\n", + printf("Type: %-12s Name: %-48s Page: %06lx\n", mdb_get_objtype_string(entry->object_type), entry->object_name, - (unsigned int) entry->table_pg, - (unsigned int) entry->kkd_pg, - entry->kkd_rowid); + entry->table_pg); } - } + } return; } = diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/data.c b/src/migrat= ion/mdb/3rdparty/mdbtools/libmdb/data.c index 1e03418..756aefb 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/data.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/data.c @@ -12,14 +12,13 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = +#include +#include #include "mdbtools.h" -#include "time.h" -#include "math.h" = #ifdef DMALLOC #include "dmalloc.h" @@ -28,9 +27,10 @@ #define OFFSET_MASK 0x1fff = char *mdb_money_to_string(MdbHandle *mdb, int start); +char *mdb_numeric_to_string(MdbHandle *mdb, int start, int prec, int scale= ); + static int _mdb_attempt_bind(MdbHandle *mdb, MdbColumn *col, unsigned char isnull, int offset, int len); -static char *mdb_num_to_string(MdbHandle *mdb, int start, int datatype, in= t prec, int scale); static char *mdb_date_to_string(MdbHandle *mdb, int start); #ifdef MDB_COPY_OLE static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size= ); @@ -59,7 +59,7 @@ void mdb_bind_column(MdbTableDef *table, int col_num, voi= d *bind_ptr, int *len_p col->len_ptr =3D len_ptr; } int -mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_pt= r, int *len_ptr) +mdb_bind_column_by_name(MdbTableDef *table, const gchar *col_name, void *b= ind_ptr, int *len_ptr) { unsigned int i; int col_num =3D -1; @@ -139,12 +139,12 @@ mdb_find_end_of_row(MdbHandle *mdb, int row) if (row > 1000) return -1; = /* if lookupflag is not set, it's good (deleteflag is ok) */ - for (i =3D row; i > 0; i--) { - row_start =3D mdb_get_int16(mdb->pg_buf, (rco + i*2)); - if (!(row_start & 0x8000)) { - break; - } - } + for (i =3D row; i > 0; i--) { + row_start =3D mdb_get_int16(mdb->pg_buf, (rco + i*2)); + if (!(row_start & 0x8000)) { + break; + } + } = row_end =3D (i =3D=3D 0) ? mdb->fmt->pg_size : row_start & OFFSET_MASK; #endif @@ -206,9 +206,9 @@ static size_t mdb_xfer_bound_data(MdbHandle *mdb, int start, MdbColumn *col, int len) { int ret; - - - + //if (!strcmp("Name",col->name)) { + //printf("start %d %d\n",start, len); + //} if (len) { col->cur_value_start =3D start; col->cur_value_len =3D len; @@ -220,22 +220,12 @@ int ret; if (!len) { strcpy(col->bind_ptr, ""); } else { - + //fprintf(stdout,"len %d size %d\n",len, col->col_size); char *str; if (col->col_type =3D=3D MDB_NUMERIC) { - /*fprintf(stdout,"MDB_NUMERIC\n");*/ - str =3D mdb_num_to_string(mdb, start, - col->col_type, col->col_prec, - col->col_scale); - /*fprintf(stdout,"mdb_num_to_string()=3D%d '%s'\n", strlen= (str), str);*/ + str =3D mdb_numeric_to_string(mdb, start, col->col_prec, col->col_scal= e); } else { - /*fprintf(stdout,"!MDB_NUMERIC : %d len=3D%d\n", col->col_= type, len);*/ - str =3D mdb_col_to_string(mdb, mdb->pg_buf, start, - col->col_type, len); - /*if (strlen(str) > MDB_BIND_SIZE) { - fprintf(stdout, "!!!!!!\n"); - } - fprintf(stdout,"mdb_col_to_string()=3D%d '%s'\n", strlen(s= tr), str);*/ + str =3D mdb_col_to_string(mdb, mdb->pg_buf, start, col->col_type, len); } strcpy(col->bind_ptr, str); g_free(str); @@ -253,7 +243,6 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) MdbHandle *mdb =3D table->entry->mdb; MdbColumn *col; unsigned int i; - int rc; int row_start; size_t row_size; int delflag, lookupflag; @@ -263,7 +252,10 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) if (table->num_rows =3D=3D 0) return 0; = - mdb_find_row(mdb, row, &row_start, &row_size); + if (mdb_find_row(mdb, row, &row_start, &row_size)) { + fprintf(stderr, "warning: mdb_find_row failed."); + return 0; + } = delflag =3D lookupflag =3D 0; if (row_start & 0x8000) lookupflag++; @@ -289,14 +281,14 @@ int mdb_read_row(MdbTableDef *table, unsigned int row) #endif = #if MDB_DEBUG - buffer_dump(mdb->pg_buf, row_start, row_size); + mdb_buffer_dump(mdb->pg_buf, row_start, row_size); #endif = /* take advantage of mdb_crack_row() to clean up binding */ /* use num_cols instead of num_fields -- bsb 03/04/02 */ for (i =3D 0; i < table->num_cols; i++) { col =3D g_ptr_array_index(table->columns,fields[i].colnum); - rc =3D _mdb_attempt_bind(mdb, col, fields[i].is_null, + _mdb_attempt_bind(mdb, col, fields[i].is_null, fields[i].start, fields[i].siz); } = @@ -315,13 +307,15 @@ static int _mdb_attempt_bind(MdbHandle *mdb, } else if (col->col_type =3D=3D MDB_OLE) { mdb_xfer_bound_ole(mdb, offset, col, len); } else { - - - + //if (!mdb_test_sargs(mdb, col, offset, len)) { + //return 0; + //} mdb_xfer_bound_data(mdb, offset, col, len); } return 1; } + +/* Read next data page into mdb->pg_buf */ int mdb_read_next_dpg(MdbTableDef *table) { MdbCatalogEntry *entry =3D table->entry; @@ -329,16 +323,28 @@ int mdb_read_next_dpg(MdbTableDef *table) int next_pg; = #ifndef SLOW_READ - next_pg =3D mdb_map_find_next(mdb, table->usage_map, - table->map_sz, table->cur_phys_pg); + while (1) { + next_pg =3D mdb_map_find_next(mdb, table->usage_map, + table->map_sz, table->cur_phys_pg); + if (next_pg < 0) + break; /* unknow map type: goto fallback */ + if (!next_pg) + return 0; = - if (next_pg >=3D 0) { - if (mdb_read_pg(mdb, next_pg)) { - table->cur_phys_pg =3D next_pg; - return table->cur_phys_pg; - } else { + if (!mdb_read_pg(mdb, next_pg)) { + fprintf(stderr, "error: reading page %d failed.\n", next_pg); return 0; } + + table->cur_phys_pg =3D next_pg; + if (mdb->pg_buf[0]=3D=3DMDB_PAGE_DATA && mdb_get_int32(mdb->pg_buf, 4)= =3D=3Dentry->table_pg) + return table->cur_phys_pg; + + /* On rare occasion, mdb_map_find_next will return a wrong page */ + /* Found in a big file, over 4,000,000 records */ + fprintf(stderr, + "warning: page %d from map doesn't match: Type=3D%d, buf[4..7]=3D%ld Ex= pected table_pg=3D%ld\n", + next_pg, mdb->pg_buf[0], mdb_get_int32(mdb->pg_buf, 4), entry->table_pg= ); } fprintf(stderr, "Warning: defaulting to brute force read\n"); #endif @@ -346,7 +352,7 @@ int mdb_read_next_dpg(MdbTableDef *table) do { if (!mdb_read_pg(mdb, table->cur_phys_pg++)) return 0; - } while (mdb->pg_buf[0]!=3D0x01 || mdb_get_int32(mdb->pg_buf, 4)!=3Dentry= ->table_pg); + } while (mdb->pg_buf[0]!=3DMDB_PAGE_DATA || mdb_get_int32(mdb->pg_buf, 4)= !=3Dentry->table_pg); /* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */ return table->cur_phys_pg; } @@ -403,7 +409,7 @@ mdb_fetch_row(MdbTableDef *table) } else { rows =3D mdb_get_int16(mdb->pg_buf,fmt->row_count_offset); = - /* if at end of page, find a new page */ + /* if at end of page, find a new data page */ if (table->cur_row >=3D rows) { table->cur_row=3D0; = @@ -457,6 +463,12 @@ int i; return text; } #endif +/* + * ole_ptr should point to the original blob value of the field. + * If omited, there will be no multi-page check to that the caller is + * responsible for not calling this function. Then, it doesn't have to + * preserve the original value. + */ size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr) { @@ -465,24 +477,30 @@ mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, voi= d *ole_ptr) int row_start; size_t len; = - ole_len =3D mdb_get_int32(ole_ptr, 0); + if (ole_ptr) { + ole_len =3D mdb_get_int32(ole_ptr, 0); + mdb_debug(MDB_DEBUG_OLE,"ole len =3D %d ole flags =3D %02x", + ole_len & 0x00ffffff, ole_len >> 24); = - if ((ole_len & 0x80000000) - || (ole_len & 0x40000000)) { - /* inline or single-page fields don't have a next */ - return 0; - } else { - if (mdb_find_pg_row(mdb, col->cur_blob_pg_row, - &buf, &row_start, &len)) { + if ((ole_len & 0x80000000) + || (ole_len & 0x40000000)) + /* inline or single-page fields don't have a next */ return 0; - } - if (col->bind_ptr) - memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); - col->cur_blob_pg_row =3D mdb_get_int32(buf, row_start); - - return len; } - return 0; + mdb_debug(MDB_DEBUG_OLE, "pg_row %d", col->cur_blob_pg_row); + if (!col->cur_blob_pg_row) + return 0; /* we are done */ + if (mdb_find_pg_row(mdb, col->cur_blob_pg_row, + &buf, &row_start, &len)) { + return 0; + } + mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); + + if (col->bind_ptr) + memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); + col->cur_blob_pg_row =3D mdb_get_int32(buf, row_start); + + return len - 4; } size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size) @@ -526,26 +544,64 @@ mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ol= e_ptr, int chunk_size) if (col->bind_ptr) { memcpy(col->bind_ptr, (char*)buf + row_start, len); if (mdb_get_option(MDB_DEBUG_OLE)) - buffer_dump(col->bind_ptr, 0, 16); + mdb_buffer_dump(col->bind_ptr, 0, 16); } return len; } else if ((ole_len & 0xff000000) =3D=3D 0) { col->cur_blob_pg_row =3D mdb_get_int32(ole_ptr, 4); + mdb_debug(MDB_DEBUG_OLE,"ole row =3D %d ole pg =3D %ld", + col->cur_blob_pg_row & 0xff, + col->cur_blob_pg_row >> 8); = if (mdb_find_pg_row(mdb, col->cur_blob_pg_row, &buf, &row_start, &len)) { return 0; } + mdb_debug(MDB_DEBUG_OLE,"start %d len %d", row_start, len); + if (col->bind_ptr) memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4); col->cur_blob_pg_row =3D mdb_get_int32(buf, row_start); + mdb_debug(MDB_DEBUG_OLE, "next pg_row %d", col->cur_blob_pg_row); = - return len; + return len - 4; } else { fprintf(stderr,"Unhandled ole field flags =3D %02x\n", ole_len >> 24); return 0; } } +/* + * mdb_ole_read_full calls mdb_ole_read then loop over mdb_ole_read_next a= s much as necessary. + * returns the result in a big buffer. + * The call must free it. + * Note that this function is not indempotent: It may be called only once = per column after each bind. + */ +void* +mdb_ole_read_full(MdbHandle *mdb, MdbColumn *col, size_t *size) +{ + char ole_ptr[MDB_MEMO_OVERHEAD]; + char *result =3D malloc(MDB_BIND_SIZE); + size_t result_buffer_size =3D MDB_BIND_SIZE; + size_t len, pos; + + memcpy(ole_ptr, col->bind_ptr, MDB_MEMO_OVERHEAD); + + len =3D mdb_ole_read(mdb, col, ole_ptr, MDB_BIND_SIZE); + memcpy(result, col->bind_ptr, len); + pos =3D len; + while ((len =3D mdb_ole_read_next(mdb, col, ole_ptr))) { + if (pos+len >=3D result_buffer_size) { + result_buffer_size +=3D MDB_BIND_SIZE; + result =3D realloc(result, result_buffer_size); + } + memcpy(result + pos, col->bind_ptr, len); + pos +=3D len; + } + if (size) + *size =3D pos; + return result; +} + #ifdef MDB_COPY_OLE static size_t mdb_copy_ole(MdbHandle *mdb, void *dest, int start, int size) { @@ -617,17 +673,15 @@ static char *mdb_memo_to_string(MdbHandle *mdb, int s= tart, int size) gint32 row_start, pg_row; size_t len; void *buf, *pg_buf =3D mdb->pg_buf; - char *text =3D 0; + char *text =3D (char *) g_malloc(MDB_BIND_SIZE); = - /*printf("mdb_memo_to_string: size=3D%d\n", size);*/ if (sizepg_buf+start+13, 4); - negative =3D (*(mdb->pg_buf+start) & 0x80) ? 1 : 0; - text =3D (char *) g_malloc(prec+2+negative); - if (negative) { - sprintf(text, "-%0*" G_GINT32_FORMAT, prec, GINT32_FROM_LE(l)); - } else { - sprintf(text, "%0*" G_GINT32_FORMAT, prec, GINT32_FROM_LE(l)); - } - if (scale) { - memmove(text+prec-scale+1+negative, text+prec-scale+negative, scale+1); - text[prec-scale+negative] =3D '.'; - } - return text; -} = +#if 0 static int trim_trailing_zeros(char * buff) { char *p; @@ -746,66 +772,96 @@ static int trim_trailing_zeros(char * buff) = return 0; } +#endif = /* Date/Time is stored as a double, where the whole part is the days from 12/30/1899 and the fractional part is the fractional part of one day. */ -static char * -mdb_date_to_string(MdbHandle *mdb, int start) + +void +mdb_date_to_tm(double td, struct tm *t) { - struct tm t; long int day, time; int yr, q; int *cal; int noleap_cal[] =3D {0,31,59,90,120,151,181,212,243,273,304,334,365}; int leap_cal[] =3D {0,31,60,91,121,152,182,213,244,274,305,335,366}; = - char *text =3D (char *) g_malloc(MDB_BIND_SIZE); - double td =3D mdb_get_double(mdb->pg_buf, start); - day =3D (long int)(td); time =3D (long int)(fabs(td - day) * 86400.0 + 0.5); - t.tm_hour =3D time / 3600; - t.tm_min =3D (time / 60) % 60; - t.tm_sec =3D time % 60; - t.tm_year =3D 1 - 1900; + t->tm_hour =3D time / 3600; + t->tm_min =3D (time / 60) % 60; + t->tm_sec =3D time % 60; + t->tm_year =3D 1 - 1900; = day +=3D 693593; /* Days from 1/1/1 to 12/31/1899 */ - t.tm_wday =3D (day+1) % 7; + t->tm_wday =3D (day+1) % 7; = q =3D day / 146097; /* 146097 days in 400 years */ - t.tm_year +=3D 400 * q; + t->tm_year +=3D 400 * q; day -=3D q * 146097; = q =3D day / 36524; /* 36524 days in 100 years */ if (q > 3) q =3D 3; - t.tm_year +=3D 100 * q; + t->tm_year +=3D 100 * q; day -=3D q * 36524; = q =3D day / 1461; /* 1461 days in 4 years */ - t.tm_year +=3D 4 * q; + t->tm_year +=3D 4 * q; day -=3D q * 1461; = q =3D day / 365; /* 365 days in 1 year */ if (q > 3) q =3D 3; - t.tm_year +=3D q; + t->tm_year +=3D q; day -=3D q * 365; = - yr =3D t.tm_year + 1900; + yr =3D t->tm_year + 1900; cal =3D ((yr)%4=3D=3D0 && ((yr)%100!=3D0 || (yr)%400=3D=3D0)) ? leap_cal : noleap_cal; - for (t.tm_mon=3D0; t.tm_mon<12; t.tm_mon++) { - if (day < cal[t.tm_mon+1]) break; + for (t->tm_mon=3D0; t->tm_mon<12; t->tm_mon++) { + if (day < cal[t->tm_mon+1]) break; } - t.tm_mday =3D day - cal[t.tm_mon] + 1; - t.tm_yday =3D day; - t.tm_isdst =3D -1; + t->tm_mday =3D day - cal[t->tm_mon] + 1; + t->tm_yday =3D day; + t->tm_isdst =3D -1; +} + +static char * +mdb_date_to_string(MdbHandle *mdb, int start) +{ + struct tm t; + char *text =3D (char *) g_malloc(MDB_BIND_SIZE); + double td =3D mdb_get_double(mdb->pg_buf, start); + + mdb_date_to_tm(td, &t); = strftime(text, MDB_BIND_SIZE, date_fmt, &t); = return text; } = +static char * +mdb_uuid_to_string(MdbHandle *mdb, int start) +{ + char *text =3D NULL; + unsigned short uuid1, uuid2, uuid3, uuid4, uuid5, uuid6, uuid7, uuid8; + + uuid1 =3D mdb_get_int16(mdb->pg_buf, start); + uuid2 =3D mdb_get_int16(mdb->pg_buf, start + 2); + uuid3 =3D mdb_get_int16(mdb->pg_buf, start + 4); + uuid4 =3D mdb_get_int16(mdb->pg_buf, start + 6); + uuid5 =3D mdb_get_int16(mdb->pg_buf, start + 8); + uuid6 =3D mdb_get_int16(mdb->pg_buf, start + 10); + uuid7 =3D mdb_get_int16(mdb->pg_buf, start + 12); + uuid8 =3D mdb_get_int16(mdb->pg_buf, start + 14); + + text =3D g_strdup_printf("{%04x%04x-%04x-%04x-%04x-%04x%04x%04x}", + uuid1, uuid2, uuid3, uuid4, uuid5, uuid6, uuid7, uuid8); + + return text; +} + +#if 0 int floor_log10(double f, int is_single) { unsigned int i; @@ -814,7 +870,7 @@ int floor_log10(double f, int is_single) if (f < 0.0) f =3D -f; = - if ((f =3D=3D 0.0) || (f =3D=3D 1.0)) { + if ((f =3D=3D 0.0) || (f =3D=3D 1.0) || isinf(f)) { return 0; } else if (f < 1.0) { if (is_single) { @@ -834,6 +890,7 @@ int floor_log10(double f, int is_single) return (int)i; } } +#endif = char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype= , int size) { @@ -850,24 +907,29 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, in= t start, int datatype, int text =3D g_strdup_printf("%d", mdb_get_byte(buf, start)); break; case MDB_INT: - text =3D g_strdup_printf("%ld", - (long)mdb_get_int16(buf, start)); + text =3D g_strdup_printf("%hd", + (short)mdb_get_int16(buf, start)); break; case MDB_LONGINT: + case MDB_COMPLEX: text =3D g_strdup_printf("%ld", mdb_get_int32(buf, start)); break; case MDB_FLOAT: tf =3D mdb_get_single(buf, start); - text =3D g_strdup_printf("%.*f", - FLT_DIG - floor_log10(tf,1) - 1, tf); - trim_trailing_zeros(text); + text =3D g_strdup_printf("%.8e", tf); break; case MDB_DOUBLE: td =3D mdb_get_double(buf, start); - text =3D g_strdup_printf("%.*f", - DBL_DIG - floor_log10(td,0) - 1, td); - trim_trailing_zeros(text); + text =3D g_strdup_printf("%.16e", td); + break; + case MDB_BINARY: + if (size<0) { + text =3D g_strdup(""); + } else { + text =3D g_malloc(size); + memcpy((char*)buf+start, text, size); + } break; case MDB_TEXT: if (size<0) { @@ -878,7 +940,7 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int = start, int datatype, int size, text, MDB_BIND_SIZE); } break; - case MDB_SDATETIME: + case MDB_DATETIME: text =3D mdb_date_to_string(mdb, start); break; case MDB_MEMO: @@ -888,6 +950,9 @@ char *mdb_col_to_string(MdbHandle *mdb, void *buf, int = start, int datatype, int text =3D mdb_money_to_string(mdb, start); case MDB_NUMERIC: break; + case MDB_REPID: + text =3D mdb_uuid_to_string(mdb, start); + break; default: text =3D g_strdup(""); break; @@ -907,6 +972,7 @@ int mdb_col_disp_size(MdbColumn *col) return 6; break; case MDB_LONGINT: + case MDB_COMPLEX: return 11; break; case MDB_FLOAT: @@ -918,7 +984,7 @@ int mdb_col_disp_size(MdbColumn *col) case MDB_TEXT: return col->col_size; break; - case MDB_SDATETIME: + case MDB_DATETIME: return 20; break; case MDB_MEMO: @@ -943,6 +1009,7 @@ int mdb_col_fixed_size(MdbColumn *col) return 2; break; case MDB_LONGINT: + case MDB_COMPLEX: return 4; break; case MDB_FLOAT: @@ -954,9 +1021,12 @@ int mdb_col_fixed_size(MdbColumn *col) case MDB_TEXT: return -1; break; - case MDB_SDATETIME: + case MDB_DATETIME: return 4; break; + case MDB_BINARY: + return -1; + break; case MDB_MEMO: return -1; break; diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/dump.c b/src/migrat= ion/mdb/3rdparty/mdbtools/libmdb/dump.c index ffd9c11..afa002d 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/dump.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/dump.c @@ -1,3 +1,21 @@ +/* MDB Tools - A library for reading MS Access database files + * Copyright (C) 2000-2011 Brian Bruns and others + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA + */ + #include #include #include @@ -6,7 +24,7 @@ #include "dmalloc.h" #endif = -void buffer_dump(const void* buf, int start, size_t len) +void mdb_buffer_dump(const void* buf, int start, size_t len) { char asc[20]; int j, k; diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/file.c b/src/migrat= ion/mdb/3rdparty/mdbtools/libmdb/file.c index d8688d2..1792e9f 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/file.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/file.c @@ -12,11 +12,11 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = +#include #include "mdbtools.h" = #ifdef DMALLOC @@ -35,7 +35,7 @@ typedef struct { guint16 tab_first_dpg_offset; guint16 tab_cols_start_offset; guint16 tab_ridx_entry_size; - guint16 col_fixed_offset; + guint16 col_flags_offset; guint16 col_size_offset; guint16 col_num_offset; guint16 tab_col_entry_size; @@ -52,8 +52,69 @@ MdbFormatConstants MdbJet3Constants =3D { 2048, 0x08, 12, 25, 27, 31, 35, 36, 43, 8, 13, 16, 1, 18, 39, 3, 14, 5 }; = +typedef struct _RC4_KEY +{ + unsigned char state[256]; + unsigned char x; + unsigned char y; +} RC4_KEY; + +#define swap_byte(x,y) t =3D *(x); *(x) =3D *(y); *(y) =3D t + static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg= ); = +static void RC4_set_key(RC4_KEY *key, int key_data_len, unsigned char *key= _data_ptr) +{ + unsigned char t; + unsigned char index1; + unsigned char index2; + unsigned char* state; + short counter; + + state =3D &key->state[0]; + for(counter =3D 0; counter < 256; counter++) + state[counter] =3D counter; + key->x =3D 0; + key->y =3D 0; + index1 =3D 0; + index2 =3D 0; + for(counter =3D 0; counter < 256; counter++) { + index2 =3D (key_data_ptr[index1] + state[counter] + index2) % 256; + swap_byte(&state[counter], &state[index2]); + index1 =3D (index1 + 1) % key_data_len; + } +} + +/* + * this algorithm does 'encrypt in place' instead of inbuff/outbuff + * note also: encryption and decryption use same routine + * implementation supplied by (Adam Back) at + */ + +static void RC4(RC4_KEY *key, int buffer_len, unsigned char * buff) +{ + unsigned char t; + unsigned char x; + unsigned char y; + unsigned char* state; + unsigned char xorIndex; + short counter; + + x =3D key->x; + y =3D key->y; + state =3D &key->state[0]; + for(counter =3D 0; counter < buffer_len; counter++) { + x =3D (x + 1) % 256; + y =3D (state[x] + y) % 256; + swap_byte(&state[x], &state[y]); + xorIndex =3D (state[x] + state[y]) % 256; + buff[counter] ^=3D state[xorIndex]; + } + key->x =3D x; + key->y =3D y; +} + + /** * mdb_find_file: * @filename: path to MDB (database) file @@ -73,7 +134,11 @@ static char *mdb_find_file(const char *file_name) = /* try the provided file name first */ if (!stat(file_name, &status)) { - return g_strdup(file_name); + char *result; + result =3D g_strdup(file_name); + if (!result) + fprintf(stderr, "Can't alloc filename\n"); + return result; } = /* Now pull apart $MDBPATH and try those */ @@ -134,6 +199,8 @@ void mdb_set_encoding(MdbHandle *mdb, const char *encod= ing_name) MdbHandle *mdb_open(const char *filename, MdbFileFlags flags) { MdbHandle *mdb; + int key[] =3D {0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e= , 0x28, 0xe6, 0x13, 0xb6}; + int j, pos; int open_flags; = mdb =3D (MdbHandle *) g_malloc0(sizeof(MdbHandle)); @@ -152,7 +219,7 @@ MdbHandle *mdb_open(const char *filename, MdbFileFlags = flags) mdb->f->fd =3D -1; mdb->f->filename =3D mdb_find_file(filename); if (!mdb->f->filename) { - fprintf(stderr, "Can't alloc filename\n"); + fprintf(stderr, "File not found\n"); mdb_close(mdb); return NULL; } @@ -184,15 +251,56 @@ MdbHandle *mdb_open(const char *filename, MdbFileFlag= s flags) return NULL; } mdb->f->jet_version =3D mdb_get_int32(mdb->pg_buf, 0x14); - if (IS_JET4(mdb)) { - mdb->fmt =3D &MdbJet4Constants; - } else if (IS_JET3(mdb)) { + switch(mdb->f->jet_version) { + case MDB_VER_JET3: mdb->fmt =3D &MdbJet3Constants; - } else { + break; + case MDB_VER_JET4: + case MDB_VER_ACCDB_2007: + case MDB_VER_ACCDB_2010: + mdb->fmt =3D &MdbJet4Constants; + break; + default: fprintf(stderr,"Unknown Jet version.\n"); mdb_close(mdb); return NULL; } + mdb->f->db_key =3D mdb_get_int32(mdb->pg_buf, 0x3e); + /* I don't know if this value is valid for some versions? + * it doesn't seem to be valid for the databases I have + * + * f->db_key ^=3D 0xe15e01b9; + */ + mdb->f->db_key ^=3D 0x4ebc8afb; + /* fprintf(stderr, "Encrypted file, RC4 key seed=3D %d\n", mdb->f->db_key= ); */ + if (mdb->f->db_key) { + /* write is not supported for encrypted files yet */ + mdb->f->writable =3D FALSE; + /* that should be enought, but reopen the file read only just to be + * sure we don't write invalid data */ + close(mdb->f->fd); + open_flags =3D O_RDONLY; +#ifdef _WIN32 + open_flags |=3D O_BINARY; +#endif + mdb->f->fd =3D open(mdb->f->filename, open_flags); + if (mdb->f->fd=3D=3D-1) { + fprintf(stderr, "Couldn't ropen file %s in read only\n", mdb->f->filena= me); + mdb_close(mdb); + return NULL; + } + } + + /* get the db password located at 0x42 bytes into the file */ + for (pos=3D0;pos<14;pos++) { + j =3D mdb_get_int32(mdb->pg_buf, 0x42+pos); + j ^=3D key[pos]; + if ( j !=3D 0) + mdb->f->db_passwd[pos] =3D j; + else + mdb->f->db_passwd[pos] =3D '\0'; + } + mdb_iconv_init(mdb); = return mdb; @@ -282,7 +390,7 @@ ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg) if (pg && mdb->cur_pg =3D=3D pg) return mdb->fmt->pg_size; = len =3D _mdb_read_pg(mdb, mdb->pg_buf, pg); - + //fprintf(stderr, "read page %d type %02x\n", pg, mdb->pg_buf[0]); mdb->cur_pg =3D pg; /* kan - reset the cur_pos on a new page read */ mdb->cur_pos =3D 0; /* kan */ @@ -303,7 +411,7 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_bu= f, unsigned long pg) = fstat(mdb->f->fd, &status); if (status.st_size < offset) { - fprintf(stderr,"offset %lu is beyond EOF\n",offset); + fprintf(stderr,"offset %jd is beyond EOF\n",(intmax_t)offs= et); return 0; } #if !MDB_NO_STATS @@ -320,6 +428,18 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_b= uf, unsigned long pg) /* fprintf(stderr,"EOF reached %d bytes returned.\n",len, mdb->fmt->pg_s= ize); */ return 0; } + /* + * unencrypt the page if necessary. + * it might make sense to cache the unencrypted data blocks? + */ + if (pg !=3D 0 && mdb->f->db_key !=3D 0) + { + RC4_KEY rc4_key; + unsigned int tmp_key =3D mdb->f->db_key ^ pg; + RC4_set_key(&rc4_key, 4, (unsigned char *)&tmp_key); + RC4(&rc4_key, mdb->fmt->pg_size, pg_buf); + } + return len; } void mdb_swap_pgbuf(MdbHandle *mdb) diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/iconv.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/iconv.c index ab19cbd..7f19cc0 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/iconv.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/iconv.c @@ -12,13 +12,12 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = +#include #include "mdbtools.h" -#include "errno.h" = #ifdef DMALLOC #include "dmalloc.h" @@ -43,7 +42,7 @@ mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t slen,= char *dest, size_t dle return 0; = /* Uncompress 'Unicode Compressed' string into tmp */ - if (IS_JET4(mdb) && (slen>=3D2) + if (!IS_JET3(mdb) && (slen>=3D2) && ((src[0]&0xff)=3D=3D0xff) && ((src[1]&0xff)=3D=3D0xfe)) { unsigned int compress=3D1; src +=3D 2; @@ -72,22 +71,25 @@ mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t sle= n, char *dest, size_t dle len_out =3D dlen; = #if HAVE_ICONV - + //printf("1 len_in %d len_out %d\n",len_in, len_out); while (1) { iconv(mdb->iconv_in, &in_ptr, &len_in, &out_ptr, &len_out); if ((!len_in) || (errno =3D=3D E2BIG)) break; /* Don't bail if impossible conversion is encountered */ - in_ptr +=3D (IS_JET4(mdb)) ? 2 : 1; - len_in -=3D (IS_JET4(mdb)) ? 2 : 1; + in_ptr +=3D (IS_JET3(mdb)) ? 1 : 2; + len_in -=3D (IS_JET3(mdb)) ? 1 : 2; *out_ptr++ =3D '?'; len_out--; } - + //printf("2 len_in %d len_out %d\n",len_in, len_out); dlen -=3D len_out; #else if (IS_JET3(mdb)) { - strncpy(out_ptr, in_ptr, len_in); - dlen =3D len_in; + size_t copy_len =3D len_in; + if (copy_len > dlen) + copy_len =3D dlen; + strncpy(out_ptr, in_ptr, copy_len); + dlen =3D copy_len; } else { /* rough UCS-2LE to ISO-8859-1 conversion */ unsigned int i; @@ -99,7 +101,7 @@ mdb_unicode2ascii(MdbHandle *mdb, char *src, size_t slen= , char *dest, size_t dle = if (tmp) g_free(tmp); dest[dlen]=3D'\0'; - + //printf("dest %s\n",dest); return dlen; } = @@ -123,7 +125,7 @@ mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t sle= n, char *dest, size_t dle = #ifdef HAVE_ICONV iconv(mdb->iconv_out, &in_ptr, &len_in, &out_ptr, &len_out); - + //printf("len_in %d len_out %d\n", len_in, len_out); dlen -=3D len_out; #else if (IS_JET3(mdb)) { @@ -141,7 +143,7 @@ mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t sle= n, char *dest, size_t dle #endif = /* Unicode Compression */ - if(IS_JET4(mdb) && (dlen>4)) { + if(!IS_JET3(mdb) && (dlen>4)) { unsigned char *tmp =3D g_malloc(dlen); unsigned int tptr =3D 0, dptr =3D 0; int comp =3D 1; @@ -182,6 +184,21 @@ mdb_ascii2unicode(MdbHandle *mdb, char *src, size_t sl= en, char *dest, size_t dle return dlen; } = +const char* +mdb_target_charset(MdbHandle *mdb) +{ +#ifdef HAVE_ICONV + const char *iconv_code =3D getenv("MDBICONV"); + if (!iconv_code) + iconv_code =3D "UTF-8"; + return iconv_code; +#else + if (!IS_JET3(mdb)) + return "ISO-8859-1"; + return NULL; // same as input: unknown +#endif +} + void mdb_iconv_init(MdbHandle *mdb) { const char *iconv_code; @@ -192,10 +209,10 @@ void mdb_iconv_init(MdbHandle *mdb) } = #ifdef HAVE_ICONV - if (IS_JET4(mdb)) { - mdb->iconv_out =3D iconv_open("UCS-2LE", iconv_code); - mdb->iconv_in =3D iconv_open(iconv_code, "UCS-2LE"); - } else { + if (!IS_JET3(mdb)) { + mdb->iconv_out =3D iconv_open("UCS-2LE", iconv_code); + mdb->iconv_in =3D iconv_open(iconv_code, "UCS-2LE"); + } else { /* According to Microsoft Knowledge Base pages 289525 and */ /* 202427, code page info is not contained in the database */ = @@ -208,8 +225,9 @@ void mdb_iconv_init(MdbHandle *mdb) // get the default from OS char default_encoding[] =3D "CP "; if (GetLocaleInfoA( MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),= SORT_DEFAULT), - LOCALE_IDEFAULTANSICODEPAGE, default_encoding+2, sizeof(default_encodi= ng)-2-1 )) + LOCALE_IDEFAULTANSICODEPAGE, default_encoding+2, sizeof(default= _encoding)-2-1 )) { mdb->jet3_iconv_code =3D g_strdup(default_encoding); + } else #endif mdb->jet3_iconv_code =3D g_strdup("CP1252"); @@ -223,7 +241,9 @@ void mdb_iconv_init(MdbHandle *mdb) void mdb_iconv_close(MdbHandle *mdb) { #ifdef HAVE_ICONV - if (mdb->iconv_out !=3D (iconv_t)-1) iconv_close(mdb->iconv_out); - if (mdb->iconv_in !=3D (iconv_t)-1) iconv_close(mdb->iconv_in); + if (mdb->iconv_out !=3D (iconv_t)-1) iconv_close(mdb->iconv_out); + if (mdb->iconv_in !=3D (iconv_t)-1) iconv_close(mdb->iconv_in); #endif } + + diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/index.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/index.c index f517f2b..865d5a4 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/index.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/index.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include "mdbtools.h" @@ -69,24 +68,29 @@ mdb_read_indices(MdbTableDef *table) MdbHandle *mdb =3D entry->mdb; MdbFormatConstants *fmt =3D mdb->fmt; MdbIndex *pidx; - unsigned int i, j; - int idx_num, key_num, col_num; + unsigned int i, j, k; + int key_num, col_num, cleaned_col_num; int cur_pos, name_sz, idx2_sz, type_offset; int index_start_pg =3D mdb->cur_pg; gchar *tmpbuf; = - table->indices =3D g_ptr_array_new(); + table->indices =3D g_ptr_array_new(); = - if (IS_JET4(mdb)) { - cur_pos =3D table->index_start + 52 * table->num_real_idxs; - idx2_sz =3D 28; - type_offset =3D 23; - } else { + if (IS_JET3(mdb)) { cur_pos =3D table->index_start + 39 * table->num_real_idxs; idx2_sz =3D 20; type_offset =3D 19; + } else { + cur_pos =3D table->index_start + 52 * table->num_real_idxs; + idx2_sz =3D 28; + type_offset =3D 23; } = + //fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, tabl= e->num_real_idxs); + /* num_real_idxs should be the number of indexes of type 2. + * It's not always the case. Happens on Northwind Orders table. + */ + table->num_real_idxs =3D 0; tmpbuf =3D (gchar *) g_malloc(idx2_sz); for (i=3D0;inum_idxs;i++) { read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); @@ -95,45 +99,64 @@ mdb_read_indices(MdbTableDef *table) pidx->index_num =3D mdb_get_int16(tmpbuf, 4); pidx->index_type =3D tmpbuf[type_offset]; g_ptr_array_add(table->indices, pidx); + /* + { + gint32 dumy0 =3D mdb_get_int32(tmpbuf, 0); + gint8 dumy1 =3D tmpbuf[8]; + gint32 dumy2 =3D mdb_get_int32(tmpbuf, 9); + gint32 dumy3 =3D mdb_get_int32(tmpbuf, 13); + gint16 dumy4 =3D mdb_get_int16(tmpbuf, 17); + fprintf(stderr, "idx #%d: num2:%d type:%d\n", i, pidx->index_num, pidx-= >index_type); + fprintf(stderr, "idx #%d: %d %d %d %d %d\n", i, dumy0, dumy1, dumy2, du= my3, dumy4); + }*/ + if (pidx->index_type!=3D2) + table->num_real_idxs++; } + //fprintf(stderr, "num_idxs:%d num_real_idxs:%d\n", table->num_idxs, tabl= e->num_real_idxs); g_free(tmpbuf); = for (i=3D0;inum_idxs;i++) { pidx =3D g_ptr_array_index (table->indices, i); - if (IS_JET4(mdb)) { - name_sz=3Dread_pg_if_16(mdb, &cur_pos); - } else { + if (IS_JET3(mdb)) { name_sz=3Dread_pg_if_8(mdb, &cur_pos); + } else { + name_sz=3Dread_pg_if_16(mdb, &cur_pos); } tmpbuf =3D g_malloc(name_sz); read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); mdb_unicode2ascii(mdb, tmpbuf, name_sz, pidx->name, MDB_MAX_OBJ_NAME); g_free(tmpbuf); - + //fprintf(stderr, "index %d type %d name %s\n", pidx->index_num, pidx->i= ndex_type, pidx->name); } = mdb_read_alt_pg(mdb, entry->table_pg); mdb_read_pg(mdb, index_start_pg); cur_pos =3D table->index_start; - idx_num=3D0; for (i=3D0;inum_real_idxs;i++) { - if (IS_JET4(mdb)) cur_pos +=3D 4; - do { - pidx =3D g_ptr_array_index (table->indices, idx_num++); - } while (idx_num < table->num_real_idxs && pidx /*&& pidx !=3D 0x7= 36e6f6300616d65 && pidx!=3D(MdbIndex*)0xbaadf00d*/ /*(js) temp? hack*/&& pi= dx->index_type=3D=3D2); - - /* if there are more real indexes than index entries left after - removing type 2's decrement real indexes and continue. Happens - on Northwind Orders table. - */ - if (idx_num =3D=3D table->num_real_idxs || !pidx /*|| pidx=3D=3D(MdbInde= x*)0xbaadf00d*/ /*(js) temp? hack*/ /*|| pidx !=3D 0x736e6f6300616d65*/) { - table->num_real_idxs--; + if (!IS_JET3(mdb)) cur_pos +=3D 4; + /* look for index number i */ + for (j=3D0; jnum_idxs; ++j) { + pidx =3D g_ptr_array_index (table->indices, j); + if (pidx->index_type!=3D2 && pidx->index_num=3D=3Di) + break; + } + if (j=3D=3Dtable->num_idxs) { + fprintf(stderr, "ERROR: can't find index #%d.\n", i); continue; } + //fprintf(stderr, "index %d #%d (%s) index_type:%d\n", i, pidx->index_nu= m, pidx->name, pidx->index_type); = pidx->num_rows =3D mdb_get_int32(mdb->alt_pg_buf, fmt->tab_cols_start_offset + - (i*fmt->tab_ridx_entry_size)); + (pidx->index_num*fmt->tab_ridx_entry_size)); + /* + fprintf(stderr, "ridx block1 i:%d data1:0x%08x data2:0x%08x\n", + i, + mdb_get_int32(mdb->pg_buf, + fmt->tab_cols_start_offset + pidx->index_num * fmt->tab_ridx_entry_siz= e), + mdb_get_int32(mdb->pg_buf, + fmt->tab_cols_start_offset + pidx->index_num * fmt->tab_ridx_entry_siz= e +4)); + fprintf(stderr, "pidx->num_rows:%d\n", pidx->num_rows);*/ = key_num=3D0; for (j=3D0;jnum_cols; k++) { + MdbColumn *col =3D g_ptr_array_index(table->columns,k); + if (col->col_num =3D=3D col_num) { + cleaned_col_num =3D k; + break; + } + } + if (cleaned_col_num=3D=3D-1) { + fprintf(stderr, "CRITICAL: can't find column with internal id %d in in= dex %s\n", + col_num, pidx->name); + cur_pos++; + continue; + } /* set column number to a 1 based column number and store */ - pidx->key_col_num[key_num] =3D col_num + 1; + pidx->key_col_num[key_num] =3D cleaned_col_num + 1; pidx->key_col_order[key_num] =3D (read_pg_if_8(mdb, &cur_pos)) ? MDB_ASC : MDB_DESC; + //fprintf(stderr, "component %d using column #%d (internally %d)\n", j,= cleaned_col_num, col_num); key_num++; } pidx->num_keys =3D key_num; = cur_pos +=3D 4; + //fprintf(stderr, "pidx->unknown_pre_first_pg:0x%08x\n", read_pg_if_32(m= db, &cur_pos)); pidx->first_pg =3D read_pg_if_32(mdb, &cur_pos); pidx->flags =3D read_pg_if_8(mdb, &cur_pos); - if (IS_JET4(mdb)) cur_pos +=3D 9; + //fprintf(stderr, "pidx->first_pg:%d pidx->flags:0x%02x\n", pidx->first_= pg, pidx->flags); + if (!IS_JET3(mdb)) cur_pos +=3D 9; } return NULL; } @@ -185,7 +227,7 @@ mdb_index_swap_n(unsigned char *src, int sz, unsigned c= har *dest) void mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, MdbSarg *idx_sarg) { - + //guint32 cache_int; unsigned char *c; = switch (col->col_type) { @@ -195,10 +237,10 @@ mdb_index_cache_sarg(MdbColumn *col, MdbSarg *sarg, M= dbSarg *idx_sarg) = case MDB_LONGINT: idx_sarg->value.i =3D GUINT32_SWAP_LE_BE(sarg->value.i); - + //cache_int =3D sarg->value.i * -1; c =3D (unsigned char *) &(idx_sarg->value.i); c[0] |=3D 0x80; - + //printf("int %08x %02x %02x %02x %02x\n", sarg->value.i, c[0], c[1], c[= 2], c[3]); break; = case MDB_INT: @@ -247,25 +289,25 @@ mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, c= har *buf, int len) MdbSarg *sarg; MdbField field; MdbSargNode node; - + //int c_offset =3D 0, int c_len; = - - - - + //fprintf(stderr,"mdb_index_test_sargs called on "); + //for (i=3D0;ipg_buf[offset+i]); + //fprintf(stderr,"\n"); for (i=3D0;inum_keys;i++) { - + //c_offset++; /* the per column null indicator/flags */ col=3Dg_ptr_array_index(table->columns,idx->key_col_num[i]-1); /* * This will go away eventually */ if (col->col_type=3D=3DMDB_TEXT) { - + //c_len =3D strlen(&mdb->pg_buf[offset + c_offset]); c_len =3D strlen(buf); } else { c_len =3D col->col_size; - + //fprintf(stderr,"Only text types currently supported. How did we get = here?\n"); } /* * If we have no cached index values for this column, @@ -276,7 +318,7 @@ mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, cha= r *buf, int len) for (j=3D0;jnum_sargs;j++) { sarg =3D g_ptr_array_index (col->sargs, j); idx_sarg =3D g_memdup(sarg,sizeof(MdbSarg)); - + //printf("calling mdb_index_cache_sarg\n"); mdb_index_cache_sarg(col, sarg, idx_sarg); g_ptr_array_add(col->idx_sarg_cache, idx_sarg); } @@ -287,7 +329,7 @@ mdb_index_test_sargs(MdbHandle *mdb, MdbIndex *idx, cha= r *buf, int len) /* XXX - kludge */ node.op =3D sarg->op; node.value =3D sarg->value; - + //field.value =3D &mdb->pg_buf[offset + c_offset]; field.value =3D buf; field.siz =3D c_len; field.is_null =3D FALSE; @@ -314,9 +356,9 @@ mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) start =3D ipg->idx_starts[elem++]; = while (start) { - + //fprintf(stdout, "elem %d is %d\n", elem, ipg->idx_starts[elem]); len =3D ipg->idx_starts[elem] - start; - + //fprintf(stdout, "len is %d\n", len); for (i=3D0; i < len; i++) { mask_bit++; if (mask_bit=3D=3D8) { @@ -327,7 +369,7 @@ mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg) /* upon reaching the len, set the bit */ } mask_byte =3D (1 << mask_bit) | mask_byte; - + //fprintf(stdout, "mask byte is %02x at %d\n", mask_byte, mask_pos); start =3D ipg->idx_starts[elem++]; } /* flush the last byte if any */ @@ -353,7 +395,7 @@ mdb_index_unpack_bitmap(MdbHandle *mdb, MdbIndexPage *i= pg) = ipg->idx_starts[elem++]=3Dstart; = - + //fprintf(stdout, "Unpacking index page %lu\n", ipg->pg); do { len =3D 0; do { @@ -365,7 +407,7 @@ mdb_index_unpack_bitmap(MdbHandle *mdb, MdbIndexPage *i= pg) mask_byte =3D mdb->pg_buf[mask_pos]; len++; } while (mask_pos <=3D 0xf8 && !((1 << mask_bit) & mask_byte)); - + //fprintf(stdout, "%d %d %d %d\n", mask_pos, mask_bit, mask_byte, len); = start +=3D len; if (mask_pos < 0xf8) ipg->idx_starts[elem++]=3Dstart; @@ -388,7 +430,7 @@ mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPag= e *ipg) = /* if this page has not been unpacked to it */ if (!ipg->idx_starts[0]){ - + //fprintf(stdout, "Unpacking page %d\n", ipg->pg); mdb_index_unpack_bitmap(mdb, ipg); } = @@ -396,7 +438,7 @@ mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPag= e *ipg) if (ipg->idx_starts[ipg->start_pos + 1]=3D=3D0) return 0; ipg->len =3D ipg->idx_starts[ipg->start_pos+1] - ipg->idx_starts[ipg->sta= rt_pos]; ipg->start_pos++; - + //fprintf(stdout, "Start pos %d\n", ipg->start_pos); = return ipg->len; } @@ -443,13 +485,13 @@ mdb_find_next_leaf(MdbHandle *mdb, MdbIndex *idx, Mdb= IndexChain *chain) */ do { ipg->len =3D 0; - + //printf("finding next on pg %lu\n", ipg->pg); if (!mdb_index_find_next_on_page(mdb, ipg)) { - + //printf("find_next_on_page returned 0\n"); return 0; } pg =3D mdb_get_int32_msb(mdb->pg_buf, ipg->offset + ipg->len - 3) >> 8; - + //printf("Looking at pg %lu at %lu %d\n", pg, ipg->offset, ipg->len); ipg->offset +=3D ipg->len; = /* @@ -458,7 +500,7 @@ mdb_find_next_leaf(MdbHandle *mdb, MdbIndex *idx, MdbIn= dexChain *chain) */ newipg =3D mdb_chain_add_page(mdb, chain, pg); newipg =3D mdb_find_next_leaf(mdb, idx, chain); - + //printf("returning pg %lu\n",newipg->pg); return newipg; } while (!passed); /* no more pages */ @@ -517,9 +559,9 @@ mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbInde= xChain *chain) { MdbIndexPage *ipg; = - + //printf("page %lu finished\n",ipg->pg); if (chain->cur_depth=3D=3D1) { - + //printf("cur_depth =3D=3D 1 we're out\n"); return NULL; } /* @@ -528,13 +570,13 @@ mdb_index_unwind(MdbHandle *mdb, MdbIndex *idx, MdbIn= dexChain *chain) */ ipg =3D NULL; while (chain->cur_depth>1 && ipg=3D=3DNULL) { - + //printf("chain depth %d\n", chain->cur_depth); chain->cur_depth--; ipg =3D mdb_find_next_leaf(mdb, idx, chain); if (ipg) mdb_index_find_next_on_page(mdb, ipg); } if (chain->cur_depth=3D=3D1) { - + //printf("last leaf %lu\n", chain->last_leaf_found); return NULL; } return ipg; @@ -577,20 +619,20 @@ mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, Md= bIndexChain *chain, guint32 chain->clean_up_mode =3D 1; } if (chain->clean_up_mode) { - + //fprintf(stdout,"in cleanup mode\n"); = if (!chain->last_leaf_found) return 0; mdb_read_pg(mdb, chain->last_leaf_found); chain->last_leaf_found =3D mdb_get_int32( mdb->pg_buf, 0x0c); - + //printf("next leaf %lu\n", chain->last_leaf_found); mdb_read_pg(mdb, chain->last_leaf_found); /* reuse the chain for cleanup mode */ chain->cur_depth =3D 1; ipg =3D &chain->pages[0]; mdb_index_page_init(ipg); ipg->pg =3D chain->last_leaf_found; - + //printf("next on page %d\n", if (!mdb_index_find_next_on_page(mdb, ipg)) return 0; } @@ -598,28 +640,28 @@ mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, Md= bIndexChain *chain, guint32 pg_row =3D mdb_get_int32_msb(mdb->pg_buf, ipg->offset + ipg->len - 4); *row =3D pg_row & 0xff; *pg =3D pg_row >> 8; - + //printf("row =3D %d pg =3D %lu ipg->pg =3D %lu offset =3D %lu len =3D %= d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len); col=3Dg_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1); idx_sz =3D mdb_col_fixed_size(col); /* handle compressed indexes, single key indexes only? */ if (idx->num_keys=3D=3D1 && idx_sz>0 && ipg->len - 4 < idx_sz) { - - + //printf("short index found\n"); + //mdb_buffer_dump(ipg->cache_value, 0, idx_sz); memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->of= fset], ipg->len); - + //mdb_buffer_dump(ipg->cache_value, 0, idx_sz); } else { idx_start =3D ipg->offset + (ipg->len - 4 - idx_sz); memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz); } = - + //idx_start =3D ipg->offset + (ipg->len - 4 - idx_sz); passed =3D mdb_index_test_sargs(mdb, idx, (char *)(ipg->cache_value), id= x_sz); = ipg->offset +=3D ipg->len; } while (!passed); = - - + //fprintf(stdout,"len =3D %d pos %d\n", ipg->len, ipg->mask_pos); + //mdb_buffer_dump(mdb->pg_buf, ipg->offset, ipg->len); = return ipg->len; } @@ -677,11 +719,12 @@ mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, Mdb= IndexChain *chain, guint32 = void mdb_index_walk(MdbTableDef *table, MdbIndex *idx) { -MdbHandle *mdb =3D table->entry->mdb; -int cur_pos =3D 0; -unsigned char marker; -MdbColumn *col; -unsigned int i; +/* + MdbHandle *mdb =3D table->entry->mdb; + int cur_pos =3D 0; + unsigned char marker; + MdbColumn *col; + unsigned int i; = if (idx->num_keys!=3D1) return; = @@ -691,8 +734,9 @@ unsigned int i; for (i=3D0;inum_keys;i++) { marker =3D mdb->pg_buf[cur_pos++]; col=3Dg_ptr_array_index(table->columns,idx->key_col_num[i]-1); - + //printf("column %d coltype %d col_size %d (%d)\n",i,col->col_type, mdb_= col_fixed_size(col), col->col_size); } +*/ } void mdb_index_dump(MdbTableDef *table, MdbIndex *idx) @@ -759,7 +803,7 @@ int mdb_index_compute_cost(MdbTableDef *table, MdbIndex= *idx) */ if (idx->flags & MDB_IDX_UNIQUE) { if (idx->num_keys =3D=3D 1) { - + //printf("op is %d\n", sarg->op); switch (sarg->op) { case MDB_EQUAL: return 1; break; @@ -831,7 +875,7 @@ mdb_choose_index(MdbTableDef *table, int *choice) for (i=3D0;inum_idxs;i++) { idx =3D g_ptr_array_index (table->indices, i); cost =3D mdb_index_compute_cost(table, idx); - + //printf("cost for %s is %d\n", idx->name, cost); if (cost && cost < least) { least =3D cost; *choice =3D i; @@ -852,9 +896,9 @@ mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table) table->chain =3D g_malloc0(sizeof(MdbIndexChain)); table->mdbidx =3D mdb_clone_handle(mdb); mdb_read_pg(table->mdbidx, table->scan_idx->first_pg); - + //printf("best index is %s\n",table->scan_idx->name); } - + //printf("TABLE SCAN? %d\n", table->strategy); } void mdb_index_scan_free(MdbTableDef *table) diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/like.c b/src/migrat= ion/mdb/3rdparty/mdbtools/libmdb/like.c index 4e6d554..e89c11d 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/like.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/like.c @@ -12,14 +12,13 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include #include -#include +#include "mdbtools.h" = #ifdef DMALLOC #include "dmalloc.h" diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/map.c b/src/migrati= on/mdb/3rdparty/mdbtools/libmdb/map.c index 1788b27..2566074 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/map.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/map.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include "mdbtools.h" @@ -23,7 +22,7 @@ #include "dmalloc.h" #endif = -static guint32 +static gint32 mdb_map_find_next0(MdbHandle *mdb, unsigned char *map, unsigned int map_sz= , guint32 start_pg) { guint32 pgnum, i, usage_bitlen; @@ -42,7 +41,7 @@ mdb_map_find_next0(MdbHandle *mdb, unsigned char *map, un= signed int map_sz, guin /* didn't find anything */ return 0; } -static int +static gint32 mdb_map_find_next1(MdbHandle *mdb, unsigned char *map, unsigned int map_sz= , guint32 start_pg) { guint32 map_ind, max_map_pgs, offset, usage_bitlen; @@ -83,7 +82,10 @@ mdb_map_find_next1(MdbHandle *mdb, unsigned char *map, u= nsigned int map_sz, guin /* didn't find anything */ return 0; } -guint32 + +/* returns 0 on EOF */ +/* returns -1 on error (unsupported map type) */ +gint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz,= guint32 start_pg) { if (map[0] =3D=3D 0) { @@ -114,11 +116,14 @@ mdb_map_find_next_freepage(MdbTableDef *table, int ro= w_size) pgnum =3D mdb_map_find_next(mdb, table->free_usage_map, table->freemap_sz, cur_pg); - + //printf("looking at page %d\n", pgnum); if (!pgnum) { /* allocate new page */ pgnum =3D mdb_alloc_page(table); return pgnum; + } else if (pgnum=3D=3D-1) { + fprintf(stderr, "Error: mdb_map_find_next_freepage error while reading = maps.\n"); + exit(1); } cur_pg =3D pgnum; = @@ -127,7 +132,7 @@ mdb_map_find_next_freepage(MdbTableDef *table, int row_= size) = } while (free_space < row_size); = - + //printf("page %d has %d bytes left\n", pgnum, free_space); = return pgnum; } diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/mem.c b/src/migrati= on/mdb/3rdparty/mdbtools/libmdb/mem.c index 92fc20c..6f871cd 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/mem.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/mem.c @@ -12,45 +12,20 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ -#ifdef JAVA -#include "javadefines.h" -#else + #include "mdbtools.h" -#include = -#ifdef DMALLOC -#include "dmalloc.h" -#endif -#endif /* JAVA */ -/** - * mdb_init: - * - * Initializes the LibMDB library. This function should be called exactly= once - * by calling program and prior to any other function. - * - **/ -/* METHOD */ void mdb_init() +MDB_DEPRECATED(void, +mdb_init()) { -#if !MDB_NO_BACKENDS - mdb_init_backends(); -#endif + fprintf(stderr, "mdb_init() is DEPRECATED and does nothing. Stop calling = it.\n"); } = -/** - * mdb_exit: - * - * Cleans up the LibMDB library. This function should be called exactly o= nce - * by the calling program prior to exiting (or prior to final use of LibMDB - * functions). - * - **/ -/* METHOD */ void mdb_exit() +MDB_DEPRECATED(void, +mdb_exit()) { -#if !MDB_NO_BACKENDS - mdb_remove_backends(); -#endif + fprintf(stderr, "mdb_exit() is DEPRECATED and does nothing. Stop calling = it.\n"); } diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/money.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/money.c index 370d632..488d570 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/money.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/money.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include @@ -24,10 +23,10 @@ #include "dmalloc.h" #endif = -#define MAXPRECISION 19 +#define MAX_NUMERIC_PRECISION 28 /* ** these routines are copied from the freetds project which does something -** very similar +** very similiar */ = static int multiply_byte(unsigned char *product, int num, unsigned char *m= ultiplier); @@ -43,41 +42,70 @@ static char *array_to_string(unsigned char *array, int = unsigned scale, int neg); */ char *mdb_money_to_string(MdbHandle *mdb, int start) { - #define num_bytes 8 + int num_bytes=3D8, scale=3D4; int i; int neg=3D0; - unsigned char multiplier[MAXPRECISION], temp[MAXPRECISION]; - unsigned char product[MAXPRECISION]; - unsigned char money[num_bytes]; + unsigned char multiplier[MAX_NUMERIC_PRECISION], temp[MAX_NUMERIC_P= RECISION]; + unsigned char product[MAX_NUMERIC_PRECISION]; + unsigned char bytes[num_bytes]; = - memset(multiplier,0,MAXPRECISION); - memset(product,0,MAXPRECISION); + memset(multiplier,0,MAX_NUMERIC_PRECISION); + memset(product,0,MAX_NUMERIC_PRECISION); multiplier[0]=3D1; - memcpy(money, mdb->pg_buf + start, num_bytes); + memcpy(bytes, mdb->pg_buf + start, num_bytes); = /* Perform two's complement for negative numbers */ - if (money[7] & 0x80) { + if (bytes[num_bytes-1] & 0x80) { neg =3D 1; for (i=3D0;ipg_buf + start + 1, num_bytes); + + /* Perform two's complement for negative numbers */ + if (mdb->pg_buf[start] & 0x80) neg =3D 1; + for (i=3D0;i9) { product[j+1]+=3Dproduct[j]/10; product[j]=3Dproduct[j]%10; @@ -117,9 +145,10 @@ static char *array_to_string(unsigned char *array, uns= igned int scale, int neg) char *s; unsigned int top, i, j=3D0; = - for (top=3DMAXPRECISION;(top>0) && (top-1>scale) && !array[top-1];top--); + for (top=3DMAX_NUMERIC_PRECISION;(top>0) && (top-1>scale) && !array= [top-1];top--); = - s =3D (char *) g_malloc(22); + /* allocate enough space for all digits + minus sign + decimal poin= t + trailing NULL byte */ + s =3D (char *) g_malloc(MAX_NUMERIC_PRECISION+3); = if (neg) s[j++] =3D '-'; diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/options.c b/src/mig= ration/mdb/3rdparty/mdbtools/libmdb/options.c index 6b43a0e..02af719 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/options.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/options.c @@ -12,17 +12,15 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include #include #include #include - -#include +#include "mdbtools.h" = #ifdef DMALLOC #include "dmalloc.h" @@ -36,17 +34,17 @@ static int optset; static void load_options(); = void -mdb_debug(int klass, char *fmt, ...) +mdb_debug(int klass, const char *fmt, ...) { #ifdef DEBUG va_list ap; = if (!optset) load_options(); if (klass & opts) { - va_start(ap, fmt); - vfprintf (stdout,fmt, ap); - va_end(ap); - fprintf(stdout,"\n"); + va_start(ap, fmt); + vfprintf (stderr,fmt, ap); + va_end(ap); + fprintf(stderr,"\n"); } #endif } @@ -57,26 +55,28 @@ load_options() char *opt; char *s; = - if (!optset && (s=3Dgetenv("MDBOPTS"))) { + if (!optset && (s=3Dgetenv("MDBOPTS"))) { opt =3D strtok(s, ":"); - do { - if (!strcmp(opt, "use_index")) opts |=3D MDB_USE_INDEX; - if (!strcmp(opt, "no_memo")) opts |=3D MDB_NO_MEMO; - if (!strcmp(opt, "debug_like")) opts |=3D MDB_DEBUG_LIKE; - if (!strcmp(opt, "debug_write")) opts |=3D MDB_DEBUG_WRITE; - if (!strcmp(opt, "debug_usage")) opts |=3D MDB_DEBUG_USAGE; - if (!strcmp(opt, "debug_ole")) opts |=3D MDB_DEBUG_OLE; - if (!strcmp(opt, "debug_row")) opts |=3D MDB_DEBUG_ROW; - if (!strcmp(opt, "debug_all")) { + while (opt) { + if (!strcmp(opt, "use_index")) opts |=3D MDB_USE_INDEX; + if (!strcmp(opt, "no_memo")) opts |=3D MDB_NO_MEMO; + if (!strcmp(opt, "debug_like")) opts |=3D MDB_DEBUG_LIKE; + if (!strcmp(opt, "debug_write")) opts |=3D MDB_DEBUG_WRITE; + if (!strcmp(opt, "debug_usage")) opts |=3D MDB_DEBUG_USAGE; + if (!strcmp(opt, "debug_ole")) opts |=3D MDB_DEBUG_OLE; + if (!strcmp(opt, "debug_row")) opts |=3D MDB_DEBUG_ROW; + if (!strcmp(opt, "debug_props")) opts |=3D MDB_DEBUG_PROPS; + if (!strcmp(opt, "debug_all")) { opts |=3D MDB_DEBUG_LIKE; opts |=3D MDB_DEBUG_WRITE; opts |=3D MDB_DEBUG_USAGE; opts |=3D MDB_DEBUG_OLE; opts |=3D MDB_DEBUG_ROW; + opts |=3D MDB_DEBUG_PROPS; } opt =3D strtok(NULL,":"); - } while (opt); - } + } + } optset =3D 1; } int diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/props.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/props.c new file mode 100644 index 0000000..38e0660 --- /dev/null +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/props.c @@ -0,0 +1,215 @@ +/* MDB Tools - A library for reading MS Access database file + * Copyright (C) 2000-2011 Brian Bruns and others + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA + */ + +#include "mdbtools.h" + +static GPtrArray * +mdb_read_props_list(MdbHandle *mdb, gchar *kkd, int len) +{ + guint32 record_len; + int pos =3D 0; + gchar *name; + GPtrArray *names =3D NULL; + int i=3D0; + + names =3D g_ptr_array_new(); +#if MDB_DEBUG + mdb_buffer_dump(kkd, 0, len); +#endif + pos =3D 0; + while (pos < len) { + record_len =3D mdb_get_int16(kkd, pos); + pos +=3D 2; + if (mdb_get_option(MDB_DEBUG_PROPS)) { + fprintf(stderr, "%02d ",i++); + mdb_buffer_dump(kkd, pos - 2, record_len + 2); + } + name =3D g_malloc(3*record_len + 1); /* worst case scenario is 3 bytes o= ut per byte in */ + mdb_unicode2ascii(mdb, &kkd[pos], record_len, name, 3*record_len); + + pos +=3D record_len; + g_ptr_array_add(names, name); +#if MDB_DEBUG + printf("new len =3D %d\n", names->len); +#endif + } + return names; +} +static gboolean +free_hash_entry(gpointer key, gpointer value, gpointer user_data) +{ + g_free(key); + g_free(value); + return TRUE; +} +void +mdb_free_props(MdbProperties *props) +{ + if (!props) return; + + if (props->name) g_free(props->name); + if (props->hash) { + g_hash_table_foreach(props->hash, (GHFunc)free_hash_entry, 0); + g_hash_table_destroy(props->hash); + } + g_free(props); +} + +static void +free_names(GPtrArray *names) { + g_ptr_array_foreach(names, (GFunc)g_free, NULL); + g_ptr_array_free(names, TRUE); +} +MdbProperties * +mdb_alloc_props() +{ + MdbProperties *props; + + props =3D g_malloc0(sizeof(MdbProperties)); + + return props; +} +static MdbProperties * +mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len) +{ + guint32 record_len, name_len; + int pos =3D 0; + int elem, dtype, dsize; + gchar *name, *value; + MdbProperties *props; + int i=3D0; + +#if MDB_DEBUG + mdb_buffer_dump(kkd, 0, len); +#endif + pos =3D 0; + + record_len =3D mdb_get_int16(kkd, pos); + pos +=3D 4; + name_len =3D mdb_get_int16(kkd, pos); + pos +=3D 2; + props =3D mdb_alloc_props(); + if (name_len) { + props->name =3D g_malloc(3*name_len + 1); + mdb_unicode2ascii(mdb, kkd+pos, name_len, props->name, 3*name_len); + mdb_debug(MDB_DEBUG_PROPS,"prop block named: %s", props->name); + } + pos +=3D name_len; + + props->hash =3D g_hash_table_new(g_str_hash, g_str_equal); + + while (pos < len) { + record_len =3D mdb_get_int16(kkd, pos); + dtype =3D kkd[pos + 3]; + elem =3D mdb_get_int16(kkd, pos + 4); + dsize =3D mdb_get_int16(kkd, pos + 6); + value =3D g_malloc(dsize + 1); + strncpy(value, &kkd[pos + 8], dsize); + value[dsize] =3D '\0'; + name =3D g_ptr_array_index(names,elem); + if (mdb_get_option(MDB_DEBUG_PROPS)) { + fprintf(stderr, "%02d ",i++); + mdb_debug(MDB_DEBUG_PROPS,"elem %d (%s) dsize %d dtype %d", elem, name,= dsize, dtype); + mdb_buffer_dump(value, 0, dsize); + } + if (dtype =3D=3D MDB_MEMO) dtype =3D MDB_TEXT; + if (dtype =3D=3D MDB_BOOL) { + g_hash_table_insert(props->hash, g_strdup(name), + g_strdup(kkd[pos + 8] ? "yes" : "no")); + } else { + g_hash_table_insert(props->hash, g_strdup(name), + mdb_col_to_string(mdb, kkd, pos + 8, dtype, dsize)); + } + g_free(value); + pos +=3D record_len; + } + return props; + +} + +static void +print_keyvalue(gpointer key, gpointer value, gpointer outfile) +{ + fprintf((FILE*)outfile,"\t%s: %s\n", (gchar *)key, (gchar *)value); +} +void +mdb_dump_props(MdbProperties *props, FILE *outfile, int show_name) { + if (show_name) + fprintf(outfile,"name: %s\n", props->name ? props->name : "(none)"); + g_hash_table_foreach(props->hash, print_keyvalue, outfile); + if (show_name) + fputc('\n', outfile); +} + +/* + * That function takes a raw KKD/MR2 binary buffer, + * typically read from LvProp in table MSysbjects + * and returns a GArray of MdbProps* + */ +GArray* +mdb_kkd_to_props(MdbHandle *mdb, void *buffer, size_t len) { + guint32 record_len; + guint16 record_type; + size_t pos; + GPtrArray *names =3D NULL; + MdbProperties *props; + GArray *result; + +#if MDB_DEBUG + mdb_buffer_dump(buffer, 0, len); +#endif + mdb_debug(MDB_DEBUG_PROPS,"starting prop parsing of type %s", buffer); + + if (strcmp("KKD", buffer) && strcmp("MR2", buffer)) { + fprintf(stderr, "Unrecognized format.\n"); + mdb_buffer_dump(buffer, 0, len); + return NULL; + } + + result =3D g_array_new(0, 0, sizeof(MdbProperties*)); + + pos =3D 4; + while (pos < len) { + record_len =3D mdb_get_int32(buffer, pos); + record_type =3D mdb_get_int16(buffer, pos + 4); + mdb_debug(MDB_DEBUG_PROPS,"prop chunk type:0x%04x len:%d", record_type, = record_len); + //mdb_buffer_dump(buffer, pos+4, record_len); + switch (record_type) { + case 0x80: + if (names) free_names(names); + names =3D mdb_read_props_list(mdb, buffer+pos+6, record_len - 6); + break; + case 0x00: + case 0x01: + if (!names) { + fprintf(stderr,"sequence error!\n"); + break; + } + props =3D mdb_read_props(mdb, names, buffer+pos+6, record_len - 6); + g_array_append_val(result, props); + //mdb_dump_props(props, stderr, 1); + break; + default: + fprintf(stderr,"Unknown record type %d\n", record_type); + break; + } + pos +=3D record_len; + } + if (names) free_names(names); + return result; +} diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/sargs.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/sargs.c index 83499f7..cee28c0 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/sargs.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/sargs.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = /* @@ -27,8 +26,9 @@ * datatype support is a bit weak at this point. To add more types create * a mdb_test_[type]() function and invoke it from mdb_test_sarg() */ -#include "mdbtools.h" = +#include +#include "mdbtools.h" #ifdef DMALLOC #include "dmalloc.h" #endif @@ -76,7 +76,7 @@ int mdb_test_int(MdbSargNode *node, gint32 i) { switch (node->op) { case MDB_EQUAL: - + //fprintf(stderr, "comparing %ld and %ld\n", i, node->value.i); if (node->value.i =3D=3D i) return 1; break; case MDB_GT: @@ -97,8 +97,51 @@ int mdb_test_int(MdbSargNode *node, gint32 i) } return 0; } -#if 0 -#endif + +int +mdb_test_date(MdbSargNode *node, double td) +{ + struct tm found; + /* TODO: you should figure out a way to pull mdb_date_to_string in here + * char date_tmp[MDB_BIND_SIZE]; + */ + + time_t found_t; + time_t asked_t; + + double diff; + + mdb_date_to_tm(td, &found); + + asked_t =3D node->value.i; + found_t =3D mktime(&found); + + diff =3D difftime(asked_t, found_t); + + switch (node->op) { + case MDB_EQUAL: + if (diff=3D=3D0) return 1; + break; + case MDB_GT: + if (diff<0) return 1; + break; + case MDB_LT: + if (diff>0) return 1; + break; + case MDB_GTEQ: + if (diff<=3D0) return 1; + break; + case MDB_LTEQ: + if (diff>=3D0) return 1; + break; + default: + fprintf(stderr, "Calling mdb_test_sarg on unknown operator. Add code to = mdb_test_date() for operator %d\n", node->op); + break; + } + return 0; +} + + int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data) { @@ -120,7 +163,7 @@ mdb_find_indexable_sargs(MdbSargNode *node, gpointer da= ta) * probably better off table scanning. */ if (mdb_is_relational_op(node->op) && node->col) { - + //printf("op =3D %d value =3D %s\n", node->op, node->value.s); sarg.op =3D node->op; sarg.value =3D node->value; mdb_add_sarg(node->col, &sarg); @@ -155,6 +198,8 @@ mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNo= de *node, MdbField *field case MDB_TEXT: mdb_unicode2ascii(mdb, field->value, field->siz, tmpbuf, 256); return mdb_test_string(node, tmpbuf); + case MDB_DATETIME: + return mdb_test_date(node, mdb_get_double(field->value, 0)); default: fprintf(stderr, "Calling mdb_test_sarg on unknown type. Add code to md= b_test_sarg() for type %d\n",col->col_type); break; diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/stats.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/stats.c new file mode 100644 index 0000000..3719826 --- /dev/null +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/stats.c @@ -0,0 +1,77 @@ +/* MDB Tools - A library for reading MS Access database files + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA + */ + +#include "mdbtools.h" + +#if !MDB_NO_STATS + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + +/** + * mdb_stats_on: + * @mdb: Handle to the (open) MDB file to collect stats on. + * + * Begins collection of statistics on an MDBHandle. + * + * Statistics in LibMDB will track the number of reads from the MDB file. = The + * collection of statistics is started and stopped with the mdb_stats_on a= nd + * mdb_stats_off functions. Collected statistics are accessed by reading = the + * MdbStatistics structure or calling mdb_dump_stats. + * + */ +void +mdb_stats_on(MdbHandle *mdb) +{ + if (!mdb->stats) + mdb->stats =3D g_malloc0(sizeof(MdbStatistics)); + + mdb->stats->collect =3D TRUE; +} +/** + * mdb_stats_off: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Turns off statistics collection. + * + * If mdb_stats_off is not called, statistics will be turned off when hand= le + * is freed using mdb_close. + **/ +void +mdb_stats_off(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + mdb->stats->collect =3D FALSE; +} +/** + * mdb_dump_stats: + * @mdb: pointer to handle of MDB file with active stats collection. + * + * Dumps current statistics to stdout. + **/ +void +mdb_dump_stats(MdbHandle *mdb) +{ + if (!mdb->stats) return; + + fprintf(stdout, "Physical Page Reads: %lu\n", mdb->stats->pg_reads); +} + +#endif /* !MDB_NO_STATS */ diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/table.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/table.c index 1698e0f..89611c1 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/table.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/table.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include "mdbtools.h" @@ -76,15 +75,16 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) MdbTableDef *table; MdbHandle *mdb =3D entry->mdb; MdbFormatConstants *fmt =3D mdb->fmt; - int len, row_start, pg_row; + int row_start, pg_row; void *buf, *pg_buf =3D mdb->pg_buf; + guint i; = mdb_read_pg(mdb, entry->table_pg); if (mdb_get_byte(pg_buf, 0) !=3D 0x02) /* not a valid table def page */ return NULL; table =3D mdb_alloc_tabledef(entry); = - len =3D mdb_get_int16(pg_buf, 8); + mdb_get_int16(pg_buf, 8); /* len */ = table->num_rows =3D mdb_get_int32(pg_buf, fmt->tab_num_rows_offset); table->num_var_cols =3D mdb_get_int16(pg_buf, fmt->tab_num_cols_offset-2); @@ -97,7 +97,7 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz)); table->usage_map =3D g_memdup((char*)buf + row_start, table->map_sz); if (mdb_get_option(MDB_DEBUG_USAGE)) - buffer_dump(buf, row_start, table->map_sz); + mdb_buffer_dump(buf, row_start, table->map_sz); mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d le= n %d", pg_row >> 8, pg_row & 0xff, row_start, table->map_sz); = @@ -110,6 +110,13 @@ MdbTableDef *mdb_read_table(MdbCatalogEntry *entry) = table->first_data_pg =3D mdb_get_int16(pg_buf, fmt->tab_first_dpg_offset); = + if (entry->props) + for (i=3D0; iprops->len; ++i) { + MdbProperties *props =3D g_array_index(entry->props, MdbProperties*, i); + if (!props->name) + table->props =3D props; + } + return table; } MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int= obj_type) @@ -161,7 +168,6 @@ read_pg_if_8(MdbHandle *mdb, int *cur_pos) void * read_pg_if_n(MdbHandle *mdb, void *buf, int *cur_pos, size_t len) { - char *buf_char =3D (char *)buf; /* Advance to page which contains the first byte */ while (*cur_pos >=3D mdb->fmt->pg_size) { mdb_read_pg(mdb, mdb_get_int32(mdb->pg_buf,4)); @@ -170,20 +176,20 @@ read_pg_if_n(MdbHandle *mdb, void *buf, int *cur_pos,= size_t len) /* Copy pages into buffer */ while (*cur_pos + len >=3D mdb->fmt->pg_size) { int piece_len =3D mdb->fmt->pg_size - *cur_pos; - if (buf_char) { - memcpy(buf_char, mdb->pg_buf + *cur_pos, piece_len); - buf_char +=3D piece_len; + if (buf) { + memcpy(buf, mdb->pg_buf + *cur_pos, piece_len); + buf +=3D piece_len; } len -=3D piece_len; mdb_read_pg(mdb, mdb_get_int32(mdb->pg_buf,4)); *cur_pos =3D 8; } /* Copy into buffer from final page */ - if (len && buf_char) { - memcpy(buf_char, mdb->pg_buf + *cur_pos, len); + if (len && buf) { + memcpy(buf, mdb->pg_buf + *cur_pos, len); } *cur_pos +=3D len; - return buf_char; + return buf; } = = @@ -193,11 +199,20 @@ void mdb_append_column(GPtrArray *columns, MdbColumn = *in_col) } void mdb_free_columns(GPtrArray *columns) { - unsigned int i; + unsigned int i, j; + MdbColumn *col; = if (!columns) return; - for (i=3D0; ilen; i++) - g_free (g_ptr_array_index(columns, i)); + for (i=3D0; ilen; i++) { + col =3D (MdbColumn *) g_ptr_array_index(columns, i); + if (col->sargs) { + for (j=3D0; jsargs->len; j++) { + g_free( g_ptr_array_index(col->sargs, j)); + } + g_ptr_array_free(col->sargs, TRUE); + } + g_free(col); + } g_ptr_array_free(columns, TRUE); } GPtrArray *mdb_read_columns(MdbTableDef *table) @@ -206,9 +221,10 @@ GPtrArray *mdb_read_columns(MdbTableDef *table) MdbFormatConstants *fmt =3D mdb->fmt; MdbColumn *pcol; unsigned char *col; - unsigned int i; + unsigned int i, j; int cur_pos; size_t name_sz; + GArray *allprops; = table->columns =3D g_ptr_array_new(); = @@ -225,24 +241,26 @@ GPtrArray *mdb_read_columns(MdbTableDef *table) for (i=3D0;inum_cols;i++) { #ifdef MDB_DEBUG /* printf("column %d\n", i); - buffer_dump(mdb->pg_buf, cur_pos, fmt->tab_col_entry_size); */ + mdb_buffer_dump(mdb->pg_buf, cur_pos, fmt->tab_col_entry_size); */ #endif read_pg_if_n(mdb, col, &cur_pos, fmt->tab_col_entry_size); pcol =3D (MdbColumn *) g_malloc0(sizeof(MdbColumn)); = - pcol->col_type =3D col[0]; + pcol->table =3D table; = + pcol->col_type =3D col[0]; = + // col_num_offset =3D=3D 1 or 5 pcol->col_num =3D col[fmt->col_num_offset]; = - - + //fprintf(stdout,"----- column %d -----\n",pcol->col_num); + // col_var =3D=3D 3 or 7 pcol->var_col_num =3D mdb_get_int16(col, fmt->tab_col_offset_var); + //fprintf(stdout,"var column pos %d\n",pcol->var_col_num); = - - + // col_var =3D=3D 5 or 9 pcol->row_col_num =3D mdb_get_int16(col, fmt->tab_row_col_num_offset); - + //fprintf(stdout,"row column num %d\n",pcol->row_col_num); = /* FIXME: can this be right in Jet3 and Jet4? */ if (pcol->col_type =3D=3D MDB_NUMERIC) { @@ -250,16 +268,18 @@ GPtrArray *mdb_read_columns(MdbTableDef *table) pcol->col_scale =3D col[12]; } = + // col_flags_offset =3D=3D 13 or 15 + pcol->is_fixed =3D col[fmt->col_flags_offset] & 0x01 ? 1 : 0; + pcol->is_long_auto =3D col[fmt->col_flags_offset] & 0x04 ? 1 : 0; + pcol->is_uuid_auto =3D col[fmt->col_flags_offset] & 0x40 ? 1 : 0; = - pcol->is_fixed =3D col[fmt->col_fixed_offset] & 0x01 ? 1 : 0; - - + // tab_col_offset_fixed =3D=3D 14 or 21 pcol->fixed_offset =3D mdb_get_int16(col, fmt->tab_col_offset_fixed); - - + //fprintf(stdout,"fixed column offset %d\n",pcol->fixed_offset); + //fprintf(stdout,"col type %s\n",pcol->is_fixed ? "fixed" : "variable"); = if (pcol->col_type !=3D MDB_BOOL) { - + // col_size_offset =3D=3D 16 or 23 pcol->col_size =3D mdb_get_int16(col, fmt->col_size_offset); } else { pcol->col_size=3D0; @@ -277,24 +297,34 @@ GPtrArray *mdb_read_columns(MdbTableDef *table) char *tmp_buf; pcol =3D g_ptr_array_index(table->columns, i); = - if (IS_JET4(mdb)) { - name_sz =3D read_pg_if_16(mdb, &cur_pos); - } else if (IS_JET3(mdb)) { + if (IS_JET3(mdb)) name_sz =3D read_pg_if_8(mdb, &cur_pos); - } else { - fprintf(stderr,"Unknown MDB version\n"); - continue; - } + else + name_sz =3D read_pg_if_16(mdb, &cur_pos); tmp_buf =3D (char *) g_malloc(name_sz); read_pg_if_n(mdb, tmp_buf, &cur_pos, name_sz); mdb_unicode2ascii(mdb, tmp_buf, name_sz, pcol->name, MDB_MAX_OBJ_NAME); g_free(tmp_buf); = + } = /* Sort the columns by col_num */ g_ptr_array_sort(table->columns, (GCompareFunc)mdb_col_comparer); = + allprops =3D table->entry->props; + if (allprops) + for (i=3D0;inum_cols;i++) { + pcol =3D g_ptr_array_index(table->columns, i); + for (j=3D0; jlen; ++j) { + MdbProperties *props =3D g_array_index(allprops, MdbProperties*, j); + if (props->name && pcol->name && !strcmp(props->name, pcol->name)) { + pcol->props =3D props; + break; + } + + } + } table->index_start =3D cur_pos; return table->columns; } @@ -306,7 +336,6 @@ MdbTableDef *table; MdbColumn *col; int coln; MdbIndex *idx; -MdbHandle *mdb =3D entry->mdb; unsigned int i, bitn; guint32 pgnum; = @@ -316,6 +345,8 @@ guint32 pgnum; fprintf(stdout,"number of columns =3D %d\n",table->num_cols); fprintf(stdout,"number of indices =3D %d\n",table->num_real_idxs); = + if (table->props) + mdb_dump_props(table->props, stdout, 0); mdb_read_columns(table); mdb_read_indices(table); = @@ -324,8 +355,10 @@ guint32 pgnum; = fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n", i, col->name, - mdb_get_coltype_string(mdb->default_backend, col->col_type), + mdb_get_colbacktype_string(col), col->col_size); + if (col->props) + mdb_dump_props(col->props, stdout, 0); } = for (i=3D0;inum_idxs;i++) { @@ -371,3 +404,17 @@ int mdb_is_system_table(MdbCatalogEntry *entry) return ((entry->object_type =3D=3D MDB_TABLE) && (entry->flags & 0x80000002)) ? 1 : 0; } + +const char * +mdb_table_get_prop(const MdbTableDef *table, const gchar *key) { + if (!table->props) + return NULL; + return g_hash_table_lookup(table->props->hash, key); +} + +const char * +mdb_col_get_prop(const MdbColumn *col, const gchar *key) { + if (!col->props) + return NULL; + return g_hash_table_lookup(col->props->hash, key); +} diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/worktable.c b/src/m= igration/mdb/3rdparty/mdbtools/libmdb/worktable.c index 09c064d..a398d98 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/worktable.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/worktable.c @@ -12,9 +12,8 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = #include "mdbtools.h" @@ -74,6 +73,7 @@ mdb_create_temp_table(MdbHandle *mdb, char *name) void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col) { + col->table =3D table, col->col_num =3D table->num_cols; if (!col->is_fixed) col->var_col_num =3D table->num_var_cols++; diff --git a/src/migration/mdb/3rdparty/mdbtools/libmdb/write.c b/src/migra= tion/mdb/3rdparty/mdbtools/libmdb/write.c index 69da633..95b806e 100644 --- a/src/migration/mdb/3rdparty/mdbtools/libmdb/write.c +++ b/src/migration/mdb/3rdparty/mdbtools/libmdb/write.c @@ -12,41 +12,65 @@ * 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., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-13= 01 USA */ = +#include +#include +#include #include "mdbtools.h" -#include "time.h" -#include "math.h" = #ifdef DMALLOC #include "dmalloc.h" #endif = = - +//static int mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, MdbIndex= Page *ipg); static int mdb_add_row_to_leaf_pg(MdbTableDef *table, MdbIndex *idx, MdbIn= dexPage *ipg, MdbField *idx_fields, guint32 pgnum, guint16 rownum); = void -_mdb_put_int16(void *buf, guint32 offset, guint32 value) +mdb_put_int16(void *buf, guint32 offset, guint32 value) { value =3D GINT32_TO_LE(value); memcpy((char*)buf + offset, &value, 2); } void -_mdb_put_int32(void *buf, guint32 offset, guint32 value) +_mdb_put_int16(void *buf, guint32 offset, guint32 value) +#ifdef HAVE_ATTRIBUTE_ALIAS +__attribute__((alias("mdb_put_int16"))); +#else +{ mdb_put_int16((char*)buf, offset, value); } +#endif + +void +mdb_put_int32(void *buf, guint32 offset, guint32 value) { value =3D GINT32_TO_LE(value); memcpy((char*)buf + offset, &value, 4); } void -_mdb_put_int32_msb(void *buf, guint32 offset, guint32 value) +_mdb_put_int32(void *buf, guint32 offset, guint32 value) +#ifdef HAVE_ATTRIBUTE_ALIAS +__attribute__((alias("mdb_put_int32"))); +#else +{ mdb_put_int32((char*)buf, offset, value); } +#endif + +void +mdb_put_int32_msb(void *buf, guint32 offset, guint32 value) { value =3D GINT32_TO_BE(value); memcpy((char*)buf + offset, &value, 4); } +void +_mdb_put_int32_mdb(void *buf, guint32 offset, guint32 value) +#ifdef HAVE_ATTRIBUTE_ALIAS +__attribute__((alias("mdb_put_int32_msb"))); +#else +{ mdb_put_int32_msb((char*)buf, offset, value); } +#endif + ssize_t mdb_write_pg(MdbHandle *mdb, unsigned long pg) { @@ -57,7 +81,7 @@ mdb_write_pg(MdbHandle *mdb, unsigned long pg) fstat(mdb->f->fd, &status); /* is page beyond current size + 1 ? */ if ((size_t)status.st_size < (offset + mdb->fmt->pg_size)) { - fprintf(stderr,"offset %lu is beyond EOF\n",offset); + fprintf(stderr,"offset %jd is beyond EOF\n",(intmax_t)offset); return 0; } lseek(mdb->f->fd, offset, SEEK_SET); @@ -158,31 +182,31 @@ mdb_crack_row(MdbTableDef *table, int row_start, int = row_end, MdbField *fields) unsigned int i; = if (mdb_get_option(MDB_DEBUG_ROW)) { - buffer_dump(pg_buf, row_start, row_end - row_start + 1); + mdb_buffer_dump(pg_buf, row_start, row_end - row_start + 1); } = - if (IS_JET4(mdb)) { - row_cols =3D mdb_get_int16(pg_buf, row_start); - col_count_size =3D 2; - } else { + if (IS_JET3(mdb)) { row_cols =3D mdb_get_byte(pg_buf, row_start); col_count_size =3D 1; + } else { + row_cols =3D mdb_get_int16(pg_buf, row_start); + col_count_size =3D 2; } = bitmask_sz =3D (row_cols + 7) / 8; - nullmask =3D (unsigned char*)pg_buf + row_end - bitmask_sz + 1; + nullmask =3D (unsigned char *)pg_buf + row_end - bitmask_sz + 1; = /* read table of variable column locations */ - row_var_cols =3D IS_JET4(mdb) ? - mdb_get_int16(pg_buf, row_end - bitmask_sz - 1) : - mdb_get_byte(pg_buf, row_end - bitmask_sz); - var_col_offsets =3D (unsigned int *)g_malloc((row_var_cols+1)*sizeof(int)= ); if (table->num_var_cols > 0) { - if (IS_JET4(mdb)) { - mdb_crack_row4(mdb, row_start, row_end, bitmask_sz, + row_var_cols =3D IS_JET3(mdb) ? + mdb_get_byte(pg_buf, row_end - bitmask_sz) : + mdb_get_int16(pg_buf, row_end - bitmask_sz - 1); + var_col_offsets =3D (unsigned int *)g_malloc((row_var_cols+1)*sizeof(int= )); + if (IS_JET3(mdb)) { + mdb_crack_row3(mdb, row_start, row_end, bitmask_sz, row_var_cols, var_col_offsets); } else { - mdb_crack_row3(mdb, row_start, row_end, bitmask_sz, + mdb_crack_row4(mdb, row_start, row_end, bitmask_sz, row_var_cols, var_col_offsets); } } @@ -246,7 +270,7 @@ mdb_pack_null_mask(unsigned char *buffer, int num_field= s, MdbField *fields) /* column is null if bit is clear (0) */ if (!fields[i].is_null) { byte |=3D 1 << bit; - + //printf("%d %d %d %d\n", i, bit, 1 << bit, byte); } bit++; if (bit=3D=3D8) { @@ -404,10 +428,10 @@ mdb_pack_row(MdbTableDef *table, unsigned char *row_b= uffer, int unsigned num_fie } } } - if (IS_JET4(table->entry->mdb)) { - return mdb_pack_row4(table, row_buffer, num_fields, fields); - } else { + if (IS_JET3(table->entry->mdb)) { return mdb_pack_row3(table, row_buffer, num_fields, fields); + } else { + return mdb_pack_row4(table, row_buffer, num_fields, fields); } } int @@ -428,8 +452,8 @@ mdb_new_leaf_pg(MdbCatalogEntry *entry) MdbHandle *mdb =3D entry->mdb; void *new_pg =3D g_malloc0(mdb->fmt->pg_size); = - _mdb_put_int16(new_pg, 2, 0x0104); - _mdb_put_int32(new_pg, 4, entry->table_pg); + mdb_put_int16(new_pg, 0, 0x0104); + mdb_put_int32(new_pg, 4, entry->table_pg); = return new_pg; } @@ -439,13 +463,14 @@ mdb_new_data_pg(MdbCatalogEntry *entry) MdbFormatConstants *fmt =3D entry->mdb->fmt; void *new_pg =3D g_malloc0(fmt->pg_size); = - _mdb_put_int16(new_pg, 2, 0x0101); - _mdb_put_int16(new_pg, 2, fmt->pg_size - fmt->row_count_offset - 2); - _mdb_put_int32(new_pg, 4, entry->table_pg); + mdb_put_int16(new_pg, 0, 0x0101); + mdb_put_int16(new_pg, 2, fmt->pg_size - fmt->row_count_offset - 2); + mdb_put_int32(new_pg, 4, entry->table_pg); = return new_pg; } = +/* could be static */ int mdb_update_indexes(MdbTableDef *table, int num_fields, MdbField *fields, g= uint32 pgnum, guint16 rownum) { @@ -476,25 +501,22 @@ mdb_init_index_chain(MdbTableDef *table, MdbIndex *id= x) return 1; } = +/* could be static */ int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_field= s, MdbField *fields, guint32 pgnum, guint16 rownum) { MdbCatalogEntry *entry =3D table->entry; MdbHandle *mdb =3D entry->mdb; - /* - int idx_xref[16]; - */ + /*int idx_xref[16];*/ unsigned int i, j; MdbIndexChain *chain; MdbField idx_fields[10]; = for (i =3D 0; i < idx->num_keys; i++) { for (j =3D 0; j < num_fields; j++) { - /* key_col_num is 1 based, can't remember why though */ + // key_col_num is 1 based, can't remember why though if (fields[j].colnum =3D=3D idx->key_col_num[i]-1) { - /* - idx_xref[i] =3D j; - */ + /* idx_xref[i] =3D j; */ idx_fields[i] =3D fields[j]; } } @@ -515,10 +537,10 @@ mdb_update_index(MdbTableDef *table, MdbIndex *idx, u= nsigned int num_fields, Mdb chain =3D g_malloc0(sizeof(MdbIndexChain)); = mdb_index_find_row(mdb, idx, chain, pgnum, rownum); - - - - + //printf("chain depth =3D %d\n", chain->cur_depth); + //printf("pg =3D %" G_GUINT32_FORMAT "\n", + //chain->pages[chain->cur_depth-1].pg); + //mdb_copy_index_pg(table, idx, &chain->pages[chain->cur_depth-1]); mdb_add_row_to_leaf_pg(table, idx, &chain->pages[chain->cur_depth-1], idx= _fields, pgnum, rownum); = return 1; @@ -541,7 +563,7 @@ mdb_insert_row(MdbTableDef *table, int num_fields, MdbF= ield *fields) } new_row_size =3D mdb_pack_row(table, row_buffer, num_fields, fields); if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(row_buffer, 0, new_row_size); + mdb_buffer_dump(row_buffer, 0, new_row_size); } pgnum =3D mdb_map_find_next_freepage(table, new_row_size); if (!pgnum) { @@ -552,13 +574,13 @@ mdb_insert_row(MdbTableDef *table, int num_fields, Md= bField *fields) rownum =3D mdb_add_row_to_pg(table, row_buffer, new_row_size); = if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, 0, 40); - buffer_dump(mdb->pg_buf, fmt->pg_size - 160, 160); + mdb_buffer_dump(mdb->pg_buf, 0, 40); + mdb_buffer_dump(mdb->pg_buf, fmt->pg_size - 160, 160); } mdb_debug(MDB_DEBUG_WRITE, "writing page %d", pgnum); if (!mdb_write_pg(mdb, pgnum)) { - fprintf(stderr, "write failed! exiting...\n"); - exit(1); + fprintf(stderr, "write failed!\n"); + return 0; } = mdb_update_indexes(table, num_fields, fields, pgnum, rownum); @@ -606,7 +628,7 @@ mdb_add_row_to_pg(MdbTableDef *table, unsigned char *ro= w_buffer, int new_row_siz mdb_find_row(mdb, i, &row_start, &row_size); pos -=3D row_size; memcpy((char*)new_pg + pos, mdb->pg_buf + row_start, row_size); - _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); + mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (i*2), pos); } } = @@ -614,14 +636,14 @@ mdb_add_row_to_pg(MdbTableDef *table, unsigned char *= row_buffer, int new_row_siz pos -=3D new_row_size; memcpy((char*)new_pg + pos, row_buffer, new_row_size); /* add row to the row offset table */ - _mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); + mdb_put_int16(new_pg, (fmt->row_count_offset + 2) + (num_rows*2), pos); = /* update number rows on this page */ num_rows++; - _mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); + mdb_put_int16(new_pg, fmt->row_count_offset, num_rows); = /* update the freespace */ - _mdb_put_int16(new_pg,2,pos - fmt->row_count_offset - 2 - (num_rows*2)); + mdb_put_int16(new_pg,2,pos - fmt->row_count_offset - 2 - (num_rows*2)); = /* copy new page over old */ if (!table->is_temp_table) { @@ -655,7 +677,7 @@ unsigned int num_fields; = mdb_debug(MDB_DEBUG_WRITE,"page %lu row %d start %d end %d", (unsigned lo= ng) table->cur_phys_pg, table->cur_row-1, row_start, row_end); if (mdb_get_option(MDB_DEBUG_LIKE)) - buffer_dump(mdb->pg_buf, row_start, old_row_size); + mdb_buffer_dump(mdb->pg_buf, row_start, old_row_size); = for (i=3D0;inum_cols;i++) { col =3D g_ptr_array_index(table->columns,i); @@ -668,7 +690,7 @@ unsigned int num_fields; = if (mdb_get_option(MDB_DEBUG_WRITE)) { for (i=3D0;inum_cols;i++) { @@ -681,15 +703,21 @@ unsigned int num_fields; = new_row_size =3D mdb_pack_row(table, row_buffer, num_fields, fields); if (mdb_get_option(MDB_DEBUG_WRITE)) - buffer_dump(row_buffer, 0, new_row_size); + mdb_buffer_dump(row_buffer, 0, new_row_size); if (new_row_size > (old_row_size + mdb_pg_get_freespace(mdb))) { 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); - return 0; + return 0; /* FIXME */ } + +/* WARNING the return code is opposite to convention used elsewhere: + * returns 0 on success + * returns 1 on failure + * This might change on next ABI break. + */ int mdb_replace_row(MdbTableDef *table, int row, void *new_row, int new_row_si= ze) { @@ -704,14 +732,14 @@ guint16 num_rows; int i, pos; = if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, 0, 40); - buffer_dump(mdb->pg_buf, pg_size - 160, 160); + mdb_buffer_dump(mdb->pg_buf, 0, 40); + mdb_buffer_dump(mdb->pg_buf, pg_size - 160, 160); } mdb_debug(MDB_DEBUG_WRITE,"updating row %d on page %lu", row, (unsigned l= ong) table->cur_phys_pg); new_pg =3D mdb_new_data_pg(entry); = num_rows =3D mdb_get_int16(mdb->pg_buf, rco); - _mdb_put_int16(new_pg, rco, num_rows); + mdb_put_int16(new_pg, rco, num_rows); = pos =3D pg_size; = @@ -720,20 +748,20 @@ int i, pos; mdb_find_row(mdb, i, &row_start, &row_size); pos -=3D row_size; memcpy((char*)new_pg + pos, mdb->pg_buf + row_start, row_size); - _mdb_put_int16(new_pg, rco + 2 + i*2, pos); + mdb_put_int16(new_pg, rco + 2 + i*2, pos); } = /* our row */ pos -=3D new_row_size; memcpy((char*)new_pg + pos, new_row, new_row_size); - _mdb_put_int16(new_pg, rco + 2 + row*2, pos); + mdb_put_int16(new_pg, rco + 2 + row*2, pos); = /* rows after */ for (i=3Drow+1;ipg_buf + row_start, row_size); - _mdb_put_int16(new_pg, rco + 2 + i*2, pos); + mdb_put_int16(new_pg, rco + 2 + i*2, pos); } = /* almost done, copy page over current */ @@ -741,15 +769,15 @@ int i, pos; = g_free(new_pg); = - _mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); + mdb_put_int16(mdb->pg_buf, 2, mdb_pg_get_freespace(mdb)); if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, 0, 40); - buffer_dump(mdb->pg_buf, pg_size - 160, 160); + mdb_buffer_dump(mdb->pg_buf, 0, 40); + mdb_buffer_dump(mdb->pg_buf, pg_size - 160, 160); } /* drum roll, please */ if (!mdb_write_pg(mdb, table->cur_phys_pg)) { - fprintf(stderr, "write failed! exiting...\n"); - exit(1); + fprintf(stderr, "write failed!\n"); + return 1; } return 0; } @@ -796,16 +824,18 @@ mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, = MdbIndexPage *ipg) } = pg_row =3D mdb_get_int32_msb(mdb->pg_buf, ipg->offset + ipg->len - 4); + /* guint32 pg =3D pg_row >> 8; */ row =3D pg_row & 0xff; + /* unsigned char iflag =3D mdb->pg_buf[ipg->offset]; */ = /* turn the key hash back into a value */ mdb_index_swap_n(&mdb->pg_buf[ipg->offset + 1], col->col_size, key_hash); key_hash[col->col_size - 1] &=3D 0x7f; = if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, ipg->offset, ipg->len); - buffer_dump(mdb->pg_buf, ipg->offset + 1, col->col_size); - buffer_dump(key_hash, 0, col->col_size); + mdb_buffer_dump(mdb->pg_buf, ipg->offset, ipg->len); + mdb_buffer_dump(mdb->pg_buf, ipg->offset + 1, col->col_size); + mdb_buffer_dump(key_hash, 0, col->col_size); } = memcpy((char*)new_pg + ipg->offset, mdb->pg_buf + ipg->offset, ipg->len); @@ -815,31 +845,36 @@ mdb_copy_index_pg(MdbTableDef *table, MdbIndex *idx, = MdbIndexPage *ipg) row++; } = + if (!row) { + fprintf(stderr,"missing indexes not yet supported, aborting\n"); + return 0; + } + //mdb_put_int16(new_pg, mdb->fmt->row_count_offset, row); /* free space left */ - _mdb_put_int16(new_pg, 2, mdb->fmt->pg_size - ipg->offset); - + mdb_put_int16(new_pg, 2, mdb->fmt->pg_size - ipg->offset); + //printf("offset =3D %d\n", ipg->offset); = mdb_index_swap_n(idx_fields[0].value, col->col_size, key_hash); key_hash[0] |=3D 0x080; if (mdb_get_option(MDB_DEBUG_WRITE)) { printf("key_hash\n"); - buffer_dump(idx_fields[0].value, 0, col->col_size); - buffer_dump(key_hash, 0, col->col_size); + mdb_buffer_dump(idx_fields[0].value, 0, col->col_size); + mdb_buffer_dump(key_hash, 0, col->col_size); printf("--------\n"); } ((char *)new_pg)[ipg->offset] =3D 0x7f; memcpy((char*)new_pg + ipg->offset + 1, key_hash, col->col_size); pg_row =3D (pgnum << 8) | ((rownum-1) & 0xff); - _mdb_put_int32_msb(new_pg, ipg->offset + 5, pg_row); + mdb_put_int32_msb(new_pg, ipg->offset + 5, pg_row); ipg->idx_starts[row++] =3D ipg->offset + ipg->len; - + //ipg->idx_starts[row] =3D ipg->offset + ipg->len; if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, 0, mdb->fmt->pg_size); + mdb_buffer_dump(mdb->pg_buf, 0, mdb->fmt->pg_size); } memcpy(mdb->pg_buf, new_pg, mdb->fmt->pg_size); mdb_index_pack_bitmap(mdb, ipg); if (mdb_get_option(MDB_DEBUG_WRITE)) { - buffer_dump(mdb->pg_buf, 0, mdb->fmt->pg_size); + mdb_buffer_dump(mdb->pg_buf, 0, mdb->fmt->pg_size); } g_free(new_pg); = diff --git a/src/migration/mdb/3rdparty/mdbtools/update_diffs.sh b/src/migr= ation/mdb/3rdparty/mdbtools/update_diffs.sh deleted file mode 100755 index fae35dc..0000000 --- a/src/migration/mdb/3rdparty/mdbtools/update_diffs.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -cd libmdb -for i in `ls -1 *.c` ; do cd ..; diff -u ./libmdb.cvs/$i ./libmdb/$i > ../= diffs/`echo $i | sed -e 's/\.c/\.diff/g'` ; cd libmdb; done - -cd .. -diff -u ./include.cvs/mdbtools.h ./include/mdbtools.h > ../diffs/mdbtools.= diff diff --git a/src/migration/mdb/ChangeLog b/src/migration/mdb/ChangeLog index e7bf6b9..2db9229 100644 --- a/src/migration/mdb/ChangeLog +++ b/src/migration/mdb/ChangeLog @@ -1,3 +1,7 @@ +Mon Jun 24 21:04:51 CEST 2014 + Update to mdbtools from June. This also fixes primary keys import. +-- Jaros=C5=82aw Staniek + Mon Jun 4 14:49:44 CEST 2007 Ported to Qt4, imported into calligra/kexi/migration/ for Kexi 2.0. -- Jaros=C5=82aw Staniek diff --git a/src/migration/mdb/src/CMakeLists.txt b/src/migration/mdb/src/C= MakeLists.txt index 34e0a52..bbd90ad 100644 --- a/src/migration/mdb/src/CMakeLists.txt +++ b/src/migration/mdb/src/CMakeLists.txt @@ -3,7 +3,10 @@ if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) add_definitions(-Wno-missing-format-attribute) add_definitions(-Wno-sign-compare) add_definitions(-Wno-unused-parameter) -endif () + add_definitions(-Wno-pointer-arith) + add_definitions(-std=3Dc99) + add_definitions(-Wno-cast-qual) +endif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) = set(MDBTOOLS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src/migration/mdb/3rdparty/md= btools") = @@ -31,7 +34,9 @@ ${MDBTOOLS_SOURCE_DIR}/libmdb/map.c ${MDBTOOLS_SOURCE_DIR}/libmdb/mem.c ${MDBTOOLS_SOURCE_DIR}/libmdb/money.c ${MDBTOOLS_SOURCE_DIR}/libmdb/options.c +${MDBTOOLS_SOURCE_DIR}/libmdb/props.c ${MDBTOOLS_SOURCE_DIR}/libmdb/sargs.c +${MDBTOOLS_SOURCE_DIR}/libmdb/stats.c ${MDBTOOLS_SOURCE_DIR}/libmdb/table.c ${MDBTOOLS_SOURCE_DIR}/libmdb/worktable.c ${MDBTOOLS_SOURCE_DIR}/libmdb/write.c diff --git a/src/migration/mdb/src/keximdb/mdbmigrate.cpp b/src/migration/m= db/src/keximdb/mdbmigrate.cpp index e0c45ba..21f7b29 100644 --- a/src/migration/mdb/src/keximdb/mdbmigrate.cpp +++ b/src/migration/mdb/src/keximdb/mdbmigrate.cpp @@ -1,6 +1,6 @@ /* This file is part of the KDE project Copyright (C) 2005,2006 Martin Ellis - Copyright (C) 2005 Jaros=C5=82aw Staniek + Copyright (C) 2005-2014 Jaros=C5=82aw Staniek = This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -50,18 +50,6 @@ MDBMigrate::MDBMigrate(QObject *parent, const QVariantLi= st &args) setPropertyValue(nonUnicodePropId, QString()); setPropertyCaption(nonUnicodePropId, xi18n("Source Database Non-Unicod= e Character Encoding")); = - initBackend(); -} - -MDBMigrate::~MDBMigrate() -{ - releaseBackend(); -} - -void MDBMigrate::initBackend() -{ - mdb_init(); - // Date format associated with Qt::ISODate: YYYY-MM-DDTHH:MM:SS // (where T is a literal). The following is equivalent to %FT%T, but // backards compatible with old/Windows C libraries. @@ -69,9 +57,8 @@ void MDBMigrate::initBackend() mdb_set_date_fmt("%Y-%m-%dT%H:%M:%S"); } = -void MDBMigrate::releaseBackend() +MDBMigrate::~MDBMigrate() { - mdb_exit(); } = QVariant MDBMigrate::propertyValue(const QByteArray& propName) @@ -227,7 +214,7 @@ QVariant MDBMigrate::toQVariant(const char* data, unsig= ned int len, int type) case MDB_BOOL: //! @todo use &bool! case MDB_BYTE: return QString::fromUtf8(data, len).toShort(); - case MDB_SDATETIME: + case MDB_DATETIME: return QDateTime::fromString(data, Qt::ISODate); case MDB_INT: case MDB_LONGINT: @@ -350,7 +337,7 @@ KDbField::Type MDBMigrate::type(int type) case MDB_DOUBLE: kexiType =3D KDbField::Double; break; - case MDB_SDATETIME: + case MDB_DATETIME: kexiType =3D KDbField::DateTime; break; case MDB_TEXT: @@ -428,10 +415,10 @@ bool MDBMigrate::getPrimaryKey(KDbTableSchema* table,= MdbTableDef* tableDef) = if (ok) { //qDebug() << *p_idx; - = + // ... and add it to the table definition // but only if the PK has only one field, so far :o( - = + KDbField *f; if (idx->num_keys =3D=3D 1 && (f =3D table->field(idx->key_col_num= [0] - 1))) { f->setPrimaryKey(true); @@ -455,5 +442,3 @@ bool MDBMigrate::drv_getTableSize(const QString& table,= quint64& size) mdb_free_tabledef(tableDef); return true; } - - diff --git a/src/migration/mdb/src/keximdb/mdbmigrate.h b/src/migration/mdb= /src/keximdb/mdbmigrate.h index c27b90e..d9669f9 100644 --- a/src/migration/mdb/src/keximdb/mdbmigrate.h +++ b/src/migration/mdb/src/keximdb/mdbmigrate.h @@ -1,6 +1,6 @@ /* This file is part of the KDE project Copyright (C) 2005,2006 Martin Ellis - Copyright (C) 2005 Jaros=C5=82aw Staniek + Copyright (C) 2005-2014 Jaros=C5=82aw Staniek = This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -35,7 +35,6 @@ namespace KexiMigration = class MDBMigrate : public KexiMigrate { - Q_OBJECT KEXIMIGRATION_DRIVER = public: @@ -86,8 +85,6 @@ protected: virtual bool drv_getTableSize(const QString& table, quint64 *size); = private: - void initBackend(); - void releaseBackend(); MdbHandle *m_mdb; }; }