aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2024-03-24 16:22:08 +0100
committerJán Sučan <jan@jansucan.com>2024-03-24 16:25:41 +0100
commite86c9c6135ba0462c5a352e6d8ea4b730aa9c370 (patch)
tree0c1aa521d865c4a17576d1048692922d895112c9 /src
parentdde03ff8796277f6ed0f8c8e8b18b83b801d6d27 (diff)
Rewrite the option code in object-oriented way
Diffstat (limited to 'src')
-rw-r--r--src/backup.cpp112
-rw-r--r--src/backup.h4
-rw-r--r--src/main.cpp44
-rw-r--r--src/options.cpp294
-rw-r--r--src/options.h109
-rw-r--r--src/resources.cpp213
-rw-r--r--src/resources.h74
-rw-r--r--src/restore.cpp71
-rw-r--r--src/restore.h4
9 files changed, 373 insertions, 552 deletions
diff --git a/src/backup.cpp b/src/backup.cpp
index 0b558b6..b0b0054 100644
--- a/src/backup.cpp
+++ b/src/backup.cpp
@@ -34,14 +34,69 @@
#include <stdlib.h>
#include <string.h>
-static int check_files(const options_backup_t *const opts,
+typedef struct {
+ FILE *in_file;
+ FILE *ref_file;
+ FILE *out_file;
+
+ char *in_buffer;
+ char *ref_buffer;
+ char *out_buffer;
+
+ size_t out_buffer_size;
+} resources_backup_t;
+
+static int check_files(const OptionsBackup &opts,
const resources_backup_t *const res);
static int write_out_buffer(const char *const buffer, size_t size,
FILE *const file);
static int
-check_files(const options_backup_t *const opts,
- const resources_backup_t *const res)
+resources_allocate_for_backup(const OptionsBackup &opts,
+ resources_backup_t *const res)
+{
+ if ((res->in_file = fopen(opts.getInFilePath().c_str(), "r")) == NULL) {
+ print_error("cannot open input file: %s", strerror(errno));
+ return 1;
+ }
+
+ if ((res->ref_file = fopen(opts.getRefFilePath().c_str(), "r")) == NULL) {
+ print_error("cannot open reference file: %s", strerror(errno));
+ return 1;
+ }
+
+ /* When backing up, the output file is truncated to hold the
+ * new data
+ */
+ if ((res->out_file = fopen(opts.getOutFilePath().c_str(), "w+")) == NULL) {
+ print_error("cannot open output file: %s", strerror(errno));
+ return 1;
+ }
+
+ /* The output buffer contains also the offsets */
+ res->out_buffer_size =
+ ((opts.getBufferSize() / opts.getSectorSize()) * sizeof(uint64_t)) +
+ opts.getBufferSize();
+
+ // TODO: separate function
+ if ((res->in_buffer = (char *)malloc(opts.getBufferSize())) == NULL) {
+ print_error("cannot allocate buffer for input file data");
+ return 1;
+ } else if ((res->ref_buffer = (char *)malloc(opts.getBufferSize())) ==
+ NULL) {
+ print_error("cannot allocate buffer for reference file data");
+ return 1;
+ } else if ((res->out_buffer = (char *)malloc(res->out_buffer_size)) ==
+ NULL) {
+ print_error("cannot allocate buffer for output file data");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+check_files(const OptionsBackup &opts, const resources_backup_t *const res)
{
bool in_size_ok = false;
const size_t in_size = file_size(res->in_file, &in_size_ok);
@@ -63,10 +118,10 @@ check_files(const options_backup_t *const opts,
if (in_size != ref_size) {
print_error("input file and reference file differ in size");
return 1;
- } else if ((in_size % opts->sector_size) != 0) {
+ } else if ((in_size % opts.getSectorSize()) != 0) {
print_error(
"size of input file and reference file is not multiple of %" PRIu32,
- opts->sector_size);
+ opts.getSectorSize());
return 1;
}
@@ -87,9 +142,15 @@ write_out_buffer(const char *const buffer, size_t size, FILE *const file)
}
int
-backup(const options_backup_t *const opts, const resources_backup_t *const res)
+backup(const OptionsBackup &opts)
{
- if (check_files(opts, res) != 0) {
+ resources_backup_t res;
+
+ if (resources_allocate_for_backup(opts, &res) != 0) {
+ return 1;
+ }
+
+ if (check_files(opts, &res) != 0) {
return 1;
}
@@ -99,11 +160,12 @@ backup(const options_backup_t *const opts, const resources_backup_t *const res)
for (;;) {
/* Read the sectors from the input and reference files into the buffers
*/
- const size_t in_sectors_read = file_read_sectors(
- res->in_file, res->in_buffer, opts->buffer_size, opts->sector_size);
+ const size_t in_sectors_read =
+ file_read_sectors(res.in_file, res.in_buffer, opts.getBufferSize(),
+ opts.getSectorSize());
const size_t ref_sectors_read =
- file_read_sectors(res->ref_file, res->ref_buffer, opts->buffer_size,
- opts->sector_size);
+ file_read_sectors(res.ref_file, res.ref_buffer,
+ opts.getBufferSize(), opts.getSectorSize());
if ((in_sectors_read == 0) || (ref_sectors_read == 0)) {
break;
@@ -115,39 +177,39 @@ backup(const options_backup_t *const opts, const resources_backup_t *const res)
/* Process the sectors in the buffers */
for (size_t sector = 0; sector < in_sectors_read; ++sector) {
- const size_t buffer_offset = sector * opts->sector_size;
+ const size_t buffer_offset = sector * opts.getSectorSize();
- if (memcmp(res->in_buffer + buffer_offset,
- res->ref_buffer + buffer_offset,
- opts->sector_size) != 0) {
+ if (memcmp(res.in_buffer + buffer_offset,
+ res.ref_buffer + buffer_offset,
+ opts.getSectorSize()) != 0) {
/* Backup the changed sector */
- if (out_buffer_index >= res->out_buffer_size) {
+ if (out_buffer_index >= res.out_buffer_size) {
/* The output buffer is full. Write it to the output file */
- if (write_out_buffer(res->out_buffer, out_buffer_index,
- res->out_file) != 0) {
+ if (write_out_buffer(res.out_buffer, out_buffer_index,
+ res.out_file) != 0) {
return 1;
}
out_buffer_index = 0;
}
/* Write the next backup record */
const uint64_t o = htole64(input_file_offset);
- memcpy(res->out_buffer + out_buffer_index, (void *)&o,
+ memcpy(res.out_buffer + out_buffer_index, (void *)&o,
sizeof(o));
out_buffer_index += sizeof(o);
- memcpy(res->out_buffer + out_buffer_index,
- res->in_buffer + buffer_offset, opts->sector_size);
- out_buffer_index += opts->sector_size;
+ memcpy(res.out_buffer + out_buffer_index,
+ res.in_buffer + buffer_offset, opts.getSectorSize());
+ out_buffer_index += opts.getSectorSize();
}
- input_file_offset += opts->sector_size;
+ input_file_offset += opts.getSectorSize();
}
}
/* Write out the output buffer */
if (out_buffer_index > 0) {
- if (write_out_buffer(res->out_buffer, out_buffer_index,
- res->out_file) != 0) {
+ if (write_out_buffer(res.out_buffer, out_buffer_index, res.out_file) !=
+ 0) {
return 1;
}
}
diff --git a/src/backup.h b/src/backup.h
index 9f14559..9629cb7 100644
--- a/src/backup.h
+++ b/src/backup.h
@@ -28,9 +28,7 @@
#define BACKUP_H
#include "options.h"
-#include "resources.h"
-int backup(const options_backup_t *const opts,
- const resources_backup_t *const res);
+int backup(const OptionsBackup &opts);
#endif /* BACKUP_H */
diff --git a/src/main.cpp b/src/main.cpp
index 35e5c3d..15b9b1c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -26,38 +26,28 @@
#include "backup.h"
#include "options.h"
-#include "resources.h"
#include "restore.h"
-#include <stdlib.h>
-
-static void
-clean_exit(resources_t *const res, int exit_code)
-{
- resources_free(res);
- exit(exit_code);
-}
+#include <iostream>
int
main(int argc, char **argv)
{
- options_t opts;
-
- if (!options_parse(argc, argv, &opts)) {
- options_usage(1);
- } else if (options_is_operation(&opts, OPERATION_ID_HELP)) {
- options_usage(0);
- }
-
- resources_t res;
-
- if (resources_allocate(&opts, &res)) {
- clean_exit(&res, 1);
- } else if (options_is_operation(&opts, OPERATION_ID_BACKUP)) {
- clean_exit(&res, backup(options_get_for_backup(&opts),
- resources_get_for_backup(&res)));
- } else {
- clean_exit(&res, restore(options_get_for_restore(&opts),
- resources_get_for_restore(&res)));
+ try {
+ if (OptionParser::isHelp(argc, argv)) {
+ OptionParser::printUsage();
+ exit(0);
+ } else if (OptionParser::isBackup(argc, argv)) {
+ return backup(OptionParser::parseBackup(argc, argv));
+ } else if (OptionParser::isRestore(argc, argv)) {
+ return restore(OptionParser::parseRestore(argc, argv));
+ } else {
+ OptionParser::printUsage();
+ exit(1);
+ }
+ } catch (const OptionError &e) {
+ OptionParser::printUsage();
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ exit(1);
}
}
diff --git a/src/options.cpp b/src/options.cpp
index ecb1026..545d11a 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -26,136 +26,160 @@
#include "options.h"
-#include "print.h"
+#include <iostream>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cstring>
#include <unistd.h>
/* This header file is automatically generated at build time from the Makefile
*/
#include "program_info.h"
-#define OPTIONS_MAX_OPERATION_NAME_LENGTH 8
-#define OPTIONS_DEFAULT_SECTOR_SIZE 512
-#define OPTIONS_DEFAULT_BUFFER_SIZE (4 * 1024 * 1024)
-
-struct common_options {
- uint32_t sector_size;
- uint32_t buffer_size;
-};
-
-static int options_parse_unsigned(const char *const arg, uint32_t *const value);
-static void options_parse_operation(const char *const argv,
- options_t *const opts);
-static bool options_parse_common(int *const argc, char ***const argv,
- struct common_options *const opts);
-static bool options_parse_backup(int *const argc, char ***const argv,
- options_t *const opts);
-static bool options_parse_restore(int *const argc, char ***const argv,
- options_t *const opts);
-static const char *next_arg(char ***const argv);
+Options::Options()
+ : sector_size{Options::DEFAULT_SECTOR_SIZE},
+ buffer_size{Options::DEFAULT_BUFFER_SIZE}
+{
+}
-bool
-options_parse(int argc, char **argv, options_t *const opts)
+uint32_t
+Options::getSectorSize() const
{
- // Skip the executable name
- --argc;
- ++argv;
+ return sector_size;
+}
- options_parse_operation(argv[0], opts);
+uint32_t
+Options::getBufferSize() const
+{
+ return buffer_size;
+}
- if (options_is_operation(opts, OPERATION_ID_UNKNOWN)) {
- return false;
- }
+std::filesystem::path
+OptionsBackup::getInFilePath() const
+{
+ return in_file_path;
+}
- if (options_is_operation(opts, OPERATION_ID_BACKUP)) {
- if (!options_parse_backup(&argc, &argv, opts)) {
- return false;
- }
- } else if (options_is_operation(opts, OPERATION_ID_RESTORE)) {
- if (!options_parse_restore(&argc, &argv, opts)) {
- return false;
- }
- }
- return true;
+std::filesystem::path
+OptionsBackup::getRefFilePath() const
+{
+ return ref_file_path;
+}
+
+std::filesystem::path
+OptionsBackup::getOutFilePath() const
+{
+ return out_file_path;
+}
+
+std::filesystem::path
+OptionsRestore::getInFilePath() const
+{
+ return in_file_path;
+}
+
+std::filesystem::path
+OptionsRestore::getOutFilePath() const
+{
+ return out_file_path;
}
void
-options_usage(int exit_code)
+OptionParser::printUsage()
{
- printf("Usage: %s backup [-s SECTOR_SIZE] [-b BUFFER_SIZE] INFILE REFFILE "
- "OUTFILE\n",
- PROGRAM_NAME_STR);
- printf(" Or: %s restore [-s SECTOR_SIZE] [-b BUFFER_SIZE] REFFILE "
- "OUTFILE\n",
- PROGRAM_NAME_STR);
- printf(" Or: %s help\n", PROGRAM_NAME_STR);
- exit(exit_code);
+ std::cout << "Usage: " << PROGRAM_NAME_STR << " backup [-s SECTOR_SIZE]";
+ std::cout << " [-b BUFFER_SIZE] INFILE REFFILE OUTFILE" << std::endl;
+
+ std::cout << " Or: " << PROGRAM_NAME_STR << " restore [-s SECTOR_SIZE]";
+ std::cout << "[-b BUFFER_SIZE] REFFILE OUTFILE" << std::endl;
+
+ std::cout << " Or: " << PROGRAM_NAME_STR << " help" << std::endl;
}
bool
-options_is_operation(const options_t *const opts, operation_id_t operation_id)
+OptionParser::isHelp(int argc, char **argv)
{
- return (opts->operation_id == operation_id);
+ return isOperation(argc, argv, "help");
}
-const options_backup_t *
-options_get_for_backup(const options_t *const opts)
+bool
+OptionParser::isBackup(int argc, char **argv)
{
- return &(opts->op.backup);
+ return isOperation(argc, argv, "backup");
}
-const options_restore_t *
-options_get_for_restore(const options_t *const opts)
+bool
+OptionParser::isRestore(int argc, char **argv)
{
- return &(opts->op.restore);
+ return isOperation(argc, argv, "restore");
}
-static int
-options_parse_unsigned(const char *const arg, uint32_t *const value)
+OptionsBackup
+OptionParser::parseBackup(int argc, char **argv)
{
- char *end;
+ OptionsBackup opts;
- errno = 0;
+ parse_common(&argc, &argv, opts);
- *value = strtoul(arg, &end, 0);
+ 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.ref_file_path = next_arg(&argv);
+ opts.out_file_path = next_arg(&argv);
+ }
- return ((*end != '\0') || (errno != 0)) ? -1 : 0;
+ return opts;
}
-static void
-options_parse_operation(const char *const op_name, options_t *const opts)
+OptionsRestore
+OptionParser::parseRestore(int argc, char **argv)
{
- if (op_name == NULL) {
- opts->operation_id = OPERATION_ID_UNKNOWN;
- } else if (strncmp(op_name, "help", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_HELP;
- } else if (strncmp(op_name, "backup", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_BACKUP;
- } else if (strncmp(op_name, "restore", OPTIONS_MAX_OPERATION_NAME_LENGTH) ==
- 0) {
- opts->operation_id = OPERATION_ID_RESTORE;
+ OptionsRestore opts;
+
+ parse_common(&argc, &argv, opts);
+
+ if (argc < 2) {
+ throw OptionError("missing arguments");
+ } else if (argc > 2) {
+ throw OptionError("too many arguments");
} else {
- opts->operation_id = OPERATION_ID_UNKNOWN;
+ opts.in_file_path = next_arg(&argv);
+ opts.out_file_path = next_arg(&argv);
}
+
+ return opts;
+}
+
+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));
}
-static void
-options_init_common(struct common_options *const opts)
+int
+OptionParser::parse_unsigned(const char *const arg, uint32_t *const value)
{
- opts->sector_size = OPTIONS_DEFAULT_SECTOR_SIZE;
- opts->buffer_size = OPTIONS_DEFAULT_BUFFER_SIZE;
+ char *end;
+
+ errno = 0;
+
+ *value = strtoul(arg, &end, 0);
+
+ return ((*end != '\0') || (errno != 0)) ? -1 : 0;
}
-static bool
-options_parse_common(int *const argc, char ***const argv,
- struct common_options *const opts)
+void
+OptionParser::parse_common(int *const argc, char ***const argv, Options &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;
+
int ch;
char *arg_sector_size = NULL;
char *arg_buffer_size = NULL;
@@ -171,11 +195,11 @@ options_parse_common(int *const argc, char ***const argv,
break;
case ':':
- print_error("missing argument for option '-%c'", optopt);
- return false;
+ throw OptionError("missing argument for option '-" +
+ std::string(1, optopt) + "'");
default:
- print_error("unknown option '-%c'", optopt);
- return false;
+ throw OptionError("unknown option '-" + std::string(1, optopt) +
+ "'");
}
}
@@ -184,84 +208,24 @@ options_parse_common(int *const argc, char ***const argv,
/* Convert numbers in the arguments */
if ((arg_sector_size != NULL) &&
- options_parse_unsigned(arg_sector_size, &(opts->sector_size))) {
- print_error("incorrect sector size");
- return false;
+ parse_unsigned(arg_sector_size, &(opts.sector_size))) {
+ throw OptionError("incorrect sector size");
} else if ((arg_buffer_size != NULL) &&
- options_parse_unsigned(arg_buffer_size, &(opts->buffer_size))) {
- print_error("incorrect buffer size");
- return false;
- } else if (opts->sector_size == 0) {
- print_error("sector size cannot be 0");
- return false;
- } else if (opts->buffer_size == 0) {
- print_error("buffer size cannot be 0");
- return false;
- } else if (opts->sector_size > opts->buffer_size) {
- print_error("sector size cannot larger than buffer size");
- return false;
- } else if ((opts->buffer_size % opts->sector_size) != 0) {
- print_error("buffer size is not multiple of sector size");
- return false;
- }
-
- return true;
-}
-
-static bool
-options_parse_backup(int *const argc, char ***const argv, options_t *const opts)
-{
- struct common_options common_opts;
- options_init_common(&common_opts);
- if (!options_parse_common(argc, argv, &common_opts)) {
- return false;
- }
-
- if (*argc < 3) {
- print_error("missing arguments");
- return false;
- } else if (*argc > 3) {
- print_error("too many arguments");
- return false;
- } else {
- opts->op.backup.sector_size = common_opts.sector_size;
- opts->op.backup.buffer_size = common_opts.buffer_size;
- opts->op.backup.in_file_path = next_arg(argv);
- opts->op.backup.ref_file_path = next_arg(argv);
- opts->op.backup.out_file_path = next_arg(argv);
- }
-
- return true;
-}
-
-static bool
-options_parse_restore(int *const argc, char ***const argv,
- options_t *const opts)
-{
- struct common_options common_opts;
- options_init_common(&common_opts);
- if (!options_parse_common(argc, argv, &common_opts)) {
- return false;
+ 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");
}
-
- if (*argc < 2) {
- print_error("missing arguments");
- return false;
- } else if (*argc > 2) {
- print_error("too many arguments");
- return false;
- } else {
- opts->op.restore.sector_size = common_opts.sector_size;
- opts->op.restore.buffer_size = common_opts.buffer_size;
- opts->op.restore.in_file_path = next_arg(argv);
- opts->op.restore.out_file_path = next_arg(argv);
- }
-
- return true;
}
-static const char *
-next_arg(char ***const argv)
+const char *
+OptionParser::next_arg(char ***const argv)
{
const char *arg = **argv;
++(*argv);
diff --git a/src/options.h b/src/options.h
index e162fbe..e0c16d1 100644
--- a/src/options.h
+++ b/src/options.h
@@ -27,40 +27,89 @@
#ifndef OPTIONS_H
#define OPTIONS_H
-#include "operation_id.h"
+#include <cstdint>
+#include <filesystem>
-#include <stdbool.h>
-#include <stdint.h>
+class OptionError : public std::runtime_error
+{
+ public:
+ explicit OptionError(const std::string &message)
+ : std::runtime_error(message)
+ {
+ }
+};
-typedef struct {
- uint32_t sector_size;
- uint32_t buffer_size;
- const char *in_file_path;
- const char *ref_file_path;
- const char *out_file_path;
-} options_backup_t;
+class Options
+{
+ friend class OptionParser;
+
+ public:
+ static const int DEFAULT_SECTOR_SIZE{512};
+ static const int DEFAULT_BUFFER_SIZE{4 * 1024 * 1024};
+
+ Options();
+ virtual ~Options() = default;
-typedef struct {
+ uint32_t getSectorSize() const;
+ uint32_t getBufferSize() const;
+
+ private:
uint32_t sector_size;
uint32_t buffer_size;
- const char *in_file_path;
- const char *out_file_path;
-} options_restore_t;
-
-typedef struct {
- operation_id_t operation_id;
-
- union {
- options_backup_t backup;
- options_restore_t restore;
- } op;
-} options_t;
-
-bool options_parse(int argc, char **argv, options_t *const opts);
-void options_usage(int exit_code);
-bool options_is_operation(const options_t *const opts,
- operation_id_t operation_id);
-const options_backup_t *options_get_for_backup(const options_t *const opts);
-const options_restore_t *options_get_for_restore(const options_t *const opts);
+};
+
+class OptionsBackup : public Options
+{
+ friend class OptionParser;
+
+ public:
+ virtual ~OptionsBackup() = default;
+
+ std::filesystem::path getInFilePath() const;
+ std::filesystem::path getRefFilePath() const;
+ std::filesystem::path getOutFilePath() const;
+
+ private:
+ std::filesystem::path in_file_path;
+ std::filesystem::path ref_file_path;
+ std::filesystem::path out_file_path;
+};
+
+class OptionsRestore : public Options
+{
+ friend class OptionParser;
+
+ public:
+ virtual ~OptionsRestore() = default;
+
+ std::filesystem::path getInFilePath() const;
+ std::filesystem::path getOutFilePath() const;
+
+ private:
+ std::filesystem::path in_file_path;
+ std::filesystem::path out_file_path;
+};
+
+class OptionParser
+{
+ public:
+ static void printUsage();
+ static bool isHelp(int argc, char **argv);
+ static bool isBackup(int argc, char **argv);
+ static bool isRestore(int argc, char **argv);
+ ;
+ static OptionsBackup parseBackup(int argc, char **argv);
+ static OptionsRestore parseRestore(int argc, char **argv);
+
+ private:
+ static const size_t MAX_OPERATION_NAME_LENGTH{8};
+
+ static bool isOperation(int argc, char **argv,
+ std::string_view operationName);
+ static int parse_unsigned(const char *const arg, uint32_t *const value);
+ static void parse_common(int *const argc, char ***const argv,
+ Options &opts);
+ static const char *next_arg(char ***const argv);
+};
#endif /* OPTIONS_H */
diff --git a/src/resources.cpp b/src/resources.cpp
deleted file mode 100644
index 0829c7c..0000000
--- a/src/resources.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Copyright 2019 Ján Sučan <jan@jansucan.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "resources.h"
-
-#include "print.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-static void
-resources_init_for_backup(resources_backup_t *const res)
-{
- res->in_file = NULL;
- res->ref_file = NULL;
- res->out_file = NULL;
-
- res->in_buffer = NULL;
- res->ref_buffer = NULL;
- res->out_buffer = NULL;
-}
-
-static int
-resources_allocate_for_backup(const options_backup_t *const opts,
- resources_backup_t *const res)
-{
- if ((res->in_file = fopen(opts->in_file_path, "r")) == NULL) {
- print_error("cannot open input file: %s", strerror(errno));
- return 1;
- }
-
- if ((res->ref_file = fopen(opts->ref_file_path, "r")) == NULL) {
- print_error("cannot open reference file: %s", strerror(errno));
- return 1;
- }
-
- /* When backing up, the output file is truncated to hold the
- * new data
- */
- if ((res->out_file = fopen(opts->out_file_path, "w+")) == NULL) {
- print_error("cannot open output file: %s", strerror(errno));
- return 1;
- }
-
- /* The output buffer contains also the offsets */
- res->out_buffer_size =
- ((opts->buffer_size / opts->sector_size) * sizeof(uint64_t)) +
- opts->buffer_size;
-
- // TODO: separate function
- if ((res->in_buffer = (char *)malloc(opts->buffer_size)) == NULL) {
- print_error("cannot allocate buffer for input file data");
- return 1;
- } else if ((res->ref_buffer = (char *)malloc(opts->buffer_size)) == NULL) {
- print_error("cannot allocate buffer for reference file data");
- return 1;
- } else if ((res->out_buffer = (char *)malloc(res->out_buffer_size)) ==
- NULL) {
- print_error("cannot allocate buffer for output file data");
- return 1;
- }
-
- return 0;
-}
-
-static void
-resources_init_for_restore(resources_restore_t *const res)
-{
- res->in_file = NULL;
- res->out_file = NULL;
-
- res->in_buffer = NULL;
- res->out_buffer = NULL;
-}
-
-static int
-resources_allocate_for_restore(const options_restore_t *const opts,
- resources_restore_t *const res)
-{
- if ((res->in_file = fopen(opts->in_file_path, "r")) == NULL) {
- print_error("cannot open input file: %s", strerror(errno));
- return 1;
- }
-
- /* When restoring, the file must be opened for writing and not
- * truncated
- */
- if ((res->out_file = fopen(opts->out_file_path, "r+")) == NULL) {
- print_error("cannot open output file: %s", strerror(errno));
- return 1;
- }
-
- /* Allocate the buffer for data from the input file */
- /* The input buffer contains also the offsets */
- res->in_sector_size = sizeof(uint64_t) + opts->sector_size;
- const size_t in_buffer_sector_count =
- opts->buffer_size / res->in_sector_size;
- res->in_buffer_size = in_buffer_sector_count * res->in_sector_size;
-
- if ((res->in_buffer = (char *)malloc(res->in_buffer_size)) == NULL) {
- print_error("cannot allocate buffer for input file data");
- return 1;
- }
-
- return 0;
-}
-
-static void
-resources_close_file(FILE **const file)
-{
- if (*file != NULL) {
- fclose(*file);
- *file = NULL;
- }
-}
-
-static void
-resources_close_buffer(char **const buffer)
-{
- if (*buffer != NULL) {
- free(*buffer);
- *buffer = NULL;
- }
-}
-
-static void
-resources_free_backup(resources_backup_t *const res)
-{
- resources_close_file(&(res->in_file));
- resources_close_file(&(res->ref_file));
- resources_close_file(&(res->out_file));
-
- resources_close_buffer(&(res->in_buffer));
- resources_close_buffer(&(res->ref_buffer));
- resources_close_buffer(&(res->out_buffer));
-}
-
-static void
-resources_free_restore(resources_restore_t *const res)
-{
- resources_close_file(&(res->in_file));
- resources_close_file(&(res->out_file));
-
- resources_close_buffer(&(res->in_buffer));
- resources_close_buffer(&(res->out_buffer));
-}
-
-int
-resources_allocate(const options_t *const opts, resources_t *const res)
-{
- res->operation_id = opts->operation_id;
-
- if (res->operation_id == OPERATION_ID_BACKUP) {
- resources_init_for_backup(&(res->res.backup));
- return resources_allocate_for_backup(&(opts->op.backup),
- &(res->res.backup));
- } else if (res->operation_id == OPERATION_ID_RESTORE) {
- resources_init_for_restore(&(res->res.restore));
- return resources_allocate_for_restore(&(opts->op.restore),
- &(res->res.restore));
- }
-
- return 0;
-}
-
-const resources_backup_t *
-resources_get_for_backup(const resources_t *const res)
-{
- return &(res->res.backup);
-}
-
-const resources_restore_t *
-resources_get_for_restore(const resources_t *const res)
-{
- return &(res->res.restore);
-}
-
-void
-resources_free(resources_t *const res)
-{
- if (res->operation_id == OPERATION_ID_BACKUP) {
- resources_free_backup(&(res->res.backup));
- } else if (res->operation_id == OPERATION_ID_RESTORE) {
- resources_free_restore(&(res->res.restore));
- }
-
- res->operation_id = OPERATION_ID_UNKNOWN;
-}
diff --git a/src/resources.h b/src/resources.h
deleted file mode 100644
index 3cc0dff..0000000
--- a/src/resources.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright 2019 Ján Sučan <jan@jansucan.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef RESOURCES_H
-#define RESOURCES_H
-
-#include "operation_id.h"
-#include "options.h"
-
-#include <stdio.h>
-
-typedef struct {
- FILE *in_file;
- FILE *ref_file;
- FILE *out_file;
-
- char *in_buffer;
- char *ref_buffer;
- char *out_buffer;
-
- size_t out_buffer_size;
-} resources_backup_t;
-
-typedef struct {
- FILE *in_file;
- FILE *out_file;
-
- char *in_buffer;
- char *out_buffer;
-
- size_t in_sector_size;
- size_t in_buffer_size;
-} resources_restore_t;
-
-typedef struct {
- operation_id_t operation_id;
-
- union {
- resources_backup_t backup;
- resources_restore_t restore;
- } res;
-} resources_t;
-
-int resources_allocate(const options_t *const opts, resources_t *const res);
-const resources_backup_t *
-resources_get_for_backup(const resources_t *const res);
-const resources_restore_t *
-resources_get_for_restore(const resources_t *const res);
-void resources_free(resources_t *const res);
-
-#endif /* RESOURCES_H */
diff --git a/src/restore.cpp b/src/restore.cpp
index e73e42e..02532aa 100644
--- a/src/restore.cpp
+++ b/src/restore.cpp
@@ -36,6 +36,49 @@
#include <stdlib.h>
#include <string.h>
+typedef struct {
+ FILE *in_file;
+ FILE *out_file;
+
+ char *in_buffer;
+ char *out_buffer;
+
+ size_t in_sector_size;
+ size_t in_buffer_size;
+} resources_restore_t;
+
+static int
+resources_allocate_for_restore(const OptionsRestore &opts,
+ resources_restore_t *const res)
+{
+ if ((res->in_file = fopen(opts.getInFilePath().c_str(), "r")) == NULL) {
+ print_error("cannot open input file: %s", strerror(errno));
+ return 1;
+ }
+
+ /* When restoring, the file must be opened for writing and not
+ * truncated
+ */
+ if ((res->out_file = fopen(opts.getOutFilePath().c_str(), "r+")) == NULL) {
+ print_error("cannot open output file: %s", strerror(errno));
+ return 1;
+ }
+
+ /* Allocate the buffer for data from the input file */
+ /* The input buffer contains also the offsets */
+ res->in_sector_size = sizeof(uint64_t) + opts.getSectorSize();
+ const size_t in_buffer_sector_count =
+ opts.getBufferSize() / res->in_sector_size;
+ res->in_buffer_size = in_buffer_sector_count * res->in_sector_size;
+
+ if ((res->in_buffer = (char *)malloc(res->in_buffer_size)) == NULL) {
+ print_error("cannot allocate buffer for input file data");
+ return 1;
+ }
+
+ return 0;
+}
+
static bool
is_input_file_valid(const resources_restore_t *const res, uint32_t sector_size)
{
@@ -116,16 +159,21 @@ is_input_file_valid(const resources_restore_t *const res, uint32_t sector_size)
}
int
-restore(const options_restore_t *const opts,
- const resources_restore_t *const res)
+restore(const OptionsRestore &opts)
{
+ resources_restore_t res;
+
+ if (resources_allocate_for_restore(opts, &res) != 0) {
+ return 1;
+ }
+
/* Check validity of the input file */
- if (!is_input_file_valid(res, opts->sector_size)) {
+ if (!is_input_file_valid(&res, opts.getSectorSize())) {
return 1;
}
bool in_size_ok = false;
- const size_t in_size = file_size(res->in_file, &in_size_ok);
+ const size_t in_size = file_size(res.in_file, &in_size_ok);
if (!in_size_ok) {
print_error("cannot get size of input file: %s", strerror(errno));
@@ -136,28 +184,27 @@ restore(const options_restore_t *const opts,
for (;;) {
/* Read data of the offset and the next sector */
- const size_t in_sectors_read =
- file_read_sectors(res->in_file, res->in_buffer, res->in_buffer_size,
- res->in_sector_size);
+ const size_t in_sectors_read = file_read_sectors(
+ res.in_file, res.in_buffer, res.in_buffer_size, res.in_sector_size);
if (in_sectors_read == 0) {
break;
}
- char *in_buffer = res->in_buffer;
+ char *in_buffer = res.in_buffer;
for (size_t s = 0; s < in_sectors_read; ++s) {
const uint64_t out_offset = le64toh(*((uint64_t *)in_buffer));
in_buffer += sizeof(uint64_t);
- if (fseek(res->out_file, out_offset, SEEK_SET) != 0) {
+ if (fseek(res.out_file, out_offset, SEEK_SET) != 0) {
print_error("cannot seek in output file: %s", strerror(errno));
return 1;
}
const size_t out_written =
- fwrite(in_buffer, opts->sector_size, 1U, res->out_file);
- in_buffer += opts->sector_size;
+ fwrite(in_buffer, opts.getSectorSize(), 1U, res.out_file);
+ in_buffer += opts.getSectorSize();
if (out_written != 1U) {
print_error("cannot write to output file: %s", strerror(errno));
@@ -168,7 +215,7 @@ restore(const options_restore_t *const opts,
/* The input file must be read completely */
bool pos_ok = false;
- const size_t pos = file_tell(res->in_file, &pos_ok);
+ const size_t pos = file_tell(res.in_file, &pos_ok);
if (!pos_ok) {
print_error("cannot get position in the input file");
diff --git a/src/restore.h b/src/restore.h
index a6c09d1..457ef48 100644
--- a/src/restore.h
+++ b/src/restore.h
@@ -28,9 +28,7 @@
#define RESTORE_H
#include "options.h"
-#include "resources.h"
-int restore(const options_restore_t *const opts,
- const resources_restore_t *const res);
+int restore(const OptionsRestore &opts);
#endif /* RESTORE_H */