Use FUSE_STAT on Dokan

This commit is contained in:
Sebastian Messmer 2018-09-15 18:02:03 -07:00
parent 61451069e8
commit a866fda3a9
20 changed files with 117 additions and 86 deletions

View File

@ -11,6 +11,7 @@
#else #else
#include <sys/statvfs.h> #include <sys/statvfs.h>
#endif #endif
#include "stat_compatibility.h"
namespace fspp { namespace fspp {
namespace fuse { namespace fuse {
@ -23,8 +24,8 @@ public:
virtual int openFile(const boost::filesystem::path &path, int flags) = 0; virtual int openFile(const boost::filesystem::path &path, int flags) = 0;
virtual void flush(int descriptor) = 0; virtual void flush(int descriptor) = 0;
virtual void closeFile(int descriptor) = 0; virtual void closeFile(int descriptor) = 0;
virtual void lstat(const boost::filesystem::path &path, struct ::stat *stbuf) = 0; virtual void lstat(const boost::filesystem::path &path, fspp::fuse::STAT *stbuf) = 0;
virtual void fstat(int descriptor, struct ::stat *stbuf) = 0; virtual void fstat(int descriptor, fspp::fuse::STAT *stbuf) = 0;
//TODO Test chmod //TODO Test chmod
virtual void chmod(const boost::filesystem::path &path, ::mode_t mode) = 0; virtual void chmod(const boost::filesystem::path &path, ::mode_t mode) = 0;
//TODO Test chown //TODO Test chown

View File

@ -31,12 +31,12 @@ bool is_valid_fspp_path(const bf::path& path) {
//#define FSPP_LOG 1 //#define FSPP_LOG 1
namespace { namespace {
int fusepp_getattr(const char *path, struct stat *stbuf) { int fusepp_getattr(const char *path, fspp::fuse::STAT *stbuf) {
int rs = FUSE_OBJ->getattr(bf::path(path), stbuf); int rs = FUSE_OBJ->getattr(bf::path(path), stbuf);
return rs; return rs;
} }
int fusepp_fgetattr(const char *path, struct stat *stbuf, fuse_file_info *fileinfo) { int fusepp_fgetattr(const char *path, fspp::fuse::STAT *stbuf, fuse_file_info *fileinfo) {
return FUSE_OBJ->fgetattr(bf::path(path), stbuf, fileinfo); return FUSE_OBJ->fgetattr(bf::path(path), stbuf, fileinfo);
} }
@ -309,7 +309,7 @@ void Fuse::stop() {
} }
} }
int Fuse::getattr(const bf::path &path, struct stat *stbuf) { int Fuse::getattr(const bf::path &path, fspp::fuse::STAT *stbuf) {
#ifdef FSPP_LOG #ifdef FSPP_LOG
LOG(DEBUG, "getattr({}, _, _)", path); LOG(DEBUG, "getattr({}, _, _)", path);
#endif #endif
@ -331,7 +331,7 @@ int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
} }
} }
int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fileinfo) { int Fuse::fgetattr(const bf::path &path, fspp::fuse::STAT *stbuf, fuse_file_info *fileinfo) {
#ifdef FSPP_LOG #ifdef FSPP_LOG
LOG(DEBUG, "fgetattr({}, _, _)\n", path); LOG(DEBUG, "fgetattr({}, _, _)\n", path);
#endif #endif
@ -801,7 +801,7 @@ int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, int64
try { try {
ASSERT(is_valid_fspp_path(path), "has to be an absolute path"); ASSERT(is_valid_fspp_path(path), "has to be an absolute path");
auto entries = _fs->readDir(path); auto entries = _fs->readDir(path);
struct stat stbuf{}; fspp::fuse::STAT stbuf{};
for (const auto &entry : *entries) { for (const auto &entry : *entries) {
//We could pass more file metadata to filler() in its third parameter, //We could pass more file metadata to filler() in its third parameter,
//but it doesn't help performance since fuse ignores everything in stbuf //but it doesn't help performance since fuse ignores everything in stbuf

View File

@ -11,6 +11,7 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <cpp-utils/macros.h> #include <cpp-utils/macros.h>
#include <atomic> #include <atomic>
#include "stat_compatibility.h"
namespace fspp { namespace fspp {
class Device; class Device;
@ -27,8 +28,8 @@ public:
bool running() const; bool running() const;
void stop(); void stop();
int getattr(const boost::filesystem::path &path, struct stat *stbuf); int getattr(const boost::filesystem::path &path, fspp::fuse::STAT *stbuf);
int fgetattr(const boost::filesystem::path &path, struct stat *stbuf, fuse_file_info *fileinfo); int fgetattr(const boost::filesystem::path &path, fspp::fuse::STAT *stbuf, fuse_file_info *fileinfo);
int readlink(const boost::filesystem::path &path, char *buf, size_t size); int readlink(const boost::filesystem::path &path, char *buf, size_t size);
int mknod(const boost::filesystem::path &path, ::mode_t mode, dev_t rdev); int mknod(const boost::filesystem::path &path, ::mode_t mode, dev_t rdev);
int mkdir(const boost::filesystem::path &path, ::mode_t mode); int mkdir(const boost::filesystem::path &path, ::mode_t mode);

View File

@ -7,6 +7,8 @@
#include <fuse.h> #include <fuse.h>
#elif __APPLE__ #elif __APPLE__
#include <osxfuse/fuse.h> #include <osxfuse/fuse.h>
#elif defined(_MSC_VER)
#include <fuse.h> // Dokany fuse
#else #else
#error System not supported #error System not supported
#endif #endif

View File

@ -0,0 +1,27 @@
#pragma once
#ifndef MESSMER_FSPP_FUSE_STATCOMPATIBILITY_H
#define MESSMER_FSPP_FUSE_STATCOMPATIBILITY_H
namespace fspp {
namespace fuse {
// Dokan has a different "struct stat" called "fspp::fuse::STAT", but it's compatible.
// To make our code work with both, we use "STAT" everywhere instead of "stat"
// and define it here to the correct type
#if defined(_MSC_VER)
#include <fuse.h>
typedef struct FUSE_STAT STAT;
#else
#include <sys/stat.h>
typedef struct ::stat STAT;
#endif
}
}
#endif

View File

@ -139,7 +139,7 @@ void FilesystemImpl::closeFile(int descriptor) {
} }
namespace { namespace {
void convert_stat_info_(const fspp::Node::stat_info& input, struct ::stat *output) { void convert_stat_info_(const fspp::Node::stat_info& input, fspp::fuse::STAT *output) {
output->st_nlink = input.nlink; output->st_nlink = input.nlink;
output->st_mode = input.mode.value(); output->st_mode = input.mode.value();
output->st_uid = input.uid.value(); output->st_uid = input.uid.value();
@ -152,7 +152,7 @@ void convert_stat_info_(const fspp::Node::stat_info& input, struct ::stat *outpu
} }
} }
void FilesystemImpl::lstat(const bf::path &path, struct ::stat *stbuf) { void FilesystemImpl::lstat(const bf::path &path, fspp::fuse::STAT *stbuf) {
PROFILE(_lstatNanosec); PROFILE(_lstatNanosec);
auto node = _device->Load(path); auto node = _device->Load(path);
if(node == none) { if(node == none) {
@ -163,7 +163,7 @@ void FilesystemImpl::lstat(const bf::path &path, struct ::stat *stbuf) {
} }
} }
void FilesystemImpl::fstat(int descriptor, struct ::stat *stbuf) { void FilesystemImpl::fstat(int descriptor, fspp::fuse::STAT *stbuf) {
PROFILE(_fstatNanosec); PROFILE(_fstatNanosec);
auto stat_info = _open_files.get(descriptor)->stat(); auto stat_info = _open_files.get(descriptor)->stat();
convert_stat_info_(stat_info, stbuf); convert_stat_info_(stat_info, stbuf);

View File

@ -27,8 +27,8 @@ public:
int openFile(const boost::filesystem::path &path, int flags) override; int openFile(const boost::filesystem::path &path, int flags) override;
void flush(int descriptor) override; void flush(int descriptor) override;
void closeFile(int descriptor) override; void closeFile(int descriptor) override;
void lstat(const boost::filesystem::path &path, struct ::stat *stbuf) override; void lstat(const boost::filesystem::path &path, fspp::fuse::STAT *stbuf) override;
void fstat(int descriptor, struct ::stat *stbuf) override; void fstat(int descriptor, fspp::fuse::STAT *stbuf) override;
void chmod(const boost::filesystem::path &path, ::mode_t mode) override; void chmod(const boost::filesystem::path &path, ::mode_t mode) override;
void chown(const boost::filesystem::path &path, ::uid_t uid, ::gid_t gid) override; void chown(const boost::filesystem::path &path, ::uid_t uid, ::gid_t gid) override;
void truncate(const boost::filesystem::path &path, fspp::num_bytes_t size) override; void truncate(const boost::filesystem::path &path, fspp::num_bytes_t size) override;

View File

@ -6,7 +6,7 @@ using ::testing::Values;
class FuseLstatReturnATimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> { class FuseLstatReturnATimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> {
private: private:
void set(struct stat *stat, time_t value) override { void set(fspp::fuse::STAT *stat, time_t value) override {
stat->st_atim.tv_sec = value; stat->st_atim.tv_sec = value;
stat->st_atim.tv_nsec = 0; stat->st_atim.tv_nsec = 0;
} }
@ -19,13 +19,13 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnATimeTest, FuseLstatReturnATimeTest, Valu
)); ));
TEST_P(FuseLstatReturnATimeTest, ReturnedFileAtimeIsCorrect) { TEST_P(FuseLstatReturnATimeTest, ReturnedFileAtimeIsCorrect) {
struct ::stat result = CallFileLstatWithValue(GetParam()); fspp::fuse::STAT result = CallFileLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_atim.tv_sec); EXPECT_EQ(GetParam(), result.st_atim.tv_sec);
EXPECT_EQ(0, result.st_atim.tv_nsec); EXPECT_EQ(0, result.st_atim.tv_nsec);
} }
TEST_P(FuseLstatReturnATimeTest, ReturnedDirAtimeIsCorrect) { TEST_P(FuseLstatReturnATimeTest, ReturnedDirAtimeIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_atim.tv_sec); EXPECT_EQ(GetParam(), result.st_atim.tv_sec);
EXPECT_EQ(0, result.st_atim.tv_nsec); EXPECT_EQ(0, result.st_atim.tv_nsec);
} }

View File

@ -6,7 +6,7 @@ using ::testing::Values;
class FuseLstatReturnCtimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> { class FuseLstatReturnCtimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> {
private: private:
void set(struct stat *stat, time_t value) override { void set(fspp::fuse::STAT *stat, time_t value) override {
stat->st_ctim.tv_sec = value; stat->st_ctim.tv_sec = value;
stat->st_ctim.tv_nsec = 0; stat->st_ctim.tv_nsec = 0;
} }
@ -19,13 +19,13 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnCtimeTest, FuseLstatReturnCtimeTest, Valu
)); ));
TEST_P(FuseLstatReturnCtimeTest, ReturnedFileCtimeIsCorrect) { TEST_P(FuseLstatReturnCtimeTest, ReturnedFileCtimeIsCorrect) {
struct ::stat result = CallFileLstatWithValue(GetParam()); fspp::fuse::STAT result = CallFileLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_ctim.tv_sec); EXPECT_EQ(GetParam(), result.st_ctim.tv_sec);
EXPECT_EQ(0, result.st_ctim.tv_nsec); EXPECT_EQ(0, result.st_ctim.tv_nsec);
} }
TEST_P(FuseLstatReturnCtimeTest, ReturnedDirCtimeIsCorrect) { TEST_P(FuseLstatReturnCtimeTest, ReturnedDirCtimeIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_ctim.tv_sec); EXPECT_EQ(GetParam(), result.st_ctim.tv_sec);
EXPECT_EQ(0, result.st_ctim.tv_nsec); EXPECT_EQ(0, result.st_ctim.tv_nsec);
} }

View File

@ -5,7 +5,7 @@ using ::testing::Values;
class FuseLstatReturnGidTest: public FuseLstatReturnTest<gid_t>, public WithParamInterface<gid_t> { class FuseLstatReturnGidTest: public FuseLstatReturnTest<gid_t>, public WithParamInterface<gid_t> {
private: private:
void set(struct stat *stat, gid_t value) override { void set(fspp::fuse::STAT *stat, gid_t value) override {
stat->st_gid = value; stat->st_gid = value;
} }
}; };
@ -15,11 +15,11 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnGidTest, FuseLstatReturnGidTest, Values(
)); ));
TEST_P(FuseLstatReturnGidTest, ReturnedFileGidIsCorrect) { TEST_P(FuseLstatReturnGidTest, ReturnedFileGidIsCorrect) {
struct ::stat result = CallFileLstatWithValue(GetParam()); fspp::fuse::STAT result = CallFileLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_gid); EXPECT_EQ(GetParam(), result.st_gid);
} }
TEST_P(FuseLstatReturnGidTest, ReturnedDirGidIsCorrect) { TEST_P(FuseLstatReturnGidTest, ReturnedDirGidIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_gid); EXPECT_EQ(GetParam(), result.st_gid);
} }

