BZ2, ZLIB loaders: Move duplicated code to separate file

Also change decompressors to use mmap'ed data.
This commit is contained in:
Kim Woelders 2021-12-23 16:22:21 +01:00
parent bf93574b8b
commit c880edac55
5 changed files with 146 additions and 130 deletions

View File

@ -117,13 +117,13 @@ xpm_la_LDFLAGS = -module -avoid-version
xpm_la_LIBADD = $(top_builddir)/src/lib/libImlib2.la
xpm_la_LIBTOOLFLAGS = --tag=disable-static
bz2_la_SOURCES = loader_bz2.c
bz2_la_SOURCES = loader_bz2.c decompress_load.c
bz2_la_CPPFLAGS = $(BZ2_CFLAGS) $(AM_CPPFLAGS)
bz2_la_LDFLAGS = -module -avoid-version
bz2_la_LIBADD = $(BZ2_LIBS) $(top_builddir)/src/lib/libImlib2.la
bz2_la_LIBTOOLFLAGS = --tag=disable-static
zlib_la_SOURCES = loader_zlib.c
zlib_la_SOURCES = loader_zlib.c decompress_load.c
zlib_la_CPPFLAGS = $(ZLIB_CFLAGS) $(AM_CPPFLAGS)
zlib_la_LDFLAGS = -module -avoid-version
zlib_la_LIBADD = $(ZLIB_LIBS) $(top_builddir)/src/lib/libImlib2.la

View File

@ -0,0 +1,71 @@
#include "loader_common.h"
#include <sys/mman.h>
int
decompress_load(ImlibImage * im, int load_data, const char *const *pext,
int next, imlib_decompress_load_f * fdec)
{
int rc, i;
ImlibLoader *loader;
int dest, res;
const char *s, *p, *q;
char tmp[] = "/tmp/imlib2_loader_dec-XXXXXX";
char *real_ext;
void *fdata;
rc = LOAD_FAIL;
/* make sure this file ends in a known name and that there's another ext
* (e.g. "foo.png.bz2") */
for (p = s = im->real_file, q = NULL; *s; s++)
{
if (*s != '.' && *s != '/')
continue;
q = p;
p = s + 1;
}
if (!q)
return rc;
res = 0;
for (i = 0; i < next; i++)
{
if (strcasecmp(p, pext[i]))
continue;
res = 1;
break;
}
if (!res)
return rc;
if (!(real_ext = strndup(q, p - q - 1)))
return LOAD_OOM;
loader = __imlib_FindBestLoaderForFormat(real_ext, 0);
free(real_ext);
if (!loader)
return rc;
fdata = mmap(NULL, im->fsize, PROT_READ, MAP_SHARED, fileno(im->fp), 0);
if (fdata == MAP_FAILED)
return LOAD_BADFILE;
if ((dest = mkstemp(tmp)) < 0)
QUIT_WITH_RC(LOAD_OOM);
res = fdec(fdata, im->fsize, dest);
close(dest);
if (res)
rc = __imlib_LoadEmbedded(loader, im, tmp, load_data);
unlink(tmp);
quit:
munmap(fdata, im->fsize);
return rc;
}

View File

@ -6,94 +6,60 @@
#define INBUF_SIZE 1024
static int
uncompress_file(FILE * fp, int dest)
uncompress_file(const void *fdata, unsigned int fsize, int dest)
{
BZFILE *bf;
DATA8 outbuf[OUTBUF_SIZE];
int bytes, error, ret = 1;
int ok;
bz_stream strm = { 0 };
int ret, bytes;
char outbuf[OUTBUF_SIZE];
bf = BZ2_bzReadOpen(&error, fp, 0, 0, NULL, 0);
ok = 0;
if (error != BZ_OK)
ret = BZ2_bzDecompressInit(&strm, 0, 0);
if (ret != BZ_OK)
return ok;
strm.next_in = (void *)fdata;
strm.avail_in = fsize;
for (;;)
{
BZ2_bzReadClose(NULL, bf);
return 0;
}
strm.next_out = outbuf;
strm.avail_out = sizeof(outbuf);
while (1)
{
bytes = BZ2_bzRead(&error, bf, &outbuf, OUTBUF_SIZE);
ret = BZ2_bzDecompress(&strm);
if (error == BZ_OK || error == BZ_STREAM_END)
if (write(dest, outbuf, bytes) != bytes)
break;
if (ret != BZ_OK && ret != BZ_STREAM_END)
goto quit;
if (error == BZ_STREAM_END)
bytes = sizeof(outbuf) - strm.avail_out;
if (write(dest, outbuf, bytes) != bytes)
goto quit;
if (ret == BZ_STREAM_END)
break;
else if (error != BZ_OK)
{
ret = 0;
break;
}
}
BZ2_bzReadClose(&error, bf);
ok = 1;
return ret;
quit:
BZ2_bzDecompressEnd(&strm);
return ok;
}
static const char *const list_formats[] = { "bz2" };
int
load2(ImlibImage * im, int load_data)
{
int rc;
ImlibLoader *loader;
int dest, res;
const char *s, *p, *q;
char tmp[] = "/tmp/imlib2_loader_bz2-XXXXXX";
char *real_ext;
rc = LOAD_FAIL;
/* make sure this file ends in ".bz2" and that there's another ext
* (e.g. "foo.png.bz2") */
for (p = s = im->real_file, q = NULL; *s; s++)
{
if (*s != '.' && *s != '/')
continue;
q = p;
p = s + 1;
}
if (!q || strcasecmp(p, "bz2"))
return rc;
if (!(real_ext = strndup(q, p - q - 1)))
return rc;
loader = __imlib_FindBestLoaderForFormat(real_ext, 0);
free(real_ext);
if (!loader)
return rc;
if ((dest = mkstemp(tmp)) < 0)
return rc;
res = uncompress_file(im->fp, dest);
close(dest);
if (!res)
goto quit;
res = __imlib_LoadEmbedded(loader, im, tmp, load_data);
quit:
unlink(tmp);
return res;
return decompress_load(im, load_data, list_formats, ARRAY_SIZE(list_formats),
uncompress_file);
}
void
formats(ImlibLoader * l)
{
static const char *const list_formats[] = { "bz2" };
__imlib_LoaderSetFormats(l, list_formats, ARRAY_SIZE(list_formats));
}

