Beispiel #1
0
int mdb_read_next_dpg(MdbTableDef *table)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	int next_pg;

#ifndef SLOW_READ
	next_pg = mdb_map_find_next(mdb, table->usage_map,
		table->map_sz, table->cur_phys_pg);

	if (next_pg >= 0) {
		if (mdb_read_pg(mdb, next_pg)) {
			table->cur_phys_pg = next_pg;
			return table->cur_phys_pg;
		} else {
			return 0;
		}
	}
	fprintf(stderr, "Warning: defaulting to brute force read\n");
#endif 
	/* can't do a fast read, go back to the old way */
	do {
		if (!mdb_read_pg(mdb, table->cur_phys_pg++))
			return 0;
	} while (mdb->pg_buf[0]!=0x01 || mdb_get_int32(mdb->pg_buf, 4)!=entry->table_pg);
	/* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */
	return table->cur_phys_pg;
}
Beispiel #2
0
/*
 * Read data into a buffer, advancing pages and setting the
 * page cursor as needed.  In the case that buf in NULL, pages
 * are still advanced and the page cursor is still updated.
 */
void * 
read_pg_if_n(MdbHandle *mdb, void *buf, int *cur_pos, size_t len)
{
	/* Advance to page which contains the first byte */
	while (*cur_pos >= mdb->fmt->pg_size) {
		mdb_read_pg(mdb, mdb_get_int32(mdb->pg_buf,4));
		*cur_pos -= (mdb->fmt->pg_size - 8);
	}
	/* Copy pages into buffer */
	while (*cur_pos + len >= mdb->fmt->pg_size) {
		int piece_len = mdb->fmt->pg_size - *cur_pos;
		if (buf) {
			memcpy(buf, mdb->pg_buf + *cur_pos, piece_len);
			buf += piece_len;
		}
		len -= piece_len;
		mdb_read_pg(mdb, mdb_get_int32(mdb->pg_buf,4));
		*cur_pos = 8;
	}
	/* Copy into buffer from final page */
	if (len && buf) {
		memcpy(buf, mdb->pg_buf + *cur_pos, len);
	}
	*cur_pos += len;
	return buf;
}
Beispiel #3
0
guint32 
mdb_map_find_next_freepage(MdbTableDef *table, int row_size)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	guint32 pgnum;
	guint32 cur_pg = 0;
	int free_space;

	do {
		pgnum = 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 = mdb_alloc_page(table);
			return pgnum;
		} else if (pgnum==-1) {
			mdb->fatal_error_handler("Error: mdb_map_find_next_freepage error while reading maps.\n");
			exit(1);
		}
		cur_pg = pgnum;

		mdb_read_pg(mdb, pgnum);
		free_space = mdb_pg_get_freespace(mdb);
		
	} while (free_space < row_size);

	//printf("page %d has %d bytes left\n", pgnum, free_space);

	return pgnum;
}
Beispiel #4
0
main(int argc, char **argv)
{
int rows;
int i;
unsigned char buf[2048];
MdbHandle *mdb;
MdbCatalogEntry entry;

#if 0
	if (argc<2) {
		fprintf(stderr,"Usage: %s <file> <table>\n",argv[0]);
		exit(1);
	}
	
	mdb_init();
	mdb = mdb_open(argv[1]);

	mdb_read_pg(mdb, MDB_CATALOG_PG);
	rows = mdb_catalog_rows(mdb);

	for (i=0;i<rows;i++) {
  		if (mdb_read_catalog_entry(mdb, i, &entry)) {
			if (!strcmp(entry.object_name,argv[2])) {
				mdb_kkd_dump(&entry);
  			}
		}
	}

	mdb_free_handle(mdb);
	mdb_exit();
#endif

	exit(0);
}
Beispiel #5
0
guint32
mdb_map_find_next_freepage(MdbTableDef *table, int row_size)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	guint32 pgnum;
	guint32 cur_pg = 0;
	int free_space;

	do {
		pgnum = mdb_map_find_next(mdb,
				table->free_usage_map,
				table->freemap_sz, cur_pg);

		if (!pgnum) {
			/* allocate new page */
			pgnum = mdb_alloc_page(table);
			return pgnum;
		}
		cur_pg = pgnum;

		mdb_read_pg(mdb, pgnum);
		free_space = mdb_pg_get_freespace(mdb);

	} while (free_space < row_size);



	return pgnum;
}
Beispiel #6
0
/* Read next data page into mdb->pg_buf */
int mdb_read_next_dpg(MdbTableDef *table)
{
	MdbCatalogEntry *entry = table->entry;
	MdbHandle *mdb = entry->mdb;
	int next_pg;

#ifndef SLOW_READ
	while (1) {
		next_pg = 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 (!mdb_read_pg(mdb, next_pg)) {
			fprintf(stderr, "error: reading page %d failed.\n", next_pg);
			return 0;
		}

		table->cur_phys_pg = next_pg;
		if (mdb->pg_buf[0]==MDB_PAGE_DATA && mdb_get_int32(mdb->pg_buf, 4)==entry->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=%d, buf[4..7]=%ld Expected table_pg=%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 
	/* can't do a fast read, go back to the old way */
	do {
		if (!mdb_read_pg(mdb, table->cur_phys_pg++))
			return 0;
	} while (mdb->pg_buf[0]!=MDB_PAGE_DATA || mdb_get_int32(mdb->pg_buf, 4)!=entry->table_pg);
	/* fprintf(stderr,"returning new page %ld\n", table->cur_phys_pg); */
	return table->cur_phys_pg;
}
Beispiel #7
0
/**
 * mdb_open:
 * @filename: path to MDB (database) file
 * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write
 *
 * Opens an MDB file and returns an MdbHandle to it.  MDB File may be relative
 * to the current directory, a full path to the file, or relative to a 
 * component of $MDBPATH.
 *
 * Return value: pointer to MdbHandle structure.
 **/
MdbHandle *mdb_open(char *filename, MdbFileFlags flags)
{
	MdbHandle *mdb;

	mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
	mdb_set_default_backend(mdb, "access");
	/* need something to bootstrap with, reassign after page 0 is read */
	mdb->fmt = &MdbJet3Constants;
	mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile));
	mdb->f->refs = 1;
	mdb->f->fd = -1;
	mdb->f->filename = (char *) mdb_find_file(filename);
	if (!mdb->f->filename) { 
		fprintf(stderr, "Can't alloc filename\n");
		mdb_close(mdb);
		return NULL; 
	}
	if (flags & MDB_WRITABLE) {
		mdb->f->writable = TRUE;
		mdb->f->fd = open(mdb->f->filename,O_RDWR);
	} else {
		mdb->f->fd = open(mdb->f->filename,O_RDONLY);
	}

	if (mdb->f->fd==-1) {
		fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); 
		mdb_close(mdb);
		return NULL;
	}
	if (!mdb_read_pg(mdb, 0)) {
		fprintf(stderr,"Couldn't read first page.\n");
		mdb_close(mdb);
		return NULL;
	}
	if (mdb->pg_buf[0] != 0) {
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->jet_version = mdb_pg_get_int32(mdb, 0x14);
	if (IS_JET4(mdb)) {
		mdb->fmt = &MdbJet4Constants;
	} else if (IS_JET3(mdb)) {
		mdb->fmt = &MdbJet3Constants;
	} else {
		fprintf(stderr,"Unknown Jet version.\n");
		mdb_close(mdb);
		return NULL; 
	}

	return mdb;
}
Beispiel #8
0
MdbTableDef *mdb_read_table(MdbCatalogEntry *entry)
{
	MdbTableDef *table;
	MdbHandle *mdb = entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	int row_start, pg_row;
	void *buf, *pg_buf = mdb->pg_buf;
	guint i;

	mdb_read_pg(mdb, entry->table_pg);
	if (mdb_get_byte(pg_buf, 0) != 0x02)  /* not a valid table def page */
		return NULL;
	table = mdb_alloc_tabledef(entry);

	mdb_get_int16(pg_buf, 8); /* len */

	table->num_rows = mdb_get_int32(pg_buf, fmt->tab_num_rows_offset);
	table->num_var_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset-2);
	table->num_cols = mdb_get_int16(pg_buf, fmt->tab_num_cols_offset);
	table->num_idxs = mdb_get_int32(pg_buf, fmt->tab_num_idxs_offset);
	table->num_real_idxs = mdb_get_int32(pg_buf, fmt->tab_num_ridxs_offset);

	/* grab a copy of the usage map */
	pg_row = mdb_get_int32(pg_buf, fmt->tab_usage_map_offset);
	mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->map_sz));
	table->usage_map = g_memdup(buf + row_start, table->map_sz);
	if (mdb_get_option(MDB_DEBUG_USAGE)) 
		mdb_buffer_dump(buf, row_start, table->map_sz);
	mdb_debug(MDB_DEBUG_USAGE,"usage map found on page %ld row %d start %d len %d",
		pg_row >> 8, pg_row & 0xff, row_start, table->map_sz);

	/* grab a copy of the free space page map */
	pg_row = mdb_get_int32(pg_buf, fmt->tab_free_map_offset);
	mdb_find_pg_row(mdb, pg_row, &buf, &row_start, &(table->freemap_sz));
	table->free_usage_map = g_memdup(buf + row_start, table->freemap_sz);
	mdb_debug(MDB_DEBUG_USAGE,"free map found on page %ld row %d start %d len %d\n",
		pg_row >> 8, pg_row & 0xff, row_start, table->freemap_sz);

	table->first_data_pg = mdb_get_int16(pg_buf, fmt->tab_first_dpg_offset);

	if (entry->props)
		for (i=0; i<entry->props->len; ++i) {
			MdbProperties *props = g_array_index(entry->props, MdbProperties*, i);
			if (!props->name)
				table->props = props;
		}

	return table;
}
Beispiel #9
0
void
mdb_index_scan_init(MdbHandle *mdb, MdbTableDef *table)
{
	int i;

	if (mdb_get_option(MDB_USE_INDEX) && mdb_choose_index(table, &i) == MDB_INDEX_SCAN) {
		table->strategy = MDB_INDEX_SCAN;
		table->scan_idx = g_ptr_array_index (table->indices, i);
		table->chain = g_malloc0(sizeof(MdbIndexChain));
		table->mdbidx = 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);
}
Beispiel #10
0
void mdb_kkd_dump(MdbCatalogEntry *entry)
{
int rows;
int kkd_start, kkd_end;
int i, tmp, pos, row_type, datapos=0;
MdbColumnProp prop;
MdbHandle *mdb = entry->mdb;
int rowid = entry->kkd_rowid;


	mdb_read_pg(mdb, entry->kkd_pg);
	rows = mdb_pg_get_int16(mdb,8);
	fprintf(stdout,"number of rows = %d\n",rows);
	kkd_start = mdb_pg_get_int16(mdb,10+rowid*2);
	fprintf(stdout,"kkd start = %d %04x\n",kkd_start,kkd_start);
	kkd_end = mdb->fmt->pg_size;
	for (i=0;i<rows;i++) {
		tmp = mdb_pg_get_int16(mdb, 10+i*2);
		if (tmp < mdb->fmt->pg_size &&
		    tmp > kkd_start &&
		    tmp < kkd_end) {
			kkd_end = tmp;
		}
	}
	fprintf(stdout,"kkd end = %d %04x\n",kkd_end,kkd_end);
	pos = kkd_start + 4; /* 4 = K K D \0 */
	while (pos < kkd_end) {
		tmp = mdb_pg_get_int16(mdb,pos);
		row_type = mdb_pg_get_int16(mdb,pos+4);
		fprintf(stdout,"row size = %3d type = 0x%02x\n",tmp,row_type);
		if (row_type==0x80)  {
			fprintf(stdout,"\nColumn Properties\n");
			fprintf(stdout,"-----------------\n");
			mdb_get_column_props(entry,pos);
			for (i=0;i<entry->num_props;i++) {
				prop = g_array_index(entry->props,MdbColumnProp,i);
				fprintf(stdout,"%3d %s\n",i,prop.name); 
			}
		}
		if (row_type==0x01) datapos = pos;
		pos += tmp;
	}
	
	if (datapos) {
		mdb_get_column_def(entry, datapos);
	}
}
Beispiel #11
0
static void mdb_index_walk(MdbTableDef *table, MdbIndex *idx)
{
MdbHandle *mdb = table->entry->mdb;
int cur_pos = 0;
unsigned char marker;
MdbColumn *col;
unsigned int i;

	if (idx->num_keys!=1) return;

	mdb_read_pg(mdb, idx->first_pg);
	cur_pos = 0xf8;
	
	for (i=0;i<idx->num_keys;i++) {
		marker = mdb->pg_buf[cur_pos++];
		col=g_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);
	}
}
Beispiel #12
0
/*
 * returns the bottom page of the IndexChain, if IndexChain is empty it 
 * initializes it by reading idx->first_pg (the root page)
 */