View File

@ -5,8 +5,8 @@ using ::testing::Values;
class FuseLstatReturnModeTest: public FuseLstatTest, public WithParamInterface<mode_t> { class FuseLstatReturnModeTest: public FuseLstatTest, public WithParamInterface<mode_t> {
public: public:
struct stat CallLstatWithValue(mode_t mode) { fspp::fuse::STAT CallLstatWithValue(mode_t mode) {
return CallLstatWithImpl([mode] (struct stat *stat) { return CallLstatWithImpl([mode] (fspp::fuse::STAT *stat) {
stat->st_mode = mode; stat->st_mode = mode;
}); });
} }
@ -19,6 +19,6 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnModeTest, FuseLstatReturnModeTest, Values
)); ));
TEST_P(FuseLstatReturnModeTest, ReturnedModeIsCorrect) { TEST_P(FuseLstatReturnModeTest, ReturnedModeIsCorrect) {
struct ::stat result = CallLstatWithValue(GetParam()); fspp::fuse::STAT result = CallLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_mode); EXPECT_EQ(GetParam(), result.st_mode);
} }

View File

@ -6,7 +6,7 @@ using ::testing::Values;
class FuseLstatReturnMtimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> { class FuseLstatReturnMtimeTest: public FuseLstatReturnTest<time_t>, public WithParamInterface<time_t> {
private: private:
void set(struct stat *stat, time_t value) override { void set(fspp::fuse::STAT *stat, time_t value) override {
stat->st_mtim.tv_sec = value; stat->st_mtim.tv_sec = value;
stat->st_mtim.tv_nsec = 0; stat->st_mtim.tv_nsec = 0;
} }
@ -19,13 +19,13 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnMtimeTest, FuseLstatReturnMtimeTest, Valu
)); ));
TEST_P(FuseLstatReturnMtimeTest, ReturnedFileMtimeIsCorrect) { TEST_P(FuseLstatReturnMtimeTest, ReturnedFileMtimeIsCorrect) {
struct ::stat result = CallFileLstatWithValue(GetParam()); fspp::fuse::STAT result = CallFileLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_mtim.tv_sec); EXPECT_EQ(GetParam(), result.st_mtim.tv_sec);
EXPECT_EQ(0, result.st_mtim.tv_nsec); EXPECT_EQ(0, result.st_mtim.tv_nsec);
} }
TEST_P(FuseLstatReturnMtimeTest, ReturnedDirMtimeIsCorrect) { TEST_P(FuseLstatReturnMtimeTest, ReturnedDirMtimeIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_mtim.tv_sec); EXPECT_EQ(GetParam(), result.st_mtim.tv_sec);
EXPECT_EQ(0, result.st_mtim.tv_nsec); EXPECT_EQ(0, result.st_mtim.tv_nsec);
} }

