Upload Apkdiff Module Source Code

This commit is contained in:
2026-07-04 22:01:38 +08:00
parent dfdbf3acf6
commit 05c93e5ce9
283 changed files with 71378 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
/*
* patch_format.h - APK diff patch file format definitions
*
* Patch file layout:
* [16 bytes] Magic "APKDIFF/1.0\0\0\0"
* [4 bytes] uint32_t entry_count
* [entries...]
*
* Each entry:
* [2 bytes] uint16_t path_len
* [N bytes] path (no null terminator)
* [1 byte] type (0=patch, 1=new_file, 2=copy)
* [8 bytes] int64_t old_size (0 for new_file and copy)
* [8 bytes] int64_t new_size (0 for copy)
* [4 bytes] uint32_t compressed_size (0 for copy)
* [N bytes] compressed_data (only for patch and new_file)
*
* Entry types:
* PATCH (0): bsdiff patch data compressed with zlib
* NEW (1): full new file content compressed with zlib
* COPY (2): unchanged file, copy from old APK (no data follows)
*/
#ifndef PATCH_FORMAT_H
#define PATCH_FORMAT_H
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define APKDIFF_MAGIC "APKDIFF/1.0\0\0\0"
#define APKDIFF_MAGIC_SIZE 16
#define APKDIFF_VERSION 1
#define ENTRY_TYPE_PATCH 0
#define ENTRY_TYPE_NEW 1
#define ENTRY_TYPE_COPY 2
#pragma pack(push, 1)
typedef struct {
char magic[APKDIFF_MAGIC_SIZE];
uint32_t entry_count;
} patch_header_t;
typedef struct {
uint16_t path_len;
uint8_t type;
int64_t old_size;
int64_t new_size;
uint32_t compressed_size;
} patch_entry_header_t;
#pragma pack(pop)
/* Write the patch file header */
static inline int patch_write_header(FILE* fp, uint32_t entry_count)
{
patch_header_t hdr;
memcpy(hdr.magic, APKDIFF_MAGIC, APKDIFF_MAGIC_SIZE);
hdr.entry_count = entry_count;
return (fwrite(&hdr, sizeof(hdr), 1, fp) == 1) ? 0 : -1;
}
/* Read and validate patch file header */
static inline int patch_read_header(FILE* fp, uint32_t* entry_count)
{
patch_header_t hdr;
if (fread(&hdr, sizeof(hdr), 1, fp) != 1)
return -1;
if (memcmp(hdr.magic, APKDIFF_MAGIC, APKDIFF_MAGIC_SIZE) != 0)
return -1;
*entry_count = hdr.entry_count;
return 0;
}
/* Write a single entry header (call before writing compressed data) */
static inline int patch_write_entry_header(FILE* fp, const char* path,
uint8_t type, int64_t old_size, int64_t new_size, uint32_t compressed_size)
{
patch_entry_header_t eh;
uint16_t path_len = (uint16_t)strlen(path);
eh.path_len = path_len;
eh.type = type;
eh.old_size = old_size;
eh.new_size = new_size;
eh.compressed_size = compressed_size;
if (fwrite(&eh, sizeof(eh), 1, fp) != 1) return -1;
if (path_len > 0) {
if (fwrite(path, 1, path_len, fp) != path_len) return -1;
}
return 0;
}
/* Read a single entry header. Caller must free *out_path. */
static inline int patch_read_entry_header(FILE* fp, char** out_path,
uint8_t* type, int64_t* old_size, int64_t* new_size, uint32_t* compressed_size)
{
patch_entry_header_t eh;
char* path;
if (fread(&eh, sizeof(eh), 1, fp) != 1)
return -1;
path = (char*)malloc(eh.path_len + 1);
if (!path) return -1;
if (eh.path_len > 0) {
if (fread(path, 1, eh.path_len, fp) != eh.path_len) {
free(path);
return -1;
}
}
path[eh.path_len] = '\0';
*out_path = path;
*type = eh.type;
*old_size = eh.old_size;
*new_size = eh.new_size;
*compressed_size = eh.compressed_size;
return 0;
}
#endif /* PATCH_FORMAT_H */

View File

