Enable use of command line options

This commit is contained in:
C-3PO 2018-09-14 00:48:53 +02:00
parent 313f65609f
commit 43614e1498
Signed by: c3po
GPG key ID: 62993C4BB4D86F24
6 changed files with 137 additions and 20 deletions

View file

@ -3,7 +3,8 @@
"filereader.h": "c", "filereader.h": "c",
"decrypt.h": "c", "decrypt.h": "c",
"stdint.h": "c", "stdint.h": "c",
"decryptutilities.h": "c" "decryptutilities.h": "c",
"fileutilities.h": "c"
}, },
"cSpell.words": [ "cSpell.words": [
"init", "init",

View file

@ -1,5 +1,19 @@
This tool installs a patch, assuming the patch files are already downloaded, and if not patching from -1, that the previous patch is already installed. This tool installs a patch, assuming the patch files are already downloaded, and if not patching from -1, that the previous patch is already installed.
# Usage
To compile:
```
./build.sh
```
To use:
```
./patcher-installer --disk /tmp/patcher/cdn-patch.swtor.com/patch/assets_swtor_main/assets_swtor_main_-1to0/assets_swtor_main_-1to0.z08 --offset 267071107 --size 165738618 --keys 3393608425 2820264972 3930508185 > ../swtor_main_gfx_1.tor
```
# Dependencies # Dependencies
## Miniz <[https://github.com/richgel999/miniz](https://github.com/richgel999/miniz)> ## Miniz <[https://github.com/richgel999/miniz](https://github.com/richgel999/miniz)>

View file

@ -31,7 +31,7 @@ void initFileReader(char path[], unsigned long offset) {
} }
//Reads the given amount of bytes from the file and returns them. Automatically opens next file if EOF is reached. //Reads the given amount of bytes from the file and writes them into the given buffer. Automatically opens next file if EOF is reached.
void getBytes(uint8_t* buffer, unsigned long numBytes) { void getBytes(uint8_t* buffer, unsigned long numBytes) {
char* bufferPosition = buffer; char* bufferPosition = buffer;
unsigned long remainingBytes = numBytes; unsigned long remainingBytes = numBytes;
@ -40,8 +40,14 @@ void getBytes(uint8_t* buffer, unsigned long numBytes) {
while (remainingBytes > 0) { while (remainingBytes > 0) {
//Read as many bytes as we can from the current file //Read as many bytes as we can from the current file
const unsigned long availableBytes = min(remainingBytes, file.size - file.offset); const unsigned long availableBytes = min(remainingBytes, file.size - file.offset);
//Read bytes into buffer if we have a valid buffer, otherwise skip bytes
if (buffer) {
readBytesIntoBuffer(bufferPosition, availableBytes); readBytesIntoBuffer(bufferPosition, availableBytes);
bufferPosition += availableBytes; bufferPosition += availableBytes;
} else {
skipBytes(availableBytes);
}
remainingBytes -= availableBytes; remainingBytes -= availableBytes;
//If we've reached end of file, close file and open next file //If we've reached end of file, close file and open next file

View file

@ -1,4 +1,5 @@
#include <errno.h> #include <errno.h>
#include <getopt.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -26,24 +27,98 @@ uint32_t getUint32(uint8_t* buffer) {
(uint32_t)buffer[3] << 24; (uint32_t)buffer[3] << 24;
} }
int main(int argc, unsigned char *argv[]) { struct arguments {
if (argc != 4 && argc != 7) { /** Path to the disk file that contains the start of the file we want to extract.
fprintf(stderr, "Wrong number of arguments. Usage: patcher-installer <disk_name> <disk_offset> <file_size> [<key0> <key1> <key2>]"); * The file may stretch across multiple disks though.
*/
char* diskName;
/** Offset into the disk where the file starts. */
unsigned long diskOffset;
/** Size of the file stored in the disk. */
unsigned long fileSize;
//Decryption keys
bool isEncrypted;
uint32_t key0;
uint32_t key1;
uint32_t key2;
//TODO: For xdelta3, the location of the old file
char* prevFile;
};
static struct option long_options[] = {
{"disk", required_argument, 0, 'd'},
{"offset", required_argument, 0, 'o'},
{"size", required_argument, 0, 's'},
{"keys", required_argument, 0, 'k'},
{"prev", required_argument, 0, 'p'},
};
//Stores current state from command line arguments, initialized to zero
struct arguments state = {};
int main(int argc, char *argv[]) {
//Parse command line arguments
int requiredOptions = 0;
while (1) {
//in this variable, getopt_long stores the current position in the command line args array
int option_index = 0;
int curOption = getopt_long(argc, argv, "d:o:s:k:", long_options, &option_index);
//end of command line arguments reached
if (curOption == -1) {
break;
}
switch (curOption) {
case 'd': //disk name
state.diskName = optarg;
requiredOptions |= 1;
break;
case 'o': //offset
state.diskOffset = atol(optarg);
requiredOptions |= 2;
break;
case 's': //size
state.fileSize = atol(optarg);
requiredOptions |= 4;
break;
case 'k': { //decryption keys
//TODO: parse from optarg
uint32_t key0 = atoi(argv[8]);
uint32_t key1 = atoi(argv[9]);
uint32_t key2 = atoi(argv[10]);
//Initialize decryption (pass decryption keys)
initDecryptor(key0, key1, key2);
state.isEncrypted = true;
break;
}
default:
fprintf(stderr, "Unknown option '%c'.", (char)curOption);
exit(1); exit(1);
} }
//TODO: verify argv and assign it to variables }
char* archiveName = argv[1];
const unsigned long archiveOffset = atol(argv[2]);
const unsigned long fileLength = atol(argv[3]);
const bool isEncrypted = argc == 7; if (requiredOptions != 7) {
if (isEncrypted) { fprintf(stderr, "Missing arguments, received %i.", requiredOptions);
exit(1);
}
//TODO: verify argv and assign it to variables
//char* archiveName = argv[1];
//const unsigned long archiveOffset = atol(argv[2]);
//const unsigned long fileLength = atol(argv[3]);
//const bool isEncrypted = argc == 7;
/*if (isEncrypted) {
uint32_t key0 = atoi(argv[4]); uint32_t key0 = atoi(argv[4]);
uint32_t key1 = atoi(argv[5]); uint32_t key1 = atoi(argv[5]);
uint32_t key2 = atoi(argv[6]); uint32_t key2 = atoi(argv[6]);
//Initialize decryption (pass decryption keys) //Initialize decryption (pass decryption keys)
initDecryptor(key0, key1, key2); initDecryptor(key0, key1, key2);
} }*/
//------------------------------------------------- //-------------------------------------------------
@ -63,7 +138,7 @@ int main(int argc, unsigned char *argv[]) {
//------------------------------------------------- //-------------------------------------------------
//Initialize file reader //Initialize file reader
initFileReader(archiveName, archiveOffset); initFileReader(state.diskName, state.diskOffset);
//Skip local file header (30 bytes + additional length) //Skip local file header (30 bytes + additional length)
getBytes(compressedChunk, 30UL); getBytes(compressedChunk, 30UL);
@ -75,10 +150,12 @@ int main(int argc, unsigned char *argv[]) {
} }
//Read additional length //Read additional length
const unsigned long additionalLength = getUint16(compressedChunk + 26) + getUint16(compressedChunk + 28); const unsigned long additionalLength = getUint16(compressedChunk + 26) + getUint16(compressedChunk + 28);
getBytes(compressedChunk, additionalLength); if (additionalLength > 0UL) {
getBytes(NULL, additionalLength);
}
//If file is encrypted, skip 12-byte encryption header //If file is encrypted, skip 12-byte encryption header
if (isEncrypted) { if (state.isEncrypted) {
getBytes(compressedChunk, ENCRYPTION_HEADER_LENGTH); getBytes(compressedChunk, ENCRYPTION_HEADER_LENGTH);
decrypt(compressedChunk, ENCRYPTION_HEADER_LENGTH); decrypt(compressedChunk, ENCRYPTION_HEADER_LENGTH);
} }
@ -89,7 +166,7 @@ int main(int argc, unsigned char *argv[]) {
inflateInit(compressedChunk, uncompressedChunk, BUFFER_SIZE); inflateInit(compressedChunk, uncompressedChunk, BUFFER_SIZE);
//Read actual file //Read actual file
unsigned long remainingBytes = fileLength; unsigned long remainingBytes = state.fileSize;
bool needToRead = true; bool needToRead = true;
bool hasReachedEnd = false; bool hasReachedEnd = false;
unsigned long chunkSize; unsigned long chunkSize;
@ -101,7 +178,7 @@ int main(int argc, unsigned char *argv[]) {
remainingBytes -= chunkSize; remainingBytes -= chunkSize;
//Decrypt file if it is encrypted //Decrypt file if it is encrypted
if (isEncrypted) { if (state.isEncrypted) {
//TODO: For highest performance, we need to move if condition outside of while loop //TODO: For highest performance, we need to move if condition outside of while loop
decrypt(compressedChunk, chunkSize); decrypt(compressedChunk, chunkSize);
} }
@ -115,6 +192,7 @@ int main(int argc, unsigned 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() //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); write(1, uncompressedChunk + uncompressedPosition, inflateResult.numBytesWrittenToOutput);
uncompressedPosition += inflateResult.numBytesWrittenToOutput; uncompressedPosition += inflateResult.numBytesWrittenToOutput;
while (uncompressedPosition >= BUFFER_SIZE) { while (uncompressedPosition >= BUFFER_SIZE) {
@ -122,8 +200,9 @@ int main(int argc, unsigned char *argv[]) {
} }
//Optionally perform xdelta3 //Optionally perform xdelta3
if (state.prevFile) {
//TODO //TODO
}
} }
//release memory //release memory

View file

@ -19,6 +19,19 @@ void readBytesIntoBuffer(uint8_t* buffer, long numBytes) {
} }
//Skips the given amount of bytes in the file
void skipBytes(long numBytes) {
const int result = fseek(file.filePointer, numBytes, SEEK_CUR);
if (result != 0) {
fprintf(stderr, "Could not skip %lu bytes from file: %s\n", numBytes, strerror(errno));
exit(1);
} else {
file.offset += numBytes;
}
}
//Closes the currently opened file and opens the next file at its beginning. //Closes the currently opened file and opens the next file at its beginning.
void openNextFile() { void openNextFile() {
const int closeResult = fclose(file.filePointer); const int closeResult = fclose(file.filePointer);

View file

@ -17,5 +17,9 @@ struct FILE_INFO file;
void readBytesIntoBuffer(uint8_t* buffer, long numBytes); void readBytesIntoBuffer(uint8_t* buffer, long numBytes);
//Skips the given amount of bytes in the file
void skipBytes(long numBytes);
//Closes the currently opened file and opens the next file at its beginning. //Closes the currently opened file and opens the next file at its beginning.
void openNextFile(); void openNextFile();