From 69b8d1ab13473f851f8957e2bb6f5486f64612ad Mon Sep 17 00:00:00 2001 From: Guilherme Andrade Date: Sat, 23 Jul 2016 19:10:10 +0100 Subject: zlib: support extraction of inflation dictionary --- erts/doc/src/zlib.xml | 11 +++++++ erts/emulator/drivers/common/zlib_drv.c | 51 +++++++++++++++++++++++---------- erts/preloaded/src/zlib.erl | 41 +++++++++++++++----------- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index 138414a880..1a7c2d2b6f 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -575,6 +575,17 @@ unpack(Z, Compressed, Dict) -> + + + Return the decompression dictionary. + +

Returns the decompression dictionary currently in use + by the stream. This function must be called between + inflateInit/1,2 + and inflateEnd.

+
+
+ Open a stream and return a stream reference. diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index 440ba956d8..acbe675c41 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -44,30 +44,34 @@ #define INFLATE_INIT 8 #define INFLATE_INIT2 9 #define INFLATE_SETDICT 10 -#define INFLATE_SYNC 11 -#define INFLATE_RESET 12 -#define INFLATE_END 13 -#define INFLATE 14 +#define INFLATE_GETDICT 11 +#define INFLATE_SYNC 12 +#define INFLATE_RESET 13 +#define INFLATE_END 14 +#define INFLATE 15 -#define CRC32_0 15 -#define CRC32_1 16 -#define CRC32_2 17 +#define CRC32_0 16 +#define CRC32_1 17 +#define CRC32_2 18 -#define SET_BUFSZ 18 -#define GET_BUFSZ 19 -#define GET_QSIZE 20 +#define SET_BUFSZ 19 +#define GET_BUFSZ 20 +#define GET_QSIZE 21 -#define ADLER32_1 21 -#define ADLER32_2 22 +#define ADLER32_1 22 +#define ADLER32_2 23 -#define CRC32_COMBINE 23 -#define ADLER32_COMBINE 24 +#define CRC32_COMBINE 24 +#define ADLER32_COMBINE 25 -#define INFLATE_CHUNK 25 +#define INFLATE_CHUNK 26 #define DEFAULT_BUFSZ 4000 +/* According to zlib documentation, it can never exceed this */ +#define INFL_DICT_SZ 32768 + /* This flag is used in the same places, where zlib return codes * (Z_OK, Z_STREAM_END, Z_NEED_DICT) are. So, we need to set it to * relatively large value to avoid possible value clashes in future. @@ -248,6 +252,18 @@ static int zlib_output(ZLibData* d) return zlib_output_init(d); } +static int zlib_inflate_get_dictionary(ZLibData* d) +{ + ErlDrvBinary* dbin = driver_alloc_binary(INFL_DICT_SZ); + uInt dlen = 0; + int res = inflateGetDictionary(&d->s, (unsigned char*)dbin->orig_bytes, &dlen); + if ((res == Z_OK) && (driver_output_binary(d->port, NULL, 0, dbin, 0, dlen) < 0)) { + res = Z_ERRNO; + } + driver_free_binary(dbin); + return res; +} + static int zlib_inflate(ZLibData* d, int flush) { int res = Z_OK; @@ -586,6 +602,11 @@ static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *bu res = inflateSetDictionary(&d->s, (unsigned char*)buf, len); return zlib_return(res, rbuf, rlen); + case INFLATE_GETDICT: + if (d->state != ST_INFLATE) goto badarg; + res = zlib_inflate_get_dictionary(d); + return zlib_return(res, rbuf, rlen); + case INFLATE_SYNC: if (d->state != ST_INFLATE) goto badarg; if (len != 0) goto badarg; diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index fa0f28c5c3..8cd3e39fd7 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -23,7 +23,8 @@ -export([open/0,close/1,deflateInit/1,deflateInit/2,deflateInit/6, deflateSetDictionary/2,deflateReset/1,deflateParams/3, deflate/2,deflate/3,deflateEnd/1, - inflateInit/1,inflateInit/2,inflateSetDictionary/2, + inflateInit/1,inflateInit/2, + inflateSetDictionary/2,inflateGetDictionary/1, inflateSync/1,inflateReset/1,inflate/2,inflateEnd/1, inflateChunk/1, inflateChunk/2, setBufSize/2,getBufSize/1, @@ -98,25 +99,26 @@ -define(INFLATE_INIT, 8). -define(INFLATE_INIT2, 9). -define(INFLATE_SETDICT, 10). --define(INFLATE_SYNC, 11). --define(INFLATE_RESET, 12). --define(INFLATE_END, 13). --define(INFLATE, 14). --define(INFLATE_CHUNK, 25). +-define(INFLATE_GETDICT, 11). +-define(INFLATE_SYNC, 12). +-define(INFLATE_RESET, 13). +-define(INFLATE_END, 14). +-define(INFLATE, 15). +-define(INFLATE_CHUNK, 26). --define(CRC32_0, 15). --define(CRC32_1, 16). --define(CRC32_2, 17). +-define(CRC32_0, 16). +-define(CRC32_1, 17). +-define(CRC32_2, 18). --define(SET_BUFSZ, 18). --define(GET_BUFSZ, 19). --define(GET_QSIZE, 20). +-define(SET_BUFSZ, 19). +-define(GET_BUFSZ, 20). +-define(GET_QSIZE, 21). --define(ADLER32_1, 21). --define(ADLER32_2, 22). +-define(ADLER32_1, 22). +-define(ADLER32_2, 23). --define(CRC32_COMBINE, 23). --define(ADLER32_COMBINE, 24). +-define(CRC32_COMBINE, 24). +-define(ADLER32_COMBINE, 25). %%------------------------------------------------------------------------ @@ -242,6 +244,13 @@ inflateInit(Z, WindowBits) -> inflateSetDictionary(Z, Dictionary) -> call(Z, ?INFLATE_SETDICT, Dictionary). +-spec inflateGetDictionary(Z) -> Dictionary when + Z :: zstream(), + Dictionary :: iolist(). +inflateGetDictionary(Z) -> + _ = call(Z, ?INFLATE_GETDICT, []), + collect(Z). + -spec inflateSync(zstream()) -> 'ok'. inflateSync(Z) -> call(Z, ?INFLATE_SYNC, []). -- cgit v1.2.3