✨ Allow extracted file to be output to file instead of stdout
This commit is contained in:
parent
1897ab3813
commit
3f5a52a070
7 changed files with 36 additions and 9 deletions
|
@ -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);
|
||||
}
|
||||
|
|
21
src/main.c
21
src/main.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue