1 /* MDB Tools - A library for reading MS Access database files 2 * Copyright (C) 2000 Brian Bruns 3 * 4 * This library is free software; you can redistribute it and/or delay_load(library: &str, function: &str) -> std::result::Result<RawPtr, HRESULT>5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 #ifndef _mdbtools_h_ 20 #define _mdbtools_h_ 21 22 #ifdef __cplusplus 23 extern "C" { 24 #endif 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <stdarg.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <ctype.h> 33 #include <string.h> 34 #include <glib.h> 35 36 #ifdef HAVE_ICONV 37 #include <iconv.h> 38 #endif 39 40 #define MDB_DEBUG 0 41 42 #define MDB_PGSIZE 4096 43 #define MDB_MAX_OBJ_NAME 256 44 #define MDB_MAX_COLS 256 45 #define MDB_MAX_IDX_COLS 10 46 #define MDB_CATALOG_PG 18 47 #define MDB_MEMO_OVERHEAD 12 48 #define MDB_BIND_SIZE 16384 49 50 enum { 51 MDB_PAGE_DB = 0, 52 MDB_PAGE_DATA, 53 MDB_PAGE_TABLE, 54 MDB_PAGE_INDEX, 55 MDB_PAGE_LEAF, 56 MDB_PAGE_MAP 57 }; 58 enum { 59 MDB_VER_JET3 = 0, 60 MDB_VER_JET4 = 1 61 }; 62 enum { 63 MDB_FORM = 0, 64 MDB_TABLE, 65 MDB_MACRO, 66 MDB_SYSTEM_TABLE, 67 MDB_REPORT, 68 MDB_QUERY, 69 MDB_LINKED_TABLE, 70 MDB_MODULE, 71 MDB_RELATIONSHIP, 72 MDB_UNKNOWN_09, 73 MDB_UNKNOWN_0A, 74 MDB_DATABASE_PROPERTY, 75 MDB_ANY = -1 76 }; 77 enum { 78 MDB_BOOL = 0x01, 79 MDB_BYTE = 0x02, 80 MDB_INT = 0x03, 81 MDB_LONGINT = 0x04, 82 MDB_MONEY = 0x05, 83 MDB_FLOAT = 0x06, 84 MDB_DOUBLE = 0x07, 85 MDB_SDATETIME = 0x08, 86 MDB_TEXT = 0x0a, 87 MDB_OLE = 0x0b, 88 MDB_MEMO = 0x0c, 89 MDB_REPID = 0x0f, 90 MDB_NUMERIC = 0x10 91 }; 92 93 /* SARG operators */ 94 enum { 95 MDB_OR = 1, 96 MDB_AND, 97 MDB_NOT, 98 MDB_EQUAL, 99 MDB_GT, 100 MDB_LT, 101 MDB_GTEQ, 102 MDB_LTEQ, 103 MDB_LIKE, 104 MDB_ISNULL, 105 MDB_NOTNULL 106 }; 107 108 typedef enum { 109 MDB_TABLE_SCAN, 110 MDB_LEAF_SCAN, 111 MDB_INDEX_SCAN 112 } MdbStrategy; 113 114 typedef enum { 115 MDB_NOFLAGS = 0x00, 116 MDB_WRITABLE = 0x01 117 } MdbFileFlags; 118 119 enum { 120 MDB_DEBUG_LIKE = 0x0001, 121 MDB_DEBUG_WRITE = 0x0002, 122 MDB_DEBUG_USAGE = 0x0004, 123 MDB_DEBUG_OLE = 0x0008, 124 MDB_DEBUG_ROW = 0x0010, 125 MDB_USE_INDEX = 0x0020, 126 MDB_NO_MEMO = 0x0040 /* don't follow memo fields */ 127 }; 128 129 #define mdb_is_logical_op(x) (x == MDB_OR || \ 130 x == MDB_AND || \ 131 x == MDB_NOT ) 132 133 #define mdb_is_relational_op(x) (x == MDB_EQUAL || \ 134 x == MDB_GT || \ 135 x == MDB_LT || \ 136 x == MDB_GTEQ || \ 137 x == MDB_LTEQ || \ 138 x == MDB_LIKE || \ 139 x == MDB_ISNULL || \ 140 x == MDB_NOTNULL ) 141 142 enum { 143 MDB_ASC, 144 MDB_DESC 145 }; 146 147 enum { 148 MDB_IDX_UNIQUE = 0x01, 149 MDB_IDX_IGNORENULLS = 0x02, 150 MDB_IDX_REQUIRED = 0x08 151 }; 152 153 #define IS_JET4(mdb) (mdb->f->jet_version==MDB_VER_JET4) 154 #define IS_JET3(mdb) (mdb->f->jet_version==MDB_VER_JET3) 155 156 /* hash to store registered backends */ 157 extern GHashTable *mdb_backends; 158 159 /* forward declarations */ 160 typedef struct mdbindex MdbIndex; 161 typedef struct mdbsargtree MdbSargNode; 162 163 typedef struct { 164 char *name; 165 unsigned char needs_length; /* or precision */ 166 unsigned char needs_scale; 167 unsigned char needs_quotes; 168 } MdbBackendType; 169 170 typedef struct { 171 MdbBackendType *types_table; 172 } MdbBackend; 173 174 typedef struct { 175 gboolean collect; 176 unsigned long pg_reads; 177 } MdbStatistics; 178 179 typedef struct { 180 int fd; 181 gboolean writable; 182 char *filename; 183 guint32 jet_version; 184 guint32 db_key; 185 char db_passwd[14]; 186 MdbBackend *default_backend; 187 char *backend_name; 188 MdbStatistics *stats; 189 /* free map */ 190 int map_sz; 191 unsigned char *free_map; 192 /* reference count */ 193 int refs; 194 } MdbFile; 195 196 /* offset to row count on data pages...version dependant */ 197 typedef struct { 198 ssize_t pg_size; 199 guint16 row_count_offset; 200 guint16 tab_num_rows_offset; 201 guint16 tab_num_cols_offset; 202 guint16 tab_num_idxs_offset; 203 guint16 tab_num_ridxs_offset; 204 guint16 tab_usage_map_offset; 205 guint16 tab_first_dpg_offset; 206 guint16 tab_cols_start_offset; 207 guint16 tab_ridx_entry_size; 208 guint16 col_fixed_offset; 209 guint16 col_size_offset; 210 guint16 col_num_offset; 211 guint16 tab_col_entry_size; 212 guint16 tab_free_map_offset; 213 guint16 tab_col_offset_var; 214 guint16 tab_col_offset_fixed; 215 guint16 tab_row_col_num_offset; 216 } MdbFormatConstants; 217 218 typedef struct { 219 MdbFile *f; 220 guint32 cur_pg; 221 guint16 row_num; 222 unsigned int cur_pos; 223 unsigned char pg_buf[MDB_PGSIZE]; 224 unsigned char alt_pg_buf[MDB_PGSIZE]; 225 unsigned int num_catalog; 226 GPtrArray *catalog; 227 MdbBackend *default_backend; 228 char *backend_name; 229 MdbFormatConstants *fmt; 230 MdbStatistics *stats; 231 #ifdef HAVE_ICONV 232 iconv_t iconv_in; 233 iconv_t iconv_out; 234 #endif 235 } MdbHandle; 236 237 typedef struct { 238 MdbHandle *mdb; 239 char object_name[MDB_MAX_OBJ_NAME+1]; 240 int object_type; 241 unsigned long table_pg; /* misnomer since object may not be a table */ 242 unsigned long kkd_pg; 243 unsigned int kkd_rowid; 244 int num_props; 245 GArray *props; 246 GArray *columns; 247 int flags; 248 } MdbCatalogEntry; 249 250 typedef struct { 251 gchar *name; 252 GHashTable *hash; 253 } MdbProperties; 254 255 typedef union { 256 int i; 257 double d; 258 char s[256]; 259 } MdbAny; 260 261 typedef struct { 262 char name[MDB_MAX_OBJ_NAME+1]; 263 int col_type; 264 int col_size; 265 void *bind_ptr; 266 int *len_ptr; 267 GHashTable *properties; 268 unsigned int num_sargs; 269 GPtrArray *sargs; 270 GPtrArray *idx_sarg_cache; 271 unsigned char is_fixed; 272 int query_order; 273 /* col_num is the current column order, 274 * does not include deletes */ 275 int col_num; 276 int cur_value_start; 277 int cur_value_len; 278 /* MEMO/OLE readers */ 279 guint32 cur_blob_pg_row; 280 int chunk_size; 281 /* numerics only */ 282 int col_prec; 283 int col_scale; 284 MdbProperties *props; 285 /* info needed for handling deleted/added columns */ 286 int fixed_offset; 287 unsigned int var_col_num; 288 /* row_col_num is the row column number order, 289 * including deleted columns */ 290 int row_col_num; 291 } MdbColumn; 292 293 struct mdbsargtree { 294 int op; 295 MdbColumn *col; 296 MdbAny value; 297 void *parent; 298 MdbSargNode *left; 299 MdbSargNode *right; 300 }; 301 302 typedef struct { 303 guint32 pg; 304 int start_pos; 305 int offset; 306 int len; 307 guint16 idx_starts[2000]; 308 unsigned char cache_value[256]; 309 } MdbIndexPage; 310 311 typedef int (*MdbSargTreeFunc)(MdbSargNode *, gpointer data); 312 313 #define MDB_MAX_INDEX_DEPTH 10 314 315 typedef struct { 316 int cur_depth; 317 guint32 last_leaf_found; 318 int clean_up_mode; 319 MdbIndexPage pages[MDB_MAX_INDEX_DEPTH]; 320 } MdbIndexChain; 321 322 typedef struct { 323 MdbCatalogEntry *entry; 324 char name[MDB_MAX_OBJ_NAME+1]; 325 unsigned int num_cols; 326 GPtrArray *columns; 327 unsigned int num_rows; 328 int index_start; 329 unsigned int num_real_idxs; 330 unsigned int num_idxs; 331 GPtrArray *indices; 332 guint32 first_data_pg; 333 guint32 cur_pg_num; 334 guint32 cur_phys_pg; 335 unsigned int cur_row; 336 int noskip_del; /* don't skip deleted rows */ 337 /* object allocation map */ 338 guint32 map_base_pg; 339 unsigned int map_sz; 340 unsigned char *usage_map; 341 /* pages with free space left */ 342 guint32 freemap_base_pg; 343 unsigned int freemap_sz; 344 unsigned char *free_usage_map; 345 /* query planner */ 346 MdbSargNode *sarg_tree; 347 MdbStrategy strategy; 348 MdbIndex *scan_idx; 349 MdbHandle *mdbidx; 350 MdbIndexChain *chain; 351 MdbProperties *props; 352 unsigned int num_var_cols; /* to know if row has variable columns */ 353 /* temp table */ 354 unsigned int is_temp_table; 355 GPtrArray *temp_table_pages; 356 } MdbTableDef; 357 358 struct mdbindex { 359 int index_num; 360 char name[MDB_MAX_OBJ_NAME+1]; 361 unsigned char index_type; 362 guint32 first_pg; 363 int num_rows; /* number rows in index */ 364 unsigned int num_keys; 365 short key_col_num[MDB_MAX_IDX_COLS]; 366 unsigned char key_col_order[MDB_MAX_IDX_COLS]; 367 unsigned char flags; 368 MdbTableDef *table; 369 }; 370 371 typedef struct { 372 char name[MDB_MAX_OBJ_NAME+1]; 373 } MdbColumnProp; 374 375 typedef struct { 376 void *value; 377 int siz; 378 int start; 379 unsigned char is_null; 380 unsigned char is_fixed; 381 int colnum; 382 int offset; 383 } MdbField; 384 385 typedef struct { 386 int op; 387 MdbAny value; 388 } MdbSarg; 389 390 /* mem.c */ 391 extern void mdb_init(); 392 extern void mdb_exit(); 393 394 /* file.c */ 395 extern ssize_t mdb_read_pg(MdbHandle *mdb, unsigned long pg); 396 extern ssize_t mdb_read_alt_pg(MdbHandle *mdb, unsigned long pg); 397 extern unsigned char mdb_get_byte(unsigned char *buf, int offset); 398 extern int mdb_get_int16(unsigned char *buf, int offset); 399 extern gint32 mdb_get_int24(unsigned char *buf, int offset); 400 extern long mdb_get_int32(unsigned char *buf, int offset); 401 extern float mdb_get_single(unsigned char *buf, int offset); 402 extern double mdb_get_double(unsigned char *buf, int offset); 403 extern unsigned char mdb_pg_get_byte(MdbHandle *mdb, int offset); 404 extern int mdb_pg_get_int16(MdbHandle *mdb, int offset); 405 extern gint32 mdb_pg_get_int24(MdbHandle *mdb, int offset); 406 extern long mdb_pg_get_int32(MdbHandle *mdb, int offset); 407 extern float mdb_pg_get_single(MdbHandle *mdb, int offset); 408 extern double mdb_pg_get_double(MdbHandle *mdb, int offset); 409 extern gint32 mdb_pg_get_int24_msb(MdbHandle *mdb, int offset); 410 extern MdbHandle *mdb_open(const char *filename, MdbFileFlags flags); 411 extern void mdb_close(MdbHandle *mdb); 412 extern MdbHandle *mdb_clone_handle(MdbHandle *mdb); 413 extern void mdb_swap_pgbuf(MdbHandle *mdb); 414 extern long _mdb_get_int32(unsigned char *buf, int offset); 415 416 /* catalog.c */ 417 extern void mdb_free_catalog(MdbHandle *mdb); 418 extern GPtrArray *mdb_read_catalog(MdbHandle *mdb, int obj_type); 419 extern void mdb_dump_catalog(MdbHandle *mdb, int obj_type); 420 extern char *mdb_get_objtype_string(int obj_type); 421 422 /* table.c */ 423 extern MdbTableDef *mdb_alloc_tabledef(MdbCatalogEntry *entry); 424 extern void mdb_free_tabledef(MdbTableDef *table); 425 extern MdbTableDef *mdb_read_table(MdbCatalogEntry *entry); 426 extern MdbTableDef *mdb_read_table_by_name(MdbHandle *mdb, gchar *table_name, int obj_type); 427 extern void mdb_append_column(GPtrArray *columns, MdbColumn *in_col); 428 extern void mdb_free_columns(GPtrArray *columns); 429 extern GPtrArray *mdb_read_columns(MdbTableDef *table); 430 extern void mdb_table_dump(MdbCatalogEntry *entry); 431 extern guint16 read_pg_if_16(MdbHandle *mdb, int *cur_pos); 432 extern guint32 read_pg_if_32(MdbHandle *mdb, int *cur_pos); 433 extern int read_pg_if(MdbHandle *mdb, int *cur_pos, int offset); 434 extern guint16 read_pg_if_n(MdbHandle *mdb, unsigned char *buf, int *cur_pos, int len); 435 extern int mdb_is_user_table(MdbCatalogEntry *entry); 436 extern int mdb_is_system_table(MdbCatalogEntry *entry); 437 438 /* data.c */ 439 extern int mdb_bind_column_by_name(MdbTableDef *table, gchar *col_name, void *bind_ptr, int *len_ptr); 440 extern void mdb_data_dump(MdbTableDef *table); 441 extern void mdb_bind_column(MdbTableDef *table, int col_num, void *bind_ptr, int *len_ptr); 442 extern int mdb_rewind_table(MdbTableDef *table); 443 extern int mdb_fetch_row(MdbTableDef *table); 444 extern int mdb_is_fixed_col(MdbColumn *col); 445 extern char *mdb_col_to_string(MdbHandle *mdb, unsigned char *buf, int start, int datatype, int size); 446 extern int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len); 447 extern int mdb_find_row(MdbHandle *mdb, int row, int *start, int *len); 448 extern int mdb_find_end_of_row(MdbHandle *mdb, int row); 449 extern int mdb_col_fixed_size(MdbColumn *col); 450 extern int mdb_col_disp_size(MdbColumn *col); 451 extern size_t mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr); 452 extern size_t mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size); 453 extern void mdb_set_date_fmt(const char *); 454 extern int mdb_read_row(MdbTableDef *table, unsigned int row); 455 456 /* dump.c */ 457 extern void buffer_dump(const unsigned char* buf, int start, int end); 458 459 /* backend.c */ 460 extern char *mdb_get_coltype_string(MdbBackend *backend, int col_type); 461 extern int mdb_coltype_takes_length(MdbBackend *backend, int col_type); 462 extern void mdb_init_backends(); 463 extern void mdb_register_backend(MdbBackendType *backend, char *backend_name); 464 extern void mdb_remove_backends(); 465 extern int mdb_set_default_backend(MdbHandle *mdb, char *backend_name); 466 extern char *mdb_get_relationships(MdbHandle *mdb); 467 468 /* sargs.c */ 469 extern int mdb_test_sargs(MdbTableDef *table, MdbField *fields, int num_fields); 470 extern int mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field); 471 extern void mdb_sql_walk_tree(MdbSargNode *node, MdbSargTreeFunc func, gpointer data); 472 extern int mdb_find_indexable_sargs(MdbSargNode *node, gpointer data); 473 extern int mdb_add_sarg_by_name(MdbTableDef *table, char *colname, MdbSarg *in_sarg); 474 extern int mdb_test_string(MdbSargNode *node, char *s); 475 extern int mdb_test_int(MdbSargNode *node, gint32 i); 476 extern int mdb_add_sarg(MdbColumn *col, MdbSarg *in_sarg); 477 478 479 480 /* index.c */ 481 extern GPtrArray *mdb_read_indices(MdbTableDef *table); 482 extern void mdb_index_dump(MdbTableDef *table, MdbIndex *idx); 483 extern void mdb_index_scan_free(MdbTableDef *table); 484 extern int mdb_index_find_next_on_page(MdbHandle *mdb, MdbIndexPage *ipg); 485 extern int mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row); 486 extern void mdb_index_hash_text(guchar *text, guchar *hash); 487 extern void mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table); 488 extern int mdb_index_find_row(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 pg, guint16 row); 489 extern void mdb_index_swap_n(unsigned char *src, int sz, unsigned char *dest); 490 extern void mdb_free_indices(GPtrArray *indices); 491 void mdb_index_page_reset(MdbIndexPage *ipg); 492 extern int mdb_index_pack_bitmap(MdbHandle *mdb, MdbIndexPage *ipg); 493 494 /* stats.c */ 495 extern void mdb_stats_on(MdbHandle *mdb); 496 extern void mdb_stats_off(MdbHandle *mdb); 497 extern void mdb_dump_stats(MdbHandle *mdb); 498 499 /* like.c */ 500 extern int mdb_like_cmp(char *s, char *r); 501 502 /* write.c */ 503 extern int mdb_crack_row(MdbTableDef *table, int row_start, int row_end, MdbField *fields); 504 extern guint16 mdb_add_row_to_pg(MdbTableDef *table, unsigned char *row_buffer, int new_row_size); 505 extern int mdb_update_index(MdbTableDef *table, MdbIndex *idx, unsigned int num_fields, MdbField *fields, guint32 pgnum, guint16 rownum); 506 extern int mdb_pack_row(MdbTableDef *table, unsigned char *row_buffer, unsigned int num_fields, MdbField *fields); 507 extern int mdb_replace_row(MdbTableDef *table, int row, unsigned char *new_row, int new_row_size); 508 extern int mdb_pg_get_freespace(MdbHandle *mdb); 509 extern int mdb_update_row(MdbTableDef *table); 510 extern unsigned char *mdb_new_data_pg(MdbCatalogEntry *entry); 511 512 /* map.c */ 513 extern guint32 mdb_map_find_next_freepage(MdbTableDef *table, int row_size); 514 extern guint32 mdb_map_find_next(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg); 515 516 /* props.c */ 517 extern GPtrArray *mdb_read_props_list(gchar *kkd, int len); 518 extern void mdb_free_props(MdbProperties *props); 519 extern MdbProperties *mdb_read_props(MdbHandle *mdb, GPtrArray *names, gchar *kkd, int len); 520 521 /* worktable.c */ 522 extern MdbTableDef *mdb_create_temp_table(MdbHandle *mdb, char *name); 523 extern void mdb_temp_table_add_col(MdbTableDef *table, MdbColumn *col); 524 extern void mdb_fill_temp_col(MdbColumn *tcol, char *col_name, int col_size, int col_type, int is_fixed); 525 extern void mdb_fill_temp_field(MdbField *field, void *value, int siz, int is_fixed, int is_null, int start, int column); 526 extern void mdb_temp_columns_end(MdbTableDef *table); 527 528 /* options.c */ 529 extern int mdb_get_option(unsigned long optnum); 530 extern void mdb_debug(int klass, char *fmt, ...); 531 532 /* iconv.c */ 533 extern int mdb_unicode2ascii(MdbHandle *mdb, unsigned char *src, unsigned int slen, unsigned char *dest, unsigned int dlen); 534 extern int mdb_ascii2unicode(MdbHandle *mdb, unsigned char *src, unsigned int slen, unsigned char *dest, unsigned int dlen); 535 extern void mdb_iconv_init(MdbHandle *mdb); 536 extern void mdb_iconv_close(MdbHandle *mdb); 537 538 #ifdef __cplusplus 539 } 540 #endif 541 542 #endif /* _mdbtools_h_ */ 543