aboutsummaryrefslogtreecommitdiff
path: root/src/backup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/backup.cpp')
-rw-r--r--src/backup.cpp200
1 files changed, 101 insertions, 99 deletions
diff --git a/src/backup.cpp b/src/backup.cpp
index b0b0054..4ffbd87 100644
--- a/src/backup.cpp
+++ b/src/backup.cpp
@@ -26,133 +26,142 @@
#include "backup.h"
-#include "file.h"
-#include "print.h"
-
-#include <errno.h>
+#include <fstream>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
- FILE *in_file;
- FILE *ref_file;
- FILE *out_file;
+ std::ifstream in_file;
+ std::ifstream ref_file;
+ std::ofstream out_file;
- char *in_buffer;
- char *ref_buffer;
- char *out_buffer;
+ std::unique_ptr<char[]> in_buffer;
+ std::unique_ptr<char[]> ref_buffer;
+ std::unique_ptr<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 void check_files(const OptionsBackup &opts);
+static void write_out_buffer(const char *const buffer, size_t size,
+ std::ofstream &file);
-static int
-resources_allocate_for_backup(const OptionsBackup &opts,
- resources_backup_t *const res)
+static resources_backup_t
+resources_allocate_for_backup(const OptionsBackup &opts)
{
- if ((res->in_file = fopen(opts.getInFilePath().c_str(), "r")) == NULL) {
- print_error("cannot open input file: %s", strerror(errno));
- return 1;
+ resources_backup_t res;
+
+ res.in_file.open(opts.getInFilePath(),
+ std::ifstream::in | std::ifstream::binary);
+ if (!res.in_file) {
+ throw BackupError("cannot open input file");
}
- if ((res->ref_file = fopen(opts.getRefFilePath().c_str(), "r")) == NULL) {
- print_error("cannot open reference file: %s", strerror(errno));
- return 1;
+ res.ref_file.open(opts.getRefFilePath(),
+ std::ifstream::in | std::ifstream::binary);
+ if (!res.ref_file) {
+ throw BackupError("cannot open reference file");
}
/* 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;
+ res.out_file.open(opts.getOutFilePath(), std::ifstream::out |
+ std::ifstream::trunc |
+ std::ifstream::binary);
+ if (!res.out_file) {
+ throw BackupError("cannot open output file");
}
/* The output buffer contains also the offsets */
- res->out_buffer_size =
+ 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;
+ try {
+ res.in_buffer = std::make_unique<char[]>(opts.getBufferSize());
+ } catch (const std::bad_alloc &e) {
+ throw BackupError("cannot allocate buffer for input file data");
+ }
+
+ try {
+ res.ref_buffer = std::make_unique<char[]>(opts.getBufferSize());
+ } catch (const std::bad_alloc &e) {
+ throw BackupError("cannot allocate buffer for reference file data");
}
- return 0;
+ try {
+ res.out_buffer = std::make_unique<char[]>(res.out_buffer_size);
+ } catch (const std::bad_alloc &e) {
+ throw BackupError("cannot allocate buffer for output file data");
+ }
+
+ return res;
}
-static int
-check_files(const OptionsBackup &opts, const resources_backup_t *const res)
+static void
+check_files(const OptionsBackup &opts)
{
- bool in_size_ok = false;
- 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));
- return 1;
+ size_t in_size{0};
+ try {
+ in_size = std::filesystem::file_size(opts.getInFilePath());
+ } catch (const std::exception &e) {
+ throw BackupError("cannot get size of input file: " +
+ std::string(e.what()));
}
- bool ref_size_ok = false;
- const size_t ref_size = file_size(res->ref_file, &ref_size_ok);
-
- if (!ref_size_ok) {
- print_error("cannot get size of reference file: %s", strerror(errno));
- return 1;
+ size_t ref_size{0};
+ try {
+ ref_size = std::filesystem::file_size(opts.getRefFilePath());
+ } catch (const std::exception &e) {
+ throw BackupError("cannot get size of reference file: " +
+ std::string(e.what()));
}
/* Check sizes of the input file and the reference file */
if (in_size != ref_size) {
- print_error("input file and reference file differ in size");
- return 1;
+ throw BackupError("input file and reference file differ in size");
} else if ((in_size % opts.getSectorSize()) != 0) {
- print_error(
- "size of input file and reference file is not multiple of %" PRIu32,
- opts.getSectorSize());
- return 1;
+ throw BackupError(
+ "size of input file and reference file is not multiple of " +
+ std::to_string(opts.getSectorSize()));
}
-
- return 0;
}
-static int
-write_out_buffer(const char *const buffer, size_t size, FILE *const file)
+static void
+write_out_buffer(const char *const buffer, size_t size, std::ofstream &file)
{
- const size_t bytes_written = fwrite(buffer, 1U, size, file);
+ file.write(buffer, size);
- if (bytes_written != size) {
- print_error("cannot write to output file: %s", strerror(errno));
- return 1;
+ if (!file) {
+ throw BackupError("cannot write to output file");
}
-
- return 0;
}
-int
-backup(const OptionsBackup &opts)
+static size_t
+read_sectors(std::ifstream &file, char *const buffer, uint32_t buffer_size,
+ uint32_t sector_size)
{
- resources_backup_t res;
-
- if (resources_allocate_for_backup(opts, &res) != 0) {
- return 1;
+ file.readsome(buffer, buffer_size);
+ const size_t bytes_read = file.gcount();
+
+ if (!file.good() && !file.eof()) {
+ throw BackupError("cannot read from file");
+ } else if ((bytes_read % sector_size) != 0) {
+ throw BackupError(
+ "data read from input file is not multiple of sector size");
+ } else {
+ return (bytes_read / sector_size);
}
+}
- if (check_files(opts, &res) != 0) {
- return 1;
- }
+void
+backup(const OptionsBackup &opts)
+{
+ resources_backup_t res{resources_allocate_for_backup(opts)};
+ check_files(opts);
size_t out_buffer_index = 0;
uint64_t input_file_offset = 0;
@@ -161,44 +170,42 @@ backup(const OptionsBackup &opts)
/* 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.getBufferSize(),
- opts.getSectorSize());
+ read_sectors(res.in_file, res.in_buffer.get(), opts.getBufferSize(),
+ opts.getSectorSize());
const size_t ref_sectors_read =
- file_read_sectors(res.ref_file, res.ref_buffer,
- opts.getBufferSize(), opts.getSectorSize());
+ read_sectors(res.ref_file, res.ref_buffer.get(),
+ opts.getBufferSize(), opts.getSectorSize());
if ((in_sectors_read == 0) || (ref_sectors_read == 0)) {
break;
} else if (in_sectors_read != ref_sectors_read) {
- print_error(
+ throw BackupError(
"cannot read equal amount of sectors from the input files");
- return 1;
}
/* Process the sectors in the buffers */
for (size_t sector = 0; sector < in_sectors_read; ++sector) {
const size_t buffer_offset = sector * opts.getSectorSize();
- if (memcmp(res.in_buffer + buffer_offset,
- res.ref_buffer + buffer_offset,
+ if (memcmp(res.in_buffer.get() + buffer_offset,
+ res.ref_buffer.get() + buffer_offset,
opts.getSectorSize()) != 0) {
/* Backup the changed sector */
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) {
- return 1;
- }
+ write_out_buffer(res.out_buffer.get(), out_buffer_index,
+ res.out_file);
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.get() + 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.getSectorSize());
+ memcpy(res.out_buffer.get() + out_buffer_index,
+ res.in_buffer.get() + buffer_offset,
+ opts.getSectorSize());
out_buffer_index += opts.getSectorSize();
}
@@ -208,11 +215,6 @@ backup(const OptionsBackup &opts)
/* Write out the output buffer */
if (out_buffer_index > 0) {
- if (write_out_buffer(res.out_buffer, out_buffer_index, res.out_file) !=
- 0) {
- return 1;
- }
+ write_out_buffer(res.out_buffer.get(), out_buffer_index, res.out_file);
}
-
- return 0;
}