Set mtime (#76)

This commit is contained in:
Kuba Podgórski 2018-09-30 13:45:35 +02:00 committed by GitHub
parent b514b7d3b0
commit 51a1be4517
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 160 additions and 119 deletions

View File

@ -4306,7 +4306,8 @@ static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) {
return mktime(&tm); return mktime(&tm);
} }
static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
static void mz_zip_time_t_to_dos_time(time_t time, mz_uint16 *pDOS_time,
mz_uint16 *pDOS_date) { mz_uint16 *pDOS_date) {
#ifdef _MSC_VER #ifdef _MSC_VER
struct tm tm_struct; struct tm tm_struct;
@ -4319,42 +4320,44 @@ static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time,
} }
#else #else
struct tm *tm = localtime(&time); struct tm *tm = localtime(&time);
#endif #endif /* #ifdef _MSC_VER */
*pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
((tm->tm_sec) >> 1)); ((tm->tm_sec) >> 1));
*pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
((tm->tm_mon + 1) << 5) + tm->tm_mday); ((tm->tm_mon + 1) << 5) + tm->tm_mday);
} }
#endif #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
#ifndef MINIZ_NO_STDIO #ifndef MINIZ_NO_STDIO
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
static mz_bool mz_zip_get_file_modified_time(const char *pFilename, static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
mz_uint16 *pDOS_time, time_t *pTime) {
mz_uint16 *pDOS_date) {
#ifdef MINIZ_NO_TIME
(void)pFilename;
*pDOS_date = *pDOS_time = 0;
#else
struct MZ_FILE_STAT_STRUCT file_stat; struct MZ_FILE_STAT_STRUCT file_stat;
// On Linux with x86 glibc, this call will fail on large files (>= 0x80000000
// bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. /* On Linux with x86 glibc, this call will fail on large files (I think >=
* 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
if (MZ_FILE_STAT(pFilename, &file_stat) != 0) if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
return MZ_FALSE; return MZ_FALSE;
mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date);
#endif // #ifdef MINIZ_NO_TIME *pTime = file_stat.st_mtime;
return MZ_TRUE; return MZ_TRUE;
} }
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
#ifndef MINIZ_NO_TIME
static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time,
time_t modified_time) { time_t modified_time) {
struct utimbuf t; struct utimbuf t;
memset(&t, 0, sizeof(t));
t.actime = access_time; t.actime = access_time;
t.modtime = modified_time; t.modtime = modified_time;
return !utime(pFilename, &t); return !utime(pFilename, &t);
} }
#endif // #ifndef MINIZ_NO_TIME #endif /* #ifndef MINIZ_NO_STDIO */
#endif // #ifndef MINIZ_NO_STDIO #endif /* #ifndef MINIZ_NO_TIME */
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
mz_uint32 flags) { mz_uint32 flags) {
@ -5354,8 +5357,9 @@ mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
if (MZ_FCLOSE(pFile) == EOF) if (MZ_FCLOSE(pFile) == EOF)
return MZ_FALSE; return MZ_FALSE;
#ifndef MINIZ_NO_TIME #ifndef MINIZ_NO_TIME
if (status) if (status) {
mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
}
#endif #endif
return status; return status;
@ -5795,7 +5799,7 @@ mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
{ {
time_t cur_time; time_t cur_time;
time(&cur_time); time(&cur_time);
mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
} }
#endif // #ifndef MINIZ_NO_TIME #endif // #ifndef MINIZ_NO_TIME
@ -5938,6 +5942,7 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
mz_uint32 ext_attributes) { mz_uint32 ext_attributes) {
mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
mz_uint16 method = 0, dos_time = 0, dos_date = 0; mz_uint16 method = 0, dos_time = 0, dos_date = 0;
time_t file_modified_time;
mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0, mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0,
comp_size = 0; comp_size = 0;
size_t archive_name_size; size_t archive_name_size;
@ -5974,8 +5979,10 @@ mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
comment_size + archive_name_size) > 0xFFFFFFFF)) comment_size + archive_name_size) > 0xFFFFFFFF))
return MZ_FALSE; return MZ_FALSE;
if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) memset(&file_modified_time, 0, sizeof(file_modified_time));
if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
return MZ_FALSE; return MZ_FALSE;
mz_zip_time_t_to_dos_time(file_modified_time, &dos_time, &dos_date);
pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
if (!pSrc_file) if (!pSrc_file)

View File

