uncompress.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * uncompress.c
  4. *
  5. * (C) Copyright 1999 Linus Torvalds
  6. *
  7. * cramfs interfaces to the uncompression library. There's really just
  8. * three entrypoints:
  9. *
  10. * - cramfs_uncompress_init() - called to initialize the thing.
  11. * - cramfs_uncompress_exit() - tell me when you're done
  12. * - cramfs_uncompress_block() - uncompress a block.
  13. *
  14. * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
  15. * only have one stream, and we'll initialize it only once even if it
  16. * then is used by multiple filesystems.
  17. */
  18. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  19. #include <linux/kernel.h>
  20. #include <linux/errno.h>
  21. #include <linux/vmalloc.h>
  22. #include <linux/zlib.h>
  23. #include "internal.h"
  24. static z_stream stream;
  25. static int initialized;
  26. /* Returns length of decompressed data. */
  27. int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
  28. {
  29. int err;
  30. stream.next_in = src;
  31. stream.avail_in = srclen;
  32. stream.next_out = dst;
  33. stream.avail_out = dstlen;
  34. err = zlib_inflateReset(&stream);
  35. if (err != Z_OK) {
  36. pr_err("zlib_inflateReset error %d\n", err);
  37. zlib_inflateEnd(&stream);
  38. zlib_inflateInit(&stream);
  39. }
  40. err = zlib_inflate(&stream, Z_FINISH);
  41. if (err != Z_STREAM_END)
  42. goto err;
  43. return stream.total_out;
  44. err:
  45. pr_err("Error %d while decompressing!\n", err);
  46. pr_err("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
  47. return -EIO;
  48. }
  49. int cramfs_uncompress_init(void)
  50. {
  51. if (!initialized++) {
  52. stream.workspace = vmalloc(zlib_inflate_workspacesize());
  53. if (!stream.workspace) {
  54. initialized = 0;
  55. return -ENOMEM;
  56. }
  57. stream.next_in = NULL;
  58. stream.avail_in = 0;
  59. zlib_inflateInit(&stream);
  60. }
  61. return 0;
  62. }
  63. void cramfs_uncompress_exit(void)
  64. {
  65. if (!--initialized) {
  66. zlib_inflateEnd(&stream);
  67. vfree(stream.workspace);
  68. }
  69. }