mirror of
https://github.com/QuasarApp/zip.git
synced 2025-05-11 11:19:34 +00:00
parent
a462384060
commit
c555a9636f
114
src/zip.c
114
src/zip.c
@ -832,40 +832,24 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int zip_extract(const char *zipname, const char *dir,
|
static inline int extract(mz_zip_archive *zip_archive, const char *dir,
|
||||||
int (*on_extract)(const char *filename, void *arg), void *arg) {
|
int (*on_extract)(const char *filename, void *arg), void *arg){
|
||||||
int status = -1;
|
int status = -1;
|
||||||
mz_uint i, n;
|
mz_uint i, n;
|
||||||
char path[MAX_PATH + 1];
|
char path[MAX_PATH + 1];
|
||||||
char symlink_to[MAX_PATH + 1];
|
char symlink_to[MAX_PATH + 1];
|
||||||
mz_zip_archive zip_archive;
|
|
||||||
mz_zip_archive_file_stat info;
|
mz_zip_archive_file_stat info;
|
||||||
size_t dirlen = 0;
|
size_t dirlen = 0;
|
||||||
mz_uint32 xattr = 0;
|
mz_uint32 xattr = 0;
|
||||||
|
|
||||||
memset(path, 0, sizeof(path));
|
memset(path, 0, sizeof(path));
|
||||||
memset(symlink_to, 0, sizeof(symlink_to));
|
memset(symlink_to, 0, sizeof(symlink_to));
|
||||||
if (!memset(&(zip_archive), 0, sizeof(zip_archive))) {
|
|
||||||
// Cannot memset zip archive
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!zipname || !dir) {
|
|
||||||
// Cannot parse zip archive name
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dirlen = strlen(dir);
|
dirlen = strlen(dir);
|
||||||
if (dirlen + 1 > MAX_PATH) {
|
if (dirlen + 1 > MAX_PATH) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now try to open the archive.
|
|
||||||
if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) {
|
|
||||||
// Cannot initialize zip_archive reader
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat));
|
memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat));
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
@ -884,9 +868,9 @@ int zip_extract(const char *zipname, const char *dir,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get and print information about each file in the archive.
|
// Get and print information about each file in the archive.
|
||||||
n = mz_zip_reader_get_num_files(&zip_archive);
|
n = mz_zip_reader_get_num_files(zip_archive);
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
if (!mz_zip_reader_file_stat(&zip_archive, i, &info)) {
|
if (!mz_zip_reader_file_stat(zip_archive, i, &info)) {
|
||||||
// Cannot get information about zip archive;
|
// Cannot get information about zip archive;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -912,7 +896,7 @@ int zip_extract(const char *zipname, const char *dir,
|
|||||||
defined(__MINGW32__)
|
defined(__MINGW32__)
|
||||||
#else
|
#else
|
||||||
if (info.m_uncomp_size > MAX_PATH ||
|
if (info.m_uncomp_size > MAX_PATH ||
|
||||||
!mz_zip_reader_extract_to_mem_no_alloc(&zip_archive, i, symlink_to,
|
!mz_zip_reader_extract_to_mem_no_alloc(zip_archive, i, symlink_to,
|
||||||
MAX_PATH, 0, NULL, 0)) {
|
MAX_PATH, 0, NULL, 0)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -922,8 +906,8 @@ int zip_extract(const char *zipname, const char *dir,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!mz_zip_reader_is_file_a_directory(&zip_archive, i)) {
|
if (!mz_zip_reader_is_file_a_directory(zip_archive, i)) {
|
||||||
if (!mz_zip_reader_extract_to_file(&zip_archive, i, path, 0)) {
|
if (!mz_zip_reader_extract_to_file(zip_archive, i, path, 0)) {
|
||||||
// Cannot extract zip archive to file
|
// Cannot extract zip archive to file
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -950,10 +934,92 @@ int zip_extract(const char *zipname, const char *dir,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
// Close the archive, freeing any resources it was using
|
// Close the archive, freeing any resources it was using
|
||||||
if (!mz_zip_reader_end(&zip_archive)) {
|
if (!mz_zip_reader_end(zip_archive)) {
|
||||||
// Cannot end zip reader
|
// Cannot end zip reader
|
||||||
status = -1;
|
status = -1;
|
||||||
}
|
}
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline mz_zip_archive * zip_archive_init_file(const char *zipname, mz_uint32 flags){
|
||||||
|
mz_zip_archive *zip_archive = NULL;
|
||||||
|
zip_archive = (mz_zip_archive *)malloc(sizeof(mz_zip_archive));
|
||||||
|
if (!zip_archive){
|
||||||
|
// malloc failed.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!memset(zip_archive, 0, sizeof(mz_zip_archive))) {
|
||||||
|
// Cannot memset zip archive
|
||||||
|
free(zip_archive);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Now try to open the archive.
|
||||||
|
if (!mz_zip_reader_init_file(zip_archive, zipname, flags)) {
|
||||||
|
// Cannot initialize zip_archive reader
|
||||||
|
free(zip_archive);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return zip_archive;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zip_extract(const char *zipname, const char *dir,
|
||||||
|
int (*on_extract)(const char *filename, void *arg), void *arg) {
|
||||||
|
if (!zipname || !dir) {
|
||||||
|
// Cannot parse zip archive name
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// init zip_archive and set reader
|
||||||
|
mz_zip_archive *zip_archive = zip_archive_init_file(zipname, 0);
|
||||||
|
if (!zip_archive){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = extract(zip_archive, dir, on_extract, arg);
|
||||||
|
|
||||||
|
free(zip_archive);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline mz_zip_archive * zip_archive_init_mem(const void *stream,
|
||||||
|
size_t size, mz_uint32 flags){
|
||||||
|
mz_zip_archive *zip_archive = NULL;
|
||||||
|
zip_archive = (mz_zip_archive *)malloc(sizeof(mz_zip_archive));
|
||||||
|
if (!zip_archive){
|
||||||
|
// malloc failed.
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!memset(zip_archive, 0, sizeof(mz_zip_archive))) {
|
||||||
|
// Cannot memset zip archive
|
||||||
|
free(zip_archive);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// Now try to open the archive.
|
||||||
|
if (!mz_zip_reader_init_mem(zip_archive, stream, size, flags)) {
|
||||||
|
// Cannot initialize zip_archive reader
|
||||||
|
free(zip_archive);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return zip_archive;
|
||||||
|
}
|
||||||
|
|
||||||
|
int zip_extract_stream(const char *stream, size_t size, const char *dir,
|
||||||
|
int (*on_extract)(const char *filename, void *arg), void *arg) {
|
||||||
|
if (!stream || !dir) {
|
||||||
|
// Cannot parse zip archive stream
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// init zip_archive and set reader
|
||||||
|
mz_zip_archive *zip_archive = zip_archive_init_mem(stream, size, 0);
|
||||||
|
if (!zip_archive){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = extract(zip_archive, dir, on_extract, arg);
|
||||||
|
|
||||||
|
free(zip_archive);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
}
|
19
src/zip.h
19
src/zip.h
@ -313,6 +313,25 @@ extern int zip_extract(const char *zipname, const char *dir,
|
|||||||
int (*on_extract_entry)(const char *filename, void *arg),
|
int (*on_extract_entry)(const char *filename, void *arg),
|
||||||
void *arg);
|
void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a zip archive stream into directory.
|
||||||
|
*
|
||||||
|
* If on_extract is not NULL, the callback will be called after
|
||||||
|
* successfully extracted each zip entry.
|
||||||
|
* Returning a negative value from the callback will cause abort and return an
|
||||||
|
* error. The last argument (void *arg) is optional, which you can use to pass
|
||||||
|
* data to the on_extract callback.
|
||||||
|
*
|
||||||
|
* @param stream zip archive stream.
|
||||||
|
* @param size stream size.
|
||||||
|
* @param dir output directory.
|
||||||
|
* @param on_extract on extract callback.
|
||||||
|
* @param arg opaque pointer.
|
||||||
|
*
|
||||||
|
* @return the return code - 0 on success, negative number (< 0) on error.
|
||||||
|
*/
|
||||||
|
extern int zip_extract_stream(const char *stream, size_t size, const char *dir,
|
||||||
|
int (*on_extract)(const char *filename, void *arg), void *arg);
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
36
test/test.c
36
test/test.c
@ -462,6 +462,41 @@ static void test_unix_permissions(void) {
|
|||||||
remove(RFILE);
|
remove(RFILE);
|
||||||
remove(ZIPNAME);
|
remove(ZIPNAME);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_extract_stream(void) {
|
||||||
|
|
||||||
|
remove(ZIPNAME);
|
||||||
|
|
||||||
|
struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
|
||||||
|
assert(zip != NULL);
|
||||||
|
|
||||||
|
assert(0 == zip_entry_open(zip, RFILE));
|
||||||
|
assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1)));
|
||||||
|
assert(0 == zip_entry_close(zip));
|
||||||
|
|
||||||
|
zip_close(zip);
|
||||||
|
|
||||||
|
remove(RFILE);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
assert(0 == zip_extract_stream(stream, size, ".", NULL, NULL));
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
remove(RFILE);
|
||||||
|
remove(ZIPNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@ -485,6 +520,7 @@ int main(int argc, char *argv[]) {
|
|||||||
test_exe_permissions();
|
test_exe_permissions();
|
||||||
test_mtime();
|
test_mtime();
|
||||||
test_unix_permissions();
|
test_unix_permissions();
|
||||||
|
test_extract_stream();
|
||||||
|
|
||||||
remove(ZIPNAME);
|
remove(ZIPNAME);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user