Allow extracted file to be output to file instead of stdout

This commit is contained in:
C-3PO 2018-09-16 02:33:30 +02:00
parent 1897ab3813
commit 3f5a52a070
Signed by: c3po
GPG key ID: 62993C4BB4D86F24
7 changed files with 36 additions and 9 deletions

View file

@ -2,7 +2,7 @@
If this is not a ```-1to0``` patch, the disk file may only contain the differences to the previous release. In this case, you can supply the location of this file's previous version, and this tool will generate the new version using VCDIFF/xdelta3.
In all cases, the extracted file is written to stdout. From there, you can either dump it to disk or process it in memory.
If a target location is specified, the extracted file is saved to that location, otherwise it is written to stdout. From there, you can either dump it to disk or process it in memory.
# Usage

View file

@ -12,5 +12,6 @@ void errorAndExit() {
fprintf(stderr, " -s, --size: The stored size of the file we want to extract (= the compressed size). After inflation, the file will likely be bigger than this.\n");
fprintf(stderr, " -k, --keys: Optionally, the three decryption keys used to decrypt the file before inflation.\n");
fprintf(stderr, " -p, --previous: Optionally, the location of the previous version of this file, in case this disk only contains the xdelta3 differences and not an actual file.\n");
fprintf(stderr, " -t, --target: The path where the extracted file is saved to. If not specified, the file is outputted to stdout.\n");
exit(1);
}

View file

@ -1,3 +1,4 @@
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -84,6 +85,16 @@ int main(int argc, char *argv[]) {
xdelta3Init(state.prevFile);
}
//If a target path is specified, create a file write stream
FILE* targetFile;
if (state.target) {
targetFile = fopen(state.target, "wb");
if (!targetFile) {
fprintf(stderr, "Could not open the target file \"%s\" for writing: %s\n", state.target, strerror(errno));
errorAndExit();
}
}
//-------------------------------------------------
struct InflateOutput inflateResult;
@ -116,9 +127,13 @@ int main(int argc, char *argv[]) {
//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);
xdelta3AddInput(uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput, remainingBytes == 0 && hasReachedEnd, targetFile);
} else { //otherwise write to target file or stdout
if (state.target) {
fwrite(uncompressedChunk + uncompressedPosition, 1, inflateResult.numBytesWrittenToOutput, targetFile);
} else {
write(1, uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput);
}
}
uncompressedPosition += inflateResult.numBytesWrittenToOutput;

View file

@ -15,6 +15,7 @@ static struct option long_options[] = {
{"size", required_argument, 0, 's'},
{"keys", required_argument, 0, 'k'},
{"previous", required_argument, 0, 'p'},
{"target", required_argument, 0, 't'},
{NULL, 0, 0, 0},
};
@ -31,7 +32,7 @@ struct arguments parseArguments(int argc, char *argv[]) {
//In this variable, getopt_long stores the current long option that was found. Unused since we don't use flags in our long options
int optionIndex = 0;
int curOption = getopt_long_only(argc, argv, "d:o:s:k:p:", long_options, &optionIndex);
int curOption = getopt_long_only(argc, argv, "d:o:s:k:p:t:", long_options, &optionIndex);
//end of command line arguments reached
if (curOption == -1) {
@ -77,6 +78,9 @@ struct arguments parseArguments(int argc, char *argv[]) {
case 'p': //previous file for xdelta3
state.prevFile = optarg;
break;
case 't': //target file path where extracted file is saved to
state.target = optarg;
break;
case '?':
errorAndExit();
break;

View file

@ -15,6 +15,8 @@ struct arguments {
bool isEncrypted;
//For xdelta3, the location of the old file
char* prevFile;
//Target file location where the extracted file is saved to
char* target;
};

View file

@ -9,6 +9,7 @@ typedef unsigned long long xoff_t;
#include "../lib/xdelta3/xdelta3.c"
//Include other libraries
#include <errno.h>
#include <stdbool.h>
#include <unistd.h>
@ -29,7 +30,7 @@ unsigned long totalOut = 0UL;
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);
fprintf(stderr, "Could not open previous file %s for reading during xdelta3: %s\n", prevFile, strerror(errno));
errorAndExit();
}
@ -54,7 +55,7 @@ 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) {
void xdelta3AddInput(unsigned char* inputBuffer, unsigned int inputLength, bool isLastPart, FILE* targetFile) {
xd3_avail_input(&stream, inputBuffer, inputLength);
int returnValue;
@ -69,7 +70,11 @@ process:
case XD3_OUTPUT: {
//fprintf(stderr, "XD3_OUTPUT\n");
totalOut += stream.avail_out;
write(1, stream.next_out, stream.avail_out);
if (targetFile) {
fwrite(stream.next_out, 1, stream.avail_out, targetFile);
} else {
write(1, stream.next_out, stream.avail_out);
}
xd3_consume_output(&stream);
goto process;
}

View file

@ -4,4 +4,4 @@
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);
void xdelta3AddInput(unsigned char* inputBuffer, unsigned int inputLength, bool isLastPart, FILE* targetFile);