diff --git a/btree.tcc b/btree.tcc index ebf0636..fa16243 100644 --- a/btree.tcc +++ b/btree.tcc @@ -18,11 +18,13 @@ #include "btree.h" +#include "errors.h" #include "checksum.h" #include "transaction_manager.h" #include +using namespace base; using namespace btree_detail; using namespace persistent_data; using namespace std; @@ -37,10 +39,10 @@ namespace { crc32c sum(BTREE_CSUM_XOR); sum.append(&n->flags, MD_BLOCK_SIZE - sizeof(uint32_t)); if (sum.get_sum() != to_cpu(n->csum)) - throw runtime_error("bad checksum in btree node"); + throw checksum_error("bad checksum in btree node"); if (to_cpu(n->blocknr) != location) - throw runtime_error("bad block nr in btree node"); + throw checksum_error("bad block nr in btree node"); } virtual void prepare(block_manager<>::buffer &b, block_address location) const { diff --git a/btree_checker.h b/btree_checker.h index 4078034..9b681d6 100644 --- a/btree_checker.h +++ b/btree_checker.h @@ -160,7 +160,7 @@ namespace persistent_data { << ", sum was " << sum.get_sum() << ", on disk " << n.get_checksum(); errs_->add_child(out.str()); - throw runtime_error(out.str()); + throw checksum_error(out.str()); } } @@ -172,7 +172,7 @@ namespace persistent_data { << n.get_location() << ", claims " << n.get_block_nr(); errs_->add_child(out.str()); - throw runtime_error(out.str()); + throw checksum_error(out.str()); } } diff --git a/errors.h b/errors.h new file mode 100644 index 0000000..f0c830a --- /dev/null +++ b/errors.h @@ -0,0 +1,37 @@ +// Copyright (C) 2012 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#ifndef THINP_EXCEPTION_H +#define THINP_EXCEPTION_H + +#include + +//---------------------------------------------------------------- + +namespace base { + class checksum_error : public std::runtime_error { + public: + explicit checksum_error(std::string const &what) + : std::runtime_error(what) { + } + }; +} + +//---------------------------------------------------------------- + +#endif diff --git a/metadata.cc b/metadata.cc index 7194dc8..8de2974 100644 --- a/metadata.cc +++ b/metadata.cc @@ -45,7 +45,7 @@ namespace { crc32c sum(SUPERBLOCK_CSUM_SEED); sum.append(&sbd->flags_, MD_BLOCK_SIZE - sizeof(uint32_t)); if (sum.get_sum() != to_cpu(sbd->csum_)) - throw runtime_error("bad checksum in superblock"); + throw checksum_error("bad checksum in superblock"); } virtual void prepare(block_manager<>::buffer &b, block_address location) const { diff --git a/space_map_disk.cc b/space_map_disk.cc index 42ca283..4c7a7ed 100644 --- a/space_map_disk.cc +++ b/space_map_disk.cc @@ -43,10 +43,10 @@ namespace { crc32c sum(BITMAP_CSUM_XOR); sum.append(&data->not_used, MD_BLOCK_SIZE - sizeof(uint32_t)); if (sum.get_sum() != to_cpu(data->csum)) - throw runtime_error("bad checksum in space map bitmap"); + throw checksum_error("bad checksum in space map bitmap"); if (to_cpu(data->blocknr) != location) - throw runtime_error("bad block nr in space map bitmap"); + throw checksum_error("bad block nr in space map bitmap"); } virtual void prepare(block_manager<>::buffer &b, block_address location) const { @@ -75,10 +75,10 @@ namespace { crc32c sum(INDEX_CSUM_XOR); sum.append(&mi->padding_, MD_BLOCK_SIZE - sizeof(uint32_t)); if (sum.get_sum() != to_cpu(mi->csum_)) - throw runtime_error("bad checksum in metadata index block"); + throw checksum_error("bad checksum in metadata index block"); if (to_cpu(mi->blocknr_) != location) - throw runtime_error("bad block nr in metadata index block"); + throw checksum_error("bad block nr in metadata index block"); } virtual void prepare(block_manager<>::buffer &b, block_address location) const { diff --git a/thin_check.cc b/thin_check.cc new file mode 100644 index 0000000..9993e80 --- /dev/null +++ b/thin_check.cc @@ -0,0 +1,79 @@ +// Copyright (C) 2011 Red Hat, Inc. All rights reserved. +// +// This file is part of the thin-provisioning-tools source. +// +// thin-provisioning-tools is free software: you can redistribute it +// and/or modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// thin-provisioning-tools is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with thin-provisioning-tools. If not, see +// . + +#include +#include +#include + +#include "metadata.h" +#include "metadata_checker.h" +#include "version.h" + +using namespace persistent_data; +using namespace std; +using namespace thin_provisioning; + +namespace { + int check(string const &path) { + metadata::ptr md(new metadata(path, metadata::OPEN)); + + optional maybe_errors = metadata_check(md); + if (maybe_errors) { + cerr << error_selector(*maybe_errors, 3); + return 1; + } + + return 0; + } + + void usage(string const &cmd) { + cerr << "Usage: " << cmd << " {device|file}" << endl; + cerr << "Options:" << endl; + cerr << " {-h|--help}" << endl; + cerr << " {-V|--version}" << endl; + } +} + +int main(int argc, char **argv) +{ + int c; + const char shortopts[] = "hV"; + const struct option longopts[] = { + { "help", no_argument, NULL, 'h'}, + { "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(basename(argv[0])); + return 0; + case 'V': + cerr << THIN_PROVISIONING_TOOLS_VERSION << endl; + return 0; + } + } + + if (argc != 2) { + usage(basename(argv[0])); + exit(1); + } + + return check(argv[1]); +}