source: rtems/cpukit/libfs/src/jffs2/src/compr_zlib.c @ 0282e83

4.115
Last change on this file since 0282e83 was 3c96bee, checked in by Sebastian Huber <sebastian.huber@…>, on 09/12/13 at 13:32:07

JFFS2: Add RTEMS support

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright © 2001-2007 Red Hat, Inc.
5 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
6 *
7 * Created by David Woodhouse <dwmw2@infradead.org>
8 *
9 * For licensing information, see the file 'LICENCE' in this directory.
10 *
11 */
12
13#if !defined(__KERNEL__) && !defined(__ECOS)
14#error "The userspace support got too messy and was removed. Update your mkfs.jffs2"
15#endif
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19#include <linux/kernel.h>
20#include <linux/zlib.h>
21#include <linux/zutil.h>
22#include "nodelist.h"
23#include "compr.h"
24
25        /* Plan: call deflate() with avail_in == *sourcelen,
26                avail_out = *dstlen - 12 and flush == Z_FINISH.
27                If it doesn't manage to finish, call it again with
28                avail_in == 0 and avail_out set to the remaining 12
29                bytes for it to clean up.
30           Q: Is 12 bytes sufficient?
31        */
32#define STREAM_END_SPACE 12
33
34static DEFINE_MUTEX(deflate_mutex);
35static DEFINE_MUTEX(inflate_mutex);
36
37static rtems_jffs2_compressor_zlib_control *get_zlib_control(
38        rtems_jffs2_compressor_control *super
39)
40{
41        return (rtems_jffs2_compressor_zlib_control *) super;
42}
43
44uint16_t rtems_jffs2_compressor_zlib_compress(
45        rtems_jffs2_compressor_control *super,
46        unsigned char *data_in,
47        unsigned char *cpage_out,
48        uint32_t *sourcelen,
49        uint32_t *dstlen
50)
51{
52        rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
53        z_stream *def_strm = &self->stream;
54        int ret;
55
56        if (*dstlen <= STREAM_END_SPACE)
57                return JFFS2_COMPR_NONE;
58
59        mutex_lock(&deflate_mutex);
60
61        if (Z_OK != zlib_deflateInit(def_strm, 3)) {
62                pr_warn("deflateInit failed\n");
63                mutex_unlock(&deflate_mutex);
64                return JFFS2_COMPR_NONE;
65        }
66
67        def_strm->next_in = data_in;
68        def_strm->total_in = 0;
69
70        def_strm->next_out = cpage_out;
71        def_strm->total_out = 0;
72
73        while (def_strm->total_out < *dstlen - STREAM_END_SPACE && def_strm->total_in < *sourcelen) {
74                def_strm->avail_out = *dstlen - (def_strm->total_out + STREAM_END_SPACE);
75                def_strm->avail_in = min((unsigned)(*sourcelen-def_strm->total_in), def_strm->avail_out);
76                jffs2_dbg(1, "calling deflate with avail_in %d, avail_out %d\n",
77                          def_strm->avail_in, def_strm->avail_out);
78                ret = zlib_deflate(def_strm, Z_PARTIAL_FLUSH);
79                jffs2_dbg(1, "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n",
80                          def_strm->avail_in, def_strm->avail_out,
81                          def_strm->total_in, def_strm->total_out);
82                if (ret != Z_OK) {
83                        jffs2_dbg(1, "deflate in loop returned %d\n", ret);
84                        zlib_deflateEnd(def_strm);
85                        mutex_unlock(&deflate_mutex);
86                        return JFFS2_COMPR_NONE;
87                }
88        }
89        def_strm->avail_out += STREAM_END_SPACE;
90        def_strm->avail_in = 0;
91        ret = zlib_deflate(def_strm, Z_FINISH);
92        zlib_deflateEnd(def_strm);
93
94        if (ret != Z_STREAM_END) {
95                jffs2_dbg(1, "final deflate returned %d\n", ret);
96                ret = JFFS2_COMPR_NONE;
97                goto out;
98        }
99
100        if (def_strm->total_out >= def_strm->total_in) {
101                jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
102                          def_strm->total_in, def_strm->total_out);
103                ret = JFFS2_COMPR_NONE;
104                goto out;
105        }
106
107        jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
108                  def_strm->total_in, def_strm->total_out);
109
110        *dstlen = def_strm->total_out;
111        *sourcelen = def_strm->total_in;
112        ret = JFFS2_COMPR_ZLIB;
113 out:
114        mutex_unlock(&deflate_mutex);
115        return ret;
116}
117
118int rtems_jffs2_compressor_zlib_decompress(
119        rtems_jffs2_compressor_control *super,
120        uint16_t comprtype,
121        unsigned char *data_in,
122        unsigned char *cpage_out,
123        uint32_t srclen,
124        uint32_t destlen
125)
126{
127        rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
128        z_stream *inf_strm = &self->stream;
129        int ret;
130        int wbits = MAX_WBITS;
131
132        if (comprtype != JFFS2_COMPR_ZLIB) {
133                return -EIO;
134        }
135
136        mutex_lock(&inflate_mutex);
137
138        inf_strm->next_in = data_in;
139        inf_strm->avail_in = srclen;
140        inf_strm->total_in = 0;
141
142        inf_strm->next_out = cpage_out;
143        inf_strm->avail_out = destlen;
144        inf_strm->total_out = 0;
145
146        /* If it's deflate, and it's got no preset dictionary, then
147           we can tell zlib to skip the adler32 check. */
148        if (srclen > 2 && !(data_in[1] & PRESET_DICT) &&
149            ((data_in[0] & 0x0f) == Z_DEFLATED) &&
150            !(((data_in[0]<<8) + data_in[1]) % 31)) {
151
152                jffs2_dbg(2, "inflate skipping adler32\n");
153                wbits = -((data_in[0] >> 4) + 8);
154                inf_strm->next_in += 2;
155                inf_strm->avail_in -= 2;
156        } else {
157                /* Let this remain D1 for now -- it should never happen */
158                jffs2_dbg(1, "inflate not skipping adler32\n");
159        }
160
161
162        if (Z_OK != zlib_inflateInit2(inf_strm, wbits)) {
163                pr_warn("inflateInit failed\n");
164                mutex_unlock(&inflate_mutex);
165                return -EIO;
166        }
167
168        while((ret = zlib_inflate(inf_strm, Z_FINISH)) == Z_OK)
169                ;
170        if (ret != Z_STREAM_END) {
171                pr_notice("inflate returned %d\n", ret);
172        }
173        zlib_inflateEnd(inf_strm);
174        mutex_unlock(&inflate_mutex);
175        return 0;
176}
Note: See TracBrowser for help on using the repository browser.