Issue 153 NEW PR (#167)

* issue153

* fix issue 153

* malloc->calloc

* add zip_open_stream() to readme

Co-authored-by: hanjinfei57 <hanjinfei57@gmail.com>
This commit is contained in:
jinfeihan57 2021-03-06 18:56:21 +08:00 committed by GitHub
parent 05f412b3e6
commit bfcfd1aa4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 25 deletions

View File

@ -154,6 +154,38 @@ struct zip_t *zip = zip_open("foo.zip", 0, 'r');
zip_close(zip);
```
* Create a new zip archive in memory.
```c
char *buf_encode = NULL;
const char *buf = "Append some data here...\0";
struct zip_t *zip = zip_open_stream(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
{
zip_entry_open(zip, "foo-1.txt");
zip_entry_write(zip, buf, strlen(buf));
zip_entry_close(zip);
/* copy compressed mem to buf_encode */
size_t n = zip_copy_stream(zip, (void **)&buf_encode, NULL);
}
zip_close_stream(zip);
free(buf_encode);
```
* Extract a zip entry into a memory.
```c
char *buf = NULL;
struct zip_t *zipStream = zip_open_stream(buf_encode, n, 0, 'r');
{
zip_entry_open(zipStream, "foo-1.txt");
ssize_t bufsize;
bufsize = zip_entry_read(zipStream, (void **)&buf, NULL);
zip_entry_close(zipStream);
}
zip_close_stream(zipStream);
free(buf);
```
* List of all zip entries
```c
struct zip_t *zip = zip_open("foo.zip", 0, 'r');

View File

@ -72,7 +72,9 @@
static int file_truncate(mz_zip_archive *pZip) {
mz_zip_internal_state *pState = pZip->m_pState;
mz_uint64 file_size = pZip->m_archive_size;
if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
return 0;
}
if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
if (pState->m_pFile) {
int fd = fileno(pState->m_pFile);
@ -1076,13 +1078,30 @@ struct entry_mark {
mz_uint64 lf_length;
};
struct zip_t *zip_open_stream(const char *stream, size_t size) {
struct zip_t *zip_open_stream(const char *stream, size_t size, int level, char mode) {
struct zip_t *zip = NULL;
zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t));
if (!zip) {
return NULL;
}
if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
if (level < 0)
level = MZ_DEFAULT_LEVEL;
if ((level & 0xF) > MZ_UBER_COMPRESSION) {
// Wrong compression level
goto cleanup;
}
zip->level = (mz_uint)level;
if((stream != NULL) && (size > 0) && (mode == 'r')){
if (!mz_zip_reader_init_mem(&(zip->archive), stream, size, 0)) {
goto cleanup;
}
}else if((stream == NULL) && (size == 0) && (mode == 'w')){
// Create a new archive.
if (!mz_zip_writer_init_heap(&(zip->archive), 0, 1024)) {
// Cannot initialize zip_archive writer
goto cleanup;
}
}else{
goto cleanup;
}
return zip;
@ -1092,6 +1111,31 @@ cleanup:
return NULL;
}
static inline void zip_write_end(struct zip_t *zip){
if (zip) {
mz_zip_writer_finalize_archive(&(zip->archive));
file_truncate(&(zip->archive));
}
}
ssize_t zip_copy_stream(struct zip_t *zip, void **buf, ssize_t *bufsize){
if(zip == NULL) return -1;
zip_write_end(zip);
if(bufsize != NULL)
*bufsize = zip->archive.m_archive_size;
*buf = (char *)calloc(sizeof(unsigned char), zip->archive.m_archive_size);
memcpy(*buf, zip->archive.m_pState->m_pMem, zip->archive.m_archive_size);
return zip->archive.m_archive_size;
}
void zip_close_stream(struct zip_t *zip){
if (zip) {
mz_zip_writer_end(&(zip->archive));
mz_zip_reader_end(&(zip->archive));
CLEANUP(zip);
}
}
static mz_bool file_name_matches(const char *file_name,
const char *delete_name) {
int delete_name_length = strlen(delete_name);

View File

@ -331,7 +331,28 @@ extern int zip_extract_stream(const char *stream, size_t size, const char *dir,
*
* @return the zip archive handler or NULL on error
*/
extern struct zip_t *zip_open_stream(const char *stream, size_t size);
extern struct zip_t *zip_open_stream(const char *stream, size_t size,
int level, char mode);
/**
* Copy zip archive stream output buffer.
*
* @param zip zip archive handler.
* @param buf output buffer. User should free buf.
* @param bufsize output buffer size (in bytes).
*
* @return copy size
*/
extern ssize_t zip_copy_stream(struct zip_t *zip, void **buf, ssize_t *bufsize);
/**
* Close zip archive releases resources.
*
* @param zip zip archive handler.
*
* @return
*/
extern void zip_close_stream(struct zip_t *zip);
/**
* Deletes zip archive entries.

View File

@ -547,32 +547,20 @@ static void test_open_stream(void) {
#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__)
#else
remove(ZIPNAME);
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
/* COMPRESS MEM TO MEM */
struct zip_t *zip = zip_open_stream(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
assert(zip != NULL);
assert(0 == zip_entry_open(zip, "test/test-1.txt"));
assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
assert(0 == zip_entry_close(zip));
zip_close(zip);
FILE *fp = NULL;
fp = fopen(ZIPNAME, "r");
assert(fp != NULL);
fseek(fp, 0L, SEEK_END);
size_t filesize = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char stream[filesize];
memset(stream, 0, filesize);
size_t size = fread(stream, sizeof(char), filesize, fp);
assert(filesize == size);
fclose(fp);
struct zip_t *zipStream = zip_open_stream(stream, size);
/* write compressed mem to file */
char *buf_encode = NULL;
size_t n = zip_copy_stream(zip, (void **)&buf_encode, NULL);
zip_close_stream(zip);
/* DECOMPRESS MEM TO MEM */
struct zip_t *zipStream = zip_open_stream(buf_encode, n, 0, 'r');
assert(zipStream != NULL);
assert(0 == zip_entry_open(zipStream, "test/test-1.txt"));
@ -582,9 +570,10 @@ static void test_open_stream(void) {
bufsize = zip_entry_read(zipStream, (void **)&buf, NULL);
assert(0 == strncmp(buf, TESTDATA1, (size_t)bufsize));
assert(0 == zip_entry_close(zipStream));
zip_close_stream(zipStream);
free(buf);
zip_close(zipStream);
free(buf_encode);
remove(ZIPNAME);
#endif
}