View File

@ -13,6 +13,13 @@ __EXPORT__ char save(ImlibImage * im, ImlibProgressFunction progress,
char progress_granularity);
__EXPORT__ void formats(ImlibLoader * l);
typedef int (imlib_decompress_load_f) (const void *fdata,
unsigned int fsize, int dest);
int decompress_load(ImlibImage * im, int load_data,
const char *const *pext, int next,
imlib_decompress_load_f * fdec);
#define QUIT_WITH_RC(_err) { rc = _err; goto quit; }
#define QUITx_WITH_RC(_err, _lbl) { rc = _err; goto _lbl; }

View File

@ -5,88 +5,60 @@
#define OUTBUF_SIZE 16484
static int
uncompress_file(FILE * fp, int dest)
uncompress_file(const void *fdata, unsigned int fsize, int dest)
{
gzFile gf;
DATA8 outbuf[OUTBUF_SIZE];
int ok;
z_stream strm = { 0 };;
unsigned char outbuf[OUTBUF_SIZE];
int ret = 1, bytes;
gf = gzdopen(dup(fileno(fp)), "rb");
if (!gf)
return 0;
ok = 0;
while (1)
ret = inflateInit2(&strm, 15 + 32);
if (ret != Z_OK)
return ok;
strm.next_in = (void *)fdata;
strm.avail_in = fsize;
for (;;)
{
bytes = gzread(gf, outbuf, OUTBUF_SIZE);
strm.next_out = outbuf;
strm.avail_out = sizeof(outbuf);
if (!bytes)
break;
else if (bytes == -1)
{
ret = 0;
break;
}
else if (write(dest, outbuf, bytes) != bytes)
ret = inflate(&strm, 0);
if (ret != Z_OK && ret != Z_STREAM_END)
goto quit;
bytes = sizeof(outbuf) - strm.avail_out;
if (write(dest, outbuf, bytes) != bytes)
goto quit;
if (ret == Z_STREAM_END)
break;
}
gzclose(gf);
ok = 1;
quit:
inflateEnd(&strm);
return ret;
}
static const char *const list_formats[] = { "gz" };
int
load2(ImlibImage * im, int load_data)
{
int rc;
ImlibLoader *loader;
int dest, res;
const char *s, *p, *q;
char tmp[] = "/tmp/imlib2_loader_zlib-XXXXXX";
char *real_ext;
rc = LOAD_FAIL;
/* make sure this file ends in ".gz" and that there's another ext
* (e.g. "foo.png.gz") */
for (p = s = im->real_file, q = NULL; *s; s++)
{
if (*s != '.' && *s != '/')
continue;
q = p;
p = s + 1;
}
if (!q || strcasecmp(p, "gz"))
return rc;
if (!(real_ext = strndup(q, p - q - 1)))
return rc;
loader = __imlib_FindBestLoaderForFormat(real_ext, 0);
free(real_ext);
if (!loader)
return rc;
if ((dest = mkstemp(tmp)) < 0)
return rc;
res = uncompress_file(im->fp, dest);
close(dest);
if (!res)
goto quit;
res = __imlib_LoadEmbedded(loader, im, tmp, load_data);
quit:
unlink(tmp);
return res;
return decompress_load(im, load_data, list_formats, ARRAY_SIZE(list_formats),
uncompress_file);
}
void
formats(ImlibLoader * l)
{
static const char *const list_formats[] = { "gz" };
__imlib_LoaderSetFormats(l, list_formats, ARRAY_SIZE(list_formats));
}