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

@ -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);