diff options
Diffstat (limited to 'source4/librpc')
-rw-r--r-- | source4/librpc/ndr/ndr_compression.c | 116 |
1 files changed, 95 insertions, 21 deletions
diff --git a/source4/librpc/ndr/ndr_compression.c b/source4/librpc/ndr/ndr_compression.c index 37f95bb1b6..92c5b049df 100644 --- a/source4/librpc/ndr/ndr_compression.c +++ b/source4/librpc/ndr/ndr_compression.c @@ -57,8 +57,8 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &comp_chunk_size)); - DEBUG(10,("MSZIP plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", - plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); + DEBUG(9,("MSZIP plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", + plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); comp_chunk_offset = ndrpull->offset; NDR_CHECK(ndr_pull_advance(ndrpull, comp_chunk_size)); @@ -104,13 +104,6 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu zError(z_ret), z_ret); } - } else { - z_ret = inflateReset2(z, Z_RESET_KEEP_WINDOW); - if (z_ret != Z_OK) { - return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, - "Bad inflateReset2 error %s(%d) (PULL)", - zError(z_ret), z_ret); - } } /* call inflate untill we get Z_STREAM_END or an error */ @@ -142,6 +135,20 @@ static enum ndr_err_code ndr_pull_compression_mszip_chunk(struct ndr_pull *ndrpu *last = true; } + z_ret = inflateReset(z); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateReset error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + + z_ret = inflateSetDictionary(z, plain_chunk.data, plain_chunk.length); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad inflateSetDictionary error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + return NDR_ERR_SUCCESS; } @@ -212,14 +219,6 @@ static enum ndr_err_code ndr_push_compression_mszip_chunk(struct ndr_push *ndrpu zError(z_ret), z_ret); } - } else { - /* TODO: keep the window */ - z_ret = deflateReset(z); - if (z_ret != Z_OK) { - return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, - "Bad delateReset2 error %s(%d) (PUSH)", - zError(z_ret), z_ret); - } } /* call deflate untill we get Z_STREAM_END or an error */ @@ -241,11 +240,28 @@ static enum ndr_err_code ndr_push_compression_mszip_chunk(struct ndr_push *ndrpu comp_chunk_size = 2 + z->total_out; + z_ret = deflateReset(z); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad deflateReset error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + + z_ret = deflateSetDictionary(z, plain_chunk.data, plain_chunk.length); + if (z_ret != Z_OK) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "Bad deflateSetDictionary error %s(%d) (PULL)", + zError(z_ret), z_ret); + } + tmp_offset = ndrpush->offset; ndrpush->offset = comp_chunk_size_offset; NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk_size)); ndrpush->offset = tmp_offset; + DEBUG(9,("MSZIP comp plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", + plain_chunk.length, plain_chunk.length, comp_chunk_size, comp_chunk_size)); + ndrpush->offset += comp_chunk_size; return NDR_ERR_SUCCESS; } @@ -260,6 +276,7 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp uint32_t plain_chunk_offset; uint32_t comp_chunk_size; uint32_t plain_chunk_size; + ssize_t ret; NDR_CHECK(ndr_pull_uint32(ndrpull, NDR_SCALARS, &plain_chunk_size)); if (plain_chunk_size > 0x00010000) { @@ -279,11 +296,20 @@ static enum ndr_err_code ndr_pull_compression_xpress_chunk(struct ndr_pull *ndrp plain_chunk.length = plain_chunk_size; plain_chunk.data = ndrpush->data + plain_chunk_offset; - DEBUG(10,("XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", - plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); + DEBUG(9,("XPRESS plain_chunk_size: %08X (%u) comp_chunk_size: %08X (%u)\n", + plain_chunk_size, plain_chunk_size, comp_chunk_size, comp_chunk_size)); /* Uncompressing the buffer using LZ Xpress algorithm */ - lzxpress_decompress(&comp_chunk, &plain_chunk); + ret = lzxpress_decompress(comp_chunk.data, + comp_chunk.length, + plain_chunk.data, + plain_chunk.length); + if (ret < 0) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "XPRESS lzxpress_decompress() returned %d\n", + ret); + } + plain_chunk.length = ret; if ((plain_chunk_size < 0x00010000) || (ndrpull->offset+4 >= ndrpull->data_size)) { /* this is the last chunk */ @@ -297,7 +323,55 @@ static enum ndr_err_code ndr_push_compression_xpress_chunk(struct ndr_push *ndrp struct ndr_pull *ndrpull, bool *last) { - return ndr_push_error(ndrpush, NDR_ERR_COMPRESSION, "XPRESS compression is not supported yet (PUSH)"); + DATA_BLOB comp_chunk; + uint32_t comp_chunk_size_offset; + DATA_BLOB plain_chunk; + uint32_t plain_chunk_size; + uint32_t plain_chunk_offset; + uint32_t max_plain_size = 0x00010000; + uint32_t max_comp_size = 0x00020000 + 2; /* TODO: use the correct value here */ + uint32_t tmp_offset; + ssize_t ret; + + plain_chunk_size = MIN(max_plain_size, ndrpull->data_size - ndrpull->offset); + plain_chunk_offset = ndrpull->offset; + NDR_CHECK(ndr_pull_advance(ndrpull, plain_chunk_size)); + + plain_chunk.data = ndrpull->data + plain_chunk_offset; + plain_chunk.length = plain_chunk_size; + + if (plain_chunk_size < max_plain_size) { + *last = true; + } + + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, plain_chunk_size)); + comp_chunk_size_offset = ndrpush->offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, 0xFEFEFEFE)); + + NDR_CHECK(ndr_push_expand(ndrpush, max_comp_size)); + + comp_chunk.data = ndrpush->data + ndrpush->offset; + comp_chunk.length = max_comp_size; + + /* Compressing the buffer using LZ Xpress algorithm */ + ret = lzxpress_compress(plain_chunk.data, + plain_chunk.length, + comp_chunk.data, + comp_chunk.length); + if (ret < 0) { + return ndr_pull_error(ndrpull, NDR_ERR_COMPRESSION, + "XPRESS lzxpress_compress() returned %d\n", + ret); + } + comp_chunk.length = ret; + + tmp_offset = ndrpush->offset; + ndrpush->offset = comp_chunk_size_offset; + NDR_CHECK(ndr_push_uint32(ndrpush, NDR_SCALARS, comp_chunk.length)); + ndrpush->offset = tmp_offset; + + ndrpush->offset += comp_chunk.length; + return NDR_ERR_SUCCESS; } /* |