diff --git a/include/dwarfs/filesystem_v2.h b/include/dwarfs/filesystem_v2.h index 4dc7837b..e88776ce 100644 --- a/include/dwarfs/filesystem_v2.h +++ b/include/dwarfs/filesystem_v2.h @@ -159,6 +159,10 @@ class filesystem_v2 { int open(inode_view entry) const { return impl_->open(entry); } + int open(inode_view entry, std::error_code& ec) const { + return impl_->open(entry, ec); + } + size_t read(uint32_t inode, char* buf, size_t size, file_off_t offset = 0) const { return impl_->read(inode, buf, size, offset); @@ -277,6 +281,7 @@ class filesystem_v2 { readlink(inode_view entry, readlink_mode mode) const = 0; virtual int statvfs(vfs_stat* stbuf) const = 0; virtual int open(inode_view entry) const = 0; + virtual int open(inode_view entry, std::error_code& ec) const = 0; virtual size_t read(uint32_t inode, char* buf, size_t size, file_off_t offset) const = 0; virtual size_t read(uint32_t inode, char* buf, size_t size, diff --git a/include/dwarfs/internal/metadata_v2.h b/include/dwarfs/internal/metadata_v2.h index 0b1533ba..ac0753eb 100644 --- a/include/dwarfs/internal/metadata_v2.h +++ b/include/dwarfs/internal/metadata_v2.h @@ -125,7 +125,9 @@ class metadata_v2 { impl_->access(iv, mode, uid, gid, ec); } - int open(inode_view iv) const { return impl_->open(iv); } + int open(inode_view iv, std::error_code& ec) const { + return impl_->open(iv, ec); + } std::string readlink(inode_view iv, readlink_mode mode, std::error_code& ec) const { @@ -203,7 +205,7 @@ class metadata_v2 { virtual void access(inode_view iv, int mode, file_stat::uid_type uid, file_stat::gid_type gid, std::error_code& ec) const = 0; - virtual int open(inode_view iv) const = 0; + virtual int open(inode_view iv, std::error_code& ec) const = 0; virtual std::string readlink(inode_view iv, readlink_mode mode, std::error_code& ec) const = 0; diff --git a/src/dwarfs/filesystem_v2.cpp b/src/dwarfs/filesystem_v2.cpp index 823256a7..73716350 100644 --- a/src/dwarfs/filesystem_v2.cpp +++ b/src/dwarfs/filesystem_v2.cpp @@ -432,6 +432,7 @@ class filesystem_ final : public filesystem_v2::impl { std::string readlink(inode_view entry, readlink_mode mode) const override; int statvfs(vfs_stat* stbuf) const override; int open(inode_view entry) const override; + int open(inode_view entry, std::error_code& ec) const override; size_t read(uint32_t inode, char* buf, size_t size, file_off_t offset) const override; size_t read(uint32_t inode, char* buf, size_t size, file_off_t offset, @@ -504,6 +505,7 @@ class filesystem_ final : public filesystem_v2::impl { PERFMON_CLS_TIMER_DECL(readlink_ec) PERFMON_CLS_TIMER_DECL(statvfs) PERFMON_CLS_TIMER_DECL(open) + PERFMON_CLS_TIMER_DECL(open_ec) PERFMON_CLS_TIMER_DECL(read) PERFMON_CLS_TIMER_DECL(read_ec) PERFMON_CLS_TIMER_DECL(readv_iovec) @@ -587,6 +589,7 @@ filesystem_::filesystem_( PERFMON_CLS_TIMER_INIT(readlink_ec) PERFMON_CLS_TIMER_INIT(statvfs) PERFMON_CLS_TIMER_INIT(open) + PERFMON_CLS_TIMER_INIT(open_ec) PERFMON_CLS_TIMER_INIT(read) PERFMON_CLS_TIMER_INIT(read_ec) PERFMON_CLS_TIMER_INIT(readv_iovec) @@ -1123,10 +1126,18 @@ int filesystem_::statvfs(vfs_stat* stbuf) const { return meta_.statvfs(stbuf); } +template +int filesystem_::open(inode_view entry, + std::error_code& ec) const { + PERFMON_CLS_SCOPED_SECTION(open_ec) + return meta_.open(entry, ec); +} + template int filesystem_::open(inode_view entry) const { PERFMON_CLS_SCOPED_SECTION(open) - return meta_.open(entry); + return call_ec_throw( + [&](std::error_code& ec) { return meta_.open(entry, ec); }); } template diff --git a/src/dwarfs/internal/metadata_v2.cpp b/src/dwarfs/internal/metadata_v2.cpp index 9796307e..6ff49b0a 100644 --- a/src/dwarfs/internal/metadata_v2.cpp +++ b/src/dwarfs/internal/metadata_v2.cpp @@ -497,7 +497,7 @@ class metadata_ final : public metadata_v2::impl { void access(inode_view iv, int mode, file_stat::uid_type uid, file_stat::gid_type gid, std::error_code& ec) const override; - int open(inode_view iv) const override; + int open(inode_view iv, std::error_code& ec) const override; std::string readlink(inode_view iv, readlink_mode mode, std::error_code& ec) const override; @@ -1689,12 +1689,14 @@ void metadata_::access(inode_view iv, int mode, } template -int metadata_::open(inode_view iv) const { +int metadata_::open(inode_view iv, std::error_code& ec) const { if (iv.is_regular_file()) { + ec.clear(); return iv.inode_num(); } - return -1; + ec = std::make_error_code(std::errc::invalid_argument); + return 0; } template diff --git a/test/dwarfs_benchmark.cpp b/test/dwarfs_benchmark.cpp index c06ab312..9601700e 100644 --- a/test/dwarfs_benchmark.cpp +++ b/test/dwarfs_benchmark.cpp @@ -427,7 +427,8 @@ BENCHMARK_DEFINE_F(filesystem, open)(::benchmark::State& state) { int i = 0; for (auto _ : state) { - auto r = fs->open(entries[i++ % NUM_ENTRIES]); + std::error_code ec; + auto r = fs->open(entries[i++ % NUM_ENTRIES], ec); ::benchmark::DoNotOptimize(r); } } diff --git a/test/tool_main_test.cpp b/test/tool_main_test.cpp index eae66854..ca7e5e68 100644 --- a/test/tool_main_test.cpp +++ b/test/tool_main_test.cpp @@ -2376,7 +2376,14 @@ TEST(mkdwarfs_test, filesystem_read_error) { auto iv = fs.find("/somedir"); ASSERT_TRUE(iv); EXPECT_TRUE(iv->is_directory()); - EXPECT_EQ(-1, fs.open(*iv)); + EXPECT_THAT([&] { fs.open(*iv); }, ::testing::Throws()); + { + std::error_code ec; + auto res = fs.open(*iv, ec); + EXPECT_TRUE(ec); + EXPECT_EQ(EINVAL, ec.value()); + EXPECT_EQ(0, res); + } { char buf[1]; std::error_code ec;