This commit is contained in:
Mark Harmstone 2025-02-03 05:05:46 +00:00 committed by GitHub
commit b391d3d5ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 60 additions and 37 deletions

View File

@ -257,6 +257,8 @@ typedef struct {
typedef struct {
FILE *stream;
void *data;
size_t data_len;
gboolean writable;
guint32 jet_version;
guint32 db_key;

View File

@ -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);
/*

View File

@ -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) {