aboutsummaryrefslogtreecommitdiff
path: root/src/options.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/options.cpp')
-rw-r--r--src/options.cpp184
1 files changed, 123 insertions, 61 deletions
diff --git a/src/options.cpp b/src/options.cpp
index 280d5c6..66a8c69 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -86,11 +86,12 @@ OptionsRestore::getOutFilePath() const
void
OptionParser::printUsage()
{
- std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-s SECTOR_SIZE]";
- std::cout << " [-b BUFFER_SIZE] INFILE BASEFILE OUTFILE" << std::endl;
+ std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-S SECTOR_SIZE]";
+ std::cout << " [-B BUFFER_SIZE] -i INFILE -b BASEFILE -o OUTFILE"
+ << std::endl;
- std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-s SECTOR_SIZE]";
- std::cout << "[-b BUFFER_SIZE] DIFFFILE OUTFILE" << std::endl;
+ std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-S SECTOR_SIZE]";
+ std::cout << "[-B BUFFER_SIZE] -d DIFFFILE -o OUTFILE" << std::endl;
std::cout << " Or: " << PROGRAM_NAME_STR << " help" << std::endl;
}
@@ -118,82 +119,118 @@ OptionParser::parseBackup(int argc, char **argv)
{
OptionsBackup opts;
- parse_common(&argc, &argv, opts);
+ // Skip the executable name. Do not skip the operation name. getopt expects
+ // to start at an argument immediately preceding the possible options.
+ argc -= 1;
+ argv += 1;
- if (argc < 3) {
- throw OptionError("missing arguments");
- } else if (argc > 3) {
- throw OptionError("too many arguments");
- } else {
- opts.in_file_path = next_arg(&argv);
- opts.base_file_path = next_arg(&argv);
- opts.out_file_path = next_arg(&argv);
- }
+ int ch;
+ const char *arg_sector_size = NULL;
+ const char *arg_buffer_size = NULL;
+ const char *arg_input_file = NULL;
+ const char *arg_base_file = NULL;
+ const char *arg_output_file = NULL;
- return opts;
-}
+ while ((ch = getopt(argc, argv, ":B:S:i:b:o:")) != -1) {
+ switch (ch) {
+ case 'B':
+ arg_buffer_size = optarg;
+ break;
-OptionsRestore
-OptionParser::parseRestore(int argc, char **argv)
-{
- OptionsRestore opts;
+ case 'S':
+ arg_sector_size = optarg;
+ break;
- parse_common(&argc, &argv, opts);
+ case 'i':
+ arg_input_file = optarg;
+ break;
- if (argc < 2) {
- throw OptionError("missing arguments");
- } else if (argc > 2) {
- throw OptionError("too many arguments");
- } else {
- opts.diff_file_path = next_arg(&argv);
- opts.out_file_path = next_arg(&argv);
- }
+ case 'b':
+ arg_base_file = optarg;
+ break;
- return opts;
-}
+ case 'o':
+ arg_output_file = optarg;
+ break;
-bool
-OptionParser::isOperation(int argc, char **argv, std::string_view operationName)
-{
- return ((argc >= 2) &&
- (strncmp(argv[1], operationName.data(),
- OptionParser::MAX_OPERATION_NAME_LENGTH) == 0));
-}
+ case ':':
+ throw OptionError("missing argument for option '-" +
+ std::string(1, optopt) + "'");
+ default:
+ throw OptionError("unknown option '-" + std::string(1, optopt) +
+ "'");
+ }
+ }
-int
-OptionParser::parse_unsigned(const char *const arg, uint32_t *const value)
-{
- char *end;
+ argc -= optind;
+ argv += optind;
- errno = 0;
+ /* Convert numbers in the arguments */
+ if ((arg_sector_size != NULL) &&
+ parse_unsigned(arg_sector_size, &(opts.sector_size))) {
+ throw OptionError("incorrect sector size");
+ } else if ((arg_buffer_size != NULL) &&
+ parse_unsigned(arg_buffer_size, &(opts.buffer_size))) {
+ throw OptionError("incorrect buffer size");
+ } else if (opts.sector_size == 0) {
+ throw OptionError("sector size cannot be 0");
+ } else if (opts.buffer_size == 0) {
+ throw OptionError("buffer size cannot be 0");
+ } else if (opts.sector_size > opts.buffer_size) {
+ throw OptionError("sector size cannot larger than buffer size");
+ } else if ((opts.buffer_size % opts.sector_size) != 0) {
+ throw OptionError("buffer size is not multiple of sector size");
+ }
- *value = strtoul(arg, &end, 0);
+ if (arg_input_file == NULL) {
+ throw OptionError("missing input file");
+ } else if (arg_base_file == NULL) {
+ throw OptionError("missing base file");
+ } else if (arg_output_file == NULL) {
+ throw OptionError("missing output file");
+ } else if (argc != 0) {
+ throw OptionError("too many arguments");
+ }
- return ((*end != '\0') || (errno != 0)) ? -1 : 0;
+ opts.in_file_path = arg_input_file;
+ opts.base_file_path = arg_base_file;
+ opts.out_file_path = arg_output_file;
+
+ return opts;
}
-void
-OptionParser::parse_common(int *const argc, char ***const argv, Options &opts)
+OptionsRestore
+OptionParser::parseRestore(int argc, char **argv)
{
- // Skip the executable name. Do not skip the operation name. getopt expects
- // to start at an argument immediately preceding the possible options.
- *argc -= 1;
- *argv += 1;
+ OptionsRestore opts;
+
+ argc -= 1;
+ argv += 1;
int ch;
const char *arg_sector_size = NULL;
const char *arg_buffer_size = NULL;
+ const char *arg_diff_file = NULL;
+ const char *arg_output_file = NULL;
- while ((ch = getopt(*argc, *argv, ":b:s:")) != -1) {
+ while ((ch = getopt(argc, argv, ":B:S:d:o:")) != -1) {
switch (ch) {
- case 'b':
+ case 'B':
arg_buffer_size = optarg;
break;
- case 's':
+ case 'S':
arg_sector_size = optarg;
break;
+ case 'd':
+ arg_diff_file = optarg;
+ break;
+
+ case 'o':
+ arg_output_file = optarg;
+ break;
+
case ':':
throw OptionError("missing argument for option '-" +
std::string(1, optopt) + "'");
@@ -203,8 +240,8 @@ OptionParser::parse_common(int *const argc, char ***const argv, Options &opts)
}
}
- *argc -= optind;
- *argv += optind;
+ argc -= optind;
+ argv += optind;
/* Convert numbers in the arguments */
if ((arg_sector_size != NULL) &&
@@ -222,12 +259,37 @@ OptionParser::parse_common(int *const argc, char ***const argv, Options &opts)
} else if ((opts.buffer_size % opts.sector_size) != 0) {
throw OptionError("buffer size is not multiple of sector size");
}
+
+ if (arg_diff_file == NULL) {
+ throw OptionError("missing diff file");
+ } else if (arg_output_file == NULL) {
+ throw OptionError("missing output file");
+ } else if (argc != 0) {
+ throw OptionError("too many arguments");
+ }
+
+ opts.diff_file_path = arg_diff_file;
+ opts.out_file_path = arg_output_file;
+
+ return opts;
}
-const char *
-OptionParser::next_arg(char ***const argv)
+bool
+OptionParser::isOperation(int argc, char **argv, std::string_view operationName)
{
- const char *arg = **argv;
- ++(*argv);
- return arg;
+ return ((argc >= 2) &&
+ (strncmp(argv[1], operationName.data(),
+ OptionParser::MAX_OPERATION_NAME_LENGTH) == 0));
+}
+
+int
+OptionParser::parse_unsigned(const char *const arg, uint32_t *const value)
+{
+ char *end;
+
+ errno = 0;
+
+ *value = strtoul(arg, &end, 0);
+
+ return ((*end != '\0') || (errno != 0)) ? -1 : 0;
}