diff --git a/native/src/main/jni/archive.c b/native/src/main/jni/archive.c index b575cd7e9..f16406159 100644 --- a/native/src/main/jni/archive.c +++ b/native/src/main/jni/archive.c @@ -35,17 +35,12 @@ #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__) #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__) -#define BLOCK_SIZE 4096 * 16 - static JNIEnv *env; - static int cur_index = 0; // Current entry we haven't read any data from it yet -static struct archive* arc; - +static struct archive *arc = NULL; static bool need_encrypt = false; -static char* passwd = NULL; - -static void* archiveAddr = 0; +static char *passwd = NULL; +static void *archiveAddr = NULL; static jlong archiveSize = 0; static int filename_is_playable_file(const char *name) { @@ -77,12 +72,22 @@ static long archive_list_all_entries() { return count; } -static void archive_create() { +static void archive_release() { + if (arc) { + archive_read_close(arc); + archive_read_free(arc); + arc = NULL; + } +} + +static int archive_alloc() { + archive_release(); arc = archive_read_new(); archive_read_support_format_all(arc); archive_read_support_filter_all(arc); if (passwd) archive_read_add_passphrase(arc, passwd); + return archive_read_open_memory(arc, archiveAddr, archiveSize); } JNIEXPORT jint JNICALL @@ -91,35 +96,41 @@ Java_com_hippo_UriArchiveAccessor_openArchive(JNIEnv *_, jobject thiz, jlong add archiveSize = size; env = _; madvise(archiveAddr, archiveSize, MADV_SEQUENTIAL | MADV_WILLNEED); - archive_create(); - long r = archive_read_open_memory(arc, (const void *) archiveAddr, archiveSize); + long r = archive_alloc(); if (r) { r = 0; LOGE("%s%s", "Archive open failed:", archive_error_string(arc)); } else { - need_encrypt = archive_read_has_encrypted_entries(arc); r = archive_list_all_entries(); LOGI("%s%ld%s", "Found ", r, " image entries in archive"); + + // We must read through the file|vm then we can know whether it is encrypted + int encryptRet = archive_read_has_encrypted_entries(arc); + switch (encryptRet) { + case 1: // At lease 1 encrypted entry + need_encrypt = true; + break; + case 0: // format supports but no encrypted entry found + case ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW: // Sometimes we might not read through whole file|vm, but it means so far we haven't meet any encrypted entry yet + default: + need_encrypt = false; + } + LOGI("%s%d", "archive_read_has_encrypted_entries returns ", encryptRet); } - archive_read_close(arc); - archive_read_free(arc); - arc = NULL; + archive_release(); return r; } JNIEXPORT void JNICALL -Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index, jint fd) { +Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, jint index, + jint fd) { struct archive_entry *entry; size_t size; int ret; la_int64_t offset; - const void* buff; + const void *buff; if (!arc || index < cur_index) { - if (arc) - archive_read_close(arc); - archive_read_free(arc); - archive_create(); - archive_read_open_memory(arc, archiveAddr, archiveSize); + archive_alloc(); cur_index = 0; } while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { @@ -143,10 +154,8 @@ Java_com_hippo_UriArchiveAccessor_extracttoOutputStream(JNIEnv *_, jobject thiz, JNIEXPORT void JNICALL Java_com_hippo_UriArchiveAccessor_closeArchive(JNIEnv *jniEnv, jobject thiz) { - if (arc) { - archive_read_close(arc); - archive_read_free(arc); - } + archive_release(); + free(passwd); } JNIEXPORT jboolean JNICALL @@ -156,7 +165,7 @@ Java_com_hippo_UriArchiveAccessor_needPassword(JNIEnv *_, jobject thiz) { JNIEXPORT jboolean JNICALL Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstring str) { - struct archive_entry* entry; + struct archive_entry *entry; jboolean ret = true; int len = (*env)->GetStringUTFLength(env, str); if (passwd) @@ -164,14 +173,13 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstri passwd = calloc(len, sizeof(char)); strcpy(passwd, (*env)->GetStringUTFChars(env, str, NULL)); LOGI("%s%s", "Passwd is ", passwd); - archive_create(); - archive_read_open_memory(arc, (const void *) archiveAddr, archiveSize); + archive_alloc(); while (archive_read_next_header(arc, &entry) == ARCHIVE_OK) { if (!filename_is_playable_file(archive_entry_pathname(entry))) continue; if (!archive_entry_is_encrypted(entry)) continue; - void* tmpBuf = malloc(4096); + void *tmpBuf = malloc(4096); if (archive_read_data(arc, tmpBuf, 4096) < ARCHIVE_OK) { LOGE("%s%s", "Archive read failed:", archive_error_string(arc)); ret = false; @@ -179,8 +187,6 @@ Java_com_hippo_UriArchiveAccessor_providePassword(JNIEnv *_, jobject thiz, jstri free(tmpBuf); break; } - archive_read_close(arc); - archive_read_free(arc); - arc = NULL; + archive_release(); return ret; }