X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgzlibdecompressor.c;h=0f1da62c3e6c83ec2d4bd09dd05bebfc0bc55980;hb=4f775b7b7ff38581b110ce1664451381ca3d88b6;hp=a8e852ff0f2c37f1cc8cba147db57d6f8127b83c;hpb=73007021796f33d7ccec4e5f2bb2b2f8660347f2;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gzlibdecompressor.c b/gio/gzlibdecompressor.c index a8e852f..0f1da62 100644 --- a/gio/gzlibdecompressor.c +++ b/gio/gzlibdecompressor.c @@ -13,9 +13,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: Alexander Larsson */ @@ -28,16 +26,17 @@ #include #include +#include "gfileinfo.h" #include "gioerror.h" #include "gioenums.h" #include "gioenumtypes.h" #include "glibintl.h" -#include "gioalias.h" enum { PROP_0, - PROP_FORMAT + PROP_FORMAT, + PROP_FILE_INFO }; /** @@ -51,6 +50,12 @@ enum { static void g_zlib_decompressor_iface_init (GConverterIface *iface); +typedef struct { + gz_header gzheader; + char filename[257]; + GFileInfo *file_info; +} HeaderData; + /** * GZlibDecompressor: * @@ -62,8 +67,38 @@ struct _GZlibDecompressor GZlibCompressorFormat format; z_stream zstream; + HeaderData *header_data; }; +static void +g_zlib_decompressor_set_gzheader (GZlibDecompressor *decompressor) +{ + /* On win32, these functions were not exported before 1.2.4 */ +#if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240 + if (decompressor->format != G_ZLIB_COMPRESSOR_FORMAT_GZIP) + return; + + if (decompressor->header_data != NULL) + { + if (decompressor->header_data->file_info) + g_object_unref (decompressor->header_data->file_info); + + memset (decompressor->header_data, 0, sizeof (HeaderData)); + } + else + { + decompressor->header_data = g_new0 (HeaderData, 1); + } + + decompressor->header_data->gzheader.name = (Bytef*) &decompressor->header_data->filename; + /* We keep one byte to guarantee the string is 0-terminated */ + decompressor->header_data->gzheader.name_max = 256; + + if (inflateGetHeader (&decompressor->zstream, &decompressor->header_data->gzheader) != Z_OK) + g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg); +#endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */ +} + G_DEFINE_TYPE_WITH_CODE (GZlibDecompressor, g_zlib_decompressor, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER, g_zlib_decompressor_iface_init)) @@ -77,6 +112,13 @@ g_zlib_decompressor_finalize (GObject *object) inflateEnd (&decompressor->zstream); + if (decompressor->header_data != NULL) + { + if (decompressor->header_data->file_info) + g_object_unref (decompressor->header_data->file_info); + g_free (decompressor->header_data); + } + G_OBJECT_CLASS (g_zlib_decompressor_parent_class)->finalize (object); } @@ -120,6 +162,13 @@ g_zlib_decompressor_get_property (GObject *object, g_value_set_enum (value, decompressor->format); break; + case PROP_FILE_INFO: + if (decompressor->header_data) + g_value_set_object (value, decompressor->header_data->file_info); + else + g_value_set_object (value, NULL); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -146,7 +195,7 @@ g_zlib_decompressor_constructed (GObject *object) } else if (decompressor->format == G_ZLIB_COMPRESSOR_FORMAT_RAW) { - /* Negative for gzip */ + /* Negative for raw */ res = inflateInit2 (&decompressor->zstream, -MAX_WBITS); } else /* ZLIB */ @@ -157,6 +206,8 @@ g_zlib_decompressor_constructed (GObject *object) if (res != Z_OK) g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg); + + g_zlib_decompressor_set_gzheader (decompressor); } static void @@ -178,6 +229,25 @@ g_zlib_decompressor_class_init (GZlibDecompressorClass *klass) G_ZLIB_COMPRESSOR_FORMAT_ZLIB, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GZlibDecompressor:file-info: + * + * A #GFileInfo containing the information found in the GZIP header + * of the data stream processed, or %NULL if the header was not yet + * fully processed, is not present at all, or the compressor's + * #GZlibDecompressor:format property is not %G_ZLIB_COMPRESSOR_FORMAT_GZIP. + * + * Since: 2.26 + */ + g_object_class_install_property (gobject_class, + PROP_FILE_INFO, + g_param_spec_object ("file-info", + P_("file info"), + P_("File info"), + G_TYPE_FILE_INFO, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } /** @@ -202,6 +272,31 @@ g_zlib_decompressor_new (GZlibCompressorFormat format) return decompressor; } +/** + * g_zlib_decompressor_get_file_info: + * @decompressor: a #GZlibDecompressor + * + * Retrieves the #GFileInfo constructed from the GZIP header data + * of compressed data processed by @compressor, or %NULL if @decompressor's + * #GZlibDecompressor:format property is not %G_ZLIB_COMPRESSOR_FORMAT_GZIP, + * or the header data was not fully processed yet, or it not present in the + * data stream at all. + * + * Returns: (transfer none): a #GFileInfo, or %NULL + * + * Since: 2.26 + */ +GFileInfo * +g_zlib_decompressor_get_file_info (GZlibDecompressor *decompressor) +{ + g_return_val_if_fail (G_IS_ZLIB_DECOMPRESSOR (decompressor), NULL); + + if (decompressor->header_data) + return decompressor->header_data->file_info; + + return NULL; +} + static void g_zlib_decompressor_reset (GConverter *converter) { @@ -211,6 +306,8 @@ g_zlib_decompressor_reset (GConverter *converter) res = inflateReset (&decompressor->zstream); if (res != Z_OK) g_warning ("unexpected zlib error: %s\n", decompressor->zstream.msg); + + g_zlib_decompressor_set_gzheader (decompressor); } static GConverterResult @@ -272,17 +369,40 @@ g_zlib_decompressor_convert (GConverter *converter, return G_CONVERTER_ERROR; } - if (res == Z_OK || res == Z_STREAM_END) + g_assert (res == Z_OK || res == Z_STREAM_END); + + *bytes_read = inbuf_size - decompressor->zstream.avail_in; + *bytes_written = outbuf_size - decompressor->zstream.avail_out; + +#if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240 + if (decompressor->header_data != NULL && + decompressor->header_data->gzheader.done == 1) { - *bytes_read = inbuf_size - decompressor->zstream.avail_in; - *bytes_written = outbuf_size - decompressor->zstream.avail_out; + HeaderData *data = decompressor->header_data; - if (res == Z_STREAM_END) - return G_CONVERTER_FINISHED; - return G_CONVERTER_CONVERTED; + /* So we don't notify again */ + data->gzheader.done = 2; + + data->file_info = g_file_info_new (); + g_file_info_set_attribute_uint64 (data->file_info, + G_FILE_ATTRIBUTE_TIME_MODIFIED, + data->gzheader.time); + g_file_info_set_attribute_uint32 (data->file_info, + G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, + 0); + + if (data->filename[0] != '\0') + g_file_info_set_attribute_byte_string (data->file_info, + G_FILE_ATTRIBUTE_STANDARD_NAME, + data->filename); + + g_object_notify (G_OBJECT (decompressor), "file-info"); } +#endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */ - g_assert_not_reached (); + if (res == Z_STREAM_END) + return G_CONVERTER_FINISHED; + return G_CONVERTER_CONVERTED; } static void @@ -291,6 +411,3 @@ g_zlib_decompressor_iface_init (GConverterIface *iface) iface->convert = g_zlib_decompressor_convert; iface->reset = g_zlib_decompressor_reset; } - -#define __G_ZLIB_DECOMPRESSOR_C__ -#include "gioaliasdef.c"