mirror of
https://github.com/QuasarApp/zip.git
synced 2025-04-26 12:44:30 +00:00
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:
parent
05f412b3e6
commit
bfcfd1aa4e
32
README.md
32
README.md
@ -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');
|
||||
|
50
src/zip.c
50
src/zip.c
@ -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);
|
||||
|
23
src/zip.h
23
src/zip.h
@ -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.
|
||||
|
31
test/test.c
31
test/test.c
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user