Skip to content

Commit

Permalink
Add zip_noallocopen
Browse files Browse the repository at this point in the history
Fixes #307
  • Loading branch information
kuba-- committed Sep 24, 2023
1 parent 604d142 commit b6f040b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 30 deletions.
63 changes: 33 additions & 30 deletions src/zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ struct zip_entry_mark_t {
size_t lf_length;
};

static const char *const zip_errlist[30] = {
static const char *const zip_errlist[33] = {
NULL,
"not initialized\0",
"invalid entry name\0",
Expand Down Expand Up @@ -147,11 +147,14 @@ static const char *const zip_errlist[30] = {
"fseek error\0",
"fread error\0",
"fwrite error\0",
"cannot initialize reader\0",
"cannot initialize writer\0",
"cannot initialize writer from reader\0",
};

const char *zip_strerror(int errnum) {
errnum = -errnum;
if (errnum <= 0 || errnum >= 30) {
if (errnum <= 0 || errnum >= 33) {
return NULL;
}

Expand Down Expand Up @@ -354,8 +357,7 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir,
}

#if defined(_MSC_VER)
strncpy_s(&path[dirlen], filename_size, info.m_filename,
filename_size);
strncpy_s(&path[dirlen], filename_size, info.m_filename, filename_size);
#else
strncpy(&path[dirlen], info.m_filename, filename_size);
#endif
Expand All @@ -376,8 +378,9 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir,
defined(__MINGW32__)
#else
if (info.m_uncomp_size > MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE ||
!mz_zip_reader_extract_to_mem_no_alloc(zip_archive, i, symlink_to,
MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE, 0, NULL, 0)) {
!mz_zip_reader_extract_to_mem_no_alloc(
zip_archive, i, symlink_to, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE, 0,
NULL, 0)) {
err = ZIP_EMEMNOALLOC;
goto out;
}
Expand Down Expand Up @@ -812,32 +815,36 @@ static ssize_t zip_entries_delete_mark(struct zip_t *zip,
}

struct zip_t *zip_open(const char *zipname, int level, char mode) {
struct zip_t *zip = NULL;
struct zip_t *zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t));
if (zip_noallocopen(&zip, zipname, level, mode) < 0) {
CLEANUP(zip);
return NULL;
}
return zip;
}

int zip_noallocopen(struct zip_t **pzip, const char *zipname, int level,
char mode) {
struct zip_t *zip = *pzip;

if (!zipname || strlen(zipname) < 1) {
// zip_t archive name is empty or NULL
goto cleanup;
return ZIP_EINVZIPNAME;
}

if (level < 0)
level = MZ_DEFAULT_LEVEL;
if ((level & 0xF) > MZ_UBER_COMPRESSION) {
// Wrong compression level
goto cleanup;
return ZIP_EINVLVL;
}

zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t));
if (!zip)
goto cleanup;

zip->level = (mz_uint)level;
switch (mode) {
case 'w':
// Create a new archive.
if (!mz_zip_writer_init_file_v2(&(zip->archive), zipname, 0,
MZ_ZIP_FLAG_WRITE_ZIP64)) {
// Cannot initialize zip_archive writer
goto cleanup;
return ZIP_EWINIT;
}
break;

Expand All @@ -847,7 +854,7 @@ struct zip_t *zip_open(const char *zipname, int level, char mode) {
zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) {
// An archive file does not exist or cannot initialize
// zip_archive reader
goto cleanup;
return ZIP_ERINIT;
}
break;

Expand All @@ -858,26 +865,22 @@ struct zip_t *zip_open(const char *zipname, int level, char mode) {
zip->level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) {
// An archive file does not exist or cannot initialize
// zip_archive reader
goto cleanup;
return ZIP_ERINIT;
}
if ((mode == 'a' || mode == 'd')) {
if (!mz_zip_writer_init_from_reader_v2_noreopen(&(zip->archive), zipname,
0)) {
mz_zip_reader_end(&(zip->archive));
goto cleanup;
return ZIP_EWRINIT;
}
}
break;

default:
goto cleanup;
return ZIP_EINVMODE;
}

return zip;

cleanup:
CLEANUP(zip);
return NULL;
return 0;
}

void zip_close(struct zip_t *zip) {
Expand All @@ -886,16 +889,16 @@ void zip_close(struct zip_t *zip) {
// Always finalize, even if adding failed for some reason, so we have a
// valid central directory.
if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) {
mz_zip_writer_finalize_archive(pZip);
mz_zip_writer_finalize_archive(pZip);
}

if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING ||
if (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING ||
pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED) {
zip_archive_truncate(pZip);
mz_zip_writer_end(pZip);
zip_archive_truncate(pZip);
mz_zip_writer_end(pZip);
}
if (pZip->m_zip_mode == MZ_ZIP_MODE_READING) {
mz_zip_reader_end(pZip);
mz_zip_reader_end(pZip);
}

CLEANUP(zip);
Expand Down
18 changes: 18 additions & 0 deletions src/zip.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ typedef long ssize_t; /* byte count or error */
#define ZIP_EFSEEK -27 // fseek error
#define ZIP_EFREAD -28 // fread error
#define ZIP_EFWRITE -29 // fwrite error
#define ZIP_ERINIT -30 // cannot initialize reader
#define ZIP_EWINIT -31 // cannot initialize writer
#define ZIP_EWRINIT -32 // cannot initialize writer from reader

/**
* Looks up the error message string corresponding to an error number.
Expand Down Expand Up @@ -124,6 +127,21 @@ struct zip_t;
extern ZIP_EXPORT struct zip_t *zip_open(const char *zipname, int level,
char mode);

/**
* Opens pre-allocated zip archive with compression level using the given mode.
*
* @param zip pre-allocated zip archive.
* @param zipname zip archive file name.
* @param level compression level (0-9 are the standard zlib-style levels).
* @param mode file access mode.
* - 'r': opens a file for reading/extracting (the file must exists).
* - 'w': creates an empty file for writing.
* - 'a': appends to an existing archive.
*
* @return the return code - 0 on success, negative number (< 0) on error.
*/
extern ZIP_EXPORT int zip_noallocopen(struct zip_t **zip, const char *zipname,
int level, char mode);
/**
* Closes the zip archive, releases resources - always finalize.
*
Expand Down

0 comments on commit b6f040b

Please sign in to comment.