Improved error handling

This commit is contained in:
Marcus Holland-Moritz 2020-12-13 22:43:02 +01:00
parent 3e0d14cc0f
commit aed35f04f9
21 changed files with 418 additions and 253 deletions

View File

@ -152,6 +152,7 @@ list(
src/dwarfs/block_manager.cpp
src/dwarfs/console_writer.cpp
src/dwarfs/entry.cpp
src/dwarfs/error.cpp
src/dwarfs/filesystem_v2.cpp
src/dwarfs/filesystem_writer.cpp
src/dwarfs/fstypes.cpp
@ -351,7 +352,7 @@ target_link_libraries(
PkgConfig::LIBLZ4
PkgConfig::LIBLZMA)
foreach(tgt dwarfs-bin mkdwarfs dwarfsck dwarfsbench)
foreach(tgt ${BINARY_TARGETS})
target_link_libraries(${tgt} dwarfs)
target_link_libraries(${tgt} -Wl,--whole-archive folly_exception_tracer_base
folly_exception_tracer -Wl,--no-whole-archive)
@ -363,13 +364,8 @@ if(WITH_PYTHON)
endif()
target_link_libraries(mkdwarfs ${BOOST_PYTHON_LIBS} ${Python3_LIBRARIES})
endif()
if(WITH_TESTS)
foreach(tgt dwarfs_test dwarfs_compat_test)
target_link_libraries(${tgt} dwarfs)
endforeach()
if(WITH_PYTHON)
if(WITH_TESTS)
foreach(tgt dwarfs_test dwarfs_compat_test)
target_link_libraries(${tgt} ${BOOST_PYTHON_LIBS} ${Python3_LIBRARIES})
endforeach()

View File

@ -22,34 +22,56 @@
#pragma once
#include <exception>
#include <functional>
#include <string>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
namespace dwarfs {
class error : public std::exception {
public:
error(const std::string& str, int err_no) noexcept
: what_(str)
, errno_(err_no) {}
error(std::string const& s, char const* file, int line) noexcept
: what_(s)
, file_(file)
, line_(line) {}
error(const error& e) noexcept
: what_(e.what_)
, errno_(e.errno_) {}
char const* what() const noexcept override { return what_.c_str(); }
error& operator=(const error& e) noexcept {
if (&e != this) {
what_ = e.what_;
errno_ = e.errno_;
}
return *this;
}
char const* file() const { return file_; }
const char* what() const noexcept override { return what_.c_str(); }
int get_errno() const { return errno_; }
int line() const { return line_; }
private:
std::string what_;
int errno_;
char const* file_;
int line_;
};
class system_error : public boost::system::system_error {
public:
system_error(char const* file, int line) noexcept;
system_error(std::string const& s, char const* file, int line) noexcept;
system_error(std::string const& s, int err, char const* file,
int line) noexcept;
system_error(int err, char const* file, int line) noexcept;
int get_errno() const { return code().value(); }
char const* file() const { return file_; }
int line() const { return line_; }
private:
char const* file_;
int line_;
};
#define DWARFS_THROW(cls, ...) throw cls(__VA_ARGS__, __FILE__, __LINE__)
void dump_exceptions();
int safe_main(std::function<int(void)> fn);
} // namespace dwarfs

View File

@ -36,6 +36,7 @@
#include <type_traits>
#include <utility>
#include "dwarfs/error.h"
#include "dwarfs/util.h"
namespace dwarfs {
@ -302,7 +303,7 @@ template <template <class> class T, class CreatePolicy, class LoggerPolicyList>
struct logging_class_factory<T, CreatePolicy, LoggerPolicyList, 0> {
template <class... Args>
static typename CreatePolicy::return_type create(logger& lgr, Args&&...) {
throw std::runtime_error("no such logger policy: " + lgr.policy_name());
DWARFS_THROW(error, "no such logger policy: " + lgr.policy_name());
}
};

View File

@ -113,7 +113,7 @@ void op_init(void* /*userdata*/, struct fuse_conn_info* /*conn*/) {
&s_opts.stat_defaults, FUSE_ROOT_ID);
ti << "file system initialized";
} catch (const std::exception& e) {
} catch (std::exception const& e) {
log.error() << "error initializing file system: " << e.what();
fuse_session_exit(s_session);
}
@ -148,10 +148,10 @@ void op_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) {
return;
}
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -179,10 +179,10 @@ void op_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info*) {
return;
}
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -203,10 +203,10 @@ void op_access(fuse_req_t req, fuse_ino_t ino, int mode) {
auto ctx = fuse_req_ctx(req);
err = s_fs->access(*entry, mode, ctx->uid, ctx->gid);
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -233,10 +233,10 @@ void op_readlink(fuse_req_t req, fuse_ino_t ino) {
return;
}
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -265,10 +265,10 @@ void op_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) {
return;
}
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -300,10 +300,10 @@ void op_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
} else {
err = EIO;
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -357,10 +357,10 @@ void op_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
err = ENOTDIR;
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}
@ -383,10 +383,10 @@ void op_statfs(fuse_req_t req, fuse_ino_t /*ino*/) {
return;
}
} catch (const dwarfs::error& e) {
} catch (dwarfs::system_error const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = e.get_errno();
} catch (const std::exception& e) {
} catch (std::exception const& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
err = EIO;
}

View File

