From f0e5c7b150a3c2b62218ecb9e07a48c70a6940f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Podg=C3=B3rski?= Date: Fri, 12 Mar 2021 20:12:41 +0100 Subject: [PATCH 1/2] Return code on error --- src/zip.c | 303 +++++++++++++++++++++++----------------- src/zip.h | 34 ++++- test/test_append.c | 6 +- test/test_entry.c | 80 +++++------ test/test_extract.c | 24 ++-- test/test_permissions.c | 36 ++--- test/test_read.c | 30 ++-- test/test_write.c | 10 +- 8 files changed, 301 insertions(+), 222 deletions(-) diff --git a/src/zip.c b/src/zip.c index 37e96e2..efd5b45 100644 --- a/src/zip.c +++ b/src/zip.c @@ -148,7 +148,7 @@ static int zip_mkpath(char *path) { if (MKDIR(npath) == -1) { if (errno != EEXIST) { - return -1; + return ZIP_EMKDIR; } } } @@ -241,7 +241,7 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, int (*on_extract)(const char *filename, void *arg), void *arg) { - int status = -1; + int err = 0; mz_uint i, n; char path[MAX_PATH + 1]; char symlink_to[MAX_PATH + 1]; @@ -254,7 +254,7 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, dirlen = strlen(dir); if (dirlen + 1 > MAX_PATH) { - return -1; + return ZIP_EINVENTNAME; } memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat)); @@ -279,11 +279,14 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, for (i = 0; i < n; ++i) { if (!mz_zip_reader_file_stat(zip_archive, i, &info)) { // Cannot get information about zip archive; + err = ZIP_ENOENT; goto out; } + if (!zip_name_normalize(info.m_filename, info.m_filename, strlen(info.m_filename))) { // Cannot normalize file name; + err = ZIP_EINVENTNAME; goto out; } #if defined(_MSC_VER) @@ -292,7 +295,8 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, #else strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen); #endif - if (zip_mkpath(path) < 0) { + err = zip_mkpath(path); + if (err < 0) { // Cannot make a path goto out; } @@ -310,10 +314,12 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, if (info.m_uncomp_size > MAX_PATH || !mz_zip_reader_extract_to_mem_no_alloc(zip_archive, i, symlink_to, MAX_PATH, 0, NULL, 0)) { + err = ZIP_EMEMNOALLOC; goto out; } symlink_to[info.m_uncomp_size] = '\0'; if (symlink(symlink_to, path) != 0) { + err = ZIP_ESYMLINK; goto out; } #endif @@ -321,6 +327,7 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, if (!mz_zip_reader_is_file_a_directory(zip_archive, i)) { if (!mz_zip_reader_extract_to_file(zip_archive, i, path, 0)) { // Cannot extract zip archive to file + err = ZIP_ENOFILE; goto out; } } @@ -331,6 +338,7 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, xattr = (info.m_external_attr >> 16) & 0xFFFF; if (xattr > 0) { if (chmod(path, (mode_t)xattr) < 0) { + err = ZIP_ENOPERM; goto out; } } @@ -343,15 +351,14 @@ static int zip_archive_extract(mz_zip_archive *zip_archive, const char *dir, } } } - status = 0; out: // Close the archive, freeing any resources it was using if (!mz_zip_reader_end(zip_archive)) { // Cannot end zip reader - status = -1; + err = ZIP_ECLSZIP; } - return status; + return err; } static inline void zip_archive_finalize(mz_zip_archive *pzip) { @@ -361,16 +368,19 @@ static inline void zip_archive_finalize(mz_zip_archive *pzip) { static int zip_entry_mark(struct zip_t *zip, struct entry_mark_t *entry_mark, int n, char *const entries[], const size_t len) { + int err = 0; if (!zip || !entry_mark || !entries) { - return -1; + return ZIP_ENOINIT; } mz_zip_archive_file_stat file_stat; mz_uint64 d_pos = ~0; for (int i = 0; i < n; ++i) { - if (zip_entry_openbyindex(zip, i)) { - return -1; + + if ((err = zip_entry_openbyindex(zip, i))) { + return err; } + mz_bool name_matches = MZ_FALSE; for (int j = 0; j < (const int)len; ++j) { if (zip_name_match(zip->entry.name, entries[j])) { @@ -385,9 +395,11 @@ static int zip_entry_mark(struct zip_t *zip, struct entry_mark_t *entry_mark, } if (!mz_zip_reader_file_stat(&zip->archive, i, &file_stat)) { - return -1; + return ZIP_ENOENT; } + zip_entry_close(zip); + entry_mark[i].m_local_header_ofs = file_stat.m_local_header_ofs; entry_mark[i].file_index = -1; entry_mark[i].lf_length = 0; @@ -402,7 +414,7 @@ static int zip_entry_mark(struct zip_t *zip, struct entry_mark_t *entry_mark, entry_mark[i].type = MZ_MOVE; } } - return 0; + return err; } static int zip_index_next(mz_uint64 *local_header_ofs_array, int cur_index) { @@ -444,8 +456,8 @@ static int zip_entry_finalize(struct zip_t *zip, struct entry_mark_t *entry_mark, const int n) { mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n, sizeof(mz_uint64)); - if (local_header_ofs_array == NULL) { - return -1; + if (!local_header_ofs_array) { + return ZIP_EOOMEM; } for (int i = 0; i < n; ++i) { @@ -459,9 +471,9 @@ static int zip_entry_finalize(struct zip_t *zip, } mz_uint64 *length = (mz_uint64 *)calloc(n, sizeof(mz_uint64)); - if (length == NULL) { + if (!length) { CLEANUP(local_header_ofs_array); - return -1; + return ZIP_EOOMEM; } for (int i = 0; i < n - 1; i++) { length[i] = local_header_ofs_array[i + 1] - local_header_ofs_array[i]; @@ -479,11 +491,13 @@ static int zip_entry_finalize(struct zip_t *zip, static int zip_entry_set(struct zip_t *zip, struct entry_mark_t *entry_mark, int n, char *const entries[], const size_t len) { - if (zip_entry_mark(zip, entry_mark, n, entries, len)) { - return -1; + int err = 0; + + if ((err = zip_entry_mark(zip, entry_mark, n, entries, len)) < 0) { + return err; } - if (zip_entry_finalize(zip, entry_mark, n)) { - return -1; + if ((err = zip_entry_finalize(zip, entry_mark, n)) < 0) { + return err; } return 0; } @@ -493,44 +507,52 @@ static mz_int64 zip_file_move(MZ_FILE *m_pFile, const mz_uint64 to, mz_uint8 *move_buf, const mz_int64 capacity_size) { if ((mz_int64)length > capacity_size) { - return -1; + return ZIP_ECAPSIZE; } if (MZ_FSEEK64(m_pFile, from, SEEK_SET)) { MZ_FCLOSE(m_pFile); - return -1; + return ZIP_EFSEEK; } if (fread(move_buf, 1, length, m_pFile) != length) { MZ_FCLOSE(m_pFile); - return -1; + return ZIP_EFREAD; } if (MZ_FSEEK64(m_pFile, to, SEEK_SET)) { MZ_FCLOSE(m_pFile); - return -1; + return ZIP_EFSEEK; } if (fwrite(move_buf, 1, length, m_pFile) != length) { MZ_FCLOSE(m_pFile); - return -1; + return ZIP_EFWRITE; } return (mz_int64)length; } static mz_int64 zip_files_move(MZ_FILE *m_pFile, mz_uint64 writen_num, mz_uint64 read_num, mz_uint64 length) { + int n = 0; const mz_int64 page_size = 1 << 12; // 4K mz_uint8 *move_buf = (mz_uint8 *)calloc(1, page_size); if (move_buf == NULL) { - return -1; + return ZIP_EOOMEM; } mz_int64 moved_length = 0; mz_int64 move_count = 0; while ((mz_int64)length > 0) { move_count = ((mz_int64)length >= page_size) ? page_size : (mz_int64)length; - if (zip_file_move(m_pFile, writen_num, read_num, move_count, move_buf, - page_size) != move_count) { + n = zip_file_move(m_pFile, writen_num, read_num, move_count, move_buf, + page_size); + if (n < 0) { + moved_length = n; + goto cleanup; + } + + if (n != move_count) { goto cleanup; } + writen_num += move_count; read_num += move_count; length -= move_count; @@ -640,10 +662,18 @@ static int zip_central_dir_delete(mz_zip_internal_state *pState, static int zip_entries_delete_mark(struct zip_t *zip, struct entry_mark_t *entry_mark, int entry_num) { + mz_uint64 writen_num = 0; + mz_uint64 read_num = 0; + mz_uint64 deleted_length = 0; + mz_uint64 move_length = 0; + int i = 0; + int deleted_entry_num = 0; + int n = 0; + mz_bool *deleted_entry_flag_array = (mz_bool *)calloc(entry_num, sizeof(mz_bool)); if (deleted_entry_flag_array == NULL) { - return -1; + return ZIP_EOOMEM; } mz_zip_internal_state *pState = zip->archive.m_pState; @@ -651,15 +681,9 @@ static int zip_entries_delete_mark(struct zip_t *zip, if (MZ_FSEEK64(pState->m_pFile, 0, SEEK_SET)) { CLEANUP(deleted_entry_flag_array); - return -1; + return ZIP_ENOENT; } - mz_uint64 writen_num = 0; - mz_uint64 read_num = 0; - mz_uint64 deleted_length = 0; - mz_uint64 move_length = 0; - int i = 0; - int deleted_entry_num = 0; while (i < entry_num) { while ((entry_mark[i].type == MZ_KEEP) && (i < entry_num)) { writen_num += entry_mark[i].lf_length; @@ -682,17 +706,18 @@ static int zip_entries_delete_mark(struct zip_t *zip, MZ_ZIP_ARRAY_ELEMENT(&pState->m_central_dir_offsets, mz_uint32, i)); if (!p) { CLEANUP(deleted_entry_flag_array); - return -1; + return ZIP_ENOENT; } mz_uint32 offset = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); offset -= (mz_uint32)deleted_length; MZ_WRITE_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS, offset); i++; } - if (zip_files_move(pState->m_pFile, writen_num, read_num, move_length) != - (mz_int64)move_length) { + + n = zip_files_move(pState->m_pFile, writen_num, read_num, move_length); + if (n != (mz_int64)move_length) { CLEANUP(deleted_entry_flag_array); - return -1; + return n; } writen_num += move_length; read_num += move_length; @@ -778,14 +803,9 @@ void zip_close(struct zip_t *zip) { } int zip_is64(struct zip_t *zip) { - if (!zip) { - // zip_t handler is not initialized - return -1; - } - - if (!zip->archive.m_pState) { - // zip state is not initialized - return -1; + if (!zip || !zip->archive.m_pState) { + // zip_t handler or zip state is not initialized + return ZIP_ENOINIT; } return (int)zip->archive.m_pState->m_zip64; @@ -796,14 +816,19 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { mz_zip_archive *pzip = NULL; mz_uint num_alignment_padding_bytes, level; mz_zip_archive_file_stat stats; + int err = 0; - if (!zip || !entryname) { - return -1; + if (!zip) { + return ZIP_ENOINIT; + } + + if (!entryname) { + return ZIP_EINVENTNAME; } entrylen = strlen(entryname); - if (entrylen < 1) { - return -1; + if (entrylen == 0) { + return ZIP_EINVENTNAME; } /* @@ -823,7 +848,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { zip->entry.name = zip_strrpl(entryname, entrylen, '\\', '/'); if (!zip->entry.name) { // Cannot parse zip entry name - return -1; + return ZIP_EINVENTNAME; } pzip = &(zip->archive); @@ -831,10 +856,12 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { zip->entry.index = mz_zip_reader_locate_file(pzip, zip->entry.name, NULL, 0); if (zip->entry.index < 0) { + err = ZIP_ENOENT; goto cleanup; } if (!mz_zip_reader_file_stat(pzip, (mz_uint)zip->entry.index, &stats)) { + err = ZIP_ENOENT; goto cleanup; } @@ -873,11 +900,13 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) { - // Wrong zip mode + // Invalid zip mode + err = ZIP_EINVMODE; goto cleanup; } if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) { - // Wrong zip compression level + // Invalid zip compression level + err = ZIP_EINVLVL; goto cleanup; } // no zip64 support yet @@ -886,12 +915,14 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + entrylen) > 0xFFFFFFFF)) { // No zip64 support yet + err = ZIP_ENOSUP64; goto cleanup; } if (!mz_zip_writer_write_zeros(pzip, zip->entry.offset, num_alignment_padding_bytes + sizeof(zip->entry.header))) { // Cannot memset zip entry header + err = ZIP_EMEMSET; goto cleanup; } @@ -905,6 +936,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, zip->entry.name, entrylen) != entrylen) { // Cannot write data to zip entry + err = ZIP_EWRTENT; goto cleanup; } @@ -921,6 +953,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { (int)level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) { // Cannot initialize the zip compressor + err = ZIP_ETDEFLINIT; goto cleanup; } } @@ -931,7 +964,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) { cleanup: CLEANUP(zip->entry.name); - return -1; + return err; } int zip_entry_openbyindex(struct zip_t *zip, int index) { @@ -943,18 +976,18 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } pZip = &(zip->archive); if (pZip->m_zip_mode != MZ_ZIP_MODE_READING) { // open by index requires readonly mode - return -1; + return ZIP_EINVMODE; } if (index < 0 || (mz_uint)index >= pZip->m_total_files) { // index out of range - return -1; + return ZIP_EINVIDX; } if (!(pHeader = &MZ_ZIP_ARRAY_ELEMENT( @@ -962,7 +995,7 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) { MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, index)))) { // cannot find header in central directory - return -1; + return ZIP_ENOHDR; } namelen = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); @@ -985,11 +1018,11 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) { zip->entry.name = zip_strrpl(pFilename, namelen, '\\', '/'); if (!zip->entry.name) { // local entry name is NULL - return -1; + return ZIP_EINVENTNAME; } if (!mz_zip_reader_file_stat(pZip, (mz_uint)index, &stats)) { - return -1; + return ZIP_ENOENT; } zip->entry.index = index; @@ -1013,16 +1046,16 @@ int zip_entry_close(struct zip_t *zip) { tdefl_status done; mz_uint16 entrylen; mz_uint16 dos_time = 0, dos_date = 0; - int status = -1; + int err = 0; if (!zip) { // zip_t handler is not initialized + err = ZIP_ENOINIT; goto cleanup; } pzip = &(zip->archive); if (pzip->m_zip_mode == MZ_ZIP_MODE_READING) { - status = 0; goto cleanup; } @@ -1031,6 +1064,7 @@ int zip_entry_close(struct zip_t *zip) { done = tdefl_compress_buffer(&(zip->entry.comp), "", 0, TDEFL_FINISH); if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) { // Cannot flush compressed buffer + err = ZIP_ETDEFLBUF; goto cleanup; } zip->entry.comp_size = zip->entry.state.m_comp_size; @@ -1039,9 +1073,9 @@ int zip_entry_close(struct zip_t *zip) { } entrylen = (mz_uint16)strlen(zip->entry.name); - // no zip64 support yet if ((zip->entry.comp_size > 0xFFFFFFFF) || (zip->entry.offset > 0xFFFFFFFF)) { // No zip64 support, yet + err = ZIP_ENOSUP64; goto cleanup; } @@ -1054,6 +1088,7 @@ int zip_entry_close(struct zip_t *zip) { zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0, dos_time, dos_date)) { // Cannot create zip entry header + err = ZIP_ECRTHDR; goto cleanup; } @@ -1061,6 +1096,7 @@ int zip_entry_close(struct zip_t *zip) { zip->entry.header, sizeof(zip->entry.header)) != sizeof(zip->entry.header)) { // Cannot write zip entry header + err = ZIP_EWRTHDR; goto cleanup; } @@ -1070,19 +1106,19 @@ int zip_entry_close(struct zip_t *zip) { zip->entry.method, 0, dos_time, dos_date, zip->entry.header_offset, zip->entry.external_attr)) { // Cannot write to zip central dir + err = ZIP_EWRTDIR; goto cleanup; } pzip->m_total_files++; pzip->m_archive_size = zip->entry.offset; - status = 0; cleanup: if (zip) { zip->entry.m_time = 0; CLEANUP(zip->entry.name); } - return status; + return err; } const char *zip_entry_name(struct zip_t *zip) { @@ -1097,7 +1133,7 @@ const char *zip_entry_name(struct zip_t *zip) { int zip_entry_index(struct zip_t *zip) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } return zip->entry.index; @@ -1106,12 +1142,12 @@ int zip_entry_index(struct zip_t *zip) { int zip_entry_isdir(struct zip_t *zip) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } if (zip->entry.index < 0) { // zip entry is not opened - return -1; + return ZIP_EINVIDX; } return (int)mz_zip_reader_is_file_a_directory(&zip->archive, @@ -1133,7 +1169,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } pzip = &(zip->archive); @@ -1147,7 +1183,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) { if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, buf, bufsize) != bufsize)) { // Cannot write buffer - return -1; + return ZIP_EWRTENT; } zip->entry.offset += bufsize; zip->entry.comp_size += bufsize; @@ -1156,7 +1192,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) { TDEFL_NO_FLUSH); if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) { // Cannot compress buffer - return -1; + return ZIP_ETDEFLBUF; } } } @@ -1165,7 +1201,7 @@ int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) { } int zip_entry_fwrite(struct zip_t *zip, const char *filename) { - int status = 0; + int err = 0; size_t n = 0; FILE *stream = NULL; mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE]; @@ -1173,14 +1209,14 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } memset(buf, 0, MZ_ZIP_MAX_IO_BUF_SIZE); memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT)); if (MZ_FILE_STAT(filename, &file_stat) != 0) { // problem getting information - check errno - return -1; + return ZIP_ENOENT; } if ((file_stat.st_mode & 0200) == 0) { @@ -1197,19 +1233,19 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) { #endif { // Cannot open filename - return -1; + return ZIP_EOPNFILE; } while ((n = fread(buf, sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) > 0) { if (zip_entry_write(zip, buf, n) < 0) { - status = -1; + err = ZIP_EWRTENT; break; } } fclose(stream); - return status; + return err; } ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) { @@ -1219,19 +1255,19 @@ ssize_t zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } pzip = &(zip->archive); if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) { // the entry is not found or we do not have read access - return -1; + return ZIP_ENOENT; } idx = (mz_uint)zip->entry.index; if (mz_zip_reader_is_file_a_directory(pzip, idx)) { // the entry is a directory - return -1; + return ZIP_EINVENTTYPE; } *buf = mz_zip_reader_extract_to_heap(pzip, idx, &size, 0); @@ -1246,18 +1282,18 @@ ssize_t zip_entry_noallocread(struct zip_t *zip, void *buf, size_t bufsize) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } pzip = &(zip->archive); if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) { // the entry is not found or we do not have read access - return -1; + return ZIP_ENOENT; } if (!mz_zip_reader_extract_to_mem_no_alloc(pzip, (mz_uint)zip->entry.index, buf, bufsize, 0, NULL, 0)) { - return -1; + return ZIP_EMEMNOALLOC; } return (ssize_t)zip->entry.uncomp_size; @@ -1271,24 +1307,24 @@ int zip_entry_fread(struct zip_t *zip, const char *filename) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } memset((void *)&info, 0, sizeof(mz_zip_archive_file_stat)); pzip = &(zip->archive); if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) { // the entry is not found or we do not have read access - return -1; + return ZIP_ENOENT; } idx = (mz_uint)zip->entry.index; if (mz_zip_reader_is_file_a_directory(pzip, idx)) { // the entry is a directory - return -1; + return ZIP_EINVENTTYPE; } if (!mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) { - return -1; + return ZIP_ENOFILE; } #if defined(_MSC_VER) @@ -1296,13 +1332,13 @@ int zip_entry_fread(struct zip_t *zip, const char *filename) { #else if (!mz_zip_reader_file_stat(pzip, idx, &info)) { // Cannot get information about zip archive; - return -1; + return ZIP_ENOFILE; } xattr = (info.m_external_attr >> 16) & 0xFFFF; if (xattr > 0) { if (chmod(filename, (mode_t)xattr) < 0) { - return -1; + return ZIP_ENOPERM; } } #endif @@ -1319,25 +1355,25 @@ int zip_entry_extract(struct zip_t *zip, if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } pzip = &(zip->archive); if (pzip->m_zip_mode != MZ_ZIP_MODE_READING || zip->entry.index < 0) { // the entry is not found or we do not have read access - return -1; + return ZIP_ENOENT; } idx = (mz_uint)zip->entry.index; return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0)) ? 0 - : -1; + : ZIP_EINVIDX; } int zip_entries_total(struct zip_t *zip) { if (!zip) { // zip_t handler is not initialized - return -1; + return ZIP_ENOINIT; } return (int)zip->archive.m_total_files; @@ -1345,28 +1381,36 @@ int zip_entries_total(struct zip_t *zip) { int zip_entries_delete(struct zip_t *zip, char *const entries[], const size_t len) { + int n = 0; + int err = 0; + struct entry_mark_t *entry_mark = NULL; + if (zip == NULL || (entries == NULL && len != 0)) { - return -1; + return ZIP_ENOINIT; } + if (entries == NULL && len == 0) { return 0; } - int n = zip_entries_total(zip); - struct entry_mark_t *entry_mark_array = - (struct entry_mark_t *)calloc(n, sizeof(struct entry_mark_t)); - if (entry_mark_array == NULL) { - return -1; + + n = zip_entries_total(zip); + + entry_mark = (struct entry_mark_t *)calloc(n, sizeof(struct entry_mark_t)); + if (!entry_mark) { + return ZIP_EOOMEM; } + zip->archive.m_zip_mode = MZ_ZIP_MODE_READING; - if (zip_entry_set(zip, entry_mark_array, n, entries, len)) { - CLEANUP(entry_mark_array); - return -1; + err = zip_entry_set(zip, entry_mark, n, entries, len); + if (err < 0) { + CLEANUP(entry_mark); + return err; } - int res = zip_entries_delete_mark(zip, entry_mark_array, n); - CLEANUP(entry_mark_array); - return res; + err = zip_entries_delete_mark(zip, entry_mark, n); + CLEANUP(entry_mark); + return err; } int zip_stream_extract(const char *stream, size_t size, const char *dir, @@ -1375,20 +1419,18 @@ int zip_stream_extract(const char *stream, size_t size, const char *dir, mz_zip_archive zip_archive; if (!stream || !dir) { // Cannot parse zip archive stream - return -1; + return ZIP_ENOINIT; } if (!memset(&zip_archive, 0, sizeof(mz_zip_archive))) { // Cannot memset zip archive - return -1; + return ZIP_EMEMSET; } if (!mz_zip_reader_init_mem(&zip_archive, stream, size, 0)) { // Cannot initialize zip_archive reader - return -1; + return ZIP_ENOINIT; } - int status = zip_archive_extract(&zip_archive, dir, on_extract, arg); - - return status; + return zip_archive_extract(&zip_archive, dir, on_extract, arg); } struct zip_t *zip_stream_open(const char *stream, size_t size, int level, @@ -1429,7 +1471,7 @@ struct zip_t *zip_stream_open(const char *stream, size_t size, int level, ssize_t zip_stream_copy(struct zip_t *zip, void **buf, ssize_t *bufsize) { if (!zip) { - return -1; + return ZIP_ENOINIT; } zip_archive_finalize(&(zip->archive)); @@ -1452,7 +1494,7 @@ void zip_stream_close(struct zip_t *zip) { } int zip_create(const char *zipname, const char *filenames[], size_t len) { - int status = 0; + int err = 0; size_t i; mz_zip_archive zip_archive; struct MZ_FILE_STAT_STRUCT file_stat; @@ -1460,32 +1502,34 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) { if (!zipname || strlen(zipname) < 1) { // zip_t archive name is empty or NULL - return -1; + return ZIP_EINVZIPNAME; } // Create a new archive. if (!memset(&(zip_archive), 0, sizeof(zip_archive))) { // Cannot memset zip archive - return -1; + return ZIP_EMEMSET; } if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) { // Cannot initialize zip_archive writer - return -1; + return ZIP_ENOINIT; } - memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT)); + if (!memset((void *)&file_stat, 0, sizeof(struct MZ_FILE_STAT_STRUCT))) { + return ZIP_EMEMSET; + } for (i = 0; i < len; ++i) { const char *name = filenames[i]; if (!name) { - status = -1; + err = ZIP_EINVENTNAME; break; } if (MZ_FILE_STAT(name, &file_stat) != 0) { // problem getting information - check errno - status = -1; + err = ZIP_ENOFILE; break; } @@ -1499,34 +1543,35 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) { ZIP_DEFAULT_COMPRESSION_LEVEL, ext_attributes)) { // Cannot add file to zip_archive - status = -1; + err = ZIP_ENOFILE; break; } } mz_zip_writer_finalize_archive(&zip_archive); mz_zip_writer_end(&zip_archive); - return status; + return err; } int zip_extract(const char *zipname, const char *dir, int (*on_extract)(const char *filename, void *arg), void *arg) { mz_zip_archive zip_archive; + if (!zipname || !dir) { // Cannot parse zip archive name - return -1; + return ZIP_EINVZIPNAME; } + if (!memset(&zip_archive, 0, sizeof(mz_zip_archive))) { // Cannot memset zip archive - return -1; + return ZIP_EMEMSET; } + // Now try to open the archive. if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) { // Cannot initialize zip_archive reader - return -1; + return ZIP_ENOINIT; } - int status = zip_archive_extract(&zip_archive, dir, on_extract, arg); - - return status; + return zip_archive_extract(&zip_archive, dir, on_extract, arg); } diff --git a/src/zip.h b/src/zip.h index b33e8ea..397e40b 100644 --- a/src/zip.h +++ b/src/zip.h @@ -47,9 +47,41 @@ typedef long ssize_t; /* byte count or error */ /** * Default zip compression level. */ - #define ZIP_DEFAULT_COMPRESSION_LEVEL 6 +/** + * Error codes + */ +#define ZIP_ENOINIT -1 // not initialized +#define ZIP_EINVENTNAME -2 // invalid entry name +#define ZIP_ENOENT -3 // entry not found +#define ZIP_EINVMODE -4 // invalid zip mode +#define ZIP_EINVLVL -5 // invalid compression level +#define ZIP_ENOSUP64 -6 // no zip 64 support +#define ZIP_EMEMSET -7 // cannot memset +#define ZIP_EWRTENT -8 // cannot write data to entry +#define ZIP_ETDEFLINIT -9 // cannot initialize tdefl compressor +#define ZIP_EINVIDX -10 // invalid index +#define ZIP_ENOHDR -11 // header not found +#define ZIP_ETDEFLBUF -12 // cannot flush tdefl buffer +#define ZIP_ECRTHDR -13 // cannot create entry header +#define ZIP_EWRTHDR -14 // cannot write entry header +#define ZIP_EWRTDIR -15 // cannot write to central dir +#define ZIP_EOPNFILE -16 // cannot open file +#define ZIP_EINVENTTYPE -17 // invalid entry type +#define ZIP_EMEMNOALLOC -18 // extracting data using no memory allocation +#define ZIP_ENOFILE -19 // file not found +#define ZIP_ENOPERM -20 // no permission +#define ZIP_EOOMEM -21 // out of memory +#define ZIP_EINVZIPNAME -22 // invalid zip archive name +#define ZIP_EMKDIR -23 // make dir error +#define ZIP_ESYMLINK -24 // symlink error +#define ZIP_ECLSZIP -25 // close the archive error +#define ZIP_ECAPSIZE -26 // capacity size issue +#define ZIP_EFSEEK -27 // fseek error +#define ZIP_EFREAD -28 // fread error +#define ZIP_EFWRITE -29 // fwrite error + /** * @struct zip_t * diff --git a/test/test_append.c b/test/test_append.c index ef3c420..c49dce4 100644 --- a/test/test_append.c +++ b/test/test_append.c @@ -47,7 +47,7 @@ MU_TEST(test_append) { mu_assert_int_eq(0, zip_entry_open(zip, "test\\empty/")); mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/empty/")); mu_assert_int_eq(0, zip_entry_size(zip)); - mu_check(0 == zip_entry_crc32(zip)); + mu_assert_int_eq(0, zip_entry_crc32(zip)); mu_assert_int_eq(total_entries, zip_entry_index(zip)); mu_assert_int_eq(0, zip_entry_close(zip)); ++total_entries; @@ -55,7 +55,7 @@ MU_TEST(test_append) { mu_assert_int_eq(0, zip_entry_open(zip, "empty/")); mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "empty/")); mu_assert_int_eq(0, zip_entry_size(zip)); - mu_check(0 == zip_entry_crc32(zip)); + mu_assert_int_eq(0, zip_entry_crc32(zip)); mu_assert_int_eq(total_entries, zip_entry_index(zip)); mu_assert_int_eq(0, zip_entry_close(zip)); ++total_entries; @@ -63,7 +63,7 @@ MU_TEST(test_append) { mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test")); mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "dotfiles/.test")); mu_assert_int_eq(0, zip_entry_size(zip)); - mu_check(0 == zip_entry_crc32(zip)); + mu_assert_int_eq(0, zip_entry_crc32(zip)); mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2))); mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip)); mu_check(CRC32DATA2 == zip_entry_crc32(zip)); diff --git a/test/test_entry.c b/test/test_entry.c index eca5a31..9296956 100644 --- a/test/test_entry.c +++ b/test/test_entry.c @@ -89,22 +89,22 @@ MU_TEST(test_entry_name) { mu_check(zip_entry_name(zip) == NULL); - mu_check(0 == zip_entry_open(zip, "test\\test-1.txt")); + mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-1.txt")); mu_check(NULL != zip_entry_name(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-1.txt")); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt")); mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip)); mu_check(CRC32DATA1 == zip_entry_crc32(zip)); mu_assert_int_eq(0, zip_entry_index(zip)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 == zip_entry_open(zip, "test/test-2.txt")); + mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt")); mu_check(NULL != zip_entry_name(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-2.txt")); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt")); mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip)); mu_check(CRC32DATA2 == zip_entry_crc32(zip)); mu_assert_int_eq(1, zip_entry_index(zip)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); } @@ -113,19 +113,19 @@ MU_TEST(test_entry_index) { struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); mu_check(zip != NULL); - mu_check(0 == zip_entry_open(zip, "test\\test-1.txt")); + mu_assert_int_eq(0, zip_entry_open(zip, "test\\test-1.txt")); mu_assert_int_eq(0, zip_entry_index(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-1.txt")); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt")); mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip)); mu_check(CRC32DATA1 == zip_entry_crc32(zip)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 == zip_entry_open(zip, "test/test-2.txt")); + mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt")); mu_assert_int_eq(1, zip_entry_index(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-2.txt")); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt")); mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip)); mu_check(CRC32DATA2 == zip_entry_crc32(zip)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); } @@ -134,19 +134,19 @@ MU_TEST(test_entry_openbyindex) { struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); mu_check(zip != NULL); - mu_check(0 == zip_entry_openbyindex(zip, 1)); + mu_assert_int_eq(0, zip_entry_openbyindex(zip, 1)); mu_assert_int_eq(1, zip_entry_index(zip)); mu_assert_int_eq(strlen(TESTDATA2), zip_entry_size(zip)); mu_check(CRC32DATA2 == zip_entry_crc32(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-2.txt")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-2.txt")); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 == zip_entry_openbyindex(zip, 0)); + mu_assert_int_eq(0, zip_entry_openbyindex(zip, 0)); mu_assert_int_eq(0, zip_entry_index(zip)); mu_assert_int_eq(strlen(TESTDATA1), zip_entry_size(zip)); mu_check(CRC32DATA1 == zip_entry_crc32(zip)); - mu_check(0 == strcmp(zip_entry_name(zip), "test/test-1.txt")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/test-1.txt")); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); } @@ -161,23 +161,23 @@ MU_TEST(test_entry_read) { zip_stream_open(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); mu_check(zip != NULL); - mu_check(0 == zip_entry_open(zip, "test/test-1.txt")); - mu_check(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt")); + mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); + mu_assert_int_eq(0, zip_entry_close(zip)); ssize_t n = zip_stream_copy(zip, (void **)&bufencode1, NULL); zip_stream_copy(zip, (void **)&bufencode2, &n); - mu_check(0 == strncmp(bufencode1, bufencode2, (size_t)n)); + mu_assert_int_eq(0, strncmp(bufencode1, bufencode2, (size_t)n)); zip_stream_close(zip); struct zip_t *zipstream = zip_stream_open(bufencode1, n, 0, 'r'); mu_check(zipstream != NULL); - mu_check(0 == zip_entry_open(zipstream, "test/test-1.txt")); + mu_assert_int_eq(0, zip_entry_open(zipstream, "test/test-1.txt")); bufsize = zip_entry_read(zipstream, (void **)&buf, NULL); - mu_check(0 == strncmp(buf, TESTDATA1, (size_t)bufsize)); - mu_check(0 == zip_entry_close(zipstream)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA1, (size_t)bufsize)); + mu_assert_int_eq(0, zip_entry_close(zipstream)); zip_stream_close(zipstream); @@ -192,13 +192,13 @@ MU_TEST(test_list_entries) { int i = 0, n = zip_entries_total(zip); for (; i < n; ++i) { - mu_check(0 == zip_entry_openbyindex(zip, i)); + mu_assert_int_eq(0, zip_entry_openbyindex(zip, i)); fprintf(stdout, "[%d]: %s", i, zip_entry_name(zip)); if (zip_entry_isdir(zip)) { fprintf(stdout, " (DIR)"); } fprintf(stdout, "\n"); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); } zip_close(zip); @@ -218,23 +218,23 @@ MU_TEST(test_entries_delete) { zip = zip_open(ZIPNAME, 0, 'r'); mu_check(zip != NULL); - mu_check(0 > zip_entry_open(zip, "delete.me")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete.me")); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 > zip_entry_open(zip, "_")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "_")); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 > zip_entry_open(zip, "delete/file.1")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.1")); + mu_assert_int_eq(0, zip_entry_close(zip)); - mu_check(0 > zip_entry_open(zip, "deleteme/file.3")); - mu_check(0 == zip_entry_close(zip)); - mu_check(0 > zip_entry_open(zip, "delete/file.2")); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "deleteme/file.3")); + mu_assert_int_eq(0, zip_entry_close(zip)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.2")); + mu_assert_int_eq(0, zip_entry_close(zip)); mu_assert_int_eq(total_entries - 5, zip_entries_total(zip)); - mu_check(0 == zip_entry_open(zip, "delete/file.4")); + mu_assert_int_eq(0, zip_entry_open(zip, "delete/file.4")); size_t buftmp = 0; char *buf = NULL; @@ -242,8 +242,8 @@ MU_TEST(test_entries_delete) { mu_assert_int_eq(bufsize, strlen(TESTDATA2)); mu_assert_int_eq((size_t)bufsize, buftmp); - mu_check(0 == strncmp(buf, TESTDATA2, bufsize)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA2, bufsize)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf); buf = NULL; diff --git a/test/test_extract.c b/test/test_extract.c index d2fef23..749537e 100644 --- a/test/test_extract.c +++ b/test/test_extract.c @@ -77,11 +77,11 @@ MU_TEST(test_extract) { memset((void *)&buf, 0, sizeof(struct buffer_t)); - mu_check(0 == zip_entry_open(zip, "test/test-1.txt")); - mu_check(0 == zip_entry_extract(zip, on_extract, &buf)); + mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt")); + mu_assert_int_eq(0, zip_entry_extract(zip, on_extract, &buf)); mu_assert_int_eq(strlen(TESTDATA1), buf.size); - mu_check(0 == strncmp(buf.data, TESTDATA1, buf.size)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf.data, TESTDATA1, buf.size)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf.data); buf.data = NULL; @@ -89,11 +89,11 @@ MU_TEST(test_extract) { memset((void *)&buf, 0, sizeof(struct buffer_t)); - mu_check(0 == zip_entry_open(zip, "dotfiles/.test")); - mu_check(0 == zip_entry_extract(zip, on_extract, &buf)); + mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test")); + mu_assert_int_eq(0, zip_entry_extract(zip, on_extract, &buf)); mu_assert_int_eq(strlen(TESTDATA2), buf.size); - mu_check(0 == strncmp(buf.data, TESTDATA2, buf.size)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf.data, TESTDATA2, buf.size)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf.data); buf.data = NULL; @@ -103,9 +103,11 @@ MU_TEST(test_extract) { } MU_TEST(test_extract_stream) { - mu_check(0 > zip_extract("non_existing_directory/non_existing_archive.zip", - ".", NULL, NULL)); - mu_check(0 > zip_stream_extract("", 0, ".", NULL, NULL)); + mu_assert_int_eq( + ZIP_ENOINIT, + zip_extract("non_existing_directory/non_existing_archive.zip", ".", NULL, + NULL)); + mu_assert_int_eq(ZIP_ENOINIT, zip_stream_extract("", 0, ".", NULL, NULL)); FILE *fp = NULL; #if defined(_MSC_VER) diff --git a/test/test_permissions.c b/test/test_permissions.c index 97215ff..53f1193 100644 --- a/test/test_permissions.c +++ b/test/test_permissions.c @@ -53,12 +53,12 @@ MU_TEST(test_exe_permissions) { fclose(f); chmod(XFILE, XMODE); - mu_check(0 == zip_create(ZIPNAME, filenames, 1)); + mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1)); remove(XFILE); - mu_check(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); + mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL)); - mu_check(0 == MZ_FILE_STAT(XFILE, &file_stats)); + mu_assert_int_eq(0, MZ_FILE_STAT(XFILE, &file_stats)); mu_assert_int_eq(XMODE, file_stats.st_mode); } @@ -73,8 +73,8 @@ MU_TEST(test_read_permissions) { mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1)); remove(RFILE); - mu_check(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); - mu_check(0 == MZ_FILE_STAT(RFILE, &file_stats)); + mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL)); + mu_assert_int_eq(0, MZ_FILE_STAT(RFILE, &file_stats)); mu_assert_int_eq(RMODE, file_stats.st_mode); // chmod from 444 to 666 to be able delete the file on windows @@ -89,11 +89,11 @@ MU_TEST(test_write_permissions) { fclose(f); chmod(WFILE, WMODE); - mu_check(0 == zip_create(ZIPNAME, filenames, 1)); + mu_assert_int_eq(0, zip_create(ZIPNAME, filenames, 1)); remove(WFILE); - mu_check(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); - mu_check(0 == MZ_FILE_STAT(WFILE, &file_stats)); + mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL)); + mu_assert_int_eq(0, MZ_FILE_STAT(WFILE, &file_stats)); mu_assert_int_eq(WMODE, file_stats.st_mode); } @@ -106,15 +106,15 @@ MU_TEST(test_unix_permissions) { struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); mu_check(zip != NULL); - mu_check(0 == zip_entry_open(zip, RFILE)); - mu_check(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_open(zip, RFILE)); + mu_assert_int_eq(0, zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL)); - mu_check(0 == MZ_FILE_STAT(RFILE, &file_stats)); + mu_assert_int_eq(0, MZ_FILE_STAT(RFILE, &file_stats)); mu_assert_int_eq(UNIXMODE, file_stats.st_mode); } @@ -134,7 +134,7 @@ MU_TEST(test_mtime) { mu_fail("Cannot open filename\n"); } fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream); - mu_check(0 == fclose(stream)); + mu_assert_int_eq(0, fclose(stream)); memset(&file_stat1, 0, sizeof(file_stat1)); memset(&file_stat2, 0, sizeof(file_stat2)); @@ -142,17 +142,17 @@ MU_TEST(test_mtime) { zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); mu_check(zip != NULL); - mu_check(0 == zip_entry_open(zip, filename)); - mu_check(0 == zip_entry_fwrite(zip, filename)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_open(zip, filename)); + mu_assert_int_eq(0, zip_entry_fwrite(zip, filename)); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); - mu_check(0 == MZ_FILE_STAT(filename, &file_stat1)); + mu_assert_int_eq(0, MZ_FILE_STAT(filename, &file_stat1)); remove(filename); mu_assert_int_eq(0, zip_extract(ZIPNAME, ".", NULL, NULL)); - mu_check(0 == MZ_FILE_STAT(filename, &file_stat2)); + mu_assert_int_eq(0, MZ_FILE_STAT(filename, &file_stat2)); remove(filename); fprintf(stdout, "file_stat1.st_mtime: %lu\n", file_stat1.st_mtime); diff --git a/test/test_read.c b/test/test_read.c index 50cfb1c..372e76c 100644 --- a/test/test_read.c +++ b/test/test_read.c @@ -69,16 +69,16 @@ MU_TEST(test_read) { mu_check(CRC32DATA2 == zip_entry_crc32(zip)); bufsize = zip_entry_read(zip, (void **)&buf, NULL); mu_assert_int_eq(strlen(TESTDATA2), (size_t)bufsize); - mu_check(0 == strncmp(buf, TESTDATA2, (size_t)bufsize)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA2, (size_t)bufsize)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf); buf = NULL; - mu_check(0 == zip_entry_open(zip, "test\\empty/")); - mu_check(0 == strcmp(zip_entry_name(zip), "test/empty/")); - mu_check(0 == zip_entry_size(zip)); - mu_check(0 == zip_entry_crc32(zip)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, zip_entry_open(zip, "test\\empty/")); + mu_assert_int_eq(0, strcmp(zip_entry_name(zip), "test/empty/")); + mu_assert_int_eq(0, zip_entry_size(zip)); + mu_assert_int_eq(0, zip_entry_crc32(zip)); + mu_assert_int_eq(0, zip_entry_close(zip)); zip_close(zip); } @@ -95,28 +95,28 @@ MU_TEST(test_noallocread) { mu_assert_int_eq(0, zip_entry_open(zip, "test/test-2.txt")); bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp); mu_assert_int_eq(buftmp, (size_t)bufsize); - mu_check(0 == strncmp(buf, TESTDATA2, buftmp)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA2, buftmp)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf); buf = NULL; buftmp = strlen(TESTDATA1); buf = calloc(buftmp, sizeof(char)); - mu_check(0 == zip_entry_open(zip, "test/test-1.txt")); + mu_assert_int_eq(0, zip_entry_open(zip, "test/test-1.txt")); bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp); mu_assert_int_eq(buftmp, (size_t)bufsize); - mu_check(0 == strncmp(buf, TESTDATA1, buftmp)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA1, buftmp)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf); buf = NULL; buftmp = strlen(TESTDATA2); buf = calloc(buftmp, sizeof(char)); - mu_check(0 == zip_entry_open(zip, "dotfiles/.test")); + mu_assert_int_eq(0, zip_entry_open(zip, "dotfiles/.test")); bufsize = zip_entry_noallocread(zip, (void *)buf, buftmp); mu_assert_int_eq(buftmp, (size_t)bufsize); - mu_check(0 == strncmp(buf, TESTDATA2, buftmp)); - mu_check(0 == zip_entry_close(zip)); + mu_assert_int_eq(0, strncmp(buf, TESTDATA2, buftmp)); + mu_assert_int_eq(0, zip_entry_close(zip)); free(buf); buf = NULL; diff --git a/test/test_write.c b/test/test_write.c index a5c7bb9..47c5b23 100644 --- a/test/test_write.c +++ b/test/test_write.c @@ -55,14 +55,14 @@ MU_TEST(test_fwrite) { mu_fail("Cannot open filename\n"); } fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream); - mu_check(0 == fclose(stream)); + mu_assert_int_eq(0, fclose(stream)); zip = zip_open(ZIPNAME, 9, 'w'); mu_check(zip != NULL); - mu_check(0 == zip_entry_open(zip, WFILE)); - mu_check(0 == zip_entry_fwrite(zip, WFILE)); - mu_check(0 == zip_entry_close(zip)); - mu_check(0 == zip_is64(zip)); + mu_assert_int_eq(0, zip_entry_open(zip, WFILE)); + mu_assert_int_eq(0, zip_entry_fwrite(zip, WFILE)); + mu_assert_int_eq(0, zip_entry_close(zip)); + mu_assert_int_eq(0, zip_is64(zip)); zip_close(zip); } From 252d6c18cfeba684e64acf0d23c374bbc6f5d510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Podg=C3=B3rski?= Date: Sat, 13 Mar 2021 18:09:47 +0100 Subject: [PATCH 2/2] Add error lookup function --- src/zip.c | 67 +++++++++++++++++++++++++++++++++++++-------- src/zip.h | 14 ++++++++-- test/test_entry.c | 6 ++++ test/test_extract.c | 1 + 4 files changed, 74 insertions(+), 14 deletions(-) diff --git a/src/zip.c b/src/zip.c index efd5b45..4a1baea 100644 --- a/src/zip.c +++ b/src/zip.c @@ -91,19 +91,61 @@ struct zip_t { struct zip_entry_t entry; }; -enum modify_t { +enum zip_modify_t { MZ_KEEP = 0, MZ_DELETE = 1, MZ_MOVE = 2, }; -struct entry_mark_t { +struct zip_entry_mark_t { int file_index; - enum modify_t type; + enum zip_modify_t type; mz_uint64 m_local_header_ofs; mz_uint64 lf_length; }; +static const char *const zip_errlist[30] = { + NULL, + "not initialized\0", + "invalid entry name\0", + "entry not found\0", + "invalid zip mode\0", + "invalid compression level\0", + "no zip 64 support\0", + "memset error\0", + "cannot write data to entry\0", + "cannot initialize tdefl compressor\0", + "invalid index\0", + "header not found\0", + "cannot flush tdefl buffer\0", + "cannot write entry header\0", + "cannot create entry header\0", + "cannot write to central dir\0", + "cannot open file\0", + "invalid entry type\0", + "extracting data using no memory allocation\0", + "file not found\0", + "no permission\0", + "out of memory\0", + "invalid zip archive name\0", + "make dir error\0" + "symlink error\0" + "close archive error\0" + "capacity size too small\0", + "fseek error\0", + "fread error\0", + "fwrite error\0", +}; + +const char *zip_strerror(int errnum) { + errnum = -errnum; + if (errnum <= 0 || errnum >= 30) { + return NULL; + } + + return zip_errlist[errnum]; +} + static const char *zip_basename(const char *name) { char const *p; char const *base = name += FILESYSTEM_PREFIX_LEN(name); @@ -366,8 +408,9 @@ static inline void zip_archive_finalize(mz_zip_archive *pzip) { zip_archive_truncate(pzip); } -static int zip_entry_mark(struct zip_t *zip, struct entry_mark_t *entry_mark, - int n, char *const entries[], const size_t len) { +static int zip_entry_mark(struct zip_t *zip, + struct zip_entry_mark_t *entry_mark, int n, + char *const entries[], const size_t len) { int err = 0; if (!zip || !entry_mark || !entries) { return ZIP_ENOINIT; @@ -441,7 +484,7 @@ static int zip_sort(mz_uint64 *local_header_ofs_array, int cur_index) { return nxt_index; } -static int zip_index_update(struct entry_mark_t *entry_mark, int last_index, +static int zip_index_update(struct zip_entry_mark_t *entry_mark, int last_index, int nxt_index) { for (int j = 0; j < last_index; j++) { if (entry_mark[j].file_index >= nxt_index) { @@ -453,7 +496,8 @@ static int zip_index_update(struct entry_mark_t *entry_mark, int last_index, } static int zip_entry_finalize(struct zip_t *zip, - struct entry_mark_t *entry_mark, const int n) { + struct zip_entry_mark_t *entry_mark, + const int n) { mz_uint64 *local_header_ofs_array = (mz_uint64 *)calloc(n, sizeof(mz_uint64)); if (!local_header_ofs_array) { @@ -489,7 +533,7 @@ static int zip_entry_finalize(struct zip_t *zip, return 0; } -static int zip_entry_set(struct zip_t *zip, struct entry_mark_t *entry_mark, +static int zip_entry_set(struct zip_t *zip, struct zip_entry_mark_t *entry_mark, int n, char *const entries[], const size_t len) { int err = 0; @@ -660,7 +704,7 @@ static int zip_central_dir_delete(mz_zip_internal_state *pState, } static int zip_entries_delete_mark(struct zip_t *zip, - struct entry_mark_t *entry_mark, + struct zip_entry_mark_t *entry_mark, int entry_num) { mz_uint64 writen_num = 0; mz_uint64 read_num = 0; @@ -1383,7 +1427,7 @@ int zip_entries_delete(struct zip_t *zip, char *const entries[], const size_t len) { int n = 0; int err = 0; - struct entry_mark_t *entry_mark = NULL; + struct zip_entry_mark_t *entry_mark = NULL; if (zip == NULL || (entries == NULL && len != 0)) { return ZIP_ENOINIT; @@ -1395,7 +1439,8 @@ int zip_entries_delete(struct zip_t *zip, char *const entries[], n = zip_entries_total(zip); - entry_mark = (struct entry_mark_t *)calloc(n, sizeof(struct entry_mark_t)); + entry_mark = + (struct zip_entry_mark_t *)calloc(n, sizeof(struct zip_entry_mark_t)); if (!entry_mark) { return ZIP_EOOMEM; } diff --git a/src/zip.h b/src/zip.h index 397e40b..70ab2ce 100644 --- a/src/zip.h +++ b/src/zip.h @@ -58,7 +58,7 @@ typedef long ssize_t; /* byte count or error */ #define ZIP_EINVMODE -4 // invalid zip mode #define ZIP_EINVLVL -5 // invalid compression level #define ZIP_ENOSUP64 -6 // no zip 64 support -#define ZIP_EMEMSET -7 // cannot memset +#define ZIP_EMEMSET -7 // memset error #define ZIP_EWRTENT -8 // cannot write data to entry #define ZIP_ETDEFLINIT -9 // cannot initialize tdefl compressor #define ZIP_EINVIDX -10 // invalid index @@ -76,12 +76,20 @@ typedef long ssize_t; /* byte count or error */ #define ZIP_EINVZIPNAME -22 // invalid zip archive name #define ZIP_EMKDIR -23 // make dir error #define ZIP_ESYMLINK -24 // symlink error -#define ZIP_ECLSZIP -25 // close the archive error -#define ZIP_ECAPSIZE -26 // capacity size issue +#define ZIP_ECLSZIP -25 // close archive error +#define ZIP_ECAPSIZE -26 // capacity size too small #define ZIP_EFSEEK -27 // fseek error #define ZIP_EFREAD -28 // fread error #define ZIP_EFWRITE -29 // fwrite error +/** + * Looks up the error message string coresponding to an error number. + * @param errnum error number + * @return error message string coresponding to errnum or NULL if error is not + * found. + */ +extern const char *zip_strerror(int errnum); + /** * @struct zip_t * diff --git a/test/test_entry.c b/test/test_entry.c index 9296956..680684e 100644 --- a/test/test_entry.c +++ b/test/test_entry.c @@ -220,17 +220,23 @@ MU_TEST(test_entries_delete) { mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete.me")); mu_assert_int_eq(0, zip_entry_close(zip)); + fprintf(stdout, "delete.me: %s\n", zip_strerror(ZIP_ENOENT)); mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "_")); mu_assert_int_eq(0, zip_entry_close(zip)); + fprintf(stdout, "_: %s\n", zip_strerror(ZIP_ENOENT)); mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.1")); mu_assert_int_eq(0, zip_entry_close(zip)); + fprintf(stdout, "delete/file.1: %s\n", zip_strerror(ZIP_ENOENT)); mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "deleteme/file.3")); mu_assert_int_eq(0, zip_entry_close(zip)); + fprintf(stdout, "delete/file.3: %s\n", zip_strerror(ZIP_ENOENT)); + mu_assert_int_eq(ZIP_ENOENT, zip_entry_open(zip, "delete/file.2")); mu_assert_int_eq(0, zip_entry_close(zip)); + fprintf(stdout, "delete/file.2: %s\n", zip_strerror(ZIP_ENOENT)); mu_assert_int_eq(total_entries - 5, zip_entries_total(zip)); diff --git a/test/test_extract.c b/test/test_extract.c index 749537e..d276397 100644 --- a/test/test_extract.c +++ b/test/test_extract.c @@ -108,6 +108,7 @@ MU_TEST(test_extract_stream) { zip_extract("non_existing_directory/non_existing_archive.zip", ".", NULL, NULL)); mu_assert_int_eq(ZIP_ENOINIT, zip_stream_extract("", 0, ".", NULL, NULL)); + fprintf(stdout, "zip_stream_extract: %s\n", zip_strerror(ZIP_ENOINIT)); FILE *fp = NULL; #if defined(_MSC_VER)