@@ -0,0 +1,162 @@
/*
* zlib_stream.c - zlib compression callbacks for bsdiff/bspatch streams
*/
#include "zlib_stream.h"
#include <string.h>
#include <stdlib.h>
/* ============ Write (deflate) ============ */
static int zlib_flush_output(zlib_write_ctx* ctx)
{
int ret;
do {
ctx->zs.next_out = ctx->out_buf;
ctx->zs.avail_out = ZLIB_STREAM_BUF_SIZE;
ret = deflate(&ctx->zs, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR)
return -1;
size_t have = ZLIB_STREAM_BUF_SIZE - ctx->zs.avail_out;
if (have > 0) {
if (fwrite(ctx->out_buf, 1, have, ctx->fp) != have)
return -1;
}
} while (ctx->zs.avail_out == 0);
return 0;
}
int zlib_write_init(zlib_write_ctx* ctx, FILE* fp)
{
memset(ctx, 0, sizeof(*ctx));
ctx->fp = fp;
ctx->zs.zalloc = Z_NULL;
ctx->zs.zfree = Z_NULL;
ctx->zs.opaque = Z_NULL;
if (deflateInit(&ctx->zs, Z_BEST_COMPRESSION) != Z_OK)
return -1;
return 0;
}
int zlib_write_cb(struct bsdiff_stream* stream, const void* buffer, int size)
{
zlib_write_ctx* ctx = (zlib_write_ctx*)stream->opaque;
ctx->zs.next_in = (Bytef*)(uintptr_t)buffer;
ctx->zs.avail_in = (uInt)size;
while (ctx->zs.avail_in > 0) {
ctx->zs.next_out = ctx->out_buf;
ctx->zs.avail_out = ZLIB_STREAM_BUF_SIZE;
int ret = deflate(&ctx->zs, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR)
return -1;
size_t have = ZLIB_STREAM_BUF_SIZE - ctx->zs.avail_out;
if (have > 0) {
if (fwrite(ctx->out_buf, 1, have, ctx->fp) != have)
return -1;
}
}
return 0;
}
int zlib_write_finish(zlib_write_ctx* ctx)
{
int ret;
do {
ctx->zs.next_out = ctx->out_buf;
ctx->zs.avail_out = ZLIB_STREAM_BUF_SIZE;
ret = deflate(&ctx->zs, Z_FINISH);
if (ret == Z_STREAM_ERROR)
return -1;
size_t have = ZLIB_STREAM_BUF_SIZE - ctx->zs.avail_out;
if (have > 0) {
if (fwrite(ctx->out_buf, 1, have, ctx->fp) != have)
return -1;
}
} while (ret != Z_STREAM_END);
deflateEnd(&ctx->zs);
return 0;
}
/* ============ Read (inflate) ============ */
int zlib_read_init(zlib_read_ctx* ctx, const uint8_t* data, size_t len)
{
memset(ctx, 0, sizeof(*ctx));
ctx->data = data;
ctx->data_len = len;
ctx->zs.zalloc = Z_NULL;
ctx->zs.zfree = Z_NULL;
ctx->zs.opaque = Z_NULL;
ctx->zs.next_in = (Bytef*)(uintptr_t)data;
ctx->zs.avail_in = (uInt)len;
if (inflateInit(&ctx->zs) != Z_OK)
return -1;
ctx->inited = 1;
return 0;
}
void zlib_read_cleanup(zlib_read_ctx* ctx)
{
if (ctx->inited) {
inflateEnd(&ctx->zs);
ctx->inited = 0;
}
}
int zlib_read_cb(const struct bspatch_stream* stream, void* buffer, int length)
{
zlib_read_ctx* ctx = (zlib_read_ctx*)stream->opaque;
ctx->zs.next_out = (Bytef*)buffer;
ctx->zs.avail_out = (uInt)length;
while (ctx->zs.avail_out > 0) {
if (ctx->zs.avail_in == 0)
return -1; /* ran out of compressed data */
int ret = inflate(&ctx->zs, Z_NO_FLUSH);
if (ret == Z_STREAM_END) {
if (ctx->zs.avail_out > 0)
return -1; /* needed more data but stream ended */
break;
}
if (ret != Z_OK)
return -1;
}
return 0;
}
/* ============ Convenience setup ============ */
void zlib_setup_bsdiff_stream(struct bsdiff_stream* stream, zlib_write_ctx* ctx, FILE* fp)
{
zlib_write_init(ctx, fp);
stream->opaque = ctx;
stream->malloc = malloc;
stream->free = free;
stream->write = zlib_write_cb;
}
void zlib_setup_bspatch_stream(struct bspatch_stream* stream, zlib_read_ctx* ctx,
const uint8_t* data, size_t len)
{
zlib_read_init(ctx, data, len);
stream->opaque = ctx;
stream->read = zlib_read_cb;
}

View File

@@ -0,0 +1,62 @@
/*
* zlib_stream.h - zlib compression callbacks for bsdiff/bspatch streams
*/
#ifndef ZLIB_STREAM_H
#define ZLIB_STREAM_H
#include <stdio.h>
#include <stdint.h>
#include <zlib.h>
#include "bsdiff.h"
#include "bspatch.h"
#define ZLIB_STREAM_BUF_SIZE 8192
/* ---- Write context (used by bsdiff in gen.exe) ---- */
typedef struct {
FILE* fp;
z_stream zs;
uint8_t out_buf[ZLIB_STREAM_BUF_SIZE];
} zlib_write_ctx;
/* Initialize zlib deflate write context. Must be called before bsdiff(). */
int zlib_write_init(zlib_write_ctx* ctx, FILE* fp);
/* Flush and clean up. Must be called after bsdiff() completes. */
int zlib_write_finish(zlib_write_ctx* ctx);
/* bsdiff_stream.write callback */
int zlib_write_cb(struct bsdiff_stream* stream, const void* buffer, int size);
/* ---- Read context (used by bspatch in JNI) ---- */
typedef struct {
const uint8_t* data;
size_t data_len;
z_stream zs;
int inited;
} zlib_read_ctx;
/* Initialize zlib inflate read context from compressed data buffer. */
int zlib_read_init(zlib_read_ctx* ctx, const uint8_t* data, size_t len);
/* Clean up zlib read context. */
void zlib_read_cleanup(zlib_read_ctx* ctx);
/* bspatch_stream.read callback */
int zlib_read_cb(const struct bspatch_stream* stream, void* buffer, int length);
/* ---- Convenience setup functions ---- */
/* Fill a bsdiff_stream struct for zlib-compressed output to fp.
* Caller must call zlib_write_finish() on ctx after bsdiff() completes. */
void zlib_setup_bsdiff_stream(struct bsdiff_stream* stream, zlib_write_ctx* ctx, FILE* fp);
/* Fill a bspatch_stream struct for zlib-decompressed input from data buffer.
* Caller must call zlib_read_cleanup() on ctx when done. */
void zlib_setup_bspatch_stream(struct bspatch_stream* stream, zlib_read_ctx* ctx,
const uint8_t* data, size_t len);
#endif /* ZLIB_STREAM_H */