mirror of
https://github.com/Cisco-Talos/clamav.git
synced 2025-10-19 18:33:16 +00:00
179 lines
5.7 KiB
C
179 lines
5.7 KiB
C
/* An implementation of the mspack_system interface using only memory */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <mspack.h>
|
|
|
|
/* use a pointer to a mem_buf structure as "filenames" */
|
|
struct mem_buf {
|
|
void *data;
|
|
size_t length;
|
|
};
|
|
|
|
struct mem_file {
|
|
char *data;
|
|
size_t length, posn;
|
|
};
|
|
|
|
static void *mem_alloc(struct mspack_system *self, size_t bytes) {
|
|
/* put your memory allocator here */
|
|
return malloc(bytes);
|
|
}
|
|
|
|
static void mem_free(void *buffer) {
|
|
/* put your memory deallocator here */
|
|
free(buffer);
|
|
}
|
|
|
|
static void mem_copy(void *src, void *dest, size_t bytes) {
|
|
/* put your own memory copy routine here */
|
|
memcpy(dest, src, bytes);
|
|
}
|
|
|
|
static void mem_msg(struct mem_file *file, const char *format, ...) {
|
|
/* put your own printf-type routine here, or leave it empty */
|
|
}
|
|
|
|
static struct mem_file *mem_open(struct mspack_system *self,
|
|
struct mem_buf *fn, int mode)
|
|
{
|
|
struct mem_file *fh;
|
|
if (!fn || !fn->data || !fn->length) return NULL;
|
|
if ((fh = (struct mem_file *) mem_alloc(self, sizeof(struct mem_file)))) {
|
|
fh->data = (char *) fn->data;
|
|
fh->length = fn->length;
|
|
fh->posn = (mode == MSPACK_SYS_OPEN_APPEND) ? fn->length : 0;
|
|
}
|
|
return fh;
|
|
}
|
|
|
|
static void mem_close(struct mem_file *fh) {
|
|
if (fh) mem_free(fh);
|
|
}
|
|
|
|
static int mem_read(struct mem_file *fh, void *buffer, int bytes) {
|
|
int todo;
|
|
if (!fh || !buffer || bytes < 0) return -1;
|
|
todo = fh->length - fh->posn;
|
|
if (todo > bytes) todo = bytes;
|
|
if (todo > 0) mem_copy(&fh->data[fh->posn], buffer, (size_t) todo);
|
|
fh->posn += todo; return todo;
|
|
}
|
|
|
|
static int mem_write(struct mem_file *fh, void *buffer, int bytes) {
|
|
int todo;
|
|
if (!fh || !buffer || bytes < 0) return -1;
|
|
todo = fh->length - fh->posn;
|
|
if (todo > bytes) todo = bytes;
|
|
if (todo > 0) mem_copy(buffer, &fh->data[fh->posn], (size_t) todo);
|
|
fh->posn += todo; return todo;
|
|
}
|
|
|
|
static int mem_seek(struct mem_file *fh, off_t offset, int mode) {
|
|
if (!fh) return 1;
|
|
switch (mode) {
|
|
case MSPACK_SYS_SEEK_START: break;
|
|
case MSPACK_SYS_SEEK_CUR: offset += (off_t) fh->posn; break;
|
|
case MSPACK_SYS_SEEK_END: offset += (off_t) fh->length; break;
|
|
default: return 1;
|
|
}
|
|
if ((offset < 0) || (offset > (off_t) fh->length)) return 1;
|
|
fh->posn = (size_t) offset;
|
|
return 0;
|
|
}
|
|
|
|
static off_t mem_tell(struct mem_file *fh) {
|
|
return (fh) ? (off_t) fh->posn : -1;
|
|
}
|
|
|
|
static struct mspack_system mem_system = {
|
|
(struct mspack_file * (*)(struct mspack_system *, const char *, int)) &mem_open,
|
|
(void (*)(struct mspack_file *)) &mem_close,
|
|
(int (*)(struct mspack_file *, void *, int)) &mem_read,
|
|
(int (*)(struct mspack_file *, void *, int)) &mem_write,
|
|
(int (*)(struct mspack_file *, off_t, int)) &mem_seek,
|
|
(off_t (*)(struct mspack_file *)) &mem_tell,
|
|
(void (*)(struct mspack_file *, const char *, ...)) &mem_msg,
|
|
&mem_alloc,
|
|
&mem_free,
|
|
&mem_copy,
|
|
NULL
|
|
};
|
|
|
|
/* example of usage with mscab_decompressor */
|
|
|
|
/* a simple cabinet */
|
|
static unsigned char embedded_cab[] = {
|
|
0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x02,0x00,
|
|
0x00,0x00,0x22,0x06,0x00,0x00,0x5E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4D,
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x22,0xBA,0x59,0x20,0x00,
|
|
0x68,0x65,0x6C,0x6C,0x6F,0x2E,0x63,0x00,0x4A,0x00,0x00,0x00,0x4D,0x00,0x00,
|
|
0x00,0x00,0x00,0x6C,0x22,0xE7,0x59,0x20,0x00,0x77,0x65,0x6C,0x63,0x6F,0x6D,
|
|
0x65,0x2E,0x63,0x00,0xBD,0x5A,0xA6,0x30,0x97,0x00,0x97,0x00,0x23,0x69,0x6E,
|
|
0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,0x68,0x3E,
|
|
0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,0x28,0x76,
|
|
0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,0x70,0x72,
|
|
0x69,0x6E,0x74,0x66,0x28,0x22,0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,
|
|
0x72,0x6C,0x64,0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x23,
|
|
0x69,0x6E,0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,
|
|
0x68,0x3E,0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,
|
|
0x28,0x76,0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,
|
|
0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x22,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,
|
|
0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x0D,0x0A
|
|
};
|
|
|
|
int main() {
|
|
struct mscab_decompressor *cabd;
|
|
struct mscabd_cabinet *cab;
|
|
struct mscabd_file *file;
|
|
struct mem_buf source = { &embedded_cab[0], sizeof(embedded_cab) };
|
|
struct mem_buf output;
|
|
int err;
|
|
|
|
/* if self-test reveals an error */
|
|
MSPACK_SYS_SELFTEST(err);
|
|
if (err) return 1;
|
|
|
|
/* create a cab decompressor using our custom mspack_system interface */
|
|
if ((cabd = mspack_create_cab_decompressor(&mem_system))) {
|
|
|
|
/* open a cab file direct from memory */
|
|
if ((cab = cabd->open(cabd, (char *) &source))) {
|
|
|
|
/* for all files */
|
|
for (file = cab->files; file; file = file->next) {
|
|
/* fill out our "filename" (memory pointer and length) */
|
|
output.data = (char *) malloc(file->length);
|
|
output.length = file->length;
|
|
|
|
/* let cabd extract this file to our memory buffer */
|
|
if (output.data && cabd->extract(cabd, file, (char *) &output)) {
|
|
exit(1);
|
|
}
|
|
|
|
/* dump the memory buffer to stdout (for display purposes) */
|
|
printf("Filename: %s\nContents:\n", file->filename);
|
|
fwrite(output.data, 1, output.length, stdout);
|
|
|
|
/* free our buffer */
|
|
free(output.data);
|
|
}
|
|
cabd->close(cabd, cab);
|
|
}
|
|
else {
|
|
fprintf(stderr, "can't open cabinet (%d)\n", cabd->last_error(cabd));
|
|
}
|
|
mspack_destroy_cab_decompressor(cabd);
|
|
}
|
|
else {
|
|
fprintf(stderr, "can't make decompressor\n");
|
|
}
|
|
return 0;
|
|
|
|
}
|