1 /* 2 * Copyright (c) 1997, 2020, 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 throwInternalErrorHelper(JNIEnv *env, z_stream *strm, const char *fixmsg) { 80 const char *msg = NULL; 81 msg = (strm->msg != NULL) ? strm->msg : fixmsg; 82 JNU_ThrowInternalError(env, msg); 83 } 84 85 static void checkSetDictionaryResult(JNIEnv *env, jlong addr, jint res) 86 { 87 z_stream *strm = (z_stream *) jlong_to_ptr(addr); 88 switch (res) { 89 case Z_OK: 90 break; 91 case Z_STREAM_ERROR: 92 JNU_ThrowIllegalArgumentException(env, 0); 93 break; 94 default: 95 throwInternalErrorHelper(env, strm, "unknown error in checkSetDictionaryResult"); 96 break; 97 } 98 } 99 100 JNIEXPORT void JNICALL 101 Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr, 102 jbyteArray b, jint off, jint len) 103 { 104 int res; 105 Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); 106 if (buf == NULL) /* out of memory */ 107 return; 108 res = deflateSetDictionary(jlong_to_ptr(addr), buf, len); 109 (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); 110 checkSetDictionaryResult(env, addr, res); 111 } 112 113 JNIEXPORT void JNICALL 114 Java_java_util_zip_Deflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr, 115 jlong bufferAddr, jint len) 116 { 117 int res; 118 Bytef *buf = jlong_to_ptr(bufferAddr); 119 res = deflateSetDictionary(jlong_to_ptr(addr), buf, len); 120 checkSetDictionaryResult(env, addr, res); 121 } 122 123 static jint doDeflate(JNIEnv *env, jlong addr, 124 jbyte *input, jint inputLen, 125 jbyte *output, jint outputLen, 126 jint flush, jint params) 127 { 128 z_stream *strm = jlong_to_ptr(addr); 129 int setParams = params & 1; 130 int res; 131 132 strm->next_in = (Bytef *) input; 133 strm->next_out = (Bytef *) output; 134 strm->avail_in = inputLen; 135 strm->avail_out = outputLen; 136 137 if (setParams) { 138 int strategy = (params >> 1) & 3; 139 int level = params >> 3; 140 res = deflateParams(strm, level, strategy); 141 } else { 142 res = deflate(strm, flush); 143 } 144 return res; 145 } 146 147 static jlong checkDeflateStatus(JNIEnv *env, jlong addr, 148 jint inputLen, 149 jint outputLen, 150 jint params, int res) 151 { 152 z_stream *strm = jlong_to_ptr(addr); 153 jint inputUsed = 0, outputUsed = 0; 154 int finished = 0; 155 int setParams = params & 1; 156 157 if (setParams) { 158 switch (res) { 159 case Z_OK: 160 setParams = 0; 161 /* fall through */ 162 case Z_BUF_ERROR: 163 inputUsed = inputLen - strm->avail_in; 164 outputUsed = outputLen - strm->avail_out; 165 break; 166 default: 167 throwInternalErrorHelper(env, strm, "unknown error in checkDeflateStatus, setParams case"); 168 return 0; 169 } 170 } else { 171 switch (res) { 172 case Z_STREAM_END: 173 finished = 1; 174 /* fall through */ 175 case Z_OK: 176 case Z_BUF_ERROR: 177 inputUsed = inputLen - strm->avail_in; 178 outputUsed = outputLen - strm->avail_out; 179 break; 180 default: 181 throwInternalErrorHelper(env, strm, "unknown error in checkDeflateStatus"); 182 return 0; 183 } 184 } 185 return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)setParams) << 63); 186 } 187 188 JNIEXPORT jlong JNICALL 189 Java_java_util_zip_Deflater_deflateBytesBytes(JNIEnv *env, jobject this, jlong addr, 190 jbyteArray inputArray, jint inputOff, jint inputLen, 191 jbyteArray outputArray, jint outputOff, jint outputLen, 192 jint flush, jint params) 193 { 194 jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); 195 jbyte *output; 196 jlong retVal; 197 jint res; 198 199 if (input == NULL) { 200 if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 201 JNU_ThrowOutOfMemoryError(env, 0); 202 return 0L; 203 } 204 output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); 205 if (output == NULL) { 206 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 207 if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 208 JNU_ThrowOutOfMemoryError(env, 0); 209 return 0L; 210 } 211 212 res = doDeflate(env, addr, input + inputOff, inputLen,output + outputOff, 213 outputLen, flush, params); 214 215 (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0); 216 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 217 218 retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); 219 return retVal; 220 } 221 222 223 JNIEXPORT jlong JNICALL 224 Java_java_util_zip_Deflater_deflateBytesBuffer(JNIEnv *env, jobject this, jlong addr, 225 jbyteArray inputArray, jint inputOff, jint inputLen, 226 jlong outputBuffer, jint outputLen, 227 jint flush, jint params) 228 { 229 jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); 230 jbyte *output; 231 jlong retVal; 232 jint res; 233 if (input == NULL) { 234 if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 235 JNU_ThrowOutOfMemoryError(env, 0); 236 return 0L; 237 } 238 output = jlong_to_ptr(outputBuffer); 239 240 res = doDeflate(env, addr, input + inputOff, inputLen, output, outputLen, 241 flush, params); 242 243 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 244 245 retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); 246 return retVal; 247 } 248 249 JNIEXPORT jlong JNICALL 250 Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv *env, jobject this, jlong addr, 251 jlong inputBuffer, jint inputLen, 252 jbyteArray outputArray, jint outputOff, jint outputLen, 253 jint flush, jint params) 254 { 255 jbyte *input = jlong_to_ptr(inputBuffer); 256 jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); 257 jlong retVal; 258 jint res; 259 if (output == NULL) { 260 if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 261 JNU_ThrowOutOfMemoryError(env, 0); 262 return 0L; 263 } 264 265 res = doDeflate(env, addr, input, inputLen, output + outputOff, outputLen, 266 flush, params); 267 (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0); 268 269 retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); 270 return retVal; 271 } 272 273 JNIEXPORT jlong JNICALL 274 Java_java_util_zip_Deflater_deflateBufferBuffer(JNIEnv *env, jobject this, jlong addr, 275 jlong inputBuffer, jint inputLen, 276 jlong outputBuffer, jint outputLen, 277 jint flush, jint params) 278 { 279 jbyte *input = jlong_to_ptr(inputBuffer); 280 jbyte *output = jlong_to_ptr(outputBuffer); 281 jlong retVal; 282 jint res; 283 284 res = doDeflate(env, addr, input, inputLen, output, outputLen, flush, params); 285 retVal = checkDeflateStatus(env, addr, inputLen, outputLen, params, res); 286 return retVal; 287 } 288 289 JNIEXPORT jint JNICALL 290 Java_java_util_zip_Deflater_getAdler(JNIEnv *env, jclass cls, jlong addr) 291 { 292 return ((z_stream *)jlong_to_ptr(addr))->adler; 293 } 294 295 JNIEXPORT void JNICALL 296 Java_java_util_zip_Deflater_reset(JNIEnv *env, jclass cls, jlong addr) 297 { 298 if (deflateReset((z_stream *)jlong_to_ptr(addr)) != Z_OK) { 299 JNU_ThrowInternalError(env, "deflateReset failed"); 300 } 301 } 302 303 JNIEXPORT void JNICALL 304 Java_java_util_zip_Deflater_end(JNIEnv *env, jclass cls, jlong addr) 305 { 306 if (deflateEnd((z_stream *)jlong_to_ptr(addr)) == Z_STREAM_ERROR) { 307 JNU_ThrowInternalError(env, "deflateEnd failed"); 308 } else { 309 free((z_stream *)jlong_to_ptr(addr)); 310 } 311 }