mirror of
https://github.com/QuasarApp/zip.git
synced 2025-04-29 13:54:35 +00:00
Set mtime (#76)
This commit is contained in:
parent
b514b7d3b0
commit
51a1be4517
45
src/miniz.h
45
src/miniz.h
@ -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)
|
||||||
|
32
src/zip.c
32
src/zip.c
@ -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"))
|
||||||
|
62
test/test.c
62
test/test.c
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user