[libgsf] zip: improve timestamps in zip.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgsf] zip: improve timestamps in zip.
- Date: Sat, 29 Nov 2014 00:08:40 +0000 (UTC)
commit 08574918704ad7a7fb6b44c2825bee6ac1bc736d
Author: Morten Welinder <terra gnome org>
Date: Fri Nov 28 18:32:43 2014 -0500
zip: improve timestamps in zip.
ChangeLog | 5 ++++
NEWS | 1 +
gsf/gsf-outfile-zip.c | 54 +++++++++++++++++++++++++++++++++++++++----------
gsf/gsf-zip-impl.h | 1 +
4 files changed, 50 insertions(+), 11 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6507bd4..cb3c3d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-28 Morten Welinder <terra gnome org>
+
+ * gsf/gsf-outfile-zip.c (zip_dirent_new_out): Store mtime in zip
+ files, as long as they fit.
+
2014-11-27 Morten Welinder <terra gnome org>
* gsf/gsf-input.c (gsf_input_copy): Minor cleanups.
diff --git a/NEWS b/NEWS
index 01f577d..5dff056 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ Morten:
* Fix various issues with files larger than 4G.
* Fix minor zip file issues.
* Write zip archives with more than 64k+ members.
+ * Store unix modtime in zip. (Until that overflows.)
--------------------------------------------------------------------------
libgsf 1.14.30
diff --git a/gsf/gsf-outfile-zip.c b/gsf/gsf-outfile-zip.c
index 345fecd..6e843b8 100644
--- a/gsf/gsf-outfile-zip.c
+++ b/gsf/gsf-outfile-zip.c
@@ -187,6 +187,18 @@ zip_dirent_write (GsfOutput *sink, GsfZipDirent *dirent)
}
}
+ if (dirent->mtime && dirent->mtime <= G_MAXUINT32) {
+ /* Clearly a year 2038 problem here. */
+ char tmp[4];
+ GSF_LE_SET_GUINT16 (tmp, ZIP_DIRENT_EXTRA_FIELD_UNIXTIME);
+ GSF_LE_SET_GUINT16 (tmp + 2, 5);
+ g_string_append_len (extras, tmp, 4);
+ tmp[0] = 1;
+ g_string_append_len (extras, tmp, 1);
+ GSF_LE_SET_GUINT32 (tmp, dirent->mtime);
+ g_string_append_len (extras, tmp, 4);
+ }
+
memset (buf, 0, sizeof buf);
GSF_LE_SET_GUINT32 (buf, ZIP_DIRENT_SIGNATURE);
GSF_LE_SET_GUINT16 (buf + ZIP_DIRENT_ENCODER,
@@ -371,11 +383,6 @@ zip_time_make (GDateTime *modtime)
gint year, month, day, hour, minute, second;
guint32 ztime;
- if (!modtime)
- modtime = g_date_time_new_now_utc ();
- else
- g_date_time_ref (modtime);
-
g_date_time_get_ymd (modtime, &year, &month, &day);
hour = g_date_time_get_hour (modtime);
minute = g_date_time_get_minute (modtime);
@@ -392,8 +399,6 @@ zip_time_make (GDateTime *modtime)
ztime = (ztime << 5) | ((second / 2) & 0x1f);
}
- g_date_time_unref (modtime);
-
return ztime;
}
@@ -414,11 +419,26 @@ zip_dirent_new_out (GsfOutfileZip *zip)
*/
if (strlen (name) < G_MAXUINT16) {
GsfZipDirent *dirent = gsf_zip_dirent_new ();
+ GDateTime *modtime = gsf_output_get_modtime (GSF_OUTPUT (zip));
+ gint64 mtime64;
+
dirent->name = name;
dirent->compr_method = zip->compression_method;
- dirent->dostime = zip_time_make (gsf_output_get_modtime (GSF_OUTPUT (zip)));
+
+ if (!modtime)
+ modtime = g_date_time_new_now_utc ();
+ else
+ g_date_time_ref (modtime);
+ dirent->dostime = zip_time_make (modtime);
+ mtime64 = g_date_time_to_unix (modtime);
+ if (mtime64 == (gint64)(time_t)mtime64)
+ dirent->mtime = (time_t)mtime64;
+
dirent->zip64 = zip->zip64;
zip_dirent_update_flags (dirent);
+
+ g_date_time_unref (modtime);
+
return dirent;
} else
return NULL;
@@ -437,13 +457,13 @@ zip_header_write (GsfOutfileZip *zip)
gsf_off_t csize = has_ddesc ? 0 : dirent->csize;
gsf_off_t usize = has_ddesc ? 0 : dirent->usize;
GString *extras = g_string_sized_new (ZIP_HEADER_SIZE + nlen + 100);
- gboolean real_extra_field =
+ gboolean real_zip64 =
(dirent->zip64 == TRUE ||
(dirent->zip64 == -1 &&
(dirent->usize >= G_MAXUINT32 ||
dirent->csize >= G_MAXUINT32 ||
dirent->offset >= G_MAXUINT32)));
- const guint8 extract = real_extra_field ? 45 : 23;
+ const guint8 extract = real_zip64 ? 45 : 23;
/*
* In the has_ddesc case, we write crc32/size/usize as zero and store
@@ -457,7 +477,7 @@ zip_header_write (GsfOutfileZip *zip)
if (dirent->zip64) {
char tmp[8];
- guint16 typ = real_extra_field
+ guint16 typ = real_zip64
? ZIP_DIRENT_EXTRA_FIELD_ZIP64
: ZIP_DIRENT_EXTRA_FIELD_IGNORE;
@@ -470,6 +490,18 @@ zip_header_write (GsfOutfileZip *zip)
g_string_append_len (extras, tmp, 8);
}
+ if (dirent->mtime && dirent->mtime <= G_MAXUINT32) {
+ /* Clearly a year 2038 problem here. */
+ char tmp[4];
+ GSF_LE_SET_GUINT16 (tmp, ZIP_DIRENT_EXTRA_FIELD_UNIXTIME);
+ GSF_LE_SET_GUINT16 (tmp + 2, 5);
+ g_string_append_len (extras, tmp, 4);
+ tmp[0] = 1;
+ g_string_append_len (extras, tmp, 1);
+ GSF_LE_SET_GUINT32 (tmp, dirent->mtime);
+ g_string_append_len (extras, tmp, 4);
+ }
+
memset (hbuf, 0, sizeof hbuf);
GSF_LE_SET_GUINT32 (hbuf, ZIP_HEADER_SIGNATURE);
GSF_LE_SET_GUINT16 (hbuf + ZIP_HEADER_EXTRACT,
diff --git a/gsf/gsf-zip-impl.h b/gsf/gsf-zip-impl.h
index 8202086..2f371d4 100644
--- a/gsf/gsf-zip-impl.h
+++ b/gsf/gsf-zip-impl.h
@@ -144,6 +144,7 @@ typedef struct {
gsf_off_t offset;
gsf_off_t data_offset;
guint32 dostime;
+ time_t mtime;
guint8 zip64; /* -1 = auto, FALSE, TRUE. */
} GsfZipDirent;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]