View File

@ -5,7 +5,7 @@ using ::testing::Values;
class FuseLstatReturnNlinkTest: public FuseLstatReturnTest<nlink_t>, public WithParamInterface<nlink_t> { class FuseLstatReturnNlinkTest: public FuseLstatReturnTest<nlink_t>, public WithParamInterface<nlink_t> {
private: private:
void set(struct stat *stat, nlink_t value) override { void set(fspp::fuse::STAT *stat, nlink_t value) override {
stat->st_nlink = value; stat->st_nlink = value;
} }
}; };
@ -17,12 +17,12 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnNlinkTest, FuseLstatReturnNlinkTest, Valu
)); ));
TEST_P(FuseLstatReturnNlinkTest, ReturnedFileNlinkIsCorrect) { TEST_P(FuseLstatReturnNlinkTest, ReturnedFileNlinkIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_nlink); EXPECT_EQ(GetParam(), result.st_nlink);
} }
TEST_P(FuseLstatReturnNlinkTest, ReturnedDirNlinkIsCorrect) { TEST_P(FuseLstatReturnNlinkTest, ReturnedDirNlinkIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_nlink); EXPECT_EQ(GetParam(), result.st_nlink);
} }

View File

@ -5,7 +5,7 @@ using ::testing::Values;
class FuseLstatReturnSizeTest: public FuseLstatReturnTest<fspp::num_bytes_t>, public WithParamInterface<fspp::num_bytes_t> { class FuseLstatReturnSizeTest: public FuseLstatReturnTest<fspp::num_bytes_t>, public WithParamInterface<fspp::num_bytes_t> {
private: private:
void set(struct stat *stat, fspp::num_bytes_t value) override { void set(fspp::fuse::STAT *stat, fspp::num_bytes_t value) override {
stat->st_size = value.value(); stat->st_size = value.value();
} }
}; };
@ -17,11 +17,11 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnSizeTest, FuseLstatReturnSizeTest, Values
)); ));
TEST_P(FuseLstatReturnSizeTest, ReturnedFileSizeIsCorrect) { TEST_P(FuseLstatReturnSizeTest, ReturnedFileSizeIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), fspp::num_bytes_t(result.st_size)); EXPECT_EQ(GetParam(), fspp::num_bytes_t(result.st_size));
} }
TEST_P(FuseLstatReturnSizeTest, ReturnedDirSizeIsCorrect) { TEST_P(FuseLstatReturnSizeTest, ReturnedDirSizeIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), fspp::num_bytes_t(result.st_size)); EXPECT_EQ(GetParam(), fspp::num_bytes_t(result.st_size));
} }

