1 | /* |
2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle in the LICENSE file that accompanied this code. |
10 | * |
11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | * version 2 for more details (a copy is included in the LICENSE file that |
15 | * accompanied this code). |
16 | * |
17 | * You should have received a copy of the GNU General Public License version |
18 | * 2 along with this work; if not, write to the Free Software Foundation, |
19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
20 | * |
21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * questions. |
24 | */ |
25 | |
26 | /* |
27 | * Native method support for java.util.zip.Deflater |
28 | */ |
29 | |
30 | #include <stdio.h> |
31 | #include <stdlib.h> |
32 | #include "jlong.h" |
33 | #include "jni.h" |
34 | #include "jni_util.h" |
35 | #include <zlib.h> |
36 | |
37 | #include "java_util_zip_Deflater.h" |
38 | |
39 | #define DEF_MEM_LEVEL 8 |
40 | |
41 | JNIEXPORT jlong JNICALL |
42 | Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level, |
43 | jint strategy, jboolean nowrap) |
44 | { |
45 | z_stream *strm = calloc(1, sizeof(z_stream)); |
46 | |
47 | if (strm == 0) { |
48 | JNU_ThrowOutOfMemoryError(env, 0); |
49 | return jlong_zero; |
50 | } else { |
51 | const char *msg; |
52 | int ret = deflateInit2(strm, level, Z_DEFLATED, |
53 | nowrap ? -MAX_WBITS : MAX_WBITS, |
54 | DEF_MEM_LEVEL, strategy); |
55 | switch (ret) { |
56 | case Z_OK: |
57 | return ptr_to_jlong(strm); |
58 | case Z_MEM_ERROR: |
59 | free(strm); |
60 | JNU_ThrowOutOfMemoryError(env, 0); |
61 | return jlong_zero; |
62 | case Z_STREAM_ERROR: |
63 | free(strm); |
64 | JNU_ThrowIllegalArgumentException(env, 0); |
65 | return jlong_zero; |
66 | default: |
67 | msg = ((strm->msg != NULL) ? strm->msg : |
68 | (ret == Z_VERSION_ERROR) ? |
69 | "zlib returned Z_VERSION_ERROR: " |
70 | "compile time and runtime zlib implementations differ" : |
71 | "unknown error initializing zlib library" ); |
72 | free(strm); |
73 | JNU_ThrowInternalError(env, msg); |
74 | return jlong_zero; |
75 | } |
76 | } |
77 | } |
78 | |
79 | static void checkSetDictionaryResult(JNIEnv *env, jlong addr, jint res) |
80 | { |
81 | switch (res) { |
82 | case Z_OK: |
83 | break; |
84 | case Z_STREAM_ERROR: |
85 | JNU_ThrowIllegalArgumentException(env, 0); |
86 | break; |
87 | default: |
88 | JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg); |
89 | break; |
90 | } |
91 | } |
92 | |
93 | JNIEXPORT void JNICALL |
94 | Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr, |
95 | jbyteArray b, jint off, jint len) |
96 | { |
97 | int res; |
98 | Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); |
99 | if (buf == NULL) /* out of memory */ |
100 | return; |
101 | res = deflateSetDictionary(jlong_to_ptr(addr), buf, len); |
102 | (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); |
103 | checkSetDictionaryResult(env, addr, res); |
104 | } |
105 | |
106 | JNIEXPORT void JNICALL |
107 | Java_java_util_zip_Deflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr, |
108 | jlong bufferAddr, jint len) |
109 | { |
110 | int res; |
111 | Bytef *buf = jlong_to_ptr(bufferAddr); |
112 | res = deflateSetDictionary(jlong_to_ptr(addr), buf, len); |
113 | checkSetDictionaryResult(env, addr, res); |
114 | } |
115 | |
116 | static jint doDeflate(JNIEnv *env, jlong addr, |
117 | jbyte *input, jint inputLen, |
118 | jbyte *output, jint outputLen, |
119 | jint flush, jint params) |
120 | { |
121 | z_stream *strm = jlong_to_ptr(addr); |
122 | int setParams = params & 1; |
123 | int res; |
124 | |
125 | strm->next_in = (Bytef *) input; |
126 | strm->next_out = (Bytef *) output; |
127 | strm->avail_in = inputLen; |
128 | strm->avail_out = outputLen; |
129 | |
130 | if (setParams) { |
131 | int strategy = (params >> 1) & 3; |
132 | int level = params >> 3; |
133 | res = deflateParams(strm, level, strategy); |
134 | } else { |
135 | res = deflate(strm, flush); |
136 | } |
137 | return res; |
138 | } |
139 | |
140 | static jlong checkDeflateStatus(JNIEnv *env, jlong addr, |
141 | jint inputLen, |
142 | jint outputLen, |
143 | jint params, int res) |
144 | { |
145 | z_stream *strm = jlong_to_ptr(addr); |
146 | jint inputUsed = 0, outputUsed = 0; |
147 | int finished = 0; |
148 | int setParams = params & 1; |
149 | |
150 | if (setParams) { |
151 | switch (res) { |
152 | case Z_OK: |
153 | setParams = 0; |
154 | /* fall through */ |
155 | case Z_BUF_ERROR: |
156 | inputUsed = inputLen - strm->avail_in; |
157 | outputUsed = outputLen - strm->avail_out; |
158 | break; |
159 | default: |
160 | JNU_ThrowInternalError(env, strm->msg); |
161 | return 0; |
162 | } |
163 | } else { |
164 | switch (res) { |
165 | case Z_STREAM_END: |
166 | finished = 1; |
167 | /* fall through */ |
168 | case Z_OK: |
169 | case Z_BUF_ERROR: |
170 | inputUsed = inputLen - strm->avail_in; |
171 | outputUsed = outputLen - strm->avail_out; |
172 | break; |
173 | default: |
174 | JNU_ThrowInternalError(env, strm->msg); |
175 | return 0; |
176 | } |
177 | } |
178 | return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)setParams) << 63); |
179 | } |
180 | |
181 | JNIEXPORT jlong JNICALL |
182 | Java_java_util_zip_Deflater_deflateBytesBytes(JNIEnv *env, jobject this, jlong addr, |
183 | jbyteArray inputArray, jint inputOff, jint inputLen, |
184 | jbyteArray outputArray, jint outputOff, jint outputLen, |
185 | jint flush, jint params) |
186 | { |
187 | jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); |
188 | jbyte *output; |
189 | jlong retVal; |
190 | jint res; |
191 | |
192 | if (input == NULL) { |
193 | if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) |
194 | JNU_ThrowOutOfMemoryError(env, 0); |
195 | return 0L; |
196 | } |
197 | output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); |
198 | if (output == NULL) { |
199 | (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); |
200 | if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) |
201 | JNU_ThrowOutOfMemoryError(env, 0); |
202 | return 0L; |
203 | } |
204 | |
205 | res = doDeflate(env, addr, input + inputOff, inputLen,output + outputOff, |
206 | outputLen, flush, params); |
207 | |
208 | (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0); |
209 | (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); |
210 | |
211 | retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); |
212 | return retVal; |
213 | } |
214 | |
215 | |
216 | JNIEXPORT jlong JNICALL |
217 | Java_java_util_zip_Deflater_deflateBytesBuffer(JNIEnv *env, jobject this, jlong addr, |
218 | jbyteArray inputArray, jint inputOff, jint inputLen, |
219 | jlong outputBuffer, jint outputLen, |
220 | jint flush, jint params) |
221 | { |
222 | jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); |
223 | jbyte *output; |
224 | jlong retVal; |
225 | jint res; |
226 | if (input == NULL) { |
227 | if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) |
228 | JNU_ThrowOutOfMemoryError(env, 0); |
229 | return 0L; |
230 | } |
231 | output = jlong_to_ptr(outputBuffer); |
232 | |
233 | res = doDeflate(env, addr, input + inputOff, inputLen, output, outputLen, |
234 | flush, params); |
235 | |
236 | (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); |
237 | |
238 | retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); |
239 | return retVal; |
240 | } |
241 | |
242 | JNIEXPORT jlong JNICALL |
243 | Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv *env, jobject this, jlong addr, |
244 | jlong inputBuffer, jint inputLen, |
245 | jbyteArray outputArray, jint outputOff, jint outputLen, |
246 | jint flush, jint params) |
247 | { |
248 | jbyte *input = jlong_to_ptr(inputBuffer); |
249 | jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); |
250 | jlong retVal; |
251 | jint res; |
252 | if (output == NULL) { |
253 | if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) |
254 | JNU_ThrowOutOfMemoryError(env, 0); |
255 | return 0L; |
256 | } |
257 | |
258 | res = doDeflate(env, addr, input, inputLen, output + outputOff, outputLen, |
259 | flush, params); |
260 | (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0); |
261 | |
262 | retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); |
263 | return retVal; |
264 | } |
265 | |
266 | JNIEXPORT jlong JNICALL |
267 | Java_java_util_zip_Deflater_deflateBufferBuffer(JNIEnv *env, jobject this, jlong addr, |
268 | jlong inputBuffer, jint inputLen, |
269 | jlong outputBuffer, jint outputLen, |
270 | jint flush, jint params) |
271 | { |
272 | jbyte *input = jlong_to_ptr(inputBuffer); |
273 | jbyte *output = jlong_to_ptr(outputBuffer); |
274 | jlong retVal; |
275 | jint res; |
276 | |
277 | res = doDeflate(env, addr, input, inputLen, output, outputLen, flush, params); |
278 | retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); |
279 | return retVal; |
280 | } |
281 | |
282 | JNIEXPORT jint JNICALL |
283 | Java_java_util_zip_Deflater_getAdler(JNIEnv *env, jclass cls, jlong addr) |
284 | { |
285 | return ((z_stream *)jlong_to_ptr(addr))->adler; |
286 | } |
287 | |
288 | JNIEXPORT void JNICALL |
289 | Java_java_util_zip_Deflater_reset(JNIEnv *env, jclass cls, jlong addr) |
290 | { |
291 | if (deflateReset((z_stream *)jlong_to_ptr(addr)) != Z_OK) { |
292 | JNU_ThrowInternalError(env, 0); |
293 | } |
294 | } |
295 | |
296 | JNIEXPORT void JNICALL |
297 | Java_java_util_zip_Deflater_end(JNIEnv *env, jclass cls, jlong addr) |
298 | { |
299 | if (deflateEnd((z_stream *)jlong_to_ptr(addr)) == Z_STREAM_ERROR) { |
300 | JNU_ThrowInternalError(env, 0); |
301 | } else { |
302 | free((z_stream *)jlong_to_ptr(addr)); |
303 | } |
304 | } |
305 | |