コード例 #1
0
ファイル: data.c プロジェクト: KDE/calligra-history
size_t 
mdb_ole_read_next(MdbHandle *mdb, MdbColumn *col, void *ole_ptr)
{
	guint32 ole_len;
	void *buf;
	int row_start;
	size_t len;

	ole_len = mdb_get_int32(ole_ptr, 0);

	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)) {
			return 0;
		}
		if (col->bind_ptr)
			memcpy(col->bind_ptr, (char*)buf + row_start + 4, len - 4);
		col->cur_blob_pg_row = mdb_get_int32(buf, row_start);

		return len;
	}
	return 0;
}
コード例 #2
0
ファイル: table.c プロジェクト: kubrickfr/mdbtools
/*
 * 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;
}
コード例 #3
0
ファイル: data.c プロジェクト: rfc2616/mdbtools
/*
 * 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)
{
	guint32 ole_len;
	void *buf;
	int row_start;
	size_t len;

    if (ole_ptr) {
	    ole_len = mdb_get_int32(ole_ptr, 0);
	    mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %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;
	}
	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, buf + row_start + 4, len - 4);
	col->cur_blob_pg_row = mdb_get_int32(buf, row_start);

	return len - 4;
}
コード例 #4
0
ファイル: table.c プロジェクト: kubrickfr/mdbtools
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;
}
コード例 #5
0
ファイル: sargs.c プロジェクト: brianb/mdbtools
int 
mdb_test_sarg(MdbHandle *mdb, MdbColumn *col, MdbSargNode *node, MdbField *field)
{
	char tmpbuf[256];

	if (node->op == MDB_ISNULL)
		return field->is_null?1:0;
	else if (node->op == MDB_NOTNULL)
		return field->is_null?0:1;
	switch (col->col_type) {
		case MDB_BOOL:
			return mdb_test_int(node, !field->is_null);
			break;
		case MDB_BYTE:
			return mdb_test_int(node, (gint32)((char *)field->value)[0]);
			break;
		case MDB_INT:
			return mdb_test_int(node, (gint32)mdb_get_int16(field->value, 0));
			break;
		case MDB_LONGINT:
			return mdb_test_int(node, (gint32)mdb_get_int32(field->value, 0));
			break;
		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 mdb_test_sarg() for type %d\n",col->col_type);
			break;
	}
	return 1;
}
コード例 #6
0
ファイル: data.c プロジェクト: KDE/calligra-history
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;
}
コード例 #7
0
ファイル: table.c プロジェクト: KDE/calligra-history
void mdb_table_dump(MdbCatalogEntry *entry)
{
MdbTableDef *table;
MdbColumn *col;
int coln;
MdbIndex *idx;
MdbHandle *mdb = entry->mdb;
unsigned int i, bitn;
guint32 pgnum;

	table = mdb_read_table(entry);
	fprintf(stdout,"definition page     = %lu\n",entry->table_pg);
	fprintf(stdout,"number of datarows  = %d\n",table->num_rows);
	fprintf(stdout,"number of columns   = %d\n",table->num_cols);
	fprintf(stdout,"number of indices   = %d\n",table->num_real_idxs);

	mdb_read_columns(table);
	mdb_read_indices(table);

	for (i=0;i<table->num_cols;i++) {
		col = g_ptr_array_index(table->columns,i);
	
		fprintf(stdout,"column %d Name: %-20s Type: %s(%d)\n",
			i, col->name,
			mdb_get_coltype_string(mdb->default_backend, col->col_type),
			col->col_size);
	}

	for (i=0;i<table->num_idxs;i++) {
		idx = g_ptr_array_index (table->indices, i);
		mdb_index_dump(table, idx);
	}
	if (table->usage_map) {
		printf("pages reserved by this object\n");
		printf("usage map pg %" G_GUINT32_FORMAT "\n",
			table->map_base_pg);
		printf("free map pg %" G_GUINT32_FORMAT "\n",
			table->freemap_base_pg);
		pgnum = mdb_get_int32(table->usage_map,1);
		/* the first 5 bytes of the usage map mean something */
		coln = 0;
		for (i=5;i<table->map_sz;i++) {
			for (bitn=0;bitn<8;bitn++) {
				if (table->usage_map[i] & 1 << bitn) {
					coln++;
					printf("%6" G_GUINT32_FORMAT, pgnum);
					if (coln==10) {
						printf("\n");
						coln = 0;
					} else {
						printf(" ");
					}
				}
				pgnum++;
			}
		}
		printf("\n");
	}
}
コード例 #8
0
ファイル: table.c プロジェクト: kubrickfr/mdbtools
guint32 
read_pg_if_32(MdbHandle *mdb, int *cur_pos)
{
	char c[4];

	read_pg_if_n(mdb, c, cur_pos, 4);
	return mdb_get_int32(c, 0);
}
コード例 #9
0
ファイル: data.c プロジェクト: KDE/calligra-history
size_t 
mdb_ole_read(MdbHandle *mdb, MdbColumn *col, void *ole_ptr, int chunk_size)
{
	guint32 ole_len;
	void *buf;
	int row_start;
	size_t len;

	ole_len = mdb_get_int32(ole_ptr, 0);
	mdb_debug(MDB_DEBUG_OLE,"ole len = %d ole flags = %02x",
		ole_len & 0x00ffffff, ole_len >> 24);

	col->chunk_size = chunk_size;

	if (ole_len & 0x80000000) {
		/* inline ole field, if we can satisfy it, then do it */
		len = col->cur_value_len - MDB_MEMO_OVERHEAD;
		if ((size_t)chunk_size >= len) {
			if (col->bind_ptr) 
				memcpy(col->bind_ptr, 
					&mdb->pg_buf[col->cur_value_start + 
						MDB_MEMO_OVERHEAD],
					len);
			return len;
		} else {
			return 0;
		}
	} else if (ole_len & 0x40000000) {
		col->cur_blob_pg_row = mdb_get_int32(ole_ptr, 4);
		mdb_debug(MDB_DEBUG_OLE,"ole row = %d ole pg = %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, len);
			if (mdb_get_option(MDB_DEBUG_OLE))
				buffer_dump(col->bind_ptr, 0, 16);
		}
		return len;
	} else if ((ole_len & 0xff000000) == 0) {
コード例 #10
0
ファイル: data.c プロジェクト: rfc2616/mdbtools
/* 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;
}
コード例 #11
0
ファイル: props.c プロジェクト: amiit/mdbtools
/*
 * That function takes a raw KKD/MR2 binary buffer,
 * typically read from LvProp in table MSysbjects
 * and returns a GPtrArray 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 = 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 = g_array_new(0, 0, sizeof(MdbProperties*));

	pos = 4;
	while (pos < len) {
		record_len = mdb_get_int32(buffer, pos);
		record_type = 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 = 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 = 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 += record_len;
	}
	if (names) free_names(names);
	return result;
}
コード例 #12
0
ファイル: map.c プロジェクト: rfc2616/mdbtools
static gint32
mdb_map_find_next0(MdbHandle *mdb, unsigned char *map, unsigned int map_sz, guint32 start_pg)
{
	guint32 pgnum, i, usage_bitlen;
	unsigned char *usage_bitmap;

	pgnum = mdb_get_int32(map, 1);
	usage_bitmap = map + 5;
	usage_bitlen = (map_sz - 5) * 8;

	i = (start_pg >= pgnum) ? start_pg-pgnum+1 : 0;
	for (; i<usage_bitlen; i++) {
		if (usage_bitmap[i/8] & (1 << (i%8))) {
			return pgnum + i;
		}
	}
	/* didn't find anything */
	return 0;
}
コード例 #13
0
ファイル: map.c プロジェクト: rfc2616/mdbtools
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;
}
コード例 #14
0
ファイル: file.c プロジェクト: ASAPPinc/mdbtools
long mdb_pg_get_int32(MdbHandle *mdb, int offset)
{
	if (offset <0 || offset+4 > mdb->fmt->pg_size) return -1;
	mdb->cur_pos+=4;
	return mdb_get_int32(mdb->pg_buf, offset);
}
コード例 #15
0
ファイル: file.c プロジェクト: ASAPPinc/mdbtools
/**
 * 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;
}
コード例 #16
0
ファイル: index.c プロジェクト: justinzane/navit
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;
}
コード例 #17
0
ファイル: file.c プロジェクト: Byclosure/mdbtools
/**
 * 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;
}