MdbIndexPage *
mdb_index_read_bottom_pg(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain)
{
	MdbIndexPage *ipg;

	/*
	 * if it's new use the root index page (idx->first_pg)
	 */
	if (!chain->cur_depth) {
		ipg = &(chain->pages[0]);
		mdb_index_page_init(ipg);
		chain->cur_depth = 1;
		ipg->pg = idx->first_pg;
		if (!(ipg = mdb_find_next_leaf(mdb, idx, chain)))
			return 0;
	} else {
		ipg = &(chain->pages[chain->cur_depth - 1]);
		ipg->len = 0; 
	}

	mdb_read_pg(mdb, ipg->pg);

	return ipg;
}
Beispiel #13
0
/**
 * mdb_open:
 * @filename: path to MDB (database) file
 * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write
 *
 * Opens an MDB file and returns an MdbHandle to it.  MDB File may be relative
 * to the current directory, a full path to the file, or relative to a 
 * component of $MDBPATH.
 *
 * Return value: pointer to MdbHandle structure.
 **/
MdbHandle *mdb_open(const char *filename, MdbFileFlags flags)
{
	MdbHandle *mdb;
	int key[] = {0x86, 0xfb, 0xec, 0x37, 0x5d, 0x44, 0x9c, 0xfa, 0xc6, 0x5e, 0x28, 0xe6, 0x13, 0xb6};
	int j, pos;
	int open_flags;

	mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
	mdb_set_default_backend(mdb, "access");
#ifdef HAVE_ICONV
	mdb->iconv_in = (iconv_t)-1;
	mdb->iconv_out = (iconv_t)-1;
#endif
	/* need something to bootstrap with, reassign after page 0 is read */
	mdb->fmt = &MdbJet3Constants;
	mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile));
	mdb->f->refs = 1;
	mdb->f->fd = -1;
	mdb->f->filename = mdb_find_file(filename);
	if (!mdb->f->filename) { 
		fprintf(stderr, "File not found\n");
		mdb_close(mdb);
		return NULL; 
	}
	if (flags & MDB_WRITABLE) {
		mdb->f->writable = TRUE;
		open_flags = O_RDWR;
	} else {
		open_flags = O_RDONLY;
	}

