mirror of
https://github.com/mhx/dwarfs.git
synced 2025-09-13 06:16:55 -04:00
Improved error handling
This commit is contained in:
parent
3e0d14cc0f
commit
aed35f04f9
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
80
src/dwarfs/error.cpp
Normal 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
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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";
|
||||
|
@ -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); });
|
||||
}
|
||||
|
202
src/mkdwarfs.cpp
202
src/mkdwarfs.cpp
@ -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); });
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user