View File

@ -5,7 +5,7 @@ using ::testing::Values;
class FuseLstatReturnUidTest: public FuseLstatReturnTest<uid_t>, public WithParamInterface<uid_t> { class FuseLstatReturnUidTest: public FuseLstatReturnTest<uid_t>, public WithParamInterface<uid_t> {
private: private:
void set(struct stat *stat, uid_t value) override { void set(fspp::fuse::STAT *stat, uid_t value) override {
stat->st_uid = value; stat->st_uid = value;
} }
}; };
@ -15,11 +15,11 @@ INSTANTIATE_TEST_CASE_P(FuseLstatReturnUidTest, FuseLstatReturnUidTest, Values(
)); ));
TEST_P(FuseLstatReturnUidTest, ReturnedFileUidIsCorrect) { TEST_P(FuseLstatReturnUidTest, ReturnedFileUidIsCorrect) {
struct ::stat result = CallFileLstatWithValue(GetParam()); fspp::fuse::STAT result = CallFileLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_uid); EXPECT_EQ(GetParam(), result.st_uid);
} }
TEST_P(FuseLstatReturnUidTest, ReturnedDirUidIsCorrect) { TEST_P(FuseLstatReturnUidTest, ReturnedDirUidIsCorrect) {
struct ::stat result = CallDirLstatWithValue(GetParam()); fspp::fuse::STAT result = CallDirLstatWithValue(GetParam());
EXPECT_EQ(GetParam(), result.st_uid); EXPECT_EQ(GetParam(), result.st_uid);
} }

