Blame view

fs/squashfs/zlib_wrapper.c 3.47 KB
e6a6d3795   Phillip Lougher   Squashfs: move zl...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   * Squashfs - a compressed read only filesystem for Linux
   *
   * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
   * Phillip Lougher <phillip@lougher.demon.co.uk>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2,
   * or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   *
   * zlib_wrapper.c
   */
  
  
  #include <linux/mutex.h>
  #include <linux/buffer_head.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
e6a6d3795   Phillip Lougher   Squashfs: move zl...
28
29
30
31
32
33
  #include <linux/zlib.h>
  
  #include "squashfs_fs.h"
  #include "squashfs_fs_sb.h"
  #include "squashfs_fs_i.h"
  #include "squashfs.h"
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
34
  #include "decompressor.h"
e6a6d3795   Phillip Lougher   Squashfs: move zl...
35

4c0f0bb23   Phillip Lougher   Squashfs: add a d...
36
  static void *zlib_init(struct squashfs_sb_info *dummy)
f1a40359f   Phillip Lougher   Squashfs: factor ...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  {
  	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
  	if (stream == NULL)
  		goto failed;
  	stream->workspace = kmalloc(zlib_inflate_workspacesize(),
  		GFP_KERNEL);
  	if (stream->workspace == NULL)
  		goto failed;
  
  	return stream;
  
  failed:
  	ERROR("Failed to allocate zlib workspace
  ");
  	kfree(stream);
  	return NULL;
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
54
  static void zlib_free(void *strm)
f1a40359f   Phillip Lougher   Squashfs: factor ...
55
56
57
58
59
60
61
  {
  	z_stream *stream = strm;
  
  	if (stream)
  		kfree(stream->workspace);
  	kfree(stream);
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
62
  static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
e6a6d3795   Phillip Lougher   Squashfs: move zl...
63
64
65
66
67
  	struct buffer_head **bh, int b, int offset, int length, int srclength,
  	int pages)
  {
  	int zlib_err = 0, zlib_init = 0;
  	int avail, bytes, k = 0, page = 0;
f1a40359f   Phillip Lougher   Squashfs: factor ...
68
  	z_stream *stream = msblk->stream;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
69
70
  
  	mutex_lock(&msblk->read_data_mutex);
f1a40359f   Phillip Lougher   Squashfs: factor ...
71
72
  	stream->avail_out = 0;
  	stream->avail_in = 0;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
73
74
75
  
  	bytes = length;
  	do {
f1a40359f   Phillip Lougher   Squashfs: factor ...
76
  		if (stream->avail_in == 0 && k < b) {
e6a6d3795   Phillip Lougher   Squashfs: move zl...
77
78
79
80
81
82
83
84
85
86
87
  			avail = min(bytes, msblk->devblksize - offset);
  			bytes -= avail;
  			wait_on_buffer(bh[k]);
  			if (!buffer_uptodate(bh[k]))
  				goto release_mutex;
  
  			if (avail == 0) {
  				offset = 0;
  				put_bh(bh[k++]);
  				continue;
  			}
f1a40359f   Phillip Lougher   Squashfs: factor ...
88
89
  			stream->next_in = bh[k]->b_data + offset;
  			stream->avail_in = avail;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
90
91
  			offset = 0;
  		}
f1a40359f   Phillip Lougher   Squashfs: factor ...
92
93
94
  		if (stream->avail_out == 0 && page < pages) {
  			stream->next_out = buffer[page++];
  			stream->avail_out = PAGE_CACHE_SIZE;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
95
96
97
  		}
  
  		if (!zlib_init) {
f1a40359f   Phillip Lougher   Squashfs: factor ...
98
  			zlib_err = zlib_inflateInit(stream);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
99
100
101
102
103
104
105
106
107
  			if (zlib_err != Z_OK) {
  				ERROR("zlib_inflateInit returned unexpected "
  					"result 0x%x, srclength %d
  ",
  					zlib_err, srclength);
  				goto release_mutex;
  			}
  			zlib_init = 1;
  		}
f1a40359f   Phillip Lougher   Squashfs: factor ...
108
  		zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
109

f1a40359f   Phillip Lougher   Squashfs: factor ...
110
  		if (stream->avail_in == 0 && k < b)
e6a6d3795   Phillip Lougher   Squashfs: move zl...
111
112
113
114
115
116
117
118
  			put_bh(bh[k++]);
  	} while (zlib_err == Z_OK);
  
  	if (zlib_err != Z_STREAM_END) {
  		ERROR("zlib_inflate error, data probably corrupt
  ");
  		goto release_mutex;
  	}
f1a40359f   Phillip Lougher   Squashfs: factor ...
119
  	zlib_err = zlib_inflateEnd(stream);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
120
121
122
123
124
  	if (zlib_err != Z_OK) {
  		ERROR("zlib_inflate error, data probably corrupt
  ");
  		goto release_mutex;
  	}
792590c72   Phillip Lougher   squashfs: fix loc...
125
  	length = stream->total_out;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
126
  	mutex_unlock(&msblk->read_data_mutex);
792590c72   Phillip Lougher   squashfs: fix loc...
127
  	return length;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
128
129
130
131
132
133
134
135
136
  
  release_mutex:
  	mutex_unlock(&msblk->read_data_mutex);
  
  	for (; k < b; k++)
  		put_bh(bh[k]);
  
  	return -EIO;
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
137
138
139
140
141
142
143
144
145
  
  const struct squashfs_decompressor squashfs_zlib_comp_ops = {
  	.init = zlib_init,
  	.free = zlib_free,
  	.decompress = zlib_uncompress,
  	.id = ZLIB_COMPRESSION,
  	.name = "zlib",
  	.supported = 1
  };