|  | #include <zutil.h> | 
|  | #include <error.h> | 
|  | #include <slab.h> | 
|  | #include <mm.h> | 
|  | #include <kmalloc.h> | 
|  |  | 
|  | /* Utility function: initialize zlib, unpack binary blob, clean up zlib, | 
|  | * return len or negative error code. | 
|  | */ | 
|  | int zlib_inflate_blob(void *gunzip_buf, unsigned int sz, | 
|  | const void *buf, unsigned int len) | 
|  | { | 
|  | const uint8_t *zbuf = buf; | 
|  | struct z_stream_s *strm; | 
|  | int rc; | 
|  |  | 
|  | rc = -ENOMEM; | 
|  | strm = kmalloc(sizeof(*strm), KMALLOC_WAIT); | 
|  | if (strm == NULL) | 
|  | goto gunzip_nomem1; | 
|  | strm->workspace = kmalloc(zlib_inflate_workspacesize(), KMALLOC_WAIT); | 
|  | if (strm->workspace == NULL) | 
|  | goto gunzip_nomem2; | 
|  |  | 
|  | /* gzip header (1f,8b,08... 10 bytes total + possible asciz filename) | 
|  | * expected to be stripped from input | 
|  | */ | 
|  | strm->next_in = zbuf; | 
|  | strm->avail_in = len; | 
|  | strm->next_out = gunzip_buf; | 
|  | strm->avail_out = sz; | 
|  |  | 
|  | rc = zlib_inflateInit2(strm, -MAX_WBITS); | 
|  | if (rc == Z_OK) { | 
|  | rc = zlib_inflate(strm, Z_FINISH); | 
|  | /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ | 
|  | if (rc == Z_STREAM_END) | 
|  | rc = sz - strm->avail_out; | 
|  | else | 
|  | rc = -EINVAL; | 
|  | zlib_inflateEnd(strm); | 
|  | } else | 
|  | rc = -EINVAL; | 
|  |  | 
|  | kfree(strm->workspace); | 
|  | gunzip_nomem2: | 
|  | kfree(strm); | 
|  | gunzip_nomem1: | 
|  | return rc; /* returns Z_OK (0) if successful */ | 
|  | } |