View File

@ -4,37 +4,37 @@
#include "FuseLstatTest.h" #include "FuseLstatTest.h"
// This class offers test helpers for testing (struct stat) entries. We return them from // This class offers test helpers for testing (fspp::fuse::STAT) entries. We return them from
// our mock filesystem, set up a temporary filesystem, call lstat syscall on it, and // our mock filesystem, set up a temporary filesystem, call lstat syscall on it, and
// then check the return value. // then check the return value.
template<typename Property> template<typename Property>
class FuseLstatReturnTest: public FuseLstatTest { class FuseLstatReturnTest: public FuseLstatTest {
public: public:
// Set the specified (struct stat) entry to the given value, and test whether it is correctly returned from the syscall. // Set the specified (fspp::fuse::STAT) entry to the given value, and test whether it is correctly returned from the syscall.
// The CallFile[...] version tests it on a file node of the filesystem, the CallDir[...] version on a dir node. // The CallFile[...] version tests it on a file node of the filesystem, the CallDir[...] version on a dir node.
struct stat CallFileLstatWithValue(Property value); fspp::fuse::STAT CallFileLstatWithValue(Property value);
struct stat CallDirLstatWithValue(Property value); fspp::fuse::STAT CallDirLstatWithValue(Property value);
private: private:
std::function<void(struct stat*)> SetPropertyImpl(Property value); std::function<void(fspp::fuse::STAT*)> SetPropertyImpl(Property value);
// Override this function to specify, how to set the specified (struct stat) entry on the passed (struct stat *) object. // Override this function to specify, how to set the specified (fspp::fuse::STAT) entry on the passed (fspp::fuse::STAT *) object.
virtual void set(struct stat *stat, Property value) = 0; virtual void set(fspp::fuse::STAT *stat, Property value) = 0;
}; };
template<typename Property> template<typename Property>
struct stat FuseLstatReturnTest<Property>::CallFileLstatWithValue(Property value) { FUSE_STAT FuseLstatReturnTest<Property>::CallFileLstatWithValue(Property value) {
return CallFileLstatWithImpl(SetPropertyImpl(value)); return CallFileLstatWithImpl(SetPropertyImpl(value));
} }
template<typename Property> template<typename Property>
struct stat FuseLstatReturnTest<Property>::CallDirLstatWithValue(Property value) { FUSE_STAT FuseLstatReturnTest<Property>::CallDirLstatWithValue(Property value) {
return CallDirLstatWithImpl(SetPropertyImpl(value)); return CallDirLstatWithImpl(SetPropertyImpl(value));
} }
template<typename Property> template<typename Property>
std::function<void(struct stat*)> FuseLstatReturnTest<Property>::SetPropertyImpl(Property value) { std::function<void(fspp::fuse::STAT*)> FuseLstatReturnTest<Property>::SetPropertyImpl(Property value) {
return [this, value] (struct stat *stat) { return [this, value] (fspp::fuse::STAT *stat) {
set(stat, value); set(stat, value);
}; };
} }

