diff --git a/Makefile.in b/Makefile.in index 5fc8c84..ac3ce75 100644 --- a/Makefile.in +++ b/Makefile.in @@ -23,6 +23,7 @@ PROGRAMS=\ cache_check \ cache_dump \ cache_restore \ + cache_repair \ \ thin_check \ thin_dump \ @@ -253,6 +254,9 @@ CACHE_CHECK_OBJECTS=$(subst .cc,.o,$(CACHE_CHECK_SOURCE)) CACHE_DUMP_SOURCE=$(SOURCE) CACHE_DUMP_OBJECTS=$(subst .cc,.o,$(CACHE_DUMP_SOURCE)) +CACHE_REPAIR_SOURCE=$(SOURCE) +CACHE_REPAIR_OBJECTS=$(subst .cc,.o,$(CACHE_REPAIR_SOURCE)) + CACHE_RESTORE_SOURCE=$(SOURCE) CACHE_RESTORE_OBJECTS=$(subst .cc,.o,$(CACHE_RESTORE_SOURCE)) @@ -264,6 +268,10 @@ cache_dump: $(CACHE_DUMP_OBJECTS) caching/cache_dump.o @echo " [LD] $@" $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) +cache_repair: $(CACHE_REPAIR_OBJECTS) caching/cache_repair.o + @echo " [LD] $@" + $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) + cache_restore: $(CACHE_RESTORE_OBJECTS) caching/cache_restore.o @echo " [LD] $@" $(V) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS) $(LIBEXPAT) diff --git a/caching/cache_repair.cc b/caching/cache_repair.cc new file mode 100644 index 0000000..5d1aafa --- /dev/null +++ b/caching/cache_repair.cc @@ -0,0 +1,108 @@ +#include +#include +#include + +#include "caching/metadata.h" +#include "caching/metadata_dump.h" +#include "caching/restore_emitter.h" +#include "persistent-data/file_utils.h" +#include "version.h" + +using namespace persistent_data; +using namespace std; +using namespace caching; + +//---------------------------------------------------------------- + +namespace { + metadata::ptr open_metadata_for_read(string const &path) { + block_manager<>::ptr bm = open_bm(path, block_io<>::READ_ONLY); + return metadata::ptr(new metadata(bm, metadata::OPEN)); + } + + emitter::ptr output_emitter(string const &path) { + block_manager<>::ptr bm = open_bm(path, block_io<>::READ_WRITE); + metadata::ptr md(new metadata(bm, metadata::CREATE)); + return create_restore_emitter(md); + } + + int repair(string const &old_path, string const &new_path) { + try { + metadata_dump(open_metadata_for_read(old_path), + output_emitter(new_path), + true); + + } catch (std::exception &e) { + cerr << e.what() << endl; + return 1; + } + + return 0; + } + + void usage(ostream &out, string const &cmd) { + out << "Usage: " << cmd << " [options] {device|file}" << endl + << "Options:" << endl + << " {-h|--help}" << endl + << " {-i|--input} " << endl + << " {-o|--output} " << endl + << " {-V|--version}" << endl; + } +} + +//---------------------------------------------------------------- + +int main(int argc, char **argv) +{ + int c; + boost::optional input_path, output_path; + const char shortopts[] = "hi:o:V"; + + const struct option longopts[] = { + { "help", no_argument, NULL, 'h'}, + { "input", required_argument, NULL, 'i'}, + { "output", required_argument, NULL, 'o'}, + { "version", no_argument, NULL, 'V'}, + { NULL, no_argument, NULL, 0 } + }; + + while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { + switch(c) { + case 'h': + usage(cout, basename(argv[0])); + return 0; + + case 'i': + input_path = optarg; + break; + + case 'o': + output_path = optarg; + break; + + case 'V': + cout << THIN_PROVISIONING_TOOLS_VERSION << endl; + return 0; + + default: + usage(cerr, basename(argv[0])); + return 1; + } + } + + if (!input_path) { + cerr << "no input file provided" << endl; + usage(cerr, basename(argv[0])); + return 1; + } + + if (!output_path) { + cerr << "no output file provided" << endl; + usage(cerr, basename(argv[0])); + return 1; + } + + return repair(*input_path, *output_path); +} + +//----------------------------------------------------------------