25 26 /* 27 * Native method support for java.util.zip.Inflater 28 */ 29 30 #include <stddef.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <string.h> 35 #include "jlong.h" 36 #include "jni.h" 37 #include "jvm.h" 38 #include "jni_util.h" 39 #include <zlib.h> 40 #include "java_util_zip_Inflater.h" 41 42 #define ThrowDataFormatException(env, msg) \ 43 JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg) 44 45 static jfieldID needDictID; 46 static jfieldID finishedID; 47 static jfieldID bufID, offID, lenID; 48 49 JNIEXPORT void JNICALL 50 Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls) 51 { 52 needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z"); 53 CHECK_NULL(needDictID); 54 finishedID = (*env)->GetFieldID(env, cls, "finished", "Z"); 55 CHECK_NULL(finishedID); 56 bufID = (*env)->GetFieldID(env, cls, "buf", "[B"); 57 CHECK_NULL(bufID); 58 offID = (*env)->GetFieldID(env, cls, "off", "I"); 59 CHECK_NULL(offID); 60 lenID = (*env)->GetFieldID(env, cls, "len", "I"); 61 CHECK_NULL(lenID); 62 } 63 64 JNIEXPORT jlong JNICALL 65 Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) 66 { 67 z_stream *strm = calloc(1, sizeof(z_stream)); 68 69 if (strm == NULL) { 70 JNU_ThrowOutOfMemoryError(env, 0); 71 return jlong_zero; 72 } else { 73 const char *msg; 74 int ret = inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS); 75 switch (ret) { 76 case Z_OK: 77 return ptr_to_jlong(strm); 78 case Z_MEM_ERROR: 79 free(strm); 80 JNU_ThrowOutOfMemoryError(env, 0); 81 return jlong_zero; 82 default: 83 msg = ((strm->msg != NULL) ? strm->msg : 84 (ret == Z_VERSION_ERROR) ? 85 "zlib returned Z_VERSION_ERROR: " 86 "compile time and runtime zlib implementations differ" : 87 (ret == Z_STREAM_ERROR) ? 88 "inflateInit2 returned Z_STREAM_ERROR" : 89 "unknown error initializing zlib library"); 90 free(strm); 91 JNU_ThrowInternalError(env, msg); 92 return jlong_zero; 93 } 94 } 95 } 96 97 JNIEXPORT void JNICALL 98 Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr, 99 jarray b, jint off, jint len) 100 { 101 Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); 102 int res; 103 if (buf == 0) /* out of memory */ 104 return; 105 res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len); 106 (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); 107 switch (res) { 108 case Z_OK: 109 break; 110 case Z_STREAM_ERROR: 111 case Z_DATA_ERROR: 112 JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg); 113 break; 114 default: 115 JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg); 116 break; 117 } 118 } 119 120 JNIEXPORT jint JNICALL 121 Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr, 122 jarray b, jint off, jint len) 123 { 124 z_stream *strm = jlong_to_ptr(addr); 125 jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID); 126 jint this_off = (*env)->GetIntField(env, this, offID); 127 jint this_len = (*env)->GetIntField(env, this, lenID); 128 129 jbyte *in_buf; 130 jbyte *out_buf; 131 int ret; 132 133 in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0); 134 if (in_buf == NULL) { 135 if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL) 136 JNU_ThrowOutOfMemoryError(env, 0); 137 return 0; 138 } 139 out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); 140 if (out_buf == NULL) { 141 (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); 142 if (len != 0 && (*env)->ExceptionOccurred(env) == NULL) 143 JNU_ThrowOutOfMemoryError(env, 0); 144 return 0; 145 } 146 strm->next_in = (Bytef *) (in_buf + this_off); 147 strm->next_out = (Bytef *) (out_buf + off); 148 strm->avail_in = this_len; 149 strm->avail_out = len; 150 ret = inflate(strm, Z_PARTIAL_FLUSH); 151 (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); 152 (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); 153 154 switch (ret) { 155 case Z_STREAM_END: 156 (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE); 157 /* fall through */ 158 case Z_OK: 159 this_off += this_len - strm->avail_in; 160 (*env)->SetIntField(env, this, offID, this_off); 161 (*env)->SetIntField(env, this, lenID, strm->avail_in); 162 return (jint) (len - strm->avail_out); 163 case Z_NEED_DICT: 164 (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE); 165 /* Might have consumed some input here! */ 166 this_off += this_len - strm->avail_in; 167 (*env)->SetIntField(env, this, offID, this_off); 168 (*env)->SetIntField(env, this, lenID, strm->avail_in); 169 return 0; 170 case Z_BUF_ERROR: 171 return 0; 172 case Z_DATA_ERROR: 173 ThrowDataFormatException(env, strm->msg); 174 return 0; 175 case Z_MEM_ERROR: 176 JNU_ThrowOutOfMemoryError(env, 0); 177 return 0; 178 default: 179 JNU_ThrowInternalError(env, strm->msg); 180 return 0; 181 } 182 } 183 184 JNIEXPORT jint JNICALL 185 Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr) 186 { 187 return ((z_stream *)jlong_to_ptr(addr))->adler; 188 } 189 190 JNIEXPORT void JNICALL 191 Java_java_util_zip_Inflater_reset(JNIEnv *env, jclass cls, jlong addr) 192 { 193 if (inflateReset(jlong_to_ptr(addr)) != Z_OK) { 194 JNU_ThrowInternalError(env, 0); 195 } 196 } 197 198 JNIEXPORT void JNICALL 199 Java_java_util_zip_Inflater_end(JNIEnv *env, jclass cls, jlong addr) 200 { 201 if (inflateEnd(jlong_to_ptr(addr)) == Z_STREAM_ERROR) { | 25 26 /* 27 * Native method support for java.util.zip.Inflater 28 */ 29 30 #include <stddef.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <errno.h> 34 #include <string.h> 35 #include "jlong.h" 36 #include "jni.h" 37 #include "jvm.h" 38 #include "jni_util.h" 39 #include <zlib.h> 40 #include "java_util_zip_Inflater.h" 41 42 #define ThrowDataFormatException(env, msg) \ 43 JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg) 44 45 static jfieldID inputConsumedID; 46 static jfieldID outputConsumedID; 47 48 JNIEXPORT void JNICALL 49 Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls) 50 { 51 inputConsumedID = (*env)->GetFieldID(env, cls, "inputConsumed", "I"); 52 outputConsumedID = (*env)->GetFieldID(env, cls, "outputConsumed", "I"); 53 CHECK_NULL(inputConsumedID); 54 CHECK_NULL(outputConsumedID); 55 } 56 57 JNIEXPORT jlong JNICALL 58 Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) 59 { 60 z_stream *strm = calloc(1, sizeof(z_stream)); 61 62 if (strm == NULL) { 63 JNU_ThrowOutOfMemoryError(env, 0); 64 return jlong_zero; 65 } else { 66 const char *msg; 67 int ret = inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS); 68 switch (ret) { 69 case Z_OK: 70 return ptr_to_jlong(strm); 71 case Z_MEM_ERROR: 72 free(strm); 73 JNU_ThrowOutOfMemoryError(env, 0); 74 return jlong_zero; 75 default: 76 msg = ((strm->msg != NULL) ? strm->msg : 77 (ret == Z_VERSION_ERROR) ? 78 "zlib returned Z_VERSION_ERROR: " 79 "compile time and runtime zlib implementations differ" : 80 (ret == Z_STREAM_ERROR) ? 81 "inflateInit2 returned Z_STREAM_ERROR" : 82 "unknown error initializing zlib library"); 83 free(strm); 84 JNU_ThrowInternalError(env, msg); 85 return jlong_zero; 86 } 87 } 88 } 89 90 static void doSetDictionary(JNIEnv *env, jlong addr, jbyte *buf, jint len) 91 { 92 int res = inflateSetDictionary(jlong_to_ptr(addr), (Bytef *) buf, len); 93 switch (res) { 94 case Z_OK: 95 break; 96 case Z_STREAM_ERROR: 97 case Z_DATA_ERROR: 98 JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg); 99 break; 100 default: 101 JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg); 102 break; 103 } 104 } 105 106 JNIEXPORT void JNICALL 107 Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr, 108 jbyteArray b, jint off, jint len) 109 { 110 jbyte *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); 111 if (buf == NULL) /* out of memory */ 112 return; 113 doSetDictionary(env, addr, buf + off, len); 114 (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); 115 } 116 117 JNIEXPORT void JNICALL 118 Java_java_util_zip_Inflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr, 119 jlong bufferAddr, jint len) 120 { 121 jbyte *buf = jlong_to_ptr(bufferAddr); 122 doSetDictionary(env, addr, buf, len); 123 } 124 125 static jlong doInflate(JNIEnv *env, jobject this, jlong addr, 126 jbyte *input, jint inputLen, 127 jbyte *output, jint outputLen) 128 { 129 z_stream *strm = jlong_to_ptr(addr); 130 jint inputUsed = 0, outputUsed = 0; 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 int ret = inflate(strm, Z_PARTIAL_FLUSH); 138 int finished = 0; 139 int needDict = 0; 140 141 switch (ret) { 142 case Z_STREAM_END: 143 finished = 1; 144 /* fall through */ 145 case Z_OK: 146 inputUsed = inputLen - strm->avail_in; 147 outputUsed = outputLen - strm->avail_out; 148 break; 149 case Z_NEED_DICT: 150 needDict = 1; 151 /* Might have consumed some input here! */ 152 inputUsed = inputLen - strm->avail_in; 153 /* zlib is unclear about whether output may be produced */ 154 outputUsed = outputLen - strm->avail_out; 155 break; 156 case Z_BUF_ERROR: 157 break; 158 case Z_DATA_ERROR: 159 inputUsed = inputLen - strm->avail_in; 160 (*env)->SetIntField(env, this, inputConsumedID, inputUsed); 161 outputUsed = outputLen - strm->avail_out; 162 (*env)->SetIntField(env, this, outputConsumedID, outputUsed); 163 ThrowDataFormatException(env, strm->msg); 164 break; 165 case Z_MEM_ERROR: 166 JNU_ThrowOutOfMemoryError(env, 0); 167 break; 168 default: 169 JNU_ThrowInternalError(env, strm->msg); 170 break; 171 } 172 return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)needDict) << 63); 173 } 174 175 JNIEXPORT jlong JNICALL 176 Java_java_util_zip_Inflater_inflateBytesBytes(JNIEnv *env, jobject this, jlong addr, 177 jbyteArray inputArray, jint inputOff, jint inputLen, 178 jbyteArray outputArray, jint outputOff, jint outputLen) 179 { 180 jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); 181 if (input == NULL) { 182 if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 183 JNU_ThrowOutOfMemoryError(env, 0); 184 return 0L; 185 } 186 jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); 187 if (output == NULL) { 188 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 189 if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 190 JNU_ThrowOutOfMemoryError(env, 0); 191 return 0L; 192 } 193 194 jlong retVal = doInflate(env, this, addr, 195 input + inputOff, inputLen, 196 output + outputOff, outputLen); 197 198 (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0); 199 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 200 201 return retVal; 202 } 203 204 JNIEXPORT jlong JNICALL 205 Java_java_util_zip_Inflater_inflateBytesBuffer(JNIEnv *env, jobject this, jlong addr, 206 jbyteArray inputArray, jint inputOff, jint inputLen, 207 jlong outputBuffer, jint outputLen) 208 { 209 jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0); 210 if (input == NULL) { 211 if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 212 JNU_ThrowOutOfMemoryError(env, 0); 213 return 0L; 214 } 215 jbyte *output = jlong_to_ptr(outputBuffer); 216 217 jlong retVal = doInflate(env, this, addr, 218 input + inputOff, inputLen, 219 output, outputLen); 220 221 (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0); 222 223 return retVal; 224 } 225 226 JNIEXPORT jlong JNICALL 227 Java_java_util_zip_Inflater_inflateBufferBytes(JNIEnv *env, jobject this, jlong addr, 228 jlong inputBuffer, jint inputLen, 229 jbyteArray outputArray, jint outputOff, jint outputLen) 230 { 231 jbyte *input = jlong_to_ptr(inputBuffer); 232 jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0); 233 if (output == NULL) { 234 if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL) 235 JNU_ThrowOutOfMemoryError(env, 0); 236 return 0L; 237 } 238 239 jlong retVal = doInflate(env, this, addr, 240 input, inputLen, 241 output + outputOff, outputLen); 242 243 (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0); 244 245 return retVal; 246 } 247 248 JNIEXPORT jlong JNICALL 249 Java_java_util_zip_Inflater_inflateBufferBuffer(JNIEnv *env, jobject this, jlong addr, 250 jlong inputBuffer, jint inputLen, 251 jlong outputBuffer, jint outputLen) 252 { 253 jbyte *input = jlong_to_ptr(inputBuffer); 254 jbyte *output = jlong_to_ptr(outputBuffer); 255 256 return doInflate(env, this, addr, 257 input, inputLen, 258 output, outputLen); 259 } 260 261 JNIEXPORT jint JNICALL 262 Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr) 263 { 264 return ((z_stream *)jlong_to_ptr(addr))->adler; 265 } 266 267 JNIEXPORT void JNICALL 268 Java_java_util_zip_Inflater_reset(JNIEnv *env, jclass cls, jlong addr) 269 { 270 if (inflateReset(jlong_to_ptr(addr)) != Z_OK) { 271 JNU_ThrowInternalError(env, 0); 272 } 273 } 274 275 JNIEXPORT void JNICALL 276 Java_java_util_zip_Inflater_end(JNIEnv *env, jclass cls, jlong addr) 277 { 278 if (inflateEnd(jlong_to_ptr(addr)) == Z_STREAM_ERROR) { |