View File

@ -6,21 +6,21 @@ using ::testing::_;
using ::testing::Invoke; using ::testing::Invoke;
void FuseLstatTest::LstatPath(const std::string &path) { void FuseLstatTest::LstatPath(const std::string &path) {
struct stat dummy{}; fspp::fuse::STAT dummy{};
LstatPath(path, &dummy); LstatPath(path, &dummy);
} }
int FuseLstatTest::LstatPathReturnError(const std::string &path) { int FuseLstatTest::LstatPathReturnError(const std::string &path) {
struct stat dummy{}; fspp::fuse::STAT dummy{};
return LstatPathReturnError(path, &dummy); return LstatPathReturnError(path, &dummy);
} }
void FuseLstatTest::LstatPath(const std::string &path, struct stat *result) { void FuseLstatTest::LstatPath(const std::string &path, fspp::fuse::STAT *result) {
int error = LstatPathReturnError(path, result); int error = LstatPathReturnError(path, result);
EXPECT_EQ(0, error) << "lstat syscall failed. errno: " << error; EXPECT_EQ(0, error) << "lstat syscall failed. errno: " << error;
} }
int FuseLstatTest::LstatPathReturnError(const std::string &path, struct stat *result) { int FuseLstatTest::LstatPathReturnError(const std::string &path, fspp::fuse::STAT *result) {
auto fs = TestFS(); auto fs = TestFS();
auto realpath = fs->mountDir() / path; auto realpath = fs->mountDir() / path;
@ -32,27 +32,27 @@ int FuseLstatTest::LstatPathReturnError(const std::string &path, struct stat *re
} }
} }
struct stat FuseLstatTest::CallFileLstatWithImpl(function<void(struct stat*)> implementation) { fspp::fuse::STAT FuseLstatTest::CallFileLstatWithImpl(function<void(fspp::fuse::STAT*)> implementation) {
return CallLstatWithModeAndImpl(S_IFREG, implementation); return CallLstatWithModeAndImpl(S_IFREG, implementation);
} }
struct stat FuseLstatTest::CallDirLstatWithImpl(function<void(struct stat*)> implementation) { fspp::fuse::STAT FuseLstatTest::CallDirLstatWithImpl(function<void(fspp::fuse::STAT*)> implementation) {
return CallLstatWithModeAndImpl(S_IFDIR, implementation); return CallLstatWithModeAndImpl(S_IFDIR, implementation);
} }
struct stat FuseLstatTest::CallLstatWithImpl(function<void(struct stat*)> implementation) { fspp::fuse::STAT FuseLstatTest::CallLstatWithImpl(function<void(fspp::fuse::STAT*)> implementation) {
EXPECT_CALL(fsimpl, lstat(StrEq(FILENAME), _)).WillRepeatedly(Invoke([implementation](const char*, struct ::stat *stat) { EXPECT_CALL(fsimpl, lstat(StrEq(FILENAME), _)).WillRepeatedly(Invoke([implementation](const char*, fspp::fuse::STAT *stat) {
implementation(stat); implementation(stat);
})); }));
struct stat result{}; fspp::fuse::STAT result{};
LstatPath(FILENAME, &result); LstatPath(FILENAME, &result);
return result; return result;
} }
struct stat FuseLstatTest::CallLstatWithModeAndImpl(mode_t mode, function<void(struct stat*)> implementation) { fspp::fuse::STAT FuseLstatTest::CallLstatWithModeAndImpl(mode_t mode, function<void(fspp::fuse::STAT*)> implementation) {
return CallLstatWithImpl([mode, implementation] (struct stat *stat) { return CallLstatWithImpl([mode, implementation] (fspp::fuse::STAT *stat) {
stat->st_mode = mode; stat->st_mode = mode;
implementation(stat); implementation(stat);
}); });

View File

@ -17,27 +17,27 @@ protected:
// and call the lstat syscall on the given (filesystem-relative) path. // and call the lstat syscall on the given (filesystem-relative) path.
void LstatPath(const std::string &path); void LstatPath(const std::string &path);
// Same as LstatPath above, but also return the result of the lstat syscall. // Same as LstatPath above, but also return the result of the lstat syscall.
void LstatPath(const std::string &path, struct stat *result); void LstatPath(const std::string &path, fspp::fuse::STAT *result);
// These two functions are the same as LstatPath above, but they don't fail the test when the lstat syscall // These two functions are the same as LstatPath above, but they don't fail the test when the lstat syscall
// crashes. Instead, they return the value of errno after calling ::lstat. // crashes. Instead, they return the value of errno after calling ::lstat.
int LstatPathReturnError(const std::string &path); int LstatPathReturnError(const std::string &path);
int LstatPathReturnError(const std::string &path, struct stat *result); int LstatPathReturnError(const std::string &path, fspp::fuse::STAT *result);
// You can specify an implementation, which can modify the (struct stat *) result, // You can specify an implementation, which can modify the (fspp::fuse::STAT *) result,
// our fuse mock filesystem implementation will then return this to fuse on an lstat call. // our fuse mock filesystem implementation will then return this to fuse on an lstat call.
// This functions then set up a temporary filesystem with this mock, call lstat on a filesystem node // This functions then set up a temporary filesystem with this mock, call lstat on a filesystem node
// and return the (struct stat) returned from an lstat syscall to this filesystem. // and return the (fspp::fuse::STAT) returned from an lstat syscall to this filesystem.
struct stat CallLstatWithImpl(std::function<void(struct stat*)> implementation); fspp::fuse::STAT CallLstatWithImpl(std::function<void(fspp::fuse::STAT*)> implementation);
// These two functions are like CallLstatWithImpl, but they also modify the (struct stat).st_mode // These two functions are like CallLstatWithImpl, but they also modify the (fspp::fuse::STAT).st_mode
// field, so the node accessed is specified to be a file/directory. // field, so the node accessed is specified to be a file/directory.
struct stat CallFileLstatWithImpl(std::function<void(struct stat*)> implementation); fspp::fuse::STAT CallFileLstatWithImpl(std::function<void(fspp::fuse::STAT*)> implementation);
struct stat CallDirLstatWithImpl(std::function<void(struct stat*)> implementation); fspp::fuse::STAT CallDirLstatWithImpl(std::function<void(fspp::fuse::STAT*)> implementation);
private: private:
struct stat CallLstatWithModeAndImpl(mode_t mode, std::function<void(struct stat*)> implementation); fspp::fuse::STAT CallLstatWithModeAndImpl(mode_t mode, std::function<void(fspp::fuse::STAT*)> implementation);
}; };
#endif #endif

