jobject MOZ_JNICALL Java_org_mozilla_gecko_mozglue_NativeZip__1getInputStream(JNIEnv *jenv, jobject jzip, jlong obj, jstring path) { Zip *zip = (Zip *)obj; const char* str; str = jenv->GetStringUTFChars(path, nullptr); Zip::Stream stream; bool res = zip->GetStream(str, &stream); jenv->ReleaseStringUTFChars(path, str); if (!res) { return nullptr; } jobject buf = jenv->NewDirectByteBuffer(const_cast<void *>(stream.GetBuffer()), stream.GetSize()); if (!buf) { JNI_Throw(jenv, "java/lang/RuntimeException", "Failed to create ByteBuffer"); return nullptr; } jclass nativeZip = jenv->GetObjectClass(jzip); jmethodID method = jenv->GetMethodID(nativeZip, "createInputStream", "(Ljava/nio/ByteBuffer;I)Ljava/io/InputStream;"); // Since this function is only expected to be called from Java, it is safe // to skip exception checking for the method call below, as long as no // other Native -> Java call doesn't happen before returning to Java. return jenv->CallObjectMethod(jzip, method, buf, (jint) stream.GetType()); }
static void * extractBuf(const char * path, Zip *zip) { Zip::Stream s; if (!zip->GetStream(path, &s)) return NULL; void * buf = malloc(s.GetUncompressedSize()); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path); return NULL; } if (s.GetType() == Zip::Stream::DEFLATE) extractLib(s, buf); else memcpy(buf, s.GetBuffer(), s.GetUncompressedSize()); return buf; }
static void * extractBuf(const char * path, Zip *zip) { Zip::Stream s; if (!zip->GetStream(path, &s)) return NULL; // allocate space for a trailing null byte void * buf = malloc(s.GetUncompressedSize() + 1); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't alloc decompression buffer for %s", path); return NULL; } if (s.GetType() == Zip::Stream::DEFLATE) extractLib(s, buf); else memcpy(buf, s.GetBuffer(), s.GetUncompressedSize()); // null terminate it ((unsigned char*) buf)[s.GetUncompressedSize()] = 0; return buf; }
static void extractFile(const char * path, Zip::Stream &s) { uint32_t size = s.GetUncompressedSize(); struct stat status; if (!stat(path, &status) && status.st_size == size && apk_mtime < status.st_mtime) return; int fd = open(path, O_CREAT | O_NOATIME | O_TRUNC | O_RDWR, S_IRWXU); if (fd == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't open %s to decompress library", path); return; } if (ftruncate(fd, size) == -1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't ftruncate %s to decompress library", path); close(fd); return; } void * buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void *)-1) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't mmap decompression buffer"); close(fd); return; } z_stream strm = { next_in: (Bytef *)s.GetBuffer(), avail_in: s.GetSize(), total_in: 0, next_out: (Bytef *)buf, avail_out: size, total_out: 0 }; int ret; ret = inflateInit2(&strm, -MAX_WBITS); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateInit failed: %s", strm.msg); if (inflate(&strm, Z_FINISH) != Z_STREAM_END) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflate failed: %s", strm.msg); if (strm.total_out != size) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "extracted %d, expected %d!", strm.total_out, size); ret = inflateEnd(&strm); if (ret != Z_OK) __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "inflateEnd failed: %s", strm.msg); close(fd); #ifdef ANDROID_ARM_LINKER /* We just extracted data that is going to be executed in the future. * We thus need to ensure Instruction and Data cache coherency. */ cacheflush((unsigned) buf, (unsigned) buf + size, 0); #endif munmap(buf, size); }