✨ 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
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
19
src/main.c
19
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,10 +127,14 @@ 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
|
||||
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;
|
||||
while (uncompressedPosition >= BUFFER_SIZE) {
|
||||
|
|
|
@ -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;
|
||||
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…
Reference in a new issue