ssn-installer/src/parseArguments.c
2019-07-21 23:18:00 +02:00

120 lines
3.4 KiB
C

#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "decrypt.h"
#include "errorAndExit.h"
#include "parseArguments.h"
#include "rateLimiter.h"
//Uses GNU's getopt_long_only(), see https://www.gnu.org/software/libc/manual/html_node/Getopt-Long-Options.html
//For a description of these arguments, see errorAndExit.c
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'},
{"previous", required_argument, 0, 'p'},
{"target", required_argument, 0, 't'},
{"limit", required_argument, 0, 'l'},
{NULL, 0, 0, 0},
};
struct arguments parseArguments(int argc, char *argv[]) {
//Stores current state from command line arguments, initialized to zero
struct arguments state = {};
bool hasDisk = false;
bool hasOffset = false;
bool hasSize = false;
while (1) {
//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, "", long_options, &optionIndex);
//end of command line arguments reached
if (curOption == -1) {
break;
}
switch (curOption) {
case 'd': //disk name
state.diskName = optarg;
hasDisk = true;
break;
case 'o': //offset
state.diskOffset = atol(optarg);
hasOffset = true;
break;
case 's': //size
state.fileSize = atol(optarg);
hasSize = true;
break;
case 'k': { //decryption keys (12345,12345,12345)
//Split argument by comma into three integers
char* token = strtok(optarg, ",");
uint32_t keys[3] = { 0UL, 0UL, 0UL };
int index = 0;
while (token != NULL) {
if (index > 2) {
fprintf(stderr, "Too many decryption keys specified with --keys; only 3 are allowed.\n");
errorAndExit();
}
keys[index] = atoi(token);
index += 1;
token = strtok(NULL, ",");
}
if (index < 3) {
fprintf(stderr, "Not enough decryption keys specified with --keys; 3 are required but only found %i.\n", index);
errorAndExit();
}
//Initialize decryption (pass decryption keys)
initDecryptor(keys[0], keys[1], keys[2]);
state.isEncrypted = true;
break;
}
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 'l': //disk write limit
setDiskSpeed(atol(optarg));
break;
case '?':
errorAndExit();
break;
default:
fprintf(stderr, "Unknown option '%c'.\n", (char)curOption);
errorAndExit();
}
}
if (!hasDisk) {
fprintf(stderr, "Missing required argument --disk.\n");
errorAndExit();
}
if (!hasOffset) {
fprintf(stderr, "Missing required argument --offset.\n");
errorAndExit();
}
if (!hasSize) {
fprintf(stderr, "Missing required argument --size.\n");
errorAndExit();
}
if (optind < argc) {
fprintf(stderr, "Found %i argument(s) without an option. All arguments must be preceded by an option.\n", argc - optind);
errorAndExit();
}
return state;
}