Add xdelta3 decoding support

This commit is contained in:
C-3PO 2018-09-14 04:11:44 +02:00
parent ae59ce2256
commit 31ec793781
Signed by: c3po
GPG key ID: 62993C4BB4D86F24
5 changed files with 124 additions and 13 deletions

View file

@ -5,7 +5,7 @@
void errorAndExit() {
fprintf(stderr, "\nUsage:\n");
fprintf(stderr, " ./patcher-installer --disk main.z01 --offset 456z --size 1000 [--keys 123,123,123] [--prev oldfile.tor]\n");
fprintf(stderr, " ./patcher-installer --disk main.z01 --offset 456z --size 1000 [--keys 123,456,789] [--previous oldfile.tor]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " -d, --disk: The path to the disk file that contains the file we want to extract.\n");
fprintf(stderr, " -o, --offset: The offset into the disk, given in bytes, where the local file header of the file we want to extract starts.\n");

View file

@ -5,12 +5,13 @@
#include <unistd.h>
//Import our code
#include "utils/min.h"
#include "decrypt.h"
#include "errorAndExit.h"
#include "fileReader.h"
#include "inflate.h"
#include "parseArguments.h"
#include "utils/min.h"
#include "xdelta3.h"
//The size of the buffers where the compressed and uncompressed data is stored
#define BUFFER_SIZE 512UL * 1024UL //512 KiB
@ -75,6 +76,11 @@ int main(int argc, char *argv[]) {
decrypt(compressedChunk, ENCRYPTION_HEADER_LENGTH);
}
//Initialize xdelta3
if (state.prevFile) {
xdelta3Init(state.prevFile);
}
//-------------------------------------------------
struct InflateOutput inflateResult;
@ -106,19 +112,17 @@ int main(int argc, char *argv[]) {
//important: we must not modify uncompressedChunk since miniz may use it as dictionary and read from it during the next invocation of inflateInflate()
//Write to stdout
write(1, uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput);
//Optionally perform xdelta3
if (state.prevFile) {
xdelta3AddInput(uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput, remainingBytes == 0 && hasReachedEnd);
} else { //otherwise write to stdout
write(1, uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput);
}
uncompressedPosition += inflateResult.numBytesWrittenToOutput;
while (uncompressedPosition >= BUFFER_SIZE) {
uncompressedPosition -= BUFFER_SIZE;
}
//Optionally perform xdelta3
if (state.prevFile) {
//TODO
fprintf(stderr, "xdelta3 is not yet implemented.\n");
errorAndExit();
}
}
//release memory

View file

@ -2,7 +2,107 @@
#define SIZEOF_SIZE_T 4
#define static_assert(e,m) /* do nothing */
#define XD3_ENCODER 0
#define XD3_USE_LARGESIZET 0
typedef unsigned int usize_t;
typedef unsigned long long xoff_t;
//Include xdelta3
#include "../lib/xdelta3/xdelta3.c"
#include "../lib/xdelta3/xdelta3.h"
//Include other libraries
#include <stdbool.h>
#include <unistd.h>
//Include our own files
#include "errorAndExit.h"
#include "xdelta3.h"
//Various variables for Xdelta3
xd3_stream stream;
xd3_config config;
xd3_source source;
//The previous version of the file we want to extract
FILE* srcFile;
//Total number of bytes written to output
unsigned long totalOut = 0UL;
/** Initializes xdelta3 with the given previous file */
void xdelta3Init(char* prevFile) {
srcFile = fopen(prevFile, "rb");
if (srcFile == NULL) {
fprintf(stderr, "Could not open previous file %s for reading during xdelta3.\n", prevFile);
errorAndExit();
}
xd3_init_config(&config, XD3_ADLER32);
config.winsize = XD3_ALLOCSIZE;
xd3_config_stream(&stream, &config);
//Set source (= old file from previous release)
source.blksize = XD3_ALLOCSIZE;
source.curblk = malloc(source.blksize);
if (source.curblk == NULL) {
fprintf(stderr, "ERROR: Could not allocate source.blksize in VCDIFF.\n");
errorAndExit();
}
fseek(srcFile, 0, SEEK_SET);
source.onblk = fread((void*)source.curblk, 1, source.blksize, srcFile);
source.curblkno = 0;
xd3_set_source(&stream, &source);
//Set input (= xdelta file from current release)
xd3_set_flags(&stream, XD3_FLUSH | stream.flags);
}
/** Supplies the given input buffer to xdelta3 and undiffs the data. */
void xdelta3AddInput(unsigned char* inputBuffer, unsigned int inputLength, bool isLastPart) {
xd3_avail_input(&stream, inputBuffer, inputLength);
int returnValue;
process:
returnValue = xd3_decode_input(&stream);
switch (returnValue) {
case XD3_INPUT: {
//fprintf(stderr, "XD3_INPUT\n");
break;
}
case XD3_OUTPUT: {
//fprintf(stderr, "XD3_OUTPUT\n");
totalOut += stream.avail_out;
write(1, stream.next_out, stream.avail_out);
xd3_consume_output(&stream);
goto process;
}
case XD3_GETSRCBLK: {
//fprintf(stderr, "XD3_GETSRCBLK\n");
fseek(srcFile, source.blksize * source.getblkno, SEEK_SET);
source.onblk = fread((void*)source.curblk, 1, source.blksize, srcFile);
source.curblkno = source.getblkno;
goto process;
}
case XD3_GOTHEADER: {
//fprintf(stderr, "XD3_GOTHEADER\n");
goto process;
}
case XD3_WINSTART: {
//fprintf(stderr, "XD3_WINSTART\n");
goto process;
}
case XD3_WINFINISH: {
//fprintf(stderr, "XD3_WINFINISH\n");
goto process;
}
default: {
fprintf(stderr, "ERROR: !!! INVALID %s %d !!!\n", stream.msg, returnValue);
errorAndExit();
}
}
//If we are done, free up memory
if (isLastPart) {
free((void*)source.curblk);
xd3_close_stream(&stream);
xd3_free_stream(&stream);
fclose(srcFile);
}
}

7
src/xdelta3.h Normal file
View file

@ -0,0 +1,7 @@
#pragma once
/** Initializes xdelta3 with the given previous file */
void xdelta3Init(char* prevFile);
/** Supplies the given input buffer to xdelta3 and undiffs the data. */
void xdelta3AddInput(unsigned char* inputBuffer, unsigned int inputLength, bool isLastPart);