diff mbox series

[XEN,1/2] xen/decompress: Add a user pointer for book keeping in the callbacks

Message ID DU0P192MB1700684CB8DF7B3845B64126E3779@DU0P192MB1700.EURP192.PROD.OUTLOOK.COM (mailing list archive)
State New, archived
Headers show
Series [XEN,1/2] xen/decompress: Add a user pointer for book keeping in the callbacks | expand

Commit Message

Rafaël Kooi May 10, 2023, 12:18 a.m. UTC
Before this change the callbacks either needed to be completely
stateless or use global state for book keeping. In the case where book
keeping is needed we can't use global state in decompress.c because the
linker disallows the existence of the .data and .bss segments. This
change allows for localized book keeping with the user pointer.

Signed-off-by: Rafaël Kooi <rafael_andreas@hotmail.com>
---
 xen/common/bunzip2.c         | 23 +++++++++++++----------
 xen/common/unlz4.c           | 15 ++++++++-------
 xen/common/unlzma.c          | 30 ++++++++++++++++++------------
 xen/common/unlzo.c           | 13 +++++++------
 xen/common/unxz.c            | 11 ++++++-----
 xen/common/unzstd.c          | 13 +++++++------
 xen/include/xen/decompress.h | 10 +++++++---
 7 files changed, 66 insertions(+), 49 deletions(-)
diff mbox series

Patch

diff --git a/xen/common/bunzip2.c b/xen/common/bunzip2.c
index 4466426941..a854046524 100644
--- a/xen/common/bunzip2.c
+++ b/xen/common/bunzip2.c
@@ -1,4 +1,4 @@ 
-/* vi: set sw = 4 ts = 4: */
+/* vi: set sw=4 ts=4: */
 /*	Small bzip2 deflate implementation, by Rob Landley (rob@landley.net).
 
 	Based on bzip2 decompression code by Julian R Seward (jseward@acm.org),
@@ -86,7 +86,7 @@  struct bunzip_data {
 	/* State for interrupting output loop */
 	int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent;
 	/* I/O tracking data (file handles, buffers, positions, etc.) */
-	int (*fill)(void*, unsigned int);
+	int (*fill)(void*, unsigned int, void*);
 	int inbufCount, inbufPos /*, outbufPos*/;
 	unsigned char *inbuf /*,*outbuf*/;
 	unsigned int inbufBitCount, inbufBits;
@@ -99,6 +99,7 @@  struct bunzip_data {
 	unsigned char selectors[32768];		/* nSelectors = 15 bits */
 	struct group_data groups[MAX_GROUPS];	/* Huffman coding tables */
 	int io_error;			/* non-zero if we have IO error */
+	void *userptr;			/* user pointer to pass to fill */
 };
 
 
@@ -117,7 +118,7 @@  static unsigned int __init get_bits(struct bunzip_data *bd, char bits_wanted)
 		if (bd->inbufPos == bd->inbufCount) {
 			if (bd->io_error)
 				return 0;
-			bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE);
+			bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE, bd->userptr);
 			if (bd->inbufCount <= 0) {
 				bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF;
 				return 0;
@@ -612,7 +613,7 @@  decode_next_byte:
 	goto decode_next_byte;
 }
 
-static int __init cf_check nofill(void *buf, unsigned int len)
+static int __init cf_check nofill(void *buf, unsigned int len, void *userptr)
 {
 	return -1;
 }
@@ -621,7 +622,7 @@  static int __init cf_check nofill(void *buf, unsigned int len)
    a complete bunzip file (len bytes long).  If in_fd!=-1, inbuf and len are
    ignored, and data is read from file handle into temporary buffer. */
 static int __init start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
