2018-07-17 14:05:22 +02:00
|
|
|
#include <errno.h>
|
2018-07-24 19:56:21 +02:00
|
|
|
#include <stdbool.h>
|
2018-07-24 17:11:24 +02:00
|
|
|
#include <stdio.h>
|
2018-07-24 19:56:21 +02:00
|
|
|
#include <stdlib.h>
|
2018-07-17 14:05:22 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
//Import our code
|
|
|
|
#include "decrypt.h"
|
2018-07-17 17:19:13 +02:00
|
|
|
#include "fileReader.h"
|
2018-07-24 18:10:07 +02:00
|
|
|
#include "utils/min.h"
|
2018-07-17 14:05:22 +02:00
|
|
|
|
2018-07-24 19:56:21 +02:00
|
|
|
#define BUFFER_SIZE 0xffffUL
|
|
|
|
#define ENCRYPTION_HEADER_LENGTH 12UL
|
|
|
|
|
|
|
|
uint16_t getUint16(char* buffer) {
|
|
|
|
return (uint16_t)buffer[0] | \
|
|
|
|
(uint16_t)buffer[1] << 8;
|
|
|
|
}
|
|
|
|
uint32_t getUint32(char* buffer) {
|
|
|
|
return (uint32_t)buffer[0] | \
|
|
|
|
(uint32_t)buffer[1] << 8 | \
|
|
|
|
(uint32_t)buffer[2] << 16 | \
|
|
|
|
(uint32_t)buffer[3] << 24;
|
|
|
|
}
|
|
|
|
|
2018-07-17 14:05:22 +02:00
|
|
|
int main(int argc, unsigned char *argv[]) {
|
2018-07-24 19:56:21 +02:00
|
|
|
if (argc != 4 && argc != 7) {
|
|
|
|
fprintf(stderr, "Wrong arguments. Usage: patcher-installer <disk_name> <disk_offset> <file_size> [<key0> <key1> <key2>]");
|
|
|
|
exit(1);
|
|
|
|
}
|
2018-07-24 18:10:07 +02:00
|
|
|
//TODO: verify argv and assign it to variables
|
2018-07-24 19:56:21 +02:00
|
|
|
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 key1 = atoi(argv[5]);
|
|
|
|
uint32_t key2 = atoi(argv[6]);
|
|
|
|
//Initialise decryption (pass decryption keys)
|
|
|
|
initDecryptor(key0, key1, key2);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------
|
2018-07-17 14:05:22 +02:00
|
|
|
|
2018-07-17 15:05:57 +02:00
|
|
|
//Initialise file reader
|
2018-07-24 18:17:15 +02:00
|
|
|
initFileReader(archiveName, archiveOffset);
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-24 19:56:21 +02:00
|
|
|
//Skip local file header (30 bytes + additional length)
|
2018-07-24 17:07:47 +02:00
|
|
|
char* fileHeader = getBytes(30UL);
|
2018-07-24 19:56:21 +02:00
|
|
|
//Check that header is correct
|
|
|
|
const uint32_t magic = getUint32(fileHeader);
|
|
|
|
if (magic != (uint32_t)0x06054b50) {
|
|
|
|
fprintf(stderr, "Wrong magic in local file header, expected 0x06054b50 but found %#010x.", magic);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
free(fileHeader);
|
|
|
|
//Read additional length
|
|
|
|
const unsigned long additionalLength = getUint16(fileHeader + 26) + getUint16(fileHeader + 28);
|
|
|
|
char* additionalBytes = getBytes(additionalLength);
|
|
|
|
free(additionalBytes);
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-24 19:56:21 +02:00
|
|
|
//If file is encrypted, skip 12-byte encryption header
|
|
|
|
if (isEncrypted) {
|
|
|
|
char* encrHeader = getBytes(ENCRYPTION_HEADER_LENGTH);
|
|
|
|
decrypt(encrHeader, ENCRYPTION_HEADER_LENGTH);
|
|
|
|
free(encrHeader);
|
|
|
|
}
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-24 19:56:21 +02:00
|
|
|
//-------------------------------------------------
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-24 18:10:07 +02:00
|
|
|
//Read actual file
|
2018-07-24 18:17:15 +02:00
|
|
|
unsigned long remainingBytes = fileLength;
|
2018-07-24 18:10:07 +02:00
|
|
|
while (remainingBytes > 0) {
|
2018-07-24 19:56:21 +02:00
|
|
|
const unsigned long chunkSize = min(BUFFER_SIZE, remainingBytes);
|
2018-07-24 18:10:07 +02:00
|
|
|
char* chunk = getBytes(chunkSize);
|
|
|
|
remainingBytes -= chunkSize;
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-24 19:56:21 +02:00
|
|
|
//Decrypt file if it is encrypted
|
|
|
|
if (isEncrypted) {
|
|
|
|
//TODO: For highest performance, we need to move if condition outside of while loop
|
|
|
|
decrypt(chunk, chunkSize);
|
|
|
|
}
|
2018-07-24 18:10:07 +02:00
|
|
|
|
|
|
|
//Decompress file
|
|
|
|
//TODO
|
|
|
|
|
|
|
|
//Optionally perform xdelta3
|
|
|
|
//TODO
|
2018-07-24 19:56:21 +02:00
|
|
|
|
|
|
|
//release memory
|
|
|
|
//TODO: need to malloc once outside of while loop, and then reuse it instead of a new malloc() each loop
|
|
|
|
free(chunk);
|
2018-07-24 18:10:07 +02:00
|
|
|
}
|
2018-07-17 15:05:57 +02:00
|
|
|
|
2018-07-17 14:05:22 +02:00
|
|
|
return 0;
|
|
|
|
}
|