diff options
| author | Jan Sucan <jan@jansucan.com> | 2025-01-18 07:57:57 +0100 |
|---|---|---|
| committer | Ján Sučan <jan@jansucan.com> | 2025-01-18 12:44:04 +0100 |
| commit | 8b51499900e125a55dcdc425d29550b98a8064b4 (patch) | |
| tree | 938545b3b612bcacd3599785be3f4a23ec08bea7 /src/restore.cpp | |
| parent | a7e8d00f5140d250e339736eb49e20609bffa47f (diff) | |
Initial implementation of diff file format v2
Diffstat (limited to 'src/restore.cpp')
| -rw-r--r-- | src/restore.cpp | 139 |
1 files changed, 29 insertions, 110 deletions
diff --git a/src/restore.cpp b/src/restore.cpp index 8a5b29f..a747d16 100644 --- a/src/restore.cpp +++ b/src/restore.cpp @@ -26,93 +26,23 @@ #include "restore.h" #include "buffered_file.h" +#include "format_v2.h" #include <filesystem> #include <fstream> - -static void -check_diff_file(const OptionsRestore &opts) -{ - size_t diff_size{0}; - try { - diff_size = std::filesystem::file_size(opts.getDiffFilePath()); - } catch (const std::exception &e) { - throw RestoreError("cannot get size of diff file: " + - std::string(e.what())); - } - - if (diff_size == 0) { - throw RestoreError("diff file is empty"); - } else if ((diff_size % (sizeof(uint64_t) + opts.getSectorSize())) != 0) { - /* The diff file must hold equally sized sectors and the - * offset of each of them - */ - throw RestoreError( - "diff file has size that cannot contain valid diff data"); - } - - size_t out_size{0}; - try { - out_size = std::filesystem::file_size(opts.getOutFilePath()); - } catch (const std::exception &e) { - throw RestoreError("cannot get size of output file: " + - std::string(e.what())); - } - - std::ifstream diff_file; - diff_file.open(opts.getDiffFilePath(), std::ios::in | std::ios::binary); - if (!diff_file) { - throw RestoreError("cannot open diff file"); - } - - uint64_t prev_out_offset = 0; - bool is_first_reading = true; - - /* Scan the diff file and check */ - for (;;) { - uint64_t out_offset; - /* Read the next offset */ - diff_file.read(reinterpret_cast<char *>(&out_offset), - sizeof(out_offset)); - - if (diff_file.eof() && diff_file.fail() && !diff_file.bad()) { - break; - } else if (!diff_file.good() && !diff_file.eof()) { - throw RestoreError("cannot read from file"); - } - out_offset = le64toh(out_offset); - - if (!is_first_reading && (out_offset <= prev_out_offset)) { - throw RestoreError( - "a sector offset points behind the previous offset"); - } else if ((out_offset + opts.getSectorSize()) > out_size) { - throw RestoreError( - "a sector offset points past the end of the output file"); - } else if (!diff_file.seekg(opts.getSectorSize(), std::ios_base::cur)) { - throw RestoreError("cannot seek in diff file"); - } - - is_first_reading = false; - prev_out_offset = out_offset; - } - - /* The diff file must be read completely */ - char c; - diff_file.read(&c, 1); - if (diff_file.gcount() != 0) { - throw RestoreError("diff file is not valid"); - } - diff_file.clear(); - - diff_file.close(); -} +#include <vector> void restore(const OptionsRestore &opts) { - check_diff_file(opts); + std::fstream diff_stream; + diff_stream.open(opts.getDiffFilePath(), + std::ifstream::in | std::ifstream::binary); + if (!diff_stream) { + throw RestoreError("cannot open diff file"); + } - BufferedFileReader diff_file(opts.getDiffFilePath(), opts.getBufferSize()); + FormatV2::Reader diff_reader(diff_stream, opts.getBufferSize()); std::fstream out_file; out_file.open(opts.getOutFilePath(), @@ -121,45 +51,34 @@ restore(const OptionsRestore &opts) throw RestoreError("cannot open output file"); } - const size_t diff_buffer_size = sizeof(uint64_t) + opts.getSectorSize(); - std::unique_ptr<char[]> diff_buffer; - try { - diff_buffer = std::make_unique<char[]>(diff_buffer_size); - } catch (const std::bad_alloc &e) { - throw RestoreError("cannot allocate sector buffer for diff file data"); - } - - /* Restore data from the differential image */ - size_t diff_read_size = {0}; for (;;) { - diff_read_size = diff_file.read(diff_buffer.get(), diff_buffer_size); - - if (diff_read_size == 0) { + const uint64_t offset{diff_reader.readOffset()}; + if (diff_reader.eof()) { break; - } else if (diff_read_size != diff_buffer_size) { - throw RestoreError("cannot read from diff file"); } - const uint64_t out_offset = - le64toh(*reinterpret_cast<uint64_t *>(diff_buffer.get())); - - if (!out_file.seekp(out_offset, std::ios_base::beg)) { + if (!out_file.seekp(offset, std::ios_base::beg)) { throw RestoreError("cannot seek in output file"); } - if (!out_file.write(reinterpret_cast<char *>(diff_buffer.get()) + - sizeof(uint64_t), - opts.getSectorSize())) { - throw RestoreError("cannot write to output file"); - } - } + uint64_t size{diff_reader.readSize()}; - out_file.close(); + while (size > 0) { + char *data; + const size_t r{diff_reader.readData(size, &data)}; + if (r == 0) { + break; + } - /* The diff file must be read completely */ - char c; - diff_read_size = diff_file.read(&c, 1); - if (diff_read_size != 0) { - throw RestoreError("diff file is not valid"); + if (!out_file.write(data, r)) { + throw RestoreError("cannot write to output file"); + } + + size -= r; + } + + if (size > 0) { + throw RestoreError("cannot read all the data of the record"); + } } } |