@ -26,7 +26,6 @@
#include <cstring>
#include <iterator>
#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <sys/types.h>
@ -53,6 +52,7 @@
#endif
#include "dwarfs/block_compressor.h"
#include "dwarfs/error.h"
#include "dwarfs/fstypes.h"
namespace dwarfs {
@ -72,8 +72,8 @@ class option_map {
boost::split(kv, arg[i], boost::is_any_of("="));
if (kv.size() > 2) {
throw std::runtime_error("error parsing option " + kv[0] +
" for choice " + choice_);
DWARFS_THROW(error, "error parsing option " + kv[0] + " for choice " +
choice_);
}
opt_[kv[0]] = kv.size() > 1 ? kv[1] : std::string("1");
@ -101,8 +101,8 @@ class option_map {
std::transform(
opt_.begin(), opt_.end(), std::back_inserter(invalid),
[](const std::pair<std::string, std::string>& p) { return p.first; });
throw std::runtime_error("invalid option(s) for choice " + choice_ +
": " + boost::join(invalid, ", "));
DWARFS_THROW(error, "invalid option(s) for choice " + choice_ + ": " +
boost::join(invalid, ", "));
}
}
@ -164,7 +164,7 @@ class lzma_block_compressor : public block_compressor::impl {
auto i = vm.find(binary);
if (i == vm.end()) {
throw std::runtime_error("unsupported binary mode");
DWARFS_THROW(error, "unsupported binary mode");
}
return i->second;
@ -215,7 +215,7 @@ lzma_block_compressor::lzma_block_compressor(unsigned level, bool extreme,
: stream_(LZMA_STREAM_INIT)
, data_(block_size > 0 ? lzma_stream_buffer_bound(block_size) : 0) {
if (lzma_lzma_preset(&opt_lzma_, get_preset(level, extreme))) {
throw std::runtime_error("unsupported preset, possibly a bug");
DWARFS_THROW(error, "unsupported preset, possibly a bug");
}
if (dict_size > 0) {
@ -233,7 +233,7 @@ lzma_block_compressor::lzma_block_compressor(unsigned level, bool extreme,
auto* filters = &filters_[filters_[0].id == LZMA_VLI_UNKNOWN];
if (lzma_stream_encoder(&stream_, filters, LZMA_CHECK_CRC64)) {
throw std::runtime_error("lzma_stream_encoder");
DWARFS_THROW(error, "lzma_stream_encoder");
}
stream_.next_out = data_.data();
@ -253,18 +253,18 @@ void lzma_block_compressor::append(const uint8_t* data, size_t size,
switch (ret) {
case LZMA_STREAM_END:
if (!last) {
throw std::runtime_error("LZMA unexpected stream end");
DWARFS_THROW(error, "LZMA unexpected stream end");
}
break;
case LZMA_MEM_ERROR:
throw std::runtime_error("LZMA_MEM_ERROR");
DWARFS_THROW(error, "LZMA_MEM_ERROR");
case LZMA_DATA_ERROR:
throw std::runtime_error("LZMA_DATA_ERROR");
DWARFS_THROW(error, "LZMA_DATA_ERROR");
default:
throw std::runtime_error("unknown LZMA error");
DWARFS_THROW(error, "unknown LZMA error");
}
if (last) {
@ -280,7 +280,7 @@ lzma_block_compressor::compress(const std::vector<uint8_t>& data,
lzma_stream s = LZMA_STREAM_INIT;
if (lzma_stream_encoder(&s, filters, LZMA_CHECK_CRC64)) {
throw std::runtime_error("lzma_stream_encoder");
DWARFS_THROW(error, "lzma_stream_encoder");
}
lzma_action action = LZMA_FINISH;
@ -304,13 +304,13 @@ lzma_block_compressor::compress(const std::vector<uint8_t>& data,
break;
case LZMA_MEM_ERROR:
throw std::runtime_error("LZMA_MEM_ERROR");
DWARFS_THROW(error, "LZMA_MEM_ERROR");
case LZMA_DATA_ERROR:
throw std::runtime_error("LZMA_DATA_ERROR");
DWARFS_THROW(error, "LZMA_DATA_ERROR");
default:
throw std::runtime_error("unknown LZMA error");
DWARFS_THROW(error, "unknown LZMA error");
}
return compressed;
@ -372,7 +372,7 @@ class lz4_block_compressor : public block_compressor::impl {
Policy::compress(&data[0], &compressed[sizeof(uint32_t)], data.size(),
compressed.size() - sizeof(uint32_t), level_);
if (csize == 0) {
throw std::runtime_error("error during compression");
DWARFS_THROW(error, "error during compression");
}
compressed.resize(sizeof(uint32_t) + csize);
return compressed;
@ -474,7 +474,7 @@ block_compressor::block_compressor(const std::string& spec, size_t block_size) {
om.get<int>("level", ZSTD_maxCLevel()));
#endif
} else {
throw std::runtime_error("unknown compression: " + om.choice());
DWARFS_THROW(error, "unknown compression: " + om.choice());
}
om.report();
@ -528,7 +528,7 @@ class lzma_block_decompressor : public block_decompressor::impl {
stream_.avail_in = size;
if (lzma_stream_decoder(&stream_, UINT64_MAX, LZMA_CONCATENATED) !=
LZMA_OK) {
throw std::runtime_error("lzma_stream_decoder");
DWARFS_THROW(error, "lzma_stream_decoder");
}
decompressed_.reserve(uncompressed_size_);
}
@ -561,9 +561,10 @@ class lzma_block_decompressor : public block_decompressor::impl {
if (ret != (action == LZMA_RUN ? LZMA_OK : LZMA_STREAM_END) ||
stream_.avail_out != 0) {
throw std::runtime_error(folly::to<std::string>(
"error while decompressing LZMA stream (action=", action,
", ret=", ret, ", stream_.avail_out=", stream_.avail_out, ")"));
DWARFS_THROW(error,
fmt::format("error while decompressing LZMA stream "
"(action={0}, ret={1}, stream_.avail_out={2})",
action, ret, stream_.avail_out));
}
return ret == LZMA_STREAM_END;
@ -638,7 +639,7 @@ class zstd_block_decompressor : public block_decompressor::impl {
auto rv = ZSTD_decompress(decompressed_.data(), decompressed_.size(), data_,
size_);
if (ZSTD_isError(rv)) {
throw std::runtime_error(fmt::format("ZSTD: {}", ZSTD_getErrorName(rv)));
DWARFS_THROW(error, fmt::format("ZSTD: {}", ZSTD_getErrorName(rv)));
}
return true;
}
@ -657,7 +658,7 @@ class zstd_block_decompressor : public block_decompressor::impl {
size_t lzma_block_decompressor::get_uncompressed_size(const uint8_t* data,
size_t size) {
if (size < 2 * LZMA_STREAM_HEADER_SIZE) {
throw std::runtime_error("lzma compressed block is too small");
DWARFS_THROW(error, "lzma compressed block is too small");
}
lzma_stream s = LZMA_STREAM_INIT;
@ -671,26 +672,26 @@ size_t lzma_block_decompressor::get_uncompressed_size(const uint8_t* data,
--ptr;
if (pos < 2 * LZMA_STREAM_HEADER_SIZE) {
throw std::runtime_error("data error (stream padding)");
DWARFS_THROW(error, "data error (stream padding)");
}
}
lzma_stream_flags footer_flags;
if (lzma_stream_footer_decode(&footer_flags, data + pos) != LZMA_OK) {
throw std::runtime_error("lzma_stream_footer_decode()");
DWARFS_THROW(error, "lzma_stream_footer_decode()");
}
lzma_vli index_size = footer_flags.backward_size;
if (static_cast<lzma_vli>(pos) < index_size + LZMA_STREAM_HEADER_SIZE) {
throw std::runtime_error("data error (index size)");
DWARFS_THROW(error, "data error (index size)");
}
pos -= index_size;
lzma_index* index = NULL;
if (lzma_index_decoder(&s, &index, UINT64_MAX) != LZMA_OK) {
throw std::runtime_error("lzma_index_decoder()");
DWARFS_THROW(error, "lzma_index_decoder()");
}
s.avail_in = index_size;
@ -698,13 +699,13 @@ size_t lzma_block_decompressor::get_uncompressed_size(const uint8_t* data,
lzma_ret ret = lzma_code(&s, LZMA_RUN);
if (ret != LZMA_STREAM_END || s.avail_in != 0) {
throw std::runtime_error(
fmt::format("lzma_code(): {} (avail_in={})", ret, s.avail_in));
DWARFS_THROW(error,
fmt::format("lzma_code(): {} (avail_in={})", ret, s.avail_in));
}
pos -= LZMA_STREAM_HEADER_SIZE;
if (static_cast<lzma_vli>(pos) < lzma_index_total_size(index)) {
throw std::runtime_error("data error (index total size)");
DWARFS_THROW(error, "data error (index total size)");
}
size_t usize = lzma_index_uncompressed_size(index);
@ -745,8 +746,8 @@ block_decompressor::block_decompressor(compression_type type,
#endif
default:
throw std::runtime_error("unsupported compression type: " +
get_compression_name(type));
DWARFS_THROW(error,
"unsupported compression type: " + get_compression_name(type));
}
}
} // namespace dwarfs

View File

@ -23,7 +23,6 @@
#include <cstdint>
#include <cstring>
#include <map>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>
@ -34,6 +33,7 @@
#include "dwarfs/block_manager.h"
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/filesystem_writer.h"
#include "dwarfs/inode.h"
#include "dwarfs/inode_hasher.h"
@ -229,8 +229,7 @@ void block_manager_<LoggerPolicy>::update_hashes(const hash_map_type& hm,
auto& stats = stats_[bhi->size];
if (hmi == hm.end()) {
throw std::runtime_error(
"internal error: no hash found for window size");
DWARFS_THROW(error, "internal error: no hash found for window size");
}
const auto& hashvec = hmi->second;
@ -241,7 +240,7 @@ void block_manager_<LoggerPolicy>::update_hashes(const hash_map_type& hm,
log_.error() << "bhi=" << bhi->size
<< ", hashvec.size()=" << hashvec.size()
<< ", offset=" << offset << ", last=" << last;
throw std::runtime_error("internal error: hashvec too small");
DWARFS_THROW(error, "internal error: hashvec too small");
}
for (size_t off = 0; off < last; off += incr) {
@ -410,8 +409,7 @@ void block_manager_<LoggerPolicy>::segment_and_add_data(
auto& stats = stats_[bhcur->size];
if (hmi == hm.end()) {
throw std::runtime_error(
"internal error: no hash found for window size");
DWARFS_THROW(error, "internal error: no hash found for window size");
}
const auto& hashvec = hmi->second;

View File

@ -21,7 +21,6 @@
#include <algorithm>
#include <cstring>
#include <stdexcept>
#include <utility>
#include <openssl/sha.h>
@ -29,6 +28,7 @@
#include <fmt/format.h>
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/global_entry_data.h"
#include "dwarfs/inode.h"
#include "dwarfs/mmif.h"
@ -86,7 +86,7 @@ std::string entry::type_string() const {
return "socket";
}
throw std::runtime_error(fmt::format("unknown file type: {:#06x}", mode));
DWARFS_THROW(error, fmt::format("unknown file type: {:#06x}", mode));
}
void entry::walk(std::function<void(entry*)> const& f) { f(this); }
@ -150,7 +150,7 @@ std::string_view file::hash() const {
void file::set_inode(std::shared_ptr<inode> ino) {
if (inode_) {
throw std::runtime_error("inode already set for file");
DWARFS_THROW(error, "inode already set for file");
}
inode_ = std::move(ino);

80
src/dwarfs/error.cpp Normal file
View File

@ -0,0 +1,80 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs 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.
*
* dwarfs 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 dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cerrno>
#include <iostream>
#include <folly/String.h>
#include <folly/experimental/exception_tracer/ExceptionTracer.h>
#include <folly/experimental/symbolizer/SignalHandler.h>
#include "dwarfs/error.h"
namespace dwarfs {
system_error::system_error(char const* file, int line) noexcept
: system_error(errno, file, line) {}
system_error::system_error(std::string const& s, char const* file,
int line) noexcept
: system_error(s, errno, file, line) {}
system_error::system_error(std::string const& s, int err, char const* file,
int line) noexcept
: boost::system::system_error(err, boost::system::generic_category(),
s.c_str())
, file_(file)
, line_(line) {}
system_error::system_error(int err, char const* file, int line) noexcept
: boost::system::system_error(err, boost::system::generic_category())
, file_(file)
, line_(line) {}
void dump_exceptions() {
auto exceptions = ::folly::exception_tracer::getCurrentExceptions();
for (auto& exc : exceptions) {
std::cerr << exc << std::endl;
}
}
int safe_main(std::function<int(void)> fn) {
try {
folly::symbolizer::installFatalSignalHandler();
return fn();
} catch (system_error const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << " [" << e.file() << ":"
<< e.line() << "]" << std::endl;
dump_exceptions();
} catch (error const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << " [" << e.file() << ":"
<< e.line() << "]" << std::endl;
dump_exceptions();
} catch (std::exception const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << std::endl;
dump_exceptions();
} catch (...) {
dump_exceptions();
}
return 1;
}
} // namespace dwarfs

View File

@ -22,7 +22,6 @@
#include <cstddef>
#include <cstring>
#include <optional>
#include <stdexcept>
#include <unordered_map>
#include <vector>
@ -37,6 +36,7 @@
#include "dwarfs/block_cache.h"
#include "dwarfs/block_compressor.h"
#include "dwarfs/error.h"
#include "dwarfs/filesystem_v2.h"
#include "dwarfs/filesystem_writer.h"
#include "dwarfs/fstypes.h"
@ -62,21 +62,21 @@ class filesystem_parser {
: mm_(mm)
, offset_(sizeof(file_header)) {
if (mm_->size() < sizeof(file_header)) {
throw std::runtime_error("file too small");
DWARFS_THROW(error, "file too small");
}
const file_header* fh = mm_->as<file_header>();
if (::memcmp(&fh->magic[0], "DWARFS", 6) != 0) {
throw std::runtime_error("magic not found");
DWARFS_THROW(error, "magic not found");
}
if (fh->major != MAJOR_VERSION) {
throw std::runtime_error("different major version");
DWARFS_THROW(error, "different major version");
}
if (fh->minor > MINOR_VERSION) {
throw std::runtime_error("newer minor version");
DWARFS_THROW(error, "newer minor version");
}
}
@ -91,7 +91,7 @@ class filesystem_parser {
offset_ += sizeof(section_header);
if (offset_ + sh.length > mm_->size()) {
throw std::runtime_error("truncated file");
DWARFS_THROW(error, "truncated file");
}
start = offset_;
@ -151,11 +151,11 @@ make_metadata(logger& lgr, std::shared_ptr<mmif> mm,
auto meta_it = sections.find(section_type::METADATA_V2);
if (schema_it == sections.end()) {
throw std::runtime_error("no metadata schema found");
DWARFS_THROW(error, "no metadata schema found");
}
if (meta_it == sections.end()) {
throw std::runtime_error("no metadata found");
DWARFS_THROW(error, "no metadata found");
}
auto& meta_section = meta_it->second;
@ -166,7 +166,7 @@ make_metadata(logger& lgr, std::shared_ptr<mmif> mm,
if (lock_mode != mlock_mode::NONE) {
if (auto ec = mm->lock(meta_section.start, meta_section_range.size())) {
if (lock_mode == mlock_mode::MUST) {
throw boost::system::system_error(ec, "mlock");
DWARFS_THROW(system_error, "mlock");
} else {
log.warn() << "mlock() failed: " << ec.message();
}
@ -241,8 +241,8 @@ filesystem_<LoggerPolicy>::filesystem_(logger& lgr, std::shared_ptr<mmif> mm,
static_cast<size_t>(s->header.length));
} else {
if (!sections.emplace(s->header.type, *s).second) {
throw std::runtime_error("duplicate section: " +
get_section_name(s->header.type));
DWARFS_THROW(error,
"duplicate section: " + get_section_name(s->header.type));
}
}
}
@ -398,8 +398,8 @@ void filesystem_v2::rewrite(logger& lgr, progress& prog,
++prog.block_count;
} else {
if (!sections.emplace(s->header.type, *s).second) {
throw std::runtime_error("duplicate section: " +
get_section_name(s->header.type));
DWARFS_THROW(error,
"duplicate section: " + get_section_name(s->header.type));
}
}
}
@ -452,8 +452,8 @@ void filesystem_v2::identify(logger& lgr, std::shared_ptr<mmif> mm,
if (s->header.type != section_type::BLOCK) {
if (!sections.emplace(s->header.type, *s).second) {
throw std::runtime_error("duplicate section: " +
get_section_name(s->header.type));
DWARFS_THROW(error,
"duplicate section: " + get_section_name(s->header.type));
}
}
}

View File

@ -25,11 +25,11 @@
#include <deque>
#include <limits>
#include <numeric>
#include <stdexcept>
#include <string>
#include <vector>
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/inode.h"
#include "dwarfs/inode_manager.h"
#include "dwarfs/logger.h"
@ -56,21 +56,21 @@ class inode_ : public inode {
uint32_t similarity_hash() const override {
if (files_.empty()) {
throw std::runtime_error("inode has no file");
DWARFS_THROW(error, "inode has no file");
}
return similarity_hash_;
}
std::vector<uint64_t> const& nilsimsa_similarity_hash() const override {
if (files_.empty()) {
throw std::runtime_error("inode has no file");
DWARFS_THROW(error, "inode has no file");
}
return nilsimsa_similarity_hash_;
}
void set_files(files_vector&& fv) override {
if (!files_.empty()) {
throw std::runtime_error("files already set for inode");
DWARFS_THROW(error, "files already set for inode");
}
files_ = std::move(fv);
@ -110,7 +110,7 @@ class inode_ : public inode {
file const* any() const override {
if (files_.empty()) {
throw std::runtime_error("inode has no file");
DWARFS_THROW(error, "inode has no file");
}
return files_.front();
}
@ -247,7 +247,7 @@ void inode_manager_<LoggerPolicy>::order_inodes(
case file_order_mode::SCRIPT: {
if (!scr->has_order()) {
throw std::runtime_error("script cannot order inodes");
DWARFS_THROW(error, "script cannot order inodes");
}
log_.info() << "ordering " << count() << " inodes using script...";
auto ti = log_.timed_info();
@ -390,7 +390,7 @@ void inode_manager_<LoggerPolicy>::order_inodes_by_nilsimsa(
}
if (count != inodes_.size()) {
throw std::runtime_error("internal error: nilsimsa ordering failed");
DWARFS_THROW(error, "internal error: nilsimsa ordering failed");
}
}

View File

@ -87,7 +87,7 @@ logger::level_type logger::parse_level(std::string_view level) {
if (level == "trace") {
return TRACE;
}
throw std::runtime_error(fmt::format("invalid logger level: {}", level));
DWARFS_THROW(error, fmt::format("invalid logger level: {}", level));
}
stream_logger::stream_logger(std::ostream& os, level_type threshold)

View File

@ -37,6 +37,7 @@
#include <fmt/format.h>
#include "dwarfs/error.h"
#include "dwarfs/logger.h"
#include "dwarfs/metadata_v2.h"
#include "dwarfs/options.h"
@ -121,7 +122,8 @@ class metadata_ : public metadata_v2::impl {
log_.debug() << "device index offset: " << dev_index_offset_;
if (int(meta_.directories().size() - 1) != link_index_offset_) {
throw std::runtime_error(
DWARFS_THROW(
error,
fmt::format("metadata inconsistency: number of directories ({}) does "
"not match link index ({})",
meta_.directories().size() - 1, link_index_offset_));
@ -129,27 +131,32 @@ class metadata_ : public metadata_v2::impl {
if (int(meta_.link_index().size()) !=
(chunk_index_offset_ - link_index_offset_)) {
throw std::runtime_error(fmt::format(
"metadata inconsistency: number of links ({}) does not match "
"chunk/link index delta ({} - {} = {})",
meta_.link_index().size(), chunk_index_offset_, link_index_offset_,
chunk_index_offset_ - link_index_offset_));
DWARFS_THROW(
error,
fmt::format(
"metadata inconsistency: number of links ({}) does not match "
"chunk/link index delta ({} - {} = {})",
meta_.link_index().size(), chunk_index_offset_,
link_index_offset_, chunk_index_offset_ - link_index_offset_));
}
if (int(meta_.chunk_index().size() - 1) !=
(dev_index_offset_ - chunk_index_offset_)) {
throw std::runtime_error(fmt::format(
"metadata inconsistency: number of files ({}) does not match "
"device/chunk index delta ({} - {} = {})",
meta_.chunk_index().size() - 1, dev_index_offset_,
chunk_index_offset_, dev_index_offset_ - chunk_index_offset_));
DWARFS_THROW(
error,
fmt::format(
"metadata inconsistency: number of files ({}) does not match "
"device/chunk index delta ({} - {} = {})",
meta_.chunk_index().size() - 1, dev_index_offset_,
chunk_index_offset_, dev_index_offset_ - chunk_index_offset_));
}
if (auto devs = meta_.devices()) {
auto other_offset = find_index_offset(inode_rank::INO_OTH);
if (devs->size() != (other_offset - dev_index_offset_)) {
throw std::runtime_error(
DWARFS_THROW(
error,
fmt::format("metadata inconsistency: number of devices ({}) does "
"not match other/device index delta ({} - {} = {})",
devs->size(), other_offset, dev_index_offset_,
@ -233,7 +240,7 @@ class metadata_ : public metadata_v2::impl {
case S_IFIFO:
return inode_rank::INO_OTH;
default:
throw std::runtime_error(fmt::format("unknown file type: {:#06x}", mode));
DWARFS_THROW(error, fmt::format("unknown file type: {:#06x}", mode));
}
}
@ -254,7 +261,7 @@ class metadata_ : public metadata_v2::impl {
case S_IFIFO:
return 'p';
default:
throw std::runtime_error(fmt::format("unknown file type: {:#06x}", mode));
DWARFS_THROW(error, fmt::format("unknown file type: {:#06x}", mode));
}
}

View File

@ -20,7 +20,6 @@
*/
#include <cerrno>
#include <cstdio> // TODO
#include <fcntl.h>
#include <sys/mman.h>
@ -28,8 +27,10 @@
#include <unistd.h>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <fmt/format.h>
#include "dwarfs/error.h"
#include "dwarfs/mmap.h"
namespace dwarfs {
@ -40,8 +41,7 @@ int safe_open(const std::string& path) {
int fd = ::open(path.c_str(), O_RDONLY);
if (fd == -1) {
throw boost::system::system_error(errno, boost::system::generic_category(),
"open");
DWARFS_THROW(system_error, fmt::format("open('{}')", path));
}
return fd;
@ -50,8 +50,7 @@ int safe_open(const std::string& path) {
size_t safe_size(int fd) {
struct stat st;
if (::fstat(fd, &st) == -1) {
throw boost::system::system_error(errno, boost::system::generic_category(),
"fstat");
DWARFS_THROW(system_error, "fstat");
}
return st.st_size;
}
@ -60,8 +59,7 @@ void* safe_mmap(int fd, size_t size) {
void* addr = ::mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
throw boost::system::system_error(errno, boost::system::generic_category(),
"mmap");
DWARFS_THROW(system_error, "mmap");
}
return addr;

View File

@ -24,6 +24,7 @@
#include <fmt/format.h>
#include "dwarfs/error.h"
#include "dwarfs/options.h"
namespace dwarfs {
@ -64,7 +65,7 @@ mlock_mode parse_mlock_mode(std::string_view mode) {
if (mode == "must") {
return mlock_mode::MUST;
}
throw std::runtime_error(fmt::format("invalid lock mode: {}", mode));
DWARFS_THROW(error, fmt::format("invalid lock mode: {}", mode));
}
} // namespace dwarfs

View File

@ -19,7 +19,6 @@
* along with dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cerrno>
#include <stdexcept>
#include <vector>
@ -27,8 +26,9 @@
#include <sys/stat.h>
#include <unistd.h>
#include <boost/system/system_error.hpp>
#include <fmt/format.h>
#include "dwarfs/error.h"
#include "dwarfs/mmap.h"
#include "dwarfs/os_access_posix.h"
@ -39,8 +39,7 @@ class posix_dir_reader : public dir_reader {
posix_dir_reader(const std::string& path)
: dir_(::opendir(path.c_str())) {
if (!dir_) {
throw boost::system::system_error(
errno, boost::system::generic_category(), "opendir: " + path);
DWARFS_THROW(system_error, fmt::format("opendir('{}')", path));
}
}
@ -64,8 +63,7 @@ class posix_dir_reader : public dir_reader {
return false;
}
throw boost::system::system_error(errno, boost::system::generic_category(),
"readdir_r");
DWARFS_THROW(system_error, "readdir");
}
private:
@ -79,8 +77,7 @@ os_access_posix::opendir(const std::string& path) const {
void os_access_posix::lstat(const std::string& path, struct ::stat* st) const {
if (::lstat(path.c_str(), st) == -1) {
throw boost::system::system_error(errno, boost::system::generic_category(),
"lstat");
DWARFS_THROW(system_error, fmt::format("lstat('{}')", path));
}
}
@ -93,8 +90,7 @@ os_access_posix::readlink(const std::string& path, size_t size) const {
return std::string(linkname.begin(), linkname.end());
}
throw boost::system::system_error(errno, boost::system::generic_category(),
"readlink");
DWARFS_THROW(system_error, fmt::format("readlink('{}')", path));
}
std::shared_ptr<mmif>

View File

@ -31,6 +31,7 @@
#include <fmt/format.h>
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/inode.h"
#include "dwarfs/logger.h"
#include "dwarfs/options_interface.h"
@ -282,7 +283,7 @@ python_script::impl::impl(logger& lgr, const std::string& code,
has_order_ = has_callable(instance_, "order");
} catch (py::error_already_set const&) {
log_py_error();
throw std::runtime_error("error initializing script");
DWARFS_THROW(error, "error initializing script");
}
}
@ -347,7 +348,7 @@ void python_script::impl::configure(options_interface const& oi) {
instance_.attr("configure")(py::ptr(&oi));
} catch (py::error_already_set const&) {
log_py_error();
throw std::runtime_error("error in configure");
DWARFS_THROW(error, "error in configure");
}
}
@ -358,7 +359,7 @@ bool python_script::impl::filter(entry_interface const& ei) {
instance_.attr("filter")(std::make_shared<entry_wrapper>(ei)));
} catch (py::error_already_set const&) {
log_py_error();
throw std::runtime_error("error filtering entry");
DWARFS_THROW(error, "error filtering entry");
}
}
@ -368,7 +369,7 @@ void python_script::impl::transform(entry_interface& ei) {
instance_.attr("transform")(std::make_shared<mutable_entry_wrapper>(ei));
} catch (py::error_already_set const&) {
log_py_error();
throw std::runtime_error("error transforming entry");
DWARFS_THROW(error, "error transforming entry");
}
}
@ -407,24 +408,23 @@ void python_script::impl::order(inode_vector& iv) {
}
if (index != iv.size()) {
throw std::runtime_error("order() returned different number of files");
DWARFS_THROW(error, "order() returned different number of files");
}
std::sort(iv.begin(), iv.end(),
[&](inode_ptr const& a, inode_ptr const& b) {
auto ia = priority.find(a.get());
auto ib = priority.find(b.get());
if (ia == priority.end() || ib == priority.end()) {
throw std::runtime_error(
"invalid inode pointer while ordering files");
}
return ia->second < ib->second;
});
std::sort(
iv.begin(), iv.end(), [&](inode_ptr const& a, inode_ptr const& b) {
auto ia = priority.find(a.get());
auto ib = priority.find(b.get());
if (ia == priority.end() || ib == priority.end()) {
DWARFS_THROW(error, "invalid inode pointer while ordering files");
}
return ia->second < ib->second;
});
td << "applied new inode order";
} catch (py::error_already_set const&) {
log_py_error();
throw std::runtime_error("error ordering inodes");
DWARFS_THROW(error, "error ordering inodes");
}
}

View File

@ -40,6 +40,7 @@
#include <fmt/format.h>
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/filesystem_writer.h"
#include "dwarfs/global_entry_data.h"
#include "dwarfs/hash_util.h"
@ -336,7 +337,7 @@ scanner_<LoggerPolicy>::scan_tree(const std::string& path, progress& prog) {
auto root = entry_->create(*os_, path);
if (root->type() != entry::E_DIR) {
throw std::runtime_error(path + " must be a directory");
DWARFS_THROW(error, fmt::format("'{}' must be a directory", path));
}
std::deque<std::shared_ptr<entry>> queue({root});
@ -346,7 +347,7 @@ scanner_<LoggerPolicy>::scan_tree(const std::string& path, progress& prog) {
auto parent = std::dynamic_pointer_cast<dir>(queue.front());
if (!parent) {
throw std::runtime_error("expected directory");
DWARFS_THROW(error, "expected directory");
}
queue.pop_front();

View File

@ -21,13 +21,13 @@
#include <array>
#include <climits>
#include <stdexcept>
#include <string>
#include <unistd.h>
#include <folly/String.h>
#include "dwarfs/error.h"
#include "dwarfs/util.h"
namespace dwarfs {
@ -77,7 +77,7 @@ size_t parse_size_with_unit(const std::string& str) {
}
}
throw std::runtime_error("invalid size suffix");
DWARFS_THROW(error, "invalid size suffix");
}
std::string get_program_path() {

View File

@ -24,7 +24,6 @@
#include <cstdint>
#include <mutex>
#include <queue>
#include <stdexcept>
#include <string>
#include <thread>
#include <vector>
@ -36,6 +35,7 @@
#include <folly/Conv.h>
#include <folly/system/ThreadName.h>
#include "dwarfs/error.h"
#include "dwarfs/semaphore.h"
#include "dwarfs/worker_group.h"
@ -52,7 +52,7 @@ class basic_worker_group : public worker_group::impl, private Policy {
, pending_(0)
, max_queue_len_(max_queue_len) {
if (num_workers < 1) {
throw std::runtime_error("invalid number of worker threads");
DWARFS_THROW(error, "invalid number of worker threads");
}
if (!group_name) {
group_name = "worker";

View File

@ -27,6 +27,7 @@
#include <folly/String.h>
#include <folly/json.h>
#include "dwarfs/error.h"
#include "dwarfs/filesystem_v2.h"
#include "dwarfs/logger.h"
#include "dwarfs/mmap.h"
@ -65,25 +66,39 @@ int dwarfsck(int argc, char** argv) {
po::variables_map vm;
po::store(
po::command_line_parser(argc, argv).options(opts).positional(pos).run(),
vm);
po::notify(vm);
try {
po::store(
po::command_line_parser(argc, argv).options(opts).positional(pos).run(),
vm);
po::notify(vm);
} catch (po::error const& e) {
std::cerr << "error: " << e.what() << std::endl;
return 1;
}
if (vm.count("help") or !vm.count("input")) {
std::cout << "dwarfsck (" << DWARFS_VERSION << ")\n" << opts << std::endl;
return 0;
}
dwarfs::stream_logger lgr(std::cerr, logger::parse_level(log_level));
stream_logger lgr(std::cerr, logger::parse_level(log_level));
log_proxy<debug_logger_policy> log(lgr);
auto mm = std::make_shared<dwarfs::mmap>(input);
try {
auto mm = std::make_shared<mmap>(input);
if (json) {
dwarfs::filesystem_v2 fs(lgr, mm);
std::cout << folly::toPrettyJson(fs.metadata_as_dynamic()) << std::endl;
} else {
dwarfs::filesystem_v2::identify(lgr, mm, std::cout, detail);
if (json) {
filesystem_v2 fs(lgr, mm);
std::cout << folly::toPrettyJson(fs.metadata_as_dynamic()) << std::endl;
} else {
filesystem_v2::identify(lgr, mm, std::cout, detail);
}
} catch (system_error const& e) {
log.error() << folly::exceptionStr(e);
return 1;
} catch (error const& e) {
log.error() << folly::exceptionStr(e);
return 1;
}
return 0;
@ -92,10 +107,5 @@ int dwarfsck(int argc, char** argv) {
} // namespace dwarfs
int main(int argc, char** argv) {
try {
return dwarfs::dwarfsck(argc, argv);
} catch (std::exception const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << std::endl;
return 1;
}
return dwarfs::safe_main([&] { return dwarfs::dwarfsck(argc, argv); });
}

View File

@ -45,7 +45,6 @@
#include <folly/Conv.h>
#include <folly/FileUtil.h>
#include <folly/experimental/symbolizer/SignalHandler.h>
#include <folly/gen/String.h>
#include <fmt/format.h>
@ -58,6 +57,7 @@
#include "dwarfs/block_manager.h"
#include "dwarfs/console_writer.h"
#include "dwarfs/entry.h"
#include "dwarfs/error.h"
#include "dwarfs/filesystem_v2.h"
#include "dwarfs/filesystem_writer.h"
#include "dwarfs/logger.h"
@ -401,17 +401,24 @@ int mkdwarfs(int argc, char** argv) {
// clang-format on
po::variables_map vm;
auto parsed = po::parse_command_line(argc, argv, opts);
po::store(parsed, vm);
po::notify(vm);
try {
auto parsed = po::parse_command_line(argc, argv, opts);
auto unrecognized =
po::collect_unrecognized(parsed.options, po::include_positional);
po::store(parsed, vm);
po::notify(vm);
if (!unrecognized.empty()) {
throw std::runtime_error("unrecognized argument(s): " +
boost::join(unrecognized, " "));
auto unrecognized =
po::collect_unrecognized(parsed.options, po::include_positional);
if (!unrecognized.empty()) {
std::cerr << "error: unrecognized argument(s) '"
<< boost::join(unrecognized, " ") << "'" << std::endl;
return 1;
}
} catch (po::error const& e) {
std::cerr << "error: " << e.what() << std::endl;
return 1;
}
if (vm.count("help") or !vm.count("input") or !vm.count("output")) {
@ -478,7 +485,8 @@ int mkdwarfs(int argc, char** argv) {
}
if (level >= levels.size()) {
throw std::runtime_error("invalid compression level");
std::cerr << "error: invalid compression level" << std::endl;
return 1;
}
auto const& defaults = levels[level];
@ -509,36 +517,59 @@ int mkdwarfs(int argc, char** argv) {
std::vector<std::string> order_opts;
boost::split(order_opts, order, boost::is_any_of(":"));
if (auto it = order_choices.find(order_opts.front());
it != order_choices.end()) {
options.file_order.mode = it->second;
if (order_opts.size() > 1) {
if (options.file_order.mode != file_order_mode::NILSIMSA) {
throw std::runtime_error(
fmt::format("inode order mode '{}' does not support options",
order_opts.front()));
std::cerr << "error: inode order mode '" << order_opts.front()
<< "' does not support options" << std::endl;
return 1;
}
if (order_opts.size() > 3) {
throw std::runtime_error(fmt::format(
"too many options for inode order mode '{}'", order_opts.front()));
std::cerr << "error: too many options for inode order mode '"
<< order_opts[0] << "'" << std::endl;
return 1;
}
options.file_order.nilsimsa_limit = folly::to<int>(order_opts[1]);
if (options.file_order.nilsimsa_limit < 0 ||
options.file_order.nilsimsa_limit > 255) {
throw std::runtime_error(
fmt::format("limit ({}) out of range for '{}' (0..255)",
options.file_order.nilsimsa_limit, order_opts.front()));
if (auto val = folly::tryTo<int>(order_opts[1])) {
options.file_order.nilsimsa_limit = *val;
if (options.file_order.nilsimsa_limit < 0 ||
options.file_order.nilsimsa_limit > 255) {
std::cerr << "error: limit (" << order_opts[1]
<< ") out of range for order '" << order_opts[0]
<< "' (0..255)" << std::endl;
return 1;
}
} else {
std::cerr << "error: limit (" << order_opts[1]
<< ") is not numeric for order '" << order_opts[0] << "'"
<< std::endl;
return 1;
}
if (order_opts.size() > 2) {
options.file_order.nilsimsa_depth = folly::to<int>(order_opts[2]);
if (options.file_order.nilsimsa_depth < 0) {
throw std::runtime_error(fmt::format(
"depth ({}) cannot be negative for '{}'", order_opts.front()));
if (auto val = folly::tryTo<int>(order_opts[2])) {
options.file_order.nilsimsa_depth = *val;
if (options.file_order.nilsimsa_depth < 0) {
std::cerr << "error: depth (" << order_opts[2]
<< ") cannot be negative for order '" << order_opts[0]
<< "'" << std::endl;
}
} else {
std::cerr << "error: depth (" << order_opts[2]
<< ") is not numeric for order '" << order_opts[0] << "'"
<< std::endl;
return 1;
}
}
}
} else {
throw std::runtime_error("invalid inode order mode: " + order);
std::cerr << "error: invalid inode order mode: " << order << std::endl;
return 1;
}
size_t mem_limit = parse_size_with_unit(memory_limit);
@ -548,11 +579,17 @@ int mkdwarfs(int argc, char** argv) {
if (window_sizes != "-") {
boost::split(wsv, window_sizes, boost::is_any_of(","));
std::transform(wsv.begin(), wsv.end(),
std::back_inserter(cfg.blockhash_window_size),
[](const std::string& x) {
return static_cast<size_t>(1) << folly::to<unsigned>(x);
});
try {
std::transform(wsv.begin(), wsv.end(),
std::back_inserter(cfg.blockhash_window_size),
[](const std::string& x) {
return static_cast<size_t>(1) << folly::to<unsigned>(x);
});
} catch (folly::ConversionError const& e) {
std::cerr << "error: window size is not numeric (" << window_sizes << ")"
<< std::endl;
return 1;
}
}
worker_group wg_writer("writer", num_workers);
@ -566,7 +603,9 @@ int mkdwarfs(int argc, char** argv) {
progress_mode = "simple";
}
if (!progress_modes.count(progress_mode)) {
throw std::runtime_error("invalid progress mode: " + progress_mode);
std::cerr << "error: invalid progress mode '" << progress_mode << "'"
<< std::endl;
return 1;
}
auto pg_mode = progress_modes.at(progress_mode);
@ -594,7 +633,8 @@ int mkdwarfs(int argc, char** argv) {
if (folly::readFile(file.c_str(), code)) {
script = std::make_shared<python_script>(lgr, code, ctor);
} else {
throw std::runtime_error("could not load script: " + file);
std::cerr << "error: could not load script '" << file << "'" << std::endl;
return 1;
}
}
#endif
@ -607,8 +647,10 @@ int mkdwarfs(int argc, char** argv) {
}
if (options.file_order.mode == file_order_mode::SCRIPT && !script) {
throw std::runtime_error(
"--order=script can only be used with a valid --script option");
std::cerr << "error: '--order=script' can only be used with a valid "
"'--script' option"
<< std::endl;
return 1;
}
if (vm.count("set-owner")) {
@ -620,18 +662,32 @@ int mkdwarfs(int argc, char** argv) {
}
if (vm.count("set-time")) {
options.timestamp = timestamp == "now" ? std::time(nullptr)
: folly::to<uint64_t>(timestamp);
if (timestamp == "now") {
options.timestamp = std::time(nullptr);
} else if (auto val = folly::tryTo<uint64_t>(timestamp)) {
options.timestamp = *val;
} else {
std::cerr
<< "error: argument for option '--set-time' must be numeric or `now`"
<< std::endl;
return 1;
}
}
if (auto it = time_resolutions.find(time_resolution);
it != time_resolutions.end()) {
options.time_resolution_sec = it->second;
} else {
options.time_resolution_sec = folly::to<uint32_t>(time_resolution);
} else if (auto val = folly::tryTo<uint32_t>(time_resolution)) {
options.time_resolution_sec = *val;
if (options.time_resolution_sec == 0) {
throw std::runtime_error("timestamp resolution cannot be 0");
std::cerr << "error: the argument to '--time-resolution' must be nonzero"
<< std::endl;
return 1;
}
} else {
std::cerr << "error: the argument ('" << time_resolution
<< "') to '--time-resolution' is invalid" << std::endl;
return 1;
}
unsigned interval_ms =
@ -639,6 +695,14 @@ int mkdwarfs(int argc, char** argv) {
? 2000
: 200;
std::ofstream ofs(output, std::ios::binary);
if (ofs.bad() || !ofs.is_open()) {
std::cerr << "error: cannot open output file '" << output
<< "': " << strerror(errno) << std::endl;
return 1;
}
log_proxy<debug_logger_policy> log(lgr);
progress prog([&](const progress& p, bool last) { lgr.update(p, last); },
@ -648,22 +712,15 @@ int mkdwarfs(int argc, char** argv) {
block_compressor schema_bc(schema_compression);
block_compressor metadata_bc(metadata_compression);
std::ofstream ofs(output, std::ios::binary);
if (ofs.bad() || !ofs.is_open()) {
throw std::runtime_error(
fmt::format("cannot open '{}': {}", output, strerror(errno)));
}
filesystem_writer fsw(ofs, lgr, wg_writer, prog, bc, schema_bc, metadata_bc,
mem_limit);
auto ti = log.timed_info();
if (recompress) {
auto ti = log.timed_info();
filesystem_v2::rewrite(lgr, prog, std::make_shared<dwarfs::mmap>(path),
fsw);
wg_writer.wait();
ti << "filesystem rewritten";
} else {
options.inode.with_similarity =
force_similarity ||
@ -674,44 +731,41 @@ int mkdwarfs(int argc, char** argv) {
scanner s(lgr, wg_scanner, cfg, entry_factory::create(),
std::make_shared<os_access_posix>(), std::move(script), options);
{
auto ti = log.timed_info();
try {
s.scan(fsw, path, prog);
std::ostringstream err;
if (prog.errors) {
err << "with " << prog.errors << " error";
if (prog.errors > 1) {
err << "s";
}
} else {
err << "without errors";
}
ti << "filesystem created " << err.str();
} catch (error const& e) {
log.error() << e.what();
prog.errors++;
return 1;
}
}
ofs.close();
if (ofs.bad()) {
throw std::runtime_error(
fmt::format("failed to close '{}': {}", output, strerror(errno)));
log.error() << "failed to close output file '" << output
<< "': " << strerror(errno);
return 1;
}
std::ostringstream err;
if (prog.errors) {
err << "with " << prog.errors << " error";
if (prog.errors > 1) {
err << "s";
}
} else {
err << "without errors";
}
ti << "filesystem " << (recompress ? "rewritten" : "created ") << err.str();
return prog.errors > 0;
}
} // namespace
int main(int argc, char** argv) {
try {
folly::symbolizer::installFatalSignalHandler();
return mkdwarfs(argc, argv);
} catch (std::exception const& e) {
std::cerr << "ERROR: " << folly::exceptionStr(e) << std::endl;
return 1;
}
return dwarfs::safe_main([&] { return mkdwarfs(argc, argv); });
}