[libgsf] Modtime improvements.



commit 225faeb7d61e7dfe6552544add6ad14a38eabff8
Author: Morten Welinder <terra gnome org>
Date:   Mon Mar 4 13:39:08 2013 -0500

    Modtime improvements.
    
    Zip files members can support modtime.

 ChangeLog             |    8 ++++++++
 gsf/gsf-infile-zip.c  |   28 +++++++++++++++++++++++++++-
 gsf/gsf-outfile-zip.c |   32 +++++++++++++++++++++++---------
 gsf/gsf-output-impl.h |    1 +
 gsf/gsf-output.c      |    3 +--
 5 files changed, 60 insertions(+), 12 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8a463c0..4b32348 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2013-03-04  Morten Welinder  <terra gnome org>
 
+       * gsf/gsf-infile-zip.c (gsf_infile_zip_new_child): Set modtime of
+       child.
+       (zip_dirent_new_in): Read modtime from file.
+
+       * gsf/gsf-outfile-zip.c (gsf_outfile_zip_new_child): Parent's
+       modtime is child's default.
+       (gsf_outfile_zip_constructor): Default modtime is now.
+
        * configure.ac: Check for utime.h and sys/utime.h.  Check for
        stat.st_mtimensec and stat.st_mtim.tv_nsec.
 
diff --git a/gsf/gsf-infile-zip.c b/gsf/gsf-infile-zip.c
index 8c8d2a1..d987d89 100644
--- a/gsf/gsf-infile-zip.c
+++ b/gsf/gsf-infile-zip.c
@@ -77,6 +77,26 @@ typedef struct {
 #define GSF_INFILE_ZIP_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST ((k), GSF_INFILE_ZIP_TYPE, GsfInfileZipClass))
 #define GSF_IS_INFILE_ZIP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSF_INFILE_ZIP_TYPE))
 
+
+static GDateTime *
+zip_make_modtime (guint32 dostime)
+{
+       if (dostime == 0)
+               return NULL;
+       else {
+               gint year = (dostime >> 25) + 1980;
+               gint month = (dostime >> 21) & 0x0f;
+               gint day = (dostime >> 16) & 0x1f;
+               gint hour = (dostime >> 11) & 0x0f;
+               gint minute = (dostime >> 5) & 0x3f;
+               gint second = (dostime & 0x1f) * 2;
+               GDateTime *modtime =
+                       g_date_time_new_utc (year, month, day,
+                                            hour, minute, second);
+               return modtime;
+       }
+}
+
 static GsfZipVDir *
 vdir_child_by_name (GsfZipVDir *vdir, char const *name)
 {
@@ -190,7 +210,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
        GsfZipDirent *dirent;
        guint8 const *data;
        guint16 name_len, extras_len, comment_len, compr_method, flags;
-       guint32 crc32, csize, usize, off;
+       guint32 dostime, crc32, csize, usize, off;
        gchar *name;
 
        /* Read data and check the header */
@@ -206,6 +226,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
 
        flags =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_FLAGS);
        compr_method =  GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMPR_METHOD);
+       dostime =       GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_DOSTIME);
        crc32 =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CRC32);
        csize =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_CSIZE);
        usize =         GSF_LE_GET_GUINT32 (data + ZIP_DIRENT_USIZE);
@@ -227,6 +248,7 @@ zip_dirent_new_in (GsfInfileZip *zip, gsf_off_t *offset)
        dirent->csize =         csize;
        dirent->usize =         usize;
        dirent->offset =        off;
+       dirent->dostime =       dostime;
 #if 0
        g_print ("%s = 0x%x @ %" GSF_OFF_T_FORMAT "\n", name, off, *offset);
 #endif
@@ -614,6 +636,10 @@ gsf_infile_zip_new_child (GsfInfileZip *parent, GsfZipVDir *vdir, GError **err)
        if (dirent) {
                gsf_input_set_size (GSF_INPUT (child),
                                    (gsf_off_t) dirent->usize);
+               if (dirent->dostime)
+                       gsf_input_set_modtime (GSF_INPUT (child),
+                                              zip_make_modtime (dirent->dostime));
+
                if (zip_child_init (child, err) != FALSE) {
                        g_object_unref (child);
                        return NULL;
diff --git a/gsf/gsf-outfile-zip.c b/gsf/gsf-outfile-zip.c
index 5d319fb..1067676 100644
--- a/gsf/gsf-outfile-zip.c
+++ b/gsf/gsf-outfile-zip.c
@@ -132,6 +132,10 @@ gsf_outfile_zip_constructor (GType                  type,
                gsf_output_set_container (GSF_OUTPUT (zip), NULL);
        }
 
+       if (!gsf_output_get_modtime (GSF_OUTPUT (zip)))
+               gsf_output_set_modtime (GSF_OUTPUT (zip),
+                                       g_date_time_new_now_utc ());
+
        return (GObject *)zip;
 }
 
@@ -259,17 +263,26 @@ stream_name_build (GsfOutfileZip *zip)
 }
 
 static guint32
