minizip-ng/ioapi_mem.c

219 lines
5.5 KiB
C
Raw Normal View History

2017-06-05 13:36:52 +08:00
/* ioapi_mem.c -- IO base function header for compress/uncompress .zip
2012-01-21 15:10:18 -07:00
files using zlib + zip or unzip API
This version of ioapi is designed to access memory rather than files.
We do use a region of memory to put data in to and take it out of. We do
not have auto-extending buffers and do not inform anyone else that the
data has been written. It is really intended for accessing a zip archive
embedded in an application such that I can write an installer with no
external files. Creation of archives has not been attempted, although
parts of the framework are present.
Based on Unzip ioapi.c version 0.22, May 19th, 2003
Copyright (C) 2012-2017 Nathan Moinvaziri
https://github.com/nmoinvaz/minizip
Copyright (C) 2003 Justin Fletcher
Copyright (C) 1998-2003 Gilles Vollant
http://www.winimage.com/zLibDll/minizip.html
2012-01-21 15:10:18 -07:00
This file is under the same license as the Unzip tool it is distributed
with.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#include "ioapi.h"
#include "ioapi_mem.h"
2017-09-29 21:02:09 -07:00
typedef struct mzstream_mem_s {
mzstream stream;
char *buffer; // Memory buffer pointer
uint32_t size; // Size of the memory buffer
uint32_t limit; // Furthest we've written
uint32_t position; // Current positoin in the memory
int16_t growable; // Growable memory buffer
2017-09-29 21:02:09 -07:00
} mzstream_mem;
int32_t ZCALLBACK mzstream_mem_open(voidpf stream, const char *filename, int mode)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
2017-09-29 21:02:09 -07:00
if (mode & MZSTREAM_MODE_CREATE)
2014-01-07 19:57:18 -07:00
{
2017-09-29 21:02:09 -07:00
if (mem->growable)
2014-01-07 19:57:18 -07:00
{
2017-09-29 21:02:09 -07:00
mem->size = UINT16_MAX;
mem->buffer = (char *)malloc(mem->size);
2014-01-07 19:57:18 -07:00
}
2017-09-29 21:02:09 -07:00
// When writing we start with 0 bytes written
mem->limit = 0;
2014-01-07 19:57:18 -07:00
}
2012-01-21 15:10:18 -07:00
else
2017-09-29 21:02:09 -07:00
{
2014-01-07 19:57:18 -07:00
mem->limit = mem->size;
2017-09-29 21:02:09 -07:00
}
2012-01-21 15:10:18 -07:00
2017-09-29 21:02:09 -07:00
mem->position = 0;
2012-01-21 15:10:18 -07:00
2017-09-29 21:02:09 -07:00
return MZSTREAM_OK;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_is_open(voidpf stream)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
if (mem->buffer == NULL)
return MZSTREAM_ERR;
return MZSTREAM_OK;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_read(voidpf stream, void *buf, uint32_t size)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
2012-01-21 15:10:18 -07:00
2017-09-29 21:02:09 -07:00
if (size > mem->size - mem->position)
size = mem->size - mem->position;
2012-01-21 15:10:18 -07:00
2017-09-29 21:02:09 -07:00
memcpy(buf, mem->buffer + mem->position, size);
mem->position += size;
2012-01-21 15:10:18 -07:00
return size;
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_write(voidpf stream, const void *buf, uint32_t size)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
uint32_t new_size = 0;
char *new_buf = NULL;
2012-01-21 15:10:18 -07:00
2017-09-29 21:02:09 -07:00
if (size > mem->size - mem->position)
2014-01-07 19:57:18 -07:00
{
2017-09-29 21:02:09 -07:00
if (mem->growable)
2014-01-07 19:57:18 -07:00
{
2017-09-29 21:02:09 -07:00
new_size = mem->size;
if (size < UINT16_MAX)
new_size += UINT16_MAX;
2014-01-07 19:57:18 -07:00
else
2017-09-29 21:02:09 -07:00
new_size += size;
new_buf = (char *)malloc(new_size);
memcpy(new_buf, mem->buffer, mem->size);
free(mem->buffer);
mem->buffer = new_buf;
mem->size = new_size;
2014-01-07 19:57:18 -07:00
}
else
2017-09-29 21:02:09 -07:00
{
size = mem->size - mem->position;
}
2014-01-07 19:57:18 -07:00
}
2017-09-29 21:02:09 -07:00
memcpy(mem->buffer + mem->position, buf, size);
mem->position += size;
if (mem->position > mem->limit)
mem->limit = mem->position;
2012-01-21 15:10:18 -07:00
return size;
}
2017-09-29 21:02:09 -07:00
int64_t ZCALLBACK mzstream_mem_tell(voidpf stream)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
return mem->position;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_seek(voidpf stream, uint64_t offset, int origin)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
uint64_t new_pos = 0;
2012-01-21 15:10:18 -07:00
switch (origin)
{
2017-09-29 21:02:09 -07:00
case MZSTREAM_SEEK_CUR:
new_pos = mem->position + offset;
2014-01-07 19:57:18 -07:00
break;
2017-09-29 21:02:09 -07:00
case MZSTREAM_SEEK_END:
2014-01-07 19:57:18 -07:00
new_pos = mem->limit + offset;
break;
2017-09-29 21:02:09 -07:00
case MZSTREAM_SEEK_SET:
2014-01-07 19:57:18 -07:00
new_pos = offset;
break;
default:
2017-09-29 21:02:09 -07:00
return MZSTREAM_ERR;
2012-01-21 15:10:18 -07:00
}
if (new_pos > mem->size)
2017-09-29 21:02:09 -07:00
return MZSTREAM_ERR;
mem->position = (uint32_t)new_pos;
return MZSTREAM_OK;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_close(voidpf stream)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
// We never return errors
return MZSTREAM_OK;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
int32_t ZCALLBACK mzstream_mem_error(voidpf stream)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
// We never return errors
return MZSTREAM_OK;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
void mzstream_mem_set_buffer(voidpf stream, void *buf, uint32_t size)
2012-01-21 15:10:18 -07:00
{
2017-09-29 21:02:09 -07:00
mzstream_mem *mem = (mzstream_mem *)stream;
mem->buffer = buf;
mem->size = size;
2012-01-21 15:10:18 -07:00
}
2017-09-29 21:02:09 -07:00
void mzstream_mem_set_growable(voidpf stream, int growable)
{
mzstream_mem *mem = (mzstream_mem *)stream;
mem->growable = growable;
}
voidpf mzstream_mem_alloc(void)
{
mzstream_mem *mem = NULL;
mem = (mzstream_mem *)malloc(sizeof(mzstream_mem));
if (mem == NULL)
return NULL;
memset(mem, 0, sizeof(mzstream_mem));
mem->stream.open = mzstream_mem_open;
mem->stream.is_open = mzstream_mem_is_open;
mem->stream.read = mzstream_mem_read;
mem->stream.write = mzstream_mem_write;
mem->stream.tell = mzstream_mem_tell;
mem->stream.seek = mzstream_mem_seek;
mem->stream.close = mzstream_mem_close;
mem->stream.error = mzstream_mem_error;
mem->stream.alloc = mzstream_mem_alloc;
mem->stream.free = mzstream_mem_free;
return (voidpf)mem;
}
void mzstream_mem_free(voidpf stream)
{
mzstream_mem *mem = (mzstream_mem *)stream;
if (mem != NULL)
{
if (mem->growable && mem->buffer != NULL)
free(mem->buffer);
free(mem);
}
}