@ -121,6 +121,7 @@ struct zip_entry_t {
mz_zip_writer_add_state state; mz_zip_writer_add_state state;
tdefl_compressor comp; tdefl_compressor comp;
mz_uint32 external_attr; mz_uint32 external_attr;
time_t m_time;
}; };
struct zip_t { struct zip_t {
@ -249,6 +250,7 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
zip->entry.header_offset = stats.m_local_header_ofs; zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method; zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr; zip->entry.external_attr = stats.m_external_attr;
zip->entry.m_time = stats.m_time;
return 0; return 0;
} }
@ -319,6 +321,8 @@ int zip_entry_open(struct zip_t *zip, const char *entryname) {
} }
} }
zip->entry.m_time = time(NULL);
return 0; return 0;
cleanup: cleanup:
@ -389,6 +393,7 @@ int zip_entry_openbyindex(struct zip_t *zip, int index) {
zip->entry.header_offset = stats.m_local_header_ofs; zip->entry.header_offset = stats.m_local_header_ofs;
zip->entry.method = stats.m_method; zip->entry.method = stats.m_method;
zip->entry.external_attr = stats.m_external_attr; zip->entry.external_attr = stats.m_external_attr;
zip->entry.m_time = stats.m_time;
return 0; return 0;
} }
@ -398,17 +403,9 @@ int zip_entry_close(struct zip_t *zip) {
mz_uint level; mz_uint level;
tdefl_status done; tdefl_status done;
mz_uint16 entrylen; mz_uint16 entrylen;
time_t t;
mz_uint16 dos_time, dos_date; mz_uint16 dos_time, dos_date;
int status = -1; int status = -1;
#if defined(_MSC_VER) || defined(_WIN32) || defined(__WIN32__) || \
defined(__MINGW32__)
struct tm tmb, *tm = (struct tm *)&tmb;
#else
struct tm *tm;
#endif
if (!zip) { if (!zip) {
// zip_t handler is not initialized // zip_t handler is not initialized
goto cleanup; goto cleanup;
@ -433,28 +430,13 @@ int zip_entry_close(struct zip_t *zip) {
} }
entrylen = (mz_uint16)strlen(zip->entry.name); entrylen = (mz_uint16)strlen(zip->entry.name);
t = time(NULL);
#ifdef __STDC_LIB_EXT1__
tm = localtime_s(&t, tm);
#else
tm = localtime(&t);
#endif
if (!tm) {
goto cleanup;
}
dos_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
((tm->tm_sec) >> 1));
dos_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
((tm->tm_mon + 1) << 5) + tm->tm_mday);
// no zip64 support yet // no zip64 support yet
if ((zip->entry.comp_size > 0xFFFFFFFF) || (zip->entry.offset > 0xFFFFFFFF)) { if ((zip->entry.comp_size > 0xFFFFFFFF) || (zip->entry.offset > 0xFFFFFFFF)) {
// No zip64 support, yet // No zip64 support, yet
goto cleanup; goto cleanup;
} }
mz_zip_time_t_to_dos_time(zip->entry.m_time, &dos_time, &dos_date);
if (!mz_zip_writer_create_local_dir_header( if (!mz_zip_writer_create_local_dir_header(
pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size, pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size,
zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0, zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0,
@ -485,6 +467,7 @@ int zip_entry_close(struct zip_t *zip) {
cleanup: cleanup:
if (zip) { if (zip) {
zip->entry.m_time = 0;
CLEANUP(zip->entry.name); CLEANUP(zip->entry.name);
} }
return status; return status;
@ -592,6 +575,7 @@ int zip_entry_fwrite(struct zip_t *zip, const char *filename) {
zip->entry.external_attr |= 0x01; zip->entry.external_attr |= 0x01;
} }
zip->entry.external_attr |= (mz_uint32)((file_stat.st_mode & 0xFFFF) << 16); zip->entry.external_attr |= (mz_uint32)((file_stat.st_mode & 0xFFFF) << 16);
zip->entry.m_time = file_stat.st_mtime;
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
if (fopen_s(&stream, filename, "rb")) if (fopen_s(&stream, filename, "rb"))

View File

@ -6,6 +6,14 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__)
#define MZ_FILE_STAT_STRUCT _stat
#define MZ_FILE_STAT _stat
#else
#define MZ_FILE_STAT_STRUCT stat
#define MZ_FILE_STAT stat
#endif
#define ZIPNAME "test.zip\0" #define ZIPNAME "test.zip\0"
#define TESTDATA1 "Some test data 1...\0" #define TESTDATA1 "Some test data 1...\0"
#define CRC32DATA1 2220805626 #define CRC32DATA1 2220805626
@ -301,7 +309,7 @@ static void test_fwrite(void) {
static void test_exe_permissions(void) { static void test_exe_permissions(void) {
#if defined(_WIN32) || defined(__WIN32__) #if defined(_WIN32) || defined(__WIN32__)
#else #else
struct stat file_stats; struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {XFILE}; const char *filenames[] = {XFILE};
FILE *f = fopen(XFILE, "w"); FILE *f = fopen(XFILE, "w");
fclose(f); fclose(f);
@ -315,7 +323,7 @@ static void test_exe_permissions(void) {
assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
assert(0 == stat(XFILE, &file_stats)); assert(0 == MZ_FILE_STAT(XFILE, &file_stats));
assert(XMODE == file_stats.st_mode); assert(XMODE == file_stats.st_mode);
remove(XFILE); remove(XFILE);
@ -327,7 +335,7 @@ static void test_read_permissions(void) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
#else #else
struct stat file_stats; struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {RFILE}; const char *filenames[] = {RFILE};
FILE *f = fopen(RFILE, "w"); FILE *f = fopen(RFILE, "w");
fclose(f); fclose(f);
@ -343,7 +351,7 @@ static void test_read_permissions(void) {
assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
assert(0 == stat(RFILE, &file_stats)); assert(0 == MZ_FILE_STAT(RFILE, &file_stats));
assert(RMODE == file_stats.st_mode); assert(RMODE == file_stats.st_mode);
chmod(RFILE, WMODE); chmod(RFILE, WMODE);
@ -356,7 +364,7 @@ static void test_write_permissions(void) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
#else #else
struct stat file_stats; struct MZ_FILE_STAT_STRUCT file_stats;
const char *filenames[] = {WFILE}; const char *filenames[] = {WFILE};
FILE *f = fopen(WFILE, "w"); FILE *f = fopen(WFILE, "w");
fclose(f); fclose(f);
@ -370,7 +378,7 @@ static void test_write_permissions(void) {
assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL)); assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
assert(0 == stat(WFILE, &file_stats)); assert(0 == MZ_FILE_STAT(WFILE, &file_stats));
assert(WMODE == file_stats.st_mode); assert(WMODE == file_stats.st_mode);
remove(WFILE); remove(WFILE);
@ -378,6 +386,47 @@ static void test_write_permissions(void) {
#endif #endif
} }
static void test_mtime(void) {
struct MZ_FILE_STAT_STRUCT file_stat1, file_stat2;
const char *filename = WFILE;
FILE *stream = NULL;
struct zip_t *zip = NULL;
#if defined(_MSC_VER)
if (0 != fopen_s(&stream, filename, "w+"))
#else
if (!(stream = fopen(filename, "w+")))
#endif
{
// Cannot open filename
fprintf(stdout, "Cannot open filename\n");
assert(0 == -1);
}
fwrite(TESTDATA1, sizeof(char), strlen(TESTDATA1), stream);
assert(0 == fclose(stream));
memset(&file_stat1, 0, sizeof(file_stat1));
memset(&file_stat2, 0, sizeof(file_stat2));
zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w');
assert(zip != NULL);
assert(0 == zip_entry_open(zip, filename));
assert(0 == zip_entry_fwrite(zip, filename));
assert(0 == zip_entry_close(zip));
zip_close(zip);
assert(0 == MZ_FILE_STAT(filename, &file_stat1));
remove(filename);
assert(0 == zip_extract(ZIPNAME, ".", NULL, NULL));
assert(0 == MZ_FILE_STAT(filename, &file_stat2));
fprintf(stdout, "file_stat1.st_mtime: %lu\n", file_stat1.st_mtime);
fprintf(stdout, "file_stat2.st_mtime: %lu\n", file_stat2.st_mtime);
assert(labs(file_stat1.st_mtime - file_stat2.st_mtime) <= 1);
remove(filename);
remove(ZIPNAME);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
UNUSED(argc); UNUSED(argc);
UNUSED(argv); UNUSED(argv);
@ -397,6 +446,7 @@ int main(int argc, char *argv[]) {
test_read_permissions(); test_read_permissions();
test_write_permissions(); test_write_permissions();
test_exe_permissions(); test_exe_permissions();
test_mtime();
remove(ZIPNAME); remove(ZIPNAME);
return 0; return 0;