View File

@ -65,8 +65,8 @@ const bf::path &FuseTest::TempTestFS::mountDir() const {
return _mountDir.path(); return _mountDir.path();
} }
Action<void(const char*, struct ::stat*)> FuseTest::ReturnIsFileWithSize(fspp::num_bytes_t size) { Action<void(const char*, fspp::fuse::STAT*)> FuseTest::ReturnIsFileWithSize(fspp::num_bytes_t size) {
return Invoke([size](const char*, struct ::stat* result) { return Invoke([size](const char*, fspp::fuse::STAT* result) {
result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
result->st_nlink = 1; result->st_nlink = 1;
result->st_size = size.value(); result->st_size = size.value();
@ -74,15 +74,15 @@ Action<void(const char*, struct ::stat*)> FuseTest::ReturnIsFileWithSize(fspp::n
} }
//TODO Combine ReturnIsFile and ReturnIsFileFstat. This should be possible in gmock by either (a) using ::testing::Undefined as parameter type or (b) using action macros //TODO Combine ReturnIsFile and ReturnIsFileFstat. This should be possible in gmock by either (a) using ::testing::Undefined as parameter type or (b) using action macros
Action<void(const char*, struct ::stat*)> FuseTest::ReturnIsFile = ReturnIsFileWithSize(fspp::num_bytes_t(0)); Action<void(const char*, fspp::fuse::STAT*)> FuseTest::ReturnIsFile = ReturnIsFileWithSize(fspp::num_bytes_t(0));
Action<void(int, struct ::stat*)> FuseTest::ReturnIsFileFstat = Action<void(int, fspp::fuse::STAT*)> FuseTest::ReturnIsFileFstat =
Invoke([](int, struct ::stat* result) { Invoke([](int, fspp::fuse::STAT* result) {
result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
result->st_nlink = 1; result->st_nlink = 1;
}); });
Action<void(int, struct ::stat*)> FuseTest::ReturnIsFileFstatWithSize(fspp::num_bytes_t size) { Action<void(int, fspp::fuse::STAT*)> FuseTest::ReturnIsFileFstatWithSize(fspp::num_bytes_t size) {
return Invoke([size](int, struct ::stat *result) { return Invoke([size](int, struct ::stat *result) {
result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; result->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
result->st_nlink = 1; result->st_nlink = 1;
@ -91,13 +91,13 @@ Action<void(int, struct ::stat*)> FuseTest::ReturnIsFileFstatWithSize(fspp::num_
}); });
} }
Action<void(const char*, struct ::stat*)> FuseTest::ReturnIsDir = Action<void(const char*, fspp::fuse::STAT*)> FuseTest::ReturnIsDir =
Invoke([](const char*, struct ::stat* result) { Invoke([](const char*, fspp::fuse::STAT* result) {
result->st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH; result->st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH;
result->st_nlink = 1; result->st_nlink = 1;
}); });
Action<void(const char*, struct ::stat*)> FuseTest::ReturnDoesntExist = Throw(fspp::fuse::FuseErrnoException(ENOENT)); Action<void(const char*, fspp::fuse::STAT*)> FuseTest::ReturnDoesntExist = Throw(fspp::fuse::FuseErrnoException(ENOENT));
void FuseTest::OnOpenReturnFileDescriptor(const char *filename, int descriptor) { void FuseTest::OnOpenReturnFileDescriptor(const char *filename, int descriptor) {
EXPECT_CALL(fsimpl, openFile(StrEq(filename), _)).Times(1).WillOnce(Return(descriptor)); EXPECT_CALL(fsimpl, openFile(StrEq(filename), _)).Times(1).WillOnce(Return(descriptor));

View File

@ -46,8 +46,8 @@ public:
MOCK_PATH_METHOD2(openFile, int, int); MOCK_PATH_METHOD2(openFile, int, int);
MOCK_METHOD1(closeFile, void(int)); MOCK_METHOD1(closeFile, void(int));
MOCK_PATH_METHOD2(lstat, void, struct ::stat*); MOCK_PATH_METHOD2(lstat, void, fspp::fuse::STAT*);
MOCK_METHOD2(fstat, void(int, struct ::stat*)); MOCK_METHOD2(fstat, void(int, fspp::fuse::STAT*));
MOCK_PATH_METHOD2(truncate, void, fspp::num_bytes_t); MOCK_PATH_METHOD2(truncate, void, fspp::num_bytes_t);
MOCK_METHOD2(ftruncate, void(int, fspp::num_bytes_t)); MOCK_METHOD2(ftruncate, void(int, fspp::num_bytes_t));
MOCK_METHOD4(read, fspp::num_bytes_t(int, void*, fspp::num_bytes_t, fspp::num_bytes_t)); MOCK_METHOD4(read, fspp::num_bytes_t(int, void*, fspp::num_bytes_t, fspp::num_bytes_t));
@ -106,12 +106,12 @@ public:
//TODO Combine ReturnIsFile and ReturnIsFileFstat. This should be possible in gmock by either (a) using ::testing::Undefined as parameter type or (b) using action macros //TODO Combine ReturnIsFile and ReturnIsFileFstat. This should be possible in gmock by either (a) using ::testing::Undefined as parameter type or (b) using action macros
static ::testing::Action<void(const char*, struct ::stat*)> ReturnIsFile; static ::testing::Action<void(const char*, fspp::fuse::STAT*)> ReturnIsFile;
static ::testing::Action<void(const char*, struct ::stat*)> ReturnIsFileWithSize(fspp::num_bytes_t size); static ::testing::Action<void(const char*, fspp::fuse::STAT*)> ReturnIsFileWithSize(fspp::num_bytes_t size);
static ::testing::Action<void(int, struct ::stat*)> ReturnIsFileFstat; static ::testing::Action<void(int, fspp::fuse::STAT*)> ReturnIsFileFstat;
static ::testing::Action<void(int, struct ::stat*)> ReturnIsFileFstatWithSize(fspp::num_bytes_t size); static ::testing::Action<void(int, fspp::fuse::STAT*)> ReturnIsFileFstatWithSize(fspp::num_bytes_t size);
static ::testing::Action<void(const char*, struct ::stat*)> ReturnIsDir; static ::testing::Action<void(const char*, fspp::fuse::STAT*)> ReturnIsDir;
static ::testing::Action<void(const char*, struct ::stat*)> ReturnDoesntExist; static ::testing::Action<void(const char*, fspp::fuse::STAT*)> ReturnDoesntExist;
void ReturnIsFileOnLstat(const boost::filesystem::path &path); void ReturnIsFileOnLstat(const boost::filesystem::path &path);
void ReturnIsFileOnLstatWithSize(const boost::filesystem::path &path, fspp::num_bytes_t size); void ReturnIsFileOnLstatWithSize(const boost::filesystem::path &path, fspp::num_bytes_t size);