-			       int (*fill)(void*, unsigned int))
+			       int (*fill)(void*, unsigned int, void*), void *userptr)
 {
 	struct bunzip_data *bd;
 	unsigned int i, j, c;
@@ -644,6 +645,7 @@  static int __init start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
 		bd->fill = fill;
 	else
 		bd->fill = nofill;
+	bd->userptr = userptr;
 
 	/* Init the CRC32 table (big endian) */
 	for (i = 0; i < 256; i++) {
@@ -671,10 +673,11 @@  static int __init start_bunzip(struct bunzip_data **bdp, void *inbuf, int len,
 /* Example usage: decompress src_fd to dst_fd.  (Stops at end of bzip2 data,
    not end of file.) */
 int __init bunzip2(unsigned char *buf, unsigned int len,
-		   int(*fill)(void*, unsigned int),
-		   int(*flush)(void*, unsigned int),
+		   int(*fill)(void*, unsigned int, void*),
+		   int(*flush)(void*, unsigned int, void*),
 		   unsigned char *outbuf, unsigned int *pos,
-		   void(*error)(const char *x))
+		   void(*error)(const char *x),
+		   void *userptr)
 {
 	struct bunzip_data *bd;
 	int i = -1;
@@ -696,7 +699,7 @@  int __init bunzip2(unsigned char *buf, unsigned int len,
 		i = RETVAL_OUT_OF_MEMORY;
 		goto exit_0;
 	}
-	i = start_bunzip(&bd, inbuf, len, fill);
+	i = start_bunzip(&bd, inbuf, len, fill, userptr);
 	if (!i) {
 		for (;;) {
 			i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE);
@@ -705,7 +708,7 @@  int __init bunzip2(unsigned char *buf, unsigned int len,
 			if (!flush)
 				outbuf += i;
 			else
-				if (i != flush(outbuf, i)) {
+				if (i != flush(outbuf, i, userptr)) {
 					i = RETVAL_UNEXPECTED_OUTPUT_EOF;
 					break;
 				}
diff --git a/xen/common/unlz4.c b/xen/common/unlz4.c
index 2096b98f36..00c179732e 100644
--- a/xen/common/unlz4.c
+++ b/xen/common/unlz4.c
@@ -23,10 +23,11 @@ 
 #define ARCHIVE_MAGICNUMBER 0x184C2102
 
 int __init unlz4(unsigned char *input, unsigned int in_len,
-		 int (*fill)(void *, unsigned int),
-		 int (*flush)(void *, unsigned int),
+		 int (*fill)(void *, unsigned int, void*),
+		 int (*flush)(void *, unsigned int, void*),
 		 unsigned char *output, unsigned int *posp,
-		 void (*error)(const char *x))
+		 void (*error)(const char *x),
+		 void *userptr)
 {
 	int ret = -1;
 	size_t chunksize = 0;
@@ -75,7 +76,7 @@  int __init unlz4(unsigned char *input, unsigned int in_len,
 		*posp = 0;
 
 	if (fill)
-		fill(inp, 4);
+		fill(inp, 4, userptr);
 
 	chunksize = get_unaligned_le32(inp);
 	if (chunksize == ARCHIVE_MAGICNUMBER) {
@@ -92,7 +93,7 @@  int __init unlz4(unsigned char *input, unsigned int in_len,
 	for (;;) {
 
 		if (fill)
-			fill(inp, 4);
+			fill(inp, 4, userptr);
 
 		chunksize = get_unaligned_le32(inp);
 		if (chunksize == ARCHIVE_MAGICNUMBER) {
@@ -113,7 +114,7 @@  int __init unlz4(unsigned char *input, unsigned int in_len,
 				error("chunk length is longer than allocated");
 				goto exit_2;
 			}
-			fill(inp, chunksize);
+			fill(inp, chunksize, userptr);
 		}
 #if defined(__XEN__) || defined(__MINIOS__)
 		if (out_len >= uncomp_chunksize) {
@@ -133,7 +134,7 @@  int __init unlz4(unsigned char *input, unsigned int in_len,
 		}
 
 		ret = -1;
-		if (flush && flush(outp, dest_len) != dest_len)
+		if (flush && flush(outp, dest_len, userptr) != dest_len)
 			goto exit_2;
 		if (output)
 			outp += dest_len;
diff --git a/xen/common/unlzma.c b/xen/common/unlzma.c
index 6cd99023ad..d5dbc44881 100644
--- a/xen/common/unlzma.c
+++ b/xen/common/unlzma.c
@@ -59,7 +59,7 @@  static long long __init read_int(unsigned char *ptr, int size)
 #define LZMA_IOBUF_SIZE	0x10000
 
 struct rc {
-	int (*fill)(void*, unsigned int);
+	int (*fill)(void*, unsigned int, void*);
 	uint8_t *ptr;
 	uint8_t *buffer;
 	uint8_t *buffer_end;
@@ -68,6 +68,7 @@  struct rc {
 	uint32_t range;
 	uint32_t bound;
 	void (*error)(const char *);
+	void *userptr;
 };
 
 
@@ -76,7 +77,7 @@  struct rc {
 #define RC_MODEL_TOTAL_BITS 11
 
 
-static int __init cf_check nofill(void *buffer, unsigned int len)
+static int __init cf_check nofill(void *buffer, unsigned int len, void *userptr)
 {
 	return -1;
 }
@@ -84,7 +85,7 @@  static int __init cf_check nofill(void *buffer, unsigned int len)
 /* Called twice: once at startup and once in rc_normalize() */
 static void __init rc_read(struct rc *rc)
 {
-	rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE);
+	rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE, rc->userptr);
 	if (rc->buffer_size <= 0)
 		rc->error("unexpected EOF");
 	rc->ptr = rc->buffer;
@@ -93,8 +94,9 @@  static void __init rc_read(struct rc *rc)
 
 /* Called once */
 static inline void __init rc_init(struct rc *rc,
-				  int (*fill)(void*, unsigned int),
-				  unsigned char *buffer, int buffer_size)
+				  int (*fill)(void*, unsigned int, void*),
+				  unsigned char *buffer, int buffer_size,
+				  void *userptr)
 {
 	if (fill)
 		rc->fill = fill;
@@ -104,6 +106,7 @@  static inline void __init rc_init(struct rc *rc,
 	rc->buffer_size = buffer_size;
 	rc->buffer_end = rc->buffer + rc->buffer_size;
 	rc->ptr = rc->buffer;
+	rc->userptr = userptr;
 
 	rc->code = 0;
 	rc->range = 0xFFFFFFFF;
@@ -274,8 +277,9 @@  struct writer {
 	size_t buffer_pos;
 	int bufsize;
 	size_t global_pos;
-	int(*flush)(void*, unsigned int);
+	int(*flush)(void*, unsigned int, void*);
 	struct lzma_header *header;
+	void *userptr;
 };
 
 struct cstate {
@@ -313,7 +317,7 @@  static inline int __init write_byte(struct writer *wr, uint8_t byte)
 	if (wr->flush && wr->buffer_pos == wr->header->dict_size) {
 		wr->buffer_pos = 0;
 		wr->global_pos += wr->header->dict_size;
-		if (wr->flush((char *)wr->buffer, wr->header->dict_size)
+		if (wr->flush((char *)wr->buffer, wr->header->dict_size, wr->userptr)
 				!= wr->header->dict_size)
 			return -1;
 	}
@@ -529,10 +533,11 @@  static inline int __init process_bit1(struct writer *wr, struct rc *rc,
 
 
 int __init unlzma(unsigned char *buf, unsigned int in_len,
-		  int(*fill)(void*, unsigned int),
-		  int(*flush)(void*, unsigned int),
+		  int(*fill)(void*, unsigned int, void*),
+		  int(*flush)(void*, unsigned int, void*),
 		  unsigned char *output, unsigned int *posp,
-		  void(*error)(const char *x))
+		  void(*error)(const char *x),
+		  void *userptr)
 {
 	struct lzma_header header;
 	int lc, pb, lp;
@@ -566,8 +571,9 @@  int __init unlzma(unsigned char *buf, unsigned int in_len,
 	wr.global_pos = 0;
 	wr.previous_byte = 0;
 	wr.buffer_pos = 0;
+	wr.userptr = userptr;
 
-	rc_init(&rc, fill, inbuf, in_len);
+	rc_init(&rc, fill, inbuf, in_len, userptr);
 
 	for (i = 0; i < sizeof(header); i++) {
 		if (rc.ptr >= rc.buffer_end)
@@ -644,7 +650,7 @@  int __init unlzma(unsigned char *buf, unsigned int in_len,
 
 	if (posp)
 		*posp = rc.ptr-rc.buffer;
-	if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos)
+	if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos, wr.userptr) == wr.buffer_pos)
 		ret = 0;
 exit_3:
 	large_free(p);
diff --git a/xen/common/unlzo.c b/xen/common/unlzo.c
index 74056778eb..8908790425 100644
--- a/xen/common/unlzo.c
+++ b/xen/common/unlzo.c
@@ -115,10 +115,11 @@  static int __init parse_header(u8 *input, int *skip, int in_len)
 }
 
 int __init unlzo(unsigned char *input, unsigned int in_len,
-		 int (*fill) (void *, unsigned int),
-		 int (*flush) (void *, unsigned int),
+		 int (*fill) (void *, unsigned int, void*),
+		 int (*flush) (void *, unsigned int, void*),
 		 unsigned char *output, unsigned int *posp,
-		 void (*error) (const char *x))
+		 void (*error) (const char *x),
+		 void *userptr)
 {
 	u8 r = 0;
 	int skip = 0;
@@ -161,7 +162,7 @@  int __init unlzo(unsigned char *input, unsigned int in_len,
 		*posp = 0;
 
 	if (fill)
-		fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+		fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE), userptr);
 
 	if (!parse_header(input, &skip, in_len)) {
 		error("invalid header");
@@ -227,7 +228,7 @@  int __init unlzo(unsigned char *input, unsigned int in_len,
 			}
 		}
 
-		if (flush && flush(out_buf, dst_len) != dst_len)
+		if (flush && flush(out_buf, dst_len, userptr) != dst_len)
 			goto exit_2;
 		if (output)
 			out_buf += dst_len;
@@ -235,7 +236,7 @@  int __init unlzo(unsigned char *input, unsigned int in_len,
 			*posp += src_len + 12;
 		if (fill) {
 			in_buf = in_buf_save;
-			fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE));
+			fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE), userptr);
 		} else {
 			in_buf += src_len;
 			in_len -= src_len;
diff --git a/xen/common/unxz.c b/xen/common/unxz.c
index 17aead0adf..6f005170d3 100644
--- a/xen/common/unxz.c
+++ b/xen/common/unxz.c
@@ -158,10 +158,11 @@ 
  * fill() and flush() won't be used.
  */
 int __init unxz(unsigned char *in, unsigned int in_size,
-		int (*fill)(void *dest, unsigned int size),
-		int (*flush)(void *src, unsigned int size),
+		int (*fill)(void *dest, unsigned int size, void *userptr),
+		int (*flush)(void *src, unsigned int size, void *userptr),
 		unsigned char *out, unsigned int *in_used,
-		void (*error)(const char *x))
+		void (*error)(const char *x),
+		void *userptr)
 {
 	struct xz_buf b;
 	struct xz_dec *s;
@@ -213,7 +214,7 @@  int __init unxz(unsigned char *in, unsigned int in_size,
 
 				b.in_pos = 0;
 
-				in_size = fill(in, XZ_IOBUF_SIZE);
+				in_size = fill(in, XZ_IOBUF_SIZE, userptr);
 				if ((int) in_size < 0) {
 					/*
 					 * This isn't an optimal error code
@@ -236,7 +237,7 @@  int __init unxz(unsigned char *in, unsigned int in_size,
 				 * returned by xz_dec_run(), but probably
 				 * it's not too bad.
 				 */
-				if (flush(b.out, b.out_pos) != (int)b.out_pos)
+				if (flush(b.out, b.out_pos, userptr) != (int)b.out_pos)
 					ret = XZ_BUF_ERROR;
 
 				b.out_pos = 0;
diff --git a/xen/common/unzstd.c b/xen/common/unzstd.c
index 47073dd3e3..09e8fdef04 100644
--- a/xen/common/unzstd.c
+++ b/xen/common/unzstd.c
@@ -143,10 +143,11 @@  out:
 }
 
 int __init unzstd(unsigned char *in_buf, unsigned int in_len,
-		  int (*fill)(void*, unsigned int),
-		  int (*flush)(void*, unsigned int),
+		  int (*fill)(void*, unsigned int, void*),
+		  int (*flush)(void*, unsigned int, void*),
 		  unsigned char *out_buf, unsigned int *in_pos,
-		  void (*error)(const char *x))
+		  void (*error)(const char *x),
+		  void *userptr)
 {
 	ZSTD_inBuffer in;
 	ZSTD_outBuffer out;
@@ -190,7 +191,7 @@  int __init unzstd(unsigned char *in_buf, unsigned int in_len,
 	}
 	/* Read the first chunk, since we need to decode the frame header. */
 	if (fill != NULL)
-		in_len = fill(in_buf, ZSTD_IOBUF_SIZE);
+		in_len = fill(in_buf, ZSTD_IOBUF_SIZE, userptr);
 	if ((int)in_len < 0) {
 		error("ZSTD-compressed data is truncated");
 		err = -1;
@@ -267,7 +268,7 @@  int __init unzstd(unsigned char *in_buf, unsigned int in_len,
 		if (in.pos == in.size) {
 			if (in_pos != NULL)
 				*in_pos += in.pos;
-			in_len = fill ? fill(in_buf, ZSTD_IOBUF_SIZE) : -1;
+			in_len = fill ? fill(in_buf, ZSTD_IOBUF_SIZE, userptr) : -1;
 			if ((int)in_len < 0) {
 				error("ZSTD-compressed data is truncated");
 				err = -1;
@@ -283,7 +284,7 @@  int __init unzstd(unsigned char *in_buf, unsigned int in_len,
 			goto out;
 		/* Flush all of the data produced if using flush(). */
 		if (flush != NULL && out.pos > 0) {
-			if (out.pos != flush(out.dst, out.pos)) {
+			if (out.pos != flush(out.dst, out.pos, userptr)) {
 				error("Failed to flush()");
 				err = -1;
 				goto out;
diff --git a/xen/include/xen/decompress.h b/xen/include/xen/decompress.h
index f5bc17f2b6..804dbca963 100644
--- a/xen/include/xen/decompress.h
+++ b/xen/include/xen/decompress.h
@@ -2,10 +2,11 @@ 
 #define __XEN_GENERIC_H
 
 typedef int decompress_fn(unsigned char *inbuf, unsigned int len,
-                          int (*fill)(void*, unsigned int),
-                          int (*flush)(void*, unsigned int),
+                          int (*fill)(void*, unsigned int, void*),
+                          int (*flush)(void*, unsigned int, void*),
                           unsigned char *outbuf, unsigned int *posp,
-                          void (*error)(const char *x));
+                          void (*error)(const char *x),
+                          void *userptr);
 
 /* inbuf   - input buffer
  * len     - len of pre-read data in inbuf
@@ -15,6 +16,7 @@  typedef int decompress_fn(unsigned char *inbuf, unsigned int len,
  * posp    - if non-null, input position (number of bytes read) will be
  *           returned here
  * error   - error reporting function
+ * userptr - user pointer to pass to flush and fill
  *
  * If len != 0, inbuf should contain all the necessary input data, and fill
  * should be NULL
@@ -29,6 +31,8 @@  typedef int decompress_fn(unsigned char *inbuf, unsigned int len,
  * decompressor (outbuf = NULL), and the flush function will be called to
  * flush the output buffer at the appropriate time (decompressor and stream
  * dependent).
+ *
+ * Flush and fill's third argument is a user pointer for book keeping purposes.
  */
 
 decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4, unzstd;