]> git.street.me.uk Git - andy/viking.git/blobdiff - src/compression.c
Fix excluding own self track when creating lists of other tracks.
[andy/viking.git] / src / compression.c
index e7359d14cfccc4a87f0442191037d32f819cc7e6..05badab74b7401aa14bfaac3afee7ebbb674e654 100644 (file)
 #include <zlib.h>
 #endif
 
-#include "compression.h"
+#ifdef HAVE_BZLIB_H
+#include <bzlib.h>
+#endif
 
+#include "compression.h"
+#include <gio/gio.h>
+#include <glib/gstdio.h>
 
 #ifdef HAVE_LIBZ
 /* return size of unzip data or 0 if failed */
-/* can be made generic to uncompress zip, gzip, bzip2 data */
 static guint uncompress_data(void *uncompressed_buffer, guint uncompressed_size, void *compressed_data, guint compressed_size)
 {
        z_stream stream;
@@ -120,3 +124,81 @@ end:
        return(unzip_data);
 }
 
+/**
+ * uncompress_bzip2:
+ * @name: The name of the file to attempt to decompress
+ *
+ * Returns: The name of the uncompressed file (in a temporary location) or NULL
+ *   free the returned name after use.
+ *
+ * Also see: http://www.bzip.org/1.0.5/bzip2-manual-1.0.5.html
+ */
+gchar* uncompress_bzip2 ( gchar *name )
+{
+#ifdef HAVE_BZLIB_H
+       FILE *ff = g_fopen ( name, "r" );
+       if ( !ff )
+               return NULL;
+
+       int     bzerror;
+       BZFILE* bf = BZ2_bzReadOpen ( &bzerror, ff, 0, 0, NULL, 0 ); // This should take care of the bz2 file header
+       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 );
+       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;
+       // Now process the actual compression data
+       while ( bzerror == BZ_OK ) {
+               nBuf = BZ2_bzRead ( &bzerror, bf, buf, 4096 );
+               if ( bzerror == BZ_OK || bzerror == BZ_STREAM_END) {
+                       // do something with buf[0 .. nBuf-1]
+                       if ( g_output_stream_write ( gos, buf, nBuf, NULL, &error ) < 0 ) {
+                               g_critical ( "Couldn't write bz2 tmp %s file due to %s", tmpname, error->message );
+                               g_error_free (error);
+                               BZ2_bzReadClose ( &bzerror, bf );
+                               goto end;
+                       }
+               }
+       }
+       if ( bzerror != BZ_STREAM_END ) {
+               // handle error...
+               g_warning ( "%s: BZ error :( %d", __FUNCTION__, bzerror );
+       }
+       BZ2_bzReadClose ( &bzerror, bf );
+       g_output_stream_close ( gos, NULL, &error );
+
+ end:
+       return tmpname;
+#else
+       return NULL;
+#endif
+}