#endif
#include "compression.h"
+#include "string.h"
#include <gio/gio.h>
#include <glib/gstdio.h>
goto end;
#else
gchar *zip_data;
+ // See http://en.wikipedia.org/wiki/Zip_(file_format)
struct _lfh {
guint32 sig;
guint16 extract_version;
guint32 uncompressed_size;
guint16 filename_len;
guint16 extra_field_len;
- } __attribute__ ((__packed__)) *local_file_header = NULL;
+ } __attribute__ ((gcc_struct,__packed__)) *local_file_header = NULL;
+ if ( sizeof(struct _lfh) != 30 ) {
+ g_critical ("Incorrect internal zip header size, should be 30 but is %zd", sizeof(struct _lfh) );
+ goto end;
+ }
local_file_header = (struct _lfh *) zip_file;
if (GUINT32_FROM_LE(local_file_header->sig) != 0x04034b50) {
- g_warning("%s(): wrong format", __PRETTY_FUNCTION__);
+ g_warning("%s(): wrong format (%d)", __PRETTY_FUNCTION__, GUINT32_FROM_LE(local_file_header->sig));
g_free(unzip_data);
goto end;
}
gulong uncompressed_size = GUINT32_FROM_LE(local_file_header->uncompressed_size);
unzip_data = g_malloc(uncompressed_size);
+ // Protection against malloc failures
+ // ATM not normally been checking malloc failures in Viking but sometimes using zip files can be quite large
+ // (e.g. when using DEMs) so more potential for failure.
+ if ( !unzip_data )
+ goto end;
+
+ g_debug ("%s: method %d: from size %d to %ld", __FUNCTION__, GUINT16_FROM_LE(local_file_header->comp_method), GUINT32_FROM_LE(local_file_header->compressed_size), uncompressed_size);
+
+ if ( GUINT16_FROM_LE(local_file_header->comp_method) == 0 &&
+ (uncompressed_size == GUINT32_FROM_LE(local_file_header->compressed_size)) ) {
+ // Stored only - no need to 'uncompress'
+ // Thus just copy
+ memcpy ( unzip_data, zip_data, uncompressed_size );
+ *unzip_size = uncompressed_size;
+ goto end;
+ }
+
if (!(*unzip_size = uncompress_data(unzip_data, uncompressed_size, zip_data, GUINT32_FROM_LE(local_file_header->compressed_size)))) {
g_free(unzip_data);
unzip_data = NULL;
gchar* uncompress_bzip2 ( gchar *name )
{
#ifdef HAVE_BZLIB_H
- FILE *ff = g_fopen ( name, "r" );
+ g_debug ( "%s: bzip2 %s", __FUNCTION__, BZ2_bzlibVersion() );
+
+ FILE *ff = g_fopen ( name, "rb" );
if ( !ff )
return NULL;
if ( bzerror != BZ_OK ) {
BZ2_bzReadClose ( &bzerror, bf );
// handle error
+ g_warning ( "%s: BZ ReadOpen error on %s", __FUNCTION__, name );
return NULL;
}
GFileIOStream *gios;
GError *error = NULL;
+ gchar *tmpname = NULL;
+#if GLIB_CHECK_VERSION(2,32,0)
GFile *gf = g_file_new_tmp ( "vik-bz2-tmp.XXXXXX", &gios, &error );
- gchar *tmpname = g_file_get_path (gf);
+ tmpname = g_file_get_path (gf);
+#else
+ gint fd = g_file_open_tmp ( "vik-bz2-tmp.XXXXXX", &tmpname, &error );
+ if ( error ) {
+ g_warning ( error->message );
+ g_error_free ( error );
+ return NULL;
+ }
+ gios = g_file_open_readwrite ( g_file_new_for_path (tmpname), NULL, &error );
+ if ( error ) {
+ g_warning ( error->message );
+ g_error_free ( error );
+ return NULL;
+ }
+#endif
GOutputStream *gos = g_io_stream_get_output_stream ( G_IO_STREAM(gios) );
// Process in arbitary sized chunks
char buf[4096];
bzerror = BZ_OK;
- int nBuf;
+ int nBuf = 0;
// Now process the actual compression data
while ( bzerror == BZ_OK ) {
nBuf = BZ2_bzRead ( &bzerror, bf, buf, 4096 );
}
}
if ( bzerror != BZ_STREAM_END ) {
- BZ2_bzReadClose ( &bzerror, bf );
// handle error...
- goto end;
- } else {
- BZ2_bzReadClose ( &bzerror, bf );
- g_output_stream_close ( gos, NULL, &error );
+ g_warning ( "%s: BZ error :( %d. read %d", __FUNCTION__, bzerror, nBuf );
}
+ BZ2_bzReadClose ( &bzerror, bf );
+ g_output_stream_close ( gos, NULL, &error );
end:
+ g_object_unref ( gios );
+ fclose ( ff );
+
return tmpname;
#else
return NULL;