Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/miniz
diff options
context:
space:
mode:
authorVojtech Bubnik <bubnikv@gmail.com>2021-01-26 11:29:24 +0300
committerVojtech Bubnik <bubnikv@gmail.com>2021-01-26 11:29:34 +0300
commit500c667d7abadab88aa6c127d6cae934c7ddfb1b (patch)
tree66a9cc1ab836a7877b7271c0c1b23c29fa9ef980 /src/miniz
parent4620402ab44af3547ddc2f9ebbeb579261df0cef (diff)
Extended miniz with https://github.com/richgel999/miniz/pull/147
to support writing a file from a callback without knowing the file size up front. See comments in src/miniz/README-Prusa.txt for potential pitfalls.
Diffstat (limited to 'src/miniz')
-rw-r--r--src/miniz/README-Prusa.txt27
-rw-r--r--src/miniz/miniz.c52
-rw-r--r--src/miniz/miniz.h2
3 files changed, 59 insertions, 22 deletions
diff --git a/src/miniz/README-Prusa.txt b/src/miniz/README-Prusa.txt
new file mode 100644
index 000000000..7ed99c534
--- /dev/null
+++ b/src/miniz/README-Prusa.txt
@@ -0,0 +1,27 @@
+This library is based on miniz 2.1.0 - amalgamated version.
+
+----------------------------------------------------------------
+
+Merged with https://github.com/richgel999/miniz/pull/147
+to support writing a zipped file using a callback without
+knowing the size of the file up front.
+
+Vojtech made the following comments to the pull request above:
+
+The pull request looks good to me in general. We need such a functionality at https://github.com/prusa3d/PrusaSlicer so we are going to merge it into our project. Namely, we are exporting potentially huge model files, which are XML encoded, thus the compression ration is quite high and keeping the XML encoded model file in memory is not really practical.
+
+I am a bit uneasy about two things though:
+
+mz_zip_writer_create_zip64_extra_data() call at the start of the file block stores uncompressed and compressed size. Naturally the uncompressed size will be over estimated, while the compressed size will be zero (as it was before). I suppose it does not make any difference, as usually the decompressors do not read this block, but they rely on the copy of this block in the central directory at the end of the ZIP file. I used https://en.wikipedia.org/wiki/ZIP_(file_format) as a source and there is no definition of the ZIP64 extra data block, though the "Data descriptor" section says:
+If the bit at offset 3 (0x08) of the general-purpose flags field is set, then the CRC-32 and file sizes are not known when the header is written. The fields in the local header are filled with zero, and the CRC-32 and size are appended in a 12-byte structure (optionally preceded by a 4-byte signature) immediately after the compressed data:
+
+Thus I suppose it is all right if the file size at the start of the file block is not correct.
+
+There are weird conditions in the original code as if (uncomp_size <= 3), if (uncomp_size == 0). I am not quite sure what will happen if one called your modified mz_zip_writer_add_read_buf_callback() with maximum size >= 4, but the callback provided less than 4 bytes. This is not a problem in our application, but in general it could be an issue.
+
+Is it an issue if the maximum size mandates a 64bit format, while the callback provides less than 4GB of data? I suppose there will only be a tiny bit of performance and file size penalty, but the code will work and the exported ZIP file will be valid.
+
+Are you using your modification in a production code? How well is your modification tested?
+
+----------------------------------------------------------------
+
diff --git a/src/miniz/miniz.c b/src/miniz/miniz.c
index 9ded4c75a..66afb94c2 100644
--- a/src/miniz/miniz.c
+++ b/src/miniz/miniz.c
@@ -6370,13 +6370,13 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
return MZ_TRUE;
}
-mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
+mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
{
mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
- mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
+ mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
size_t archive_name_size;
mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
mz_uint8 *pExtra_data = NULL;
@@ -6398,7 +6398,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
pState = pZip->m_pState;
- if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
+ if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX))
{
/* Source file is too large for non-zip64 */
/*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
@@ -6455,7 +6455,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
}
#endif
- if (uncomp_size <= 3)
+ if (max_size <= 3)
level = 0;
if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
@@ -6471,7 +6471,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
}
- if (uncomp_size && level)
+ if (max_size && level)
{
method = MZ_DEFLATED;
}
@@ -6479,11 +6479,11 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
MZ_CLEAR_OBJ(local_dir_header);
if (pState->m_zip64)
{
- if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
+ if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
{
pExtra_data = extra_data;
- extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
- (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
+ extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
+ (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
}
if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
@@ -6534,9 +6534,8 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
cur_archive_file_ofs += user_extra_data_len;
}
- if (uncomp_size)
+ if (max_size)
{
- mz_uint64 uncomp_remaining = uncomp_size;
void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
if (!pRead_buf)
{
@@ -6545,19 +6544,27 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
if (!level)
{
- while (uncomp_remaining)
+ while (1)
{
- mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
- if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
+ size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
+ if (n == 0)
+ break;
+
+ if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
{
pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
}
- file_ofs += n;
+ if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)
+ {
+ pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
+ return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
+ }
+ file_ofs += n;
uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
- uncomp_remaining -= n;
cur_archive_file_ofs += n;
}
+ uncomp_size = file_ofs;
comp_size = uncomp_size;
}
else
@@ -6584,24 +6591,26 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
for (;;)
{
- size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
tdefl_status status;
tdefl_flush flush = TDEFL_NO_FLUSH;
- if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
+ size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
+ if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
{
mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
break;
}
- file_ofs += in_buf_size;
- uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
- uncomp_remaining -= in_buf_size;
+ file_ofs += n;
+ uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
flush = TDEFL_FULL_FLUSH;
- status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
+ if (n == 0)
+ flush = TDEFL_FINISH;
+
+ status = tdefl_compress_buffer(pComp, pRead_buf, n, flush);
if (status == TDEFL_STATUS_DONE)
{
result = MZ_TRUE;
@@ -6622,6 +6631,7 @@ mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pA
return MZ_FALSE;
}
+ uncomp_size = file_ofs;
comp_size = state.m_comp_size;
cur_archive_file_ofs = state.m_cur_archive_file_ofs;
}
diff --git a/src/miniz/miniz.h b/src/miniz/miniz.h
index 7db62811e..63e526787 100644
--- a/src/miniz/miniz.h
+++ b/src/miniz/miniz.h
@@ -1282,7 +1282,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n
/* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */
/* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/
-mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add,
+mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size,
const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len,
const char *user_extra_data_central, mz_uint user_extra_data_central_len);