/** * mdb_find_pg_row * @mdb: Database file handle * @pg_row: Lower byte contains the row number, the upper three contain page * @buf: Pointer for returning a pointer to the page * @off: Pointer for returning an offset to the row * @len: Pointer for returning the length of the row * * Returns: 0 on success. 1 on failure. */ int mdb_find_pg_row(MdbHandle *mdb, int pg_row, void **buf, int *off, size_t *len) { unsigned int pg = pg_row >> 8; unsigned int row = pg_row & 0xff; if (mdb_read_alt_pg(mdb, pg) != mdb->fmt->pg_size) return 1; mdb_swap_pgbuf(mdb); mdb_find_row(mdb, row, off, len); mdb_swap_pgbuf(mdb); *buf = mdb->alt_pg_buf; return 0; }
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; /* * start_pg will tell us where to (re)start the scan * for the next data page. each usage_map entry points to a * 0x05 page which bitmaps (mdb->fmt->pg_size - 4) * 8 pages. * * map_ind gives us the starting usage_map entry * offset gives us a page offset into the bitmap */ usage_bitlen = (mdb->fmt->pg_size - 4) * 8; max_map_pgs = (map_sz - 1) / 4; map_ind = (start_pg + 1) / usage_bitlen; offset = (start_pg + 1) % usage_bitlen; for (; map_ind<max_map_pgs; map_ind++) { unsigned char *usage_bitmap; guint32 i, map_pg; if (!(map_pg = mdb_get_int32(map, (map_ind*4)+1))) { continue; } if(mdb_read_alt_pg(mdb, map_pg) != mdb->fmt->pg_size) { mdb->fatal_error_handler("Oops! didn't get a full page at %d\n", map_pg); exit(1); } usage_bitmap = mdb->alt_pg_buf + 4; for (i=offset; i<usage_bitlen; i++) { if (usage_bitmap[i/8] & (1 << (i%8))) { return map_ind*usage_bitlen + i; } } offset = 0; } /* didn't find anything */ return 0; }
GPtrArray * mdb_read_indices(MdbTableDef *table) { MdbCatalogEntry *entry = table->entry; MdbHandle *mdb = entry->mdb; MdbFormatConstants *fmt = mdb->fmt; MdbIndex *pidx; unsigned int i, j; int idx_num, key_num, col_num; int cur_pos, name_sz, idx2_sz, type_offset; int index_start_pg = mdb->cur_pg; guchar *tmpbuf; table->indices = g_ptr_array_new(); if (IS_JET4(mdb)) { cur_pos = table->index_start + 52 * table->num_real_idxs; idx2_sz = 28; type_offset = 23; } else { cur_pos = table->index_start + 39 * table->num_real_idxs; idx2_sz = 20; type_offset = 19; } tmpbuf = (guchar *) g_malloc(idx2_sz); for (i=0;i<table->num_idxs;i++) { read_pg_if_n(mdb, tmpbuf, &cur_pos, idx2_sz); cur_pos += idx2_sz; pidx = (MdbIndex *) g_malloc0(sizeof(MdbIndex)); pidx->table = table; pidx->index_num = mdb_get_int16(tmpbuf, 4); pidx->index_type = tmpbuf[type_offset]; g_ptr_array_add(table->indices, pidx); } g_free(tmpbuf); for (i=0;i<table->num_idxs;i++) { pidx = g_ptr_array_index (table->indices, i); if (IS_JET4(mdb)) { name_sz=read_pg_if_16(mdb, &cur_pos); cur_pos += 2; tmpbuf = g_malloc(name_sz); read_pg_if_n(mdb, tmpbuf, &cur_pos, name_sz); cur_pos += name_sz; mdb_unicode2ascii(mdb, tmpbuf, 0, name_sz, pidx->name); g_free(tmpbuf); } else { read_pg_if(mdb, &cur_pos, 0); name_sz=mdb->pg_buf[cur_pos++]; read_pg_if_n(mdb, (unsigned char *) pidx->name, &cur_pos, name_sz); cur_pos += name_sz; pidx->name[name_sz]='\0'; } //fprintf(stderr, "index name %s\n", pidx->name); } mdb_read_alt_pg(mdb, entry->table_pg); mdb_read_pg(mdb, index_start_pg); cur_pos = table->index_start; idx_num=0; for (i=0;i<table->num_real_idxs;i++) { if (IS_JET4(mdb)) cur_pos += 4; do { pidx = g_ptr_array_index (table->indices, idx_num++); } while (pidx && pidx->index_type==2); /* 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 (!pidx) { table->num_real_idxs--; continue; } pidx->num_rows = mdb_get_int32(mdb->alt_pg_buf, fmt->tab_cols_start_offset + (i*fmt->tab_ridx_entry_size)); key_num=0; for (j=0;j<MDB_MAX_IDX_COLS;j++) { col_num=read_pg_if_16(mdb,&cur_pos); cur_pos += 2; read_pg_if(mdb, &cur_pos, 0); cur_pos++; if (col_num == 0xFFFF) continue; /* set column number to a 1 based column number and store */ pidx->key_col_num[key_num] = col_num + 1; pidx->key_col_order[key_num] = (mdb->pg_buf[cur_pos-1]) ? MDB_ASC : MDB_DESC; key_num++; } pidx->num_keys = key_num; cur_pos += 4; pidx->first_pg = read_pg_if_32(mdb, &cur_pos); cur_pos += 4; read_pg_if(mdb, &cur_pos, 0); pidx->flags = mdb->pg_buf[cur_pos++]; if (IS_JET4(mdb)) cur_pos += 9; } return NULL; }