#include #include #include #include #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; }