Avoid fdreopen if possible

Avoid using fdropen in mz_zip_add_mem_to_archive_file_in_place or
if new flag MZ_ZIP_FLAG_READ_ALLOW_WRITING is set.

This improves performance, but also fdreopen is broken on Android
(some kind of race).
This commit is contained in:
Martin 2024-10-16 23:07:17 +02:00
parent 1ff82be7d6
commit 11e7c39508
3 changed files with 33 additions and 5 deletions

View File

@ -1102,7 +1102,7 @@ static int mz_stat64(const char *path, struct __stat64 *buffer)
if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
pFile = MZ_FOPEN(pFilename, "rb"); pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_READ_ALLOW_WRITING ) ? "r+b" : "rb");
if (!pFile) if (!pFile)
return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED); return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
@ -3024,7 +3024,8 @@ static int mz_stat64(const char *path, struct __stat64 *buffer)
if (pZip->m_pIO_opaque != pZip) if (pZip->m_pIO_opaque != pZip)
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE &&
!(flags & MZ_ZIP_FLAG_READ_ALLOW_WRITING) )
{ {
if (!pFilename) if (!pFilename)
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER); return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
@ -4568,14 +4569,14 @@ static int mz_stat64(const char *path, struct __stat64 *buffer)
else else
{ {
/* Append to an existing archive. */ /* Append to an existing archive. */
if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY | MZ_ZIP_FLAG_READ_ALLOW_WRITING, 0, 0))
{ {
if (pErr) if (pErr)
*pErr = zip_archive.m_last_error; *pErr = zip_archive.m_last_error;
return MZ_FALSE; return MZ_FALSE;
} }
if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags)) if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_READ_ALLOW_WRITING))
{ {
if (pErr) if (pErr)
*pErr = zip_archive.m_last_error; *pErr = zip_archive.m_last_error;

View File

@ -104,7 +104,8 @@ extern "C"
MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000, MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000,
/*After adding a compressed file, seek back /*After adding a compressed file, seek back
to local file header and set the correct sizes*/ to local file header and set the correct sizes*/
MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000 MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000,
MZ_ZIP_FLAG_READ_ALLOW_WRITING = 0x40000
} mz_zip_flags; } mz_zip_flags;
typedef enum typedef enum

View File

@ -51,6 +51,32 @@ TEST_CASE("Zip writer tests")
REQUIRE(content_view.size() == 3); REQUIRE(content_view.size() == 3);
free(content); free(content);
mz_zip_reader_end(&zip_archive);
}
SECTION("Test repeated file addition to zip")
{
mz_zip_archive zip_archive = {};
auto b = mz_zip_writer_init_file(&zip_archive, "test2.zip", 0);
REQUIRE(b);
b = mz_zip_writer_finalize_archive(&zip_archive);
REQUIRE(b);
b = mz_zip_writer_end(&zip_archive);
REQUIRE(b);
for (int i = 0; i < 50; i++)
{
const char *str = "hello world";
b = mz_zip_add_mem_to_archive_file_in_place(
std::string("test2.zip").c_str(), ("file1.txt" + std::to_string(i)).c_str(),
str, (mz_uint16)strlen(str),
NULL, 0,
MZ_BEST_COMPRESSION);
REQUIRE(b);
}
} }
} }