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.Inflater 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <string.h> 34 #include "jlong.h" 35 #include "jni.h" 36 #include "jvm.h" 37 #include "jni_util.h" 38 #include "zlib.h" 39 #include "java_util_zip_Inflater.h" 40 41 #define MIN2(x, y) ((x) < (y) ? (x) : (y)) 42 43 #define ThrowDataFormatException(env, msg) \ 44 JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg) 45 46 static jfieldID needDictID; 47 static jfieldID finishedID; 48 static jfieldID bufID, offID, lenID; 49 50 JNIEXPORT void JNICALL 51 Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls) 52 { 53 needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z"); 54 finishedID = (*env)->GetFieldID(env, cls, "finished", "Z"); 55 bufID = (*env)->GetFieldID(env, cls, "buf", "[B"); 56 offID = (*env)->GetFieldID(env, cls, "off", "I"); 57 lenID = (*env)->GetFieldID(env, cls, "len", "I"); 58 } 59 60 JNIEXPORT jlong JNICALL 61 Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) 62 { 94 res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len); 95 (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); 96 switch (res) { 97 case Z_OK: 98 break; 99 case Z_STREAM_ERROR: 100 case Z_DATA_ERROR: 101 JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg); 102 break; 103 default: 104 JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg); 105 break; 106 } 107 } 108 109 JNIEXPORT jint JNICALL 110 Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr, 111 jarray b, jint off, jint len) 112 { 113 z_stream *strm = jlong_to_ptr(addr); 114 115 jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID); 116 jint this_off = (*env)->GetIntField(env, this, offID); 117 jint this_len = (*env)->GetIntField(env, this, lenID); 118 jbyte *in_buf; 119 jbyte *out_buf; 120 int ret; 121 /* 122 * Avoid excess copying. 123 * zlib stream usually has a few bytes of overhead for header info 124 * (depends on the underlying data) 125 * 126 * (a) 5 bytes per 16KB 127 * (b) 6 bytes for entire stream 128 * (c) 4 bytes for gzip header 129 * (d) 2 bytes for crc 130 * 131 * Use 20 bytes as the "safe cutoff" number. 132 */ 133 jint in_len = MIN2(this_len, len + 20); 134 jint consumed; 135 136 in_buf = (jbyte *) malloc(in_len); 137 if (in_buf == 0) { 138 if (in_len != 0) 139 JNU_ThrowOutOfMemoryError(env, 0); 140 return 0; 141 } 142 (*env)->GetByteArrayRegion(env, this_buf, this_off, in_len, in_buf); 143 144 out_buf = (jbyte *) malloc(len); 145 if (out_buf == 0) { 146 free(in_buf); 147 if (len != 0) 148 JNU_ThrowOutOfMemoryError(env, 0); 149 return 0; 150 } 151 152 strm->next_in = (Bytef *) in_buf; 153 strm->next_out = (Bytef *) out_buf; 154 strm->avail_in = in_len; 155 strm->avail_out = len; 156 ret = inflate(strm, Z_PARTIAL_FLUSH); 157 158 if (ret == Z_STREAM_END || ret == Z_OK) { 159 (*env)->SetByteArrayRegion(env, b, off, len - strm->avail_out, out_buf); 160 } 161 free(out_buf); 162 free(in_buf); 163 164 switch (ret) { 165 case Z_STREAM_END: 166 (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE); 167 /* fall through */ 168 case Z_OK: 169 consumed = in_len - strm->avail_in; 170 (*env)->SetIntField(env, this, offID, this_off + consumed); 171 (*env)->SetIntField(env, this, lenID, this_len - consumed); 172 return len - strm->avail_out; 173 case Z_NEED_DICT: 174 (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE); 175 /* Might have consumed some input here! */ 176 consumed = in_len - strm->avail_in; 177 (*env)->SetIntField(env, this, offID, this_off + consumed); 178 (*env)->SetIntField(env, this, lenID, this_len - consumed); 179 return 0; 180 case Z_BUF_ERROR: 181 return 0; 182 case Z_DATA_ERROR: 183 ThrowDataFormatException(env, strm->msg); 184 return 0; 185 case Z_MEM_ERROR: 186 JNU_ThrowOutOfMemoryError(env, 0); 187 return 0; 188 default: 189 JNU_ThrowInternalError(env, strm->msg); 190 return 0; 191 } 192 } 193 194 JNIEXPORT jint JNICALL 195 Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr) 196 { 197 return ((z_stream *)jlong_to_ptr(addr))->adler; 198 } | 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.Inflater 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <errno.h> 33 #include <string.h> 34 #include "jlong.h" 35 #include "jni.h" 36 #include "jvm.h" 37 #include "jni_util.h" 38 #include "zlib.h" 39 #include "java_util_zip_Inflater.h" 40 41 #define ThrowDataFormatException(env, msg) \ 42 JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg) 43 44 static jfieldID needDictID; 45 static jfieldID finishedID; 46 static jfieldID bufID, offID, lenID; 47 48 JNIEXPORT void JNICALL 49 Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls) 50 { 51 needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z"); 52 finishedID = (*env)->GetFieldID(env, cls, "finished", "Z"); 53 bufID = (*env)->GetFieldID(env, cls, "buf", "[B"); 54 offID = (*env)->GetFieldID(env, cls, "off", "I"); 55 lenID = (*env)->GetFieldID(env, cls, "len", "I"); 56 } 57 58 JNIEXPORT jlong JNICALL 59 Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap) 60 { 92 res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len); 93 (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0); 94 switch (res) { 95 case Z_OK: 96 break; 97 case Z_STREAM_ERROR: 98 case Z_DATA_ERROR: 99 JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg); 100 break; 101 default: 102 JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg); 103 break; 104 } 105 } 106 107 JNIEXPORT jint JNICALL 108 Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr, 109 jarray b, jint off, jint len) 110 { 111 z_stream *strm = jlong_to_ptr(addr); 112 jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID); 113 jint this_off = (*env)->GetIntField(env, this, offID); 114 jint this_len = (*env)->GetIntField(env, this, lenID); 115 116 jbyte *in_buf; 117 jbyte *out_buf; 118 int ret; 119 120 in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0); 121 if (in_buf == NULL) { 122 if (this_len != 0) 123 JNU_ThrowOutOfMemoryError(env, 0); 124 return 0; 125 } 126 out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0); 127 if (out_buf == NULL) { 128 (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); 129 if (len != 0) 130 JNU_ThrowOutOfMemoryError(env, 0); 131 return 0; 132 } 133 strm->next_in = (Bytef *) (in_buf + this_off); 134 strm->next_out = (Bytef *) (out_buf + off); 135 strm->avail_in = this_len; 136 strm->avail_out = len; 137 ret = inflate(strm, Z_PARTIAL_FLUSH); 138 (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0); 139 (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0); 140 141 switch (ret) { 142 case Z_STREAM_END: 143 (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE); 144 /* fall through */ 145 case Z_OK: 146 this_off += this_len - strm->avail_in; 147 (*env)->SetIntField(env, this, offID, this_off); 148 (*env)->SetIntField(env, this, lenID, strm->avail_in); 149 return len - strm->avail_out; 150 case Z_NEED_DICT: 151 (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE); 152 /* Might have consumed some input here! */ 153 this_off += this_len - strm->avail_in; 154 (*env)->SetIntField(env, this, offID, this_off); 155 (*env)->SetIntField(env, this, lenID, strm->avail_in); 156 return 0; 157 case Z_BUF_ERROR: 158 return 0; 159 case Z_DATA_ERROR: 160 ThrowDataFormatException(env, strm->msg); 161 return 0; 162 case Z_MEM_ERROR: 163 JNU_ThrowOutOfMemoryError(env, 0); 164 return 0; 165 default: 166 JNU_ThrowInternalError(env, strm->msg); 167 return 0; 168 } 169 } 170 171 JNIEXPORT jint JNICALL 172 Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr) 173 { 174 return ((z_stream *)jlong_to_ptr(addr))->adler; 175 } |