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, output, 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 }