mirror of
https://github.com/mdbtools/mdbtools.git
synced 2025-04-05 14:50:20 +08:00
Allow mdb_open_buffer to work when fmemopen not available
This commit is contained in:
parent
1f88aac676
commit
5096de91a1
@ -256,6 +256,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
FILE *stream;
|
||||
void *data;
|
||||
size_t data_len;
|
||||
gboolean writable;
|
||||
guint32 jet_version;
|
||||
guint32 db_key;
|
||||
|
@ -123,7 +123,7 @@ static char *mdb_find_file(const char *file_name)
|
||||
*
|
||||
* Return value: The handle on success, NULL on failure
|
||||
*/
|
||||
static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
static MdbHandle *mdb_handle_from_stream(FILE *stream, void *data, size_t data_len, MdbFileFlags flags) {
|
||||
MdbHandle *mdb = g_malloc0(sizeof(MdbHandle));
|
||||
mdb_set_default_backend(mdb, "access");
|
||||
mdb_set_date_fmt(mdb, "%x %X");
|
||||
@ -140,6 +140,8 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
mdb->f = g_malloc0(sizeof(MdbFile));
|
||||
mdb->f->refs = 1;
|
||||
mdb->f->stream = stream;
|
||||
mdb->f->data = data;
|
||||
mdb->f->data_len = data_len;
|
||||
if (flags & MDB_WRITABLE) {
|
||||
mdb->f->writable = TRUE;
|
||||
}
|
||||
@ -206,17 +208,7 @@ static MdbHandle *mdb_handle_from_stream(FILE *stream, MdbFileFlags flags) {
|
||||
* Return value: point to MdbHandle structure.
|
||||
*/
|
||||
MdbHandle *mdb_open_buffer(void *buffer, size_t len, MdbFileFlags flags) {
|
||||
FILE *file = NULL;
|
||||
#ifdef HAVE_FMEMOPEN
|
||||
file = fmemopen(buffer, len, (flags & MDB_WRITABLE) ? "r+" : "r");
|
||||
#else
|
||||
fprintf(stderr, "mdb_open_buffer requires a platform with support for fmemopen(3)\n");
|
||||
#endif
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Couldn't open memory buffer\n");
|
||||
return NULL;
|
||||
}
|
||||
return mdb_handle_from_stream(file, flags);
|
||||
return mdb_handle_from_stream(NULL, buffer, len, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -253,7 +245,7 @@ MdbHandle *mdb_open(const char *filename, MdbFileFlags flags)
|
||||
|
||||
g_free(filepath);
|
||||
|
||||
return mdb_handle_from_stream(file, flags);
|
||||
return mdb_handle_from_stream(file, NULL, 0, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -354,25 +346,42 @@ static ssize_t _mdb_read_pg(MdbHandle *mdb, void *pg_buf, unsigned long pg)
|
||||
ssize_t len;
|
||||
off_t offset = pg * mdb->fmt->pg_size;
|
||||
|
||||
if (fseeko(mdb->f->stream, 0, SEEK_END) == -1) {
|
||||
fprintf(stderr, "Unable to seek to end of file\n");
|
||||
return 0;
|
||||
}
|
||||
if (ftello(mdb->f->stream) < offset) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
}
|
||||
if (mdb->f->data) {
|
||||
if ((off_t)mdb->f->data_len < offset) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (fseeko(mdb->f->stream, 0, SEEK_END) == -1) {
|
||||
fprintf(stderr, "Unable to seek to end of file\n");
|
||||
return 0;
|
||||
}
|
||||
if (ftello(mdb->f->stream) < offset) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdb->stats && mdb->stats->collect)
|
||||
mdb->stats->pg_reads++;
|
||||
|
||||
if (fseeko(mdb->f->stream, offset, SEEK_SET) == -1) {
|
||||
fprintf(stderr, "Unable to seek to page %lu\n", pg);
|
||||
return 0;
|
||||
}
|
||||
len = fread(pg_buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
if (ferror(mdb->f->stream)) {
|
||||
perror("read");
|
||||
return 0;
|
||||
if (mdb->f->data) {
|
||||
if (offset + mdb->fmt->pg_size > (off_t)mdb->f->data_len)
|
||||
len = mdb->f->data_len - offset;
|
||||
else
|
||||
len = mdb->fmt->pg_size;
|
||||
|
||||
memcpy(pg_buf, (char*)mdb->f->data + offset, len);
|
||||
} else {
|
||||
if (fseeko(mdb->f->stream, offset, SEEK_SET) == -1) {
|
||||
fprintf(stderr, "Unable to seek to page %lu\n", pg);
|
||||
return 0;
|
||||
}
|
||||
len = fread(pg_buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
if (ferror(mdb->f->stream)) {
|
||||
perror("read");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memset(pg_buf + len, 0, mdb->fmt->pg_size - len);
|
||||
/*
|
||||
|
@ -79,13 +79,20 @@ mdb_write_pg(MdbHandle *mdb, unsigned long pg)
|
||||
off_t offset = pg * mdb->fmt->pg_size;
|
||||
unsigned char *buf = mdb->pg_buf;
|
||||
|
||||
fseeko(mdb->f->stream, 0, SEEK_END);
|
||||
/* is page beyond current size + 1 ? */
|
||||
if (ftello(mdb->f->stream) < offset + mdb->fmt->pg_size) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
if (mdb->f->data) {
|
||||
if ((off_t)mdb->f->data_len < offset + mdb->fmt->pg_size) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fseeko(mdb->f->stream, 0, SEEK_END);
|
||||
/* is page beyond current size + 1 ? */
|
||||
if (ftello(mdb->f->stream) < offset + mdb->fmt->pg_size) {
|
||||
fprintf(stderr,"offset %" PRIu64 " is beyond EOF\n",(uint64_t)offset);
|
||||
return 0;
|
||||
}
|
||||
fseeko(mdb->f->stream, offset, SEEK_SET);
|
||||
}
|
||||
fseeko(mdb->f->stream, offset, SEEK_SET);
|
||||
|
||||
if (pg != 0 && mdb->f->db_key != 0)
|
||||
{
|
||||
@ -94,13 +101,18 @@ mdb_write_pg(MdbHandle *mdb, unsigned long pg)
|
||||
mdbi_rc4((unsigned char*)&tmp_key, 4, buf, mdb->fmt->pg_size);
|
||||
}
|
||||
|
||||
len = fwrite(buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
if (mdb->f->data) {
|
||||
memcpy((char*)mdb->f->data + offset, mdb->pg_buf, mdb->fmt->pg_size);
|
||||
len = mdb->fmt->pg_size;
|
||||
} else {
|
||||
len = fwrite(buf, 1, mdb->fmt->pg_size, mdb->f->stream);
|
||||
}
|
||||
|
||||
if (buf != mdb->pg_buf) {
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
if (ferror(mdb->f->stream)) {
|
||||
if (!mdb->f->data && ferror(mdb->f->stream)) {
|
||||
perror("write");
|
||||
return 0;
|
||||
} else if (len<mdb->fmt->pg_size) {
|
||||
|
Loading…
Reference in New Issue
Block a user