aboutsummaryrefslogtreecommitdiff
path: root/src/resources.c
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2022-06-18 08:50:45 +0200
committerJan Sucan <jan@jansucan.com>2022-06-18 08:50:54 +0200
commit948a65cf39c8ce31c5adc0f24979e0cb55bc33c3 (patch)
treeae923f4594fef0abb777f63291d62530c345b229 /src/resources.c
parente1d10bea5d9fc94ba800ade1de430c7f3c0ccacd (diff)
Refactor the command line interface
Select operation by its name instead of by number of the arguments.
Diffstat (limited to 'src/resources.c')
-rw-r--r--src/resources.c187
1 files changed, 165 insertions, 22 deletions
diff --git a/src/resources.c b/src/resources.c
index 65b7f71..0829c7c 100644
--- a/src/resources.c
+++ b/src/resources.c
@@ -26,45 +26,188 @@
#include "resources.h"
+#include "print.h"
+
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
-void
-resources_init(resources_t *const res)
+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;
}
-void
-resources_free(resources_t *const res)
+static int
+resources_allocate_for_backup(const options_backup_t *const opts,
+ resources_backup_t *const res)
{
- if (res->in_file != NULL) {
- fclose(res->in_file);
- res->in_file = NULL;
+ 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 != NULL) {
- fclose(res->ref_file);
- res->ref_file = NULL;
+
+ if ((res->ref_file = fopen(opts->ref_file_path, "r")) == NULL) {
+ print_error("cannot open reference file: %s", strerror(errno));
+ return 1;
}
- if (res->out_file != NULL) {
- fclose(res->out_file);
- res->out_file = NULL;
+
+ /* 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;
}
- if (res->in_buffer != NULL) {
- free(res->in_buffer);
- res->in_buffer = NULL;
+
+ /* 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;
}
- if (res->ref_buffer != NULL) {
- free(res->ref_buffer);
- res->ref_buffer = NULL;
+
+ 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;
}
- if (res->out_buffer != NULL) {
- free(res->out_buffer);
- res->out_buffer = NULL;
+
+ /* 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;
}