diff -ub libgsf-1.14.12.orig/gsf/gsf-infile-zip.c libgsf-1.14.12/gsf/gsf-infile-zip.c --- libgsf-1.14.12.orig/gsf/gsf-infile-zip.c 2009-04-17 18:27:14.000000000 -0400 +++ libgsf-1.14.12/gsf/gsf-infile-zip.c 2009-05-05 14:13:19.000000000 -0400 @@ -38,6 +38,7 @@ PROP_0, PROP_SOURCE, PROP_COMPRESSION_LEVEL, + PROP_MODTIME, PROP_INTERNAL_PARENT, }; @@ -192,7 +193,7 @@ GsfZipDirent *dirent; guint8 const *data; guint16 name_len, extras_len, comment_len, compr_method; - guint32 crc32, csize, usize, off; + guint32 dostime, crc32, csize, usize, off; gchar *name; /* Read data and check the header */ @@ -207,6 +208,8 @@ comment_len = GSF_LE_GET_GUINT16 (data + ZIP_DIRENT_COMMENT_SIZE); 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); @@ -223,6 +226,7 @@ dirent->name = name; dirent->compr_method = compr_method; + dirent->dostime = dostime; dirent->crc32 = crc32; dirent->csize = csize; dirent->usize = usize; @@ -589,6 +593,28 @@ return FALSE; } +static gint32 +zip_time_translate (guint32 dostime) +{ + struct tm ltime; + time_t now = time (NULL); + + ltime = *localtime (&now); + + ltime.tm_year = (dostime >> 25) + 80; + ltime.tm_mon = ((dostime >> 21) & 0x0f) - 1; + ltime.tm_mday = (dostime >> 16) & 0x1f; + ltime.tm_hour = (dostime >> 11) & 0x0f; + ltime.tm_min = (dostime >> 5) & 0x3f; + ltime.tm_sec = (dostime & 0x1f) << 1; + + ltime.tm_wday = -1; + ltime.tm_yday = -1; + ltime.tm_isdst = -1; + + return (gint32) mktime (<ime); +} + /* GsfInfile class functions */ /*****************************************************************************/ @@ -752,6 +778,12 @@ ? zip->vdir->dirent->compr_method : 0); break; + case PROP_MODTIME: + g_value_set_int (value, + zip->vdir->dirent + ? zip_time_translate(zip->vdir->dirent->dostime) + : 0); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -833,6 +865,16 @@ G_PARAM_READABLE)); g_object_class_install_property (gobject_class, + PROP_MODTIME, + g_param_spec_int ("modification-time", + "Last modification time", + "The last modification time of the file.", + G_MININT, G_MAXINT, + 0, + GSF_PARAM_STATIC | + G_PARAM_READABLE)); + g_object_class_install_property + (gobject_class, PROP_INTERNAL_PARENT, g_param_spec_object ("internal-parent", "", diff -ub libgsf-1.14.12.orig/gsf/gsf-outfile-zip.c libgsf-1.14.12/gsf/gsf-outfile-zip.c --- libgsf-1.14.12.orig/gsf/gsf-outfile-zip.c 2009-04-17 18:27:14.000000000 -0400 +++ libgsf-1.14.12/gsf/gsf-outfile-zip.c 2009-05-05 14:56:09.000000000 -0400 @@ -37,7 +37,8 @@ PROP_0, PROP_SINK, PROP_ENTRY_NAME, - PROP_COMPRESSION_LEVEL + PROP_COMPRESSION_LEVEL, + PROP_MODTIME, }; static GObjectClass *parent_class; @@ -56,6 +57,8 @@ z_stream *stream; GsfZipCompressionMethod compression_method; + time_t modtime; + gboolean writing; guint8 *buf; @@ -281,7 +284,7 @@ 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 (zip->modtime); return dirent; } @@ -611,6 +614,7 @@ zip->root_order = NULL; zip->stream = NULL; zip->compression_method = GSF_ZIP_DEFLATED; + zip->modtime = time (NULL); zip->writing = FALSE; zip->buf = NULL; zip->buf_size = 0; @@ -658,6 +662,9 @@ case PROP_ENTRY_NAME: zip->entry_name = g_strdup (g_value_get_string (value)); break; + case PROP_MODTIME: + zip->modtime = (time_t) g_value_get_int (value); + break; case PROP_COMPRESSION_LEVEL: { int level = g_value_get_int (value); switch (level) { @@ -668,7 +675,6 @@ default: g_warning ("Unsupported compression level %d", level); } - break; } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -723,6 +729,17 @@ GSF_PARAM_STATIC | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property + (gobject_class, + PROP_MODTIME, + g_param_spec_int ("modification-time", + "Last modification time", + "The last modification time of the file.", + G_MININT, G_MAXINT, + 0, + GSF_PARAM_STATIC | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } GSF_CLASS (GsfOutfileZip, gsf_outfile_zip, diff -ub libgsf-1.14.12.orig/gsf/gsf-output-stdio.c libgsf-1.14.12/gsf/gsf-output-stdio.c --- libgsf-1.14.12.orig/gsf/gsf-output-stdio.c 2009-04-17 18:27:14.000000000 -0400 +++ libgsf-1.14.12/gsf/gsf-output-stdio.c 2009-05-05 15:56:12.000000000 -0400 @@ -34,6 +34,7 @@ #endif #include #include +#include #ifdef HAVE_SYS_STATFS_H #include #endif @@ -51,6 +52,11 @@ #define W_OK 2 #endif +enum { + PROP_0, + PROP_MODTIME, +}; + static GObjectClass *parent_class; struct _GsfOutputStdio { @@ -60,6 +66,7 @@ char *real_filename, *temp_filename; gboolean create_backup_copy, keep_open; struct stat st; + time_t modtime; }; typedef struct { @@ -121,6 +128,17 @@ #endif } +static void +set_filetime (char const *filename, time_t modtime) +{ + struct utimbuf ut; + + ut.actime = time (NULL); + ut.modtime = modtime; + + utime (filename, &ut); +} + #define GSF_MAX_LINK_LEVEL 256 /* Calls g_file_read_link() until we find a real filename. */ @@ -279,6 +297,10 @@ } chmod_wrapper (stdio->real_filename, stdio->st.st_mode); #endif + + /* Set the file modification time, if wanted */ + if (stdio->modtime) + set_filetime(stdio->real_filename, stdio->modtime); } g_free (backup_filename); @@ -387,6 +409,43 @@ stdio->file = NULL; stdio->create_backup_copy = FALSE; stdio->keep_open = FALSE; + stdio->modtime = (time_t) 0; +} + +static void +gsf_output_stdio_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GsfOutputStdio *stdio = (GsfOutputStdio *)object; + + switch (property_id) { + case PROP_MODTIME: + g_value_set_int (value, stdio->modtime); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gsf_output_stdio_set_property (GObject *object, + guint property_id, + GValue const *value, + GParamSpec *pspec) +{ + GsfOutputStdio *stdio = (GsfOutputStdio *)object; + + switch (property_id) { + case PROP_MODTIME: + stdio->modtime = (time_t) g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } } static void @@ -395,11 +454,24 @@ GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class); gobject_class->finalize = gsf_output_stdio_finalize; + gobject_class->get_property = gsf_output_stdio_get_property; + gobject_class->set_property = gsf_output_stdio_set_property; output_class->Close = gsf_output_stdio_close; output_class->Seek = gsf_output_stdio_seek; output_class->Write = gsf_output_stdio_write; output_class->Vprintf = gsf_output_stdio_vprintf; + g_object_class_install_property + (gobject_class, + PROP_MODTIME, + g_param_spec_int ("modification-time", + "Last modification time", + "The last modification time of the file.", + G_MININT, G_MAXINT, + 0, + GSF_PARAM_STATIC | + G_PARAM_READWRITE)); + parent_class = g_type_class_peek_parent (gobject_class); }