#ifdef _WIN32
	open_flags |= O_BINARY;
#endif

	mdb->f->fd = open(mdb->f->filename, open_flags);

	if (mdb->f->fd==-1) {
		fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); 
		mdb_close(mdb);
		return NULL;
	}
	if (!mdb_read_pg(mdb, 0)) {
		fprintf(stderr,"Couldn't read first page.\n");
		mdb_close(mdb);
		return NULL;
	}
	if (mdb->pg_buf[0] != 0) {
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->jet_version = mdb_get_int32(mdb->pg_buf, 0x14);
	switch(mdb->f->jet_version) {
	case MDB_VER_JET3:
		mdb->fmt = &MdbJet3Constants;
		break;
	case MDB_VER_JET4:
	case MDB_VER_ACCDB_2007:
	case MDB_VER_ACCDB_2010:
		mdb->fmt = &MdbJet4Constants;
		break;
	default:
		fprintf(stderr,"Unknown Jet version.\n");
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->db_key = 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 ^= 0xe15e01b9;
	 */
	mdb->f->db_key ^= 0x4ebc8afb;
	/* fprintf(stderr, "Encrypted file, RC4 key seed= %d\n", mdb->f->db_key); */
	if (mdb->f->db_key) {
		/* write is not supported for encrypted files yet */
		mdb->f->writable = 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 = O_RDONLY;
#ifdef _WIN32
		open_flags |= O_BINARY;
#endif
		mdb->f->fd = open(mdb->f->filename, open_flags);
		if (mdb->f->fd==-1) {
			fprintf(stderr, "Couldn't ropen file %s in read only\n", mdb->f->filename);
			mdb_close(mdb);
			return NULL;
		}
	}

	/* get the db password located at 0x42 bytes into the file */
	for (pos=0;pos<14;pos++) {
		j = mdb_get_int32(mdb->pg_buf, 0x42+pos);
		j ^= key[pos];
		if ( j != 0)
			mdb->f->db_passwd[pos] = j;
		else
			mdb->f->db_passwd[pos] = '\0';
	}

	mdb_iconv_init(mdb);

	return mdb;
}
Beispiel #14
0
/*
 * the main index function.
 * caller provides an index chain which is the current traversal of index
 * pages from the root page to the leaf.  Initially passed as blank, 
 * mdb_index_find_next will store it's state information here. Each invocation
 * then picks up where the last one left off, allowing us to scroll through
 * the index one by one.
 *
 * Sargs are applied here but also need to be applied on the whole row b/c
 * text columns may return false positives due to hashing and non-index
 * columns with sarg values can't be tested here.
 */
int
mdb_index_find_next(MdbHandle *mdb, MdbIndex *idx, MdbIndexChain *chain, guint32 *pg, guint16 *row)
{
	MdbIndexPage *ipg;
	int passed = 0;
	int idx_sz;
	int idx_start = 0;
	MdbColumn *col;

	ipg = mdb_index_read_bottom_pg(mdb, idx, chain);

	/*
	 * loop while the sargs don't match
	 */
	do {
		ipg->len = 0;
		/*
		 * if no more rows on this leaf, try to find a new leaf
		 */
		if (!mdb_index_find_next_on_page(mdb, ipg)) {
			if (!chain->clean_up_mode) {
				if (!(ipg = mdb_index_unwind(mdb, idx, chain)))
					chain->clean_up_mode = 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 = mdb_pg_get_int24(mdb, 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 = 1;
				ipg = &chain->pages[0];
				mdb_index_page_init(ipg);
				ipg->pg = chain->last_leaf_found;
				//printf("next on page %d\n",
				if (!mdb_index_find_next_on_page(mdb, ipg))
					return 0;
			}
		}
		*row = mdb->pg_buf[ipg->offset + ipg->len - 1];
#if 0
		printf("page: ");
		buffer_dump(mdb->pg_buf, ipg->offset+ipg->len-4, ipg->offset+ipg->len-2);
#endif
		*pg = mdb_pg_get_int24_msb(mdb, ipg->offset + ipg->len - 4);
#if 0
		printf("row = %d pg = %lu ipg->pg = %lu offset = %lu len = %d\n", *row, *pg, ipg->pg, ipg->offset, ipg->len);
#endif
		col=g_ptr_array_index(idx->table->columns,idx->key_col_num[0]-1);
		idx_sz = mdb_col_fixed_size(col);
		/* handle compressed indexes, single key indexes only? */
		if (idx->num_keys==1 && idx_sz>0 && ipg->len - 4 < idx_sz) {
#if 0
			printf("short index found\n");
			buffer_dump(ipg->cache_value, 0, idx_sz);
#endif
			memcpy(&ipg->cache_value[idx_sz - (ipg->len - 4)], &mdb->pg_buf[ipg->offset], ipg->len);
#if 0
			buffer_dump(ipg->cache_value, 0, idx_sz);
#endif
		} else {
			idx_start = ipg->offset + (ipg->len - 4 - idx_sz);
			memcpy(ipg->cache_value, &mdb->pg_buf[idx_start], idx_sz);
		}

		//idx_start = ipg->offset + (ipg->len - 4 - idx_sz);
		passed = mdb_index_test_sargs(mdb, idx, ipg->cache_value, idx_sz);

//		printf("passed=%d\n", passed);

		buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1);
		ipg->offset += ipg->len;

	} while (!passed);

#if 0
	fprintf(stdout,"len = %d pos %d\n", ipg->len, ipg->len);
	buffer_dump(mdb->pg_buf, ipg->offset, ipg->offset+ipg->len-1);
#endif

	return ipg->len;
}
Beispiel #15
0
/**
 * mdb_open:
 * @filename: path to MDB (database) file
 * @flags: MDB_NOFLAGS for read-only, MDB_WRITABLE for read/write
 *
 * Opens an MDB file and returns an MdbHandle to it.  MDB File may be relative
 * to the current directory, a full path to the file, or relative to a 
 * component of $MDBPATH.
 *
 * Return value: pointer to MdbHandle structure.
 **/
MdbHandle *mdb_open(const char *filename, MdbFileFlags flags)
{
	MdbHandle *mdb;
	int open_flags;

	mdb = (MdbHandle *) g_malloc0(sizeof(MdbHandle));
	mdb_set_default_backend(mdb, "access");
#ifdef HAVE_ICONV
	mdb->iconv_in = (iconv_t)-1;
	mdb->iconv_out = (iconv_t)-1;
#endif
	/* need something to bootstrap with, reassign after page 0 is read */
	mdb->fmt = &MdbJet3Constants;
	mdb->f = (MdbFile *) g_malloc0(sizeof(MdbFile));
	mdb->f->refs = 1;
	mdb->f->fd = -1;
	mdb->f->filename = mdb_find_file(filename);
	if (!mdb->f->filename) { 
		fprintf(stderr, "Can't alloc filename\n");
		mdb_close(mdb);
		return NULL; 
	}
	if (flags & MDB_WRITABLE) {
		mdb->f->writable = TRUE;
		open_flags = O_RDWR;
	} else {
		open_flags = O_RDONLY;
	}

#ifdef _WIN32
	open_flags |= O_BINARY;
#endif

	mdb->f->fd = open(mdb->f->filename, open_flags);

	if (mdb->f->fd==-1) {
		fprintf(stderr,"Couldn't open file %s\n",mdb->f->filename); 
		mdb_close(mdb);
		return NULL;
	}
	if (!mdb_read_pg(mdb, 0)) {
		fprintf(stderr,"Couldn't read first page.\n");
		mdb_close(mdb);
		return NULL;
	}
	if (mdb->pg_buf[0] != 0) {
		mdb_close(mdb);
		return NULL; 
	}
	mdb->f->jet_version = mdb_get_int32(mdb->pg_buf, 0x14);
	if (IS_JET4(mdb)) {
		mdb->fmt = &MdbJet4Constants;
	} else if (IS_JET3(mdb)) {
		mdb->fmt = &MdbJet3Constants;
	} else {
		fprintf(stderr,"Unknown Jet version.\n");
		mdb_close(mdb);
		return NULL; 
	}
	mdb_iconv_init(mdb);

	return mdb;
}
Beispiel #16
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;
}
Beispiel #17
0
int 
mdb_fetch_row(MdbTableDef *table)
{
	MdbHandle *mdb = table->entry->mdb;
	MdbFormatConstants *fmt = mdb->fmt;
	unsigned int rows;
	int rc;
	guint32 pg;

	if (table->num_rows==0)
		return 0;

	/* initialize */
	if (!table->cur_pg_num) {
		table->cur_pg_num=1;
		table->cur_row=0;
		if ((!table->is_temp_table)&&(table->strategy!=MDB_INDEX_SCAN))
			if (!mdb_read_next_dpg(table)) return 0;
	}

	do {
		if (table->is_temp_table) {
			GPtrArray *pages = table->temp_table_pages;
			rows = mdb_get_int16(
				g_ptr_array_index(pages, table->cur_pg_num-1),
				fmt->row_count_offset);
			if (table->cur_row >= rows) {
				table->cur_row = 0;
				table->cur_pg_num++;
				if (table->cur_pg_num > pages->len)
					return 0;
			}
			memcpy(mdb->pg_buf,
				g_ptr_array_index(pages, table->cur_pg_num-1),
				fmt->pg_size);
		} else if (table->strategy==MDB_INDEX_SCAN) {
		
			if (!mdb_index_find_next(table->mdbidx, table->scan_idx, table->chain, &pg, (guint16 *) &(table->cur_row))) {
				mdb_index_scan_free(table);
				return 0;
			}
			mdb_read_pg(mdb, pg);
		} else {
			rows = mdb_get_int16(mdb->pg_buf,fmt->row_count_offset);

			/* if at end of page, find a new page */
			if (table->cur_row >= rows) {
				table->cur_row=0;
	
				if (!mdb_read_next_dpg(table)) {
					return 0;
				}
			}
		}

		/* printf("page %d row %d\n",table->cur_phys_pg, table->cur_row); */
		rc = mdb_read_row(table, table->cur_row);
		table->cur_row++;
	} while (!rc);

	return 1;
}