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