mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-11 01:08:01 -05:00
142 lines
3.7 KiB
C
142 lines
3.7 KiB
C
#include "config.h"
|
|
|
|
#include "flatpak-zstd-decompressor-private.h"
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#ifdef HAVE_ZSTD
|
|
#include <zstd.h>
|
|
#endif
|
|
|
|
static void flatpak_zstd_decompressor_iface_init (GConverterIface *iface);
|
|
|
|
struct _FlatpakZstdDecompressor
|
|
{
|
|
GObject parent_instance;
|
|
|
|
#ifdef HAVE_ZSTD
|
|
ZSTD_DStream *dstream;
|
|
#endif
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (FlatpakZstdDecompressor, flatpak_zstd_decompressor, G_TYPE_OBJECT,
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_CONVERTER,
|
|
flatpak_zstd_decompressor_iface_init))
|
|
|
|
static void
|
|
flatpak_zstd_decompressor_finalize (GObject *object)
|
|
{
|
|
#ifdef HAVE_ZSTD
|
|
FlatpakZstdDecompressor *decompressor;
|
|
|
|
decompressor = FLATPAK_ZSTD_DECOMPRESSOR (object);
|
|
|
|
ZSTD_freeDStream (decompressor->dstream);
|
|
#endif
|
|
|
|
G_OBJECT_CLASS (flatpak_zstd_decompressor_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
flatpak_zstd_decompressor_init (FlatpakZstdDecompressor *decompressor)
|
|
{
|
|
#ifdef HAVE_ZSTD
|
|
decompressor->dstream = ZSTD_createDStream ();
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
flatpak_zstd_decompressor_class_init (FlatpakZstdDecompressorClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
gobject_class->finalize = flatpak_zstd_decompressor_finalize;
|
|
}
|
|
|
|
FlatpakZstdDecompressor *
|
|
flatpak_zstd_decompressor_new (void)
|
|
{
|
|
FlatpakZstdDecompressor *decompressor;
|
|
|
|
decompressor = g_object_new (FLATPAK_TYPE_ZSTD_DECOMPRESSOR, NULL);
|
|
|
|
return decompressor;
|
|
}
|
|
|
|
static void
|
|
flatpak_zstd_decompressor_reset (GConverter *converter)
|
|
{
|
|
#ifdef HAVE_ZSTD
|
|
FlatpakZstdDecompressor *decompressor = FLATPAK_ZSTD_DECOMPRESSOR (converter);
|
|
|
|
ZSTD_initDStream (decompressor->dstream);
|
|
#endif
|
|
}
|
|
|
|
static GConverterResult
|
|
flatpak_zstd_decompressor_convert (GConverter *converter,
|
|
const void *inbuf,
|
|
gsize inbuf_size,
|
|
void *outbuf,
|
|
gsize outbuf_size,
|
|
GConverterFlags flags,
|
|
gsize *bytes_read,
|
|
gsize *bytes_written,
|
|
GError **error)
|
|
{
|
|
#ifdef HAVE_ZSTD
|
|
FlatpakZstdDecompressor *decompressor;
|
|
ZSTD_inBuffer input = { inbuf, inbuf_size, 0 };
|
|
ZSTD_outBuffer output = {outbuf, outbuf_size, 0 };
|
|
size_t res;
|
|
|
|
decompressor = FLATPAK_ZSTD_DECOMPRESSOR (converter);
|
|
|
|
if (decompressor->dstream == NULL)
|
|
{
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
"Failed to initialize libzstd");
|
|
return G_CONVERTER_ERROR;
|
|
}
|
|
|
|
res = ZSTD_decompressStream(decompressor->dstream, &output , &input);
|
|
if (ZSTD_isError (res))
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
"Zstd decompression error: %s", ZSTD_getErrorName (res));
|
|
return G_CONVERTER_ERROR;
|
|
}
|
|
|
|
*bytes_read = input.pos;
|
|
*bytes_written = output.pos;
|
|
|
|
if (res == 0)
|
|
return G_CONVERTER_FINISHED;
|
|
|
|
if (input.pos == 0 && output.pos == 0)
|
|
{
|
|
/* Did nothing, need more input? */
|
|
if (flags & G_CONVERTER_INPUT_AT_END)
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Zstd failed");
|
|
else
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, "Need more zstd data");
|
|
|
|
return G_CONVERTER_ERROR;
|
|
}
|
|
|
|
return G_CONVERTER_CONVERTED;
|
|
|
|
#else
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
"libzstd not available");
|
|
return G_CONVERTER_ERROR;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
flatpak_zstd_decompressor_iface_init (GConverterIface *iface)
|
|
{
|
|
iface->convert = flatpak_zstd_decompressor_convert;
|
|
iface->reset = flatpak_zstd_decompressor_reset;
|
|
}
|