-zip_time_make (time_t t)
+zip_time_make (GDateTime *modtime)
 {
-       struct tm *localnow = localtime (&t);
+       gint year, month, day, hour, minute, second;
        guint32 ztime;
 
-       ztime = (localnow->tm_year - 80) & 0x7f;
-       ztime = (ztime << 4) | ((localnow->tm_mon + 1)  & 0x0f);
-       ztime = (ztime << 5) | (localnow->tm_mday & 0x1f);
-       ztime = (ztime << 5) | (localnow->tm_hour & 0x1f);
-       ztime = (ztime << 6) | (localnow->tm_min  & 0x3f);
-       ztime = (ztime << 5) | ((localnow->tm_sec / 2) & 0x1f);
+       g_return_val_if_fail (modtime != NULL, 0);
+
+       g_date_time_get_ymd (modtime, &year, &month, &day);
+       if (year < 1980 || year > 1980 + 0x7f)
+               return 0;
+       hour = g_date_time_get_hour (modtime);
+       minute = g_date_time_get_minute (modtime);
+       second = g_date_time_get_second (modtime);
+
+       ztime = (year - 1980) & 0x7f;
+       ztime = (ztime << 4) | (month  & 0x0f);
+       ztime = (ztime << 5) | (day & 0x1f);
+       ztime = (ztime << 5) | (hour & 0x1f);
+       ztime = (ztime << 6) | (minute & 0x3f);
+       ztime = (ztime << 5) | ((second / 2) & 0x1f);
 
        return ztime;
 }
@@ -289,7 +302,7 @@ zip_dirent_new_out (GsfOutfileZip *zip)
        GsfZipDirent *dirent = gsf_zip_dirent_new ();
        dirent->name = stream_name_build (zip);
        dirent->compr_method = zip->compression_method;
-       dirent->dostime = zip_time_make (time (NULL));
+       dirent->dostime = zip_time_make (gsf_output_get_modtime (GSF_OUTPUT (zip)));
        zip_dirent_update_flags (dirent);
        return dirent;
 }
@@ -581,6 +594,7 @@ gsf_outfile_zip_new_child (GsfOutfile *parent,
                                       &params, &n_params,
                                       "sink", zip_parent->sink,
                                       "entry-name", name,
+                                      "modtime", gsf_output_get_modtime (GSF_OUTPUT (parent)),
                                       NULL);
        gsf_property_settings_collect_valist (GSF_OUTFILE_ZIP_TYPE,
                                              &params, &n_params,
diff --git a/gsf/gsf-output-impl.h b/gsf/gsf-output-impl.h
index 7ef99cc..c3ba763 100644
--- a/gsf/gsf-output-impl.h
+++ b/gsf/gsf-output-impl.h
@@ -30,6 +30,7 @@ G_BEGIN_DECLS
 gboolean gsf_output_set_name     (GsfOutput *output, char const *name);
 gboolean gsf_output_set_name_from_filename (GsfOutput *output, char const *filename);
 gboolean gsf_output_set_container (GsfOutput *output, GsfOutfile *container);
+gboolean gsf_output_set_modtime   (GsfOutput *output, GDateTime *modtime);
 
 G_END_DECLS
 
diff --git a/gsf/gsf-output.c b/gsf/gsf-output.c
index a40d7e5..277284c 100644
--- a/gsf/gsf-output.c
+++ b/gsf/gsf-output.c
@@ -37,7 +37,6 @@
 
 static gsf_off_t gsf_output_real_vprintf (GsfOutput *output,
        char const* format, va_list args) G_GNUC_PRINTF (2, 0);
-static gboolean gsf_output_set_modtime   (GsfOutput *output, GDateTime *modtime);
 
 #define GET_CLASS(instance) G_TYPE_INSTANCE_GET_CLASS (instance, GSF_OUTPUT_TYPE, GsfOutputClass)
 
@@ -603,7 +602,7 @@ gsf_output_get_modtime (GsfOutput *output)
  *
  * Returns: %TRUE if the assignment was ok.
  */
-static gboolean
+gboolean
 gsf_output_set_modtime (GsfOutput *output, GDateTime *modtime)
 {
        g_return_val_if_fail (GSF_IS_OUTPUT (output), FALSE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]