OpenFile updates timestamps correctly, i.e. on read(), write() and truncate(). Also added test cases for it.
This commit is contained in:
parent
06a5faf2f8
commit
6448110975
@ -34,7 +34,7 @@ unique_ref<parallelaccessfsblobstore::FileBlobRef> CryFile::LoadBlob() const {
|
|||||||
return std::move(*file_blob);
|
return std::move(*file_blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ref<fspp::OpenFile> CryFile::open(int flags) const {
|
unique_ref<fspp::OpenFile> CryFile::open(int flags) {
|
||||||
// TODO Should we honor open flags?
|
// TODO Should we honor open flags?
|
||||||
UNUSED(flags);
|
UNUSED(flags);
|
||||||
device()->callFsActionCallbacks();
|
device()->callFsActionCallbacks();
|
||||||
@ -42,7 +42,7 @@ unique_ref<fspp::OpenFile> CryFile::open(int flags) const {
|
|||||||
return make_unique_ref<CryOpenFile>(device(), parent(), std::move(blob));
|
return make_unique_ref<CryOpenFile>(device(), parent(), std::move(blob));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryFile::truncate(off_t size) const {
|
void CryFile::truncate(off_t size) {
|
||||||
device()->callFsActionCallbacks();
|
device()->callFsActionCallbacks();
|
||||||
auto blob = LoadBlob();
|
auto blob = LoadBlob();
|
||||||
blob->resize(size);
|
blob->resize(size);
|
||||||
|
@ -14,8 +14,8 @@ public:
|
|||||||
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, const blockstore::Key &key);
|
CryFile(CryDevice *device, cpputils::unique_ref<parallelaccessfsblobstore::DirBlobRef> parent, const blockstore::Key &key);
|
||||||
~CryFile();
|
~CryFile();
|
||||||
|
|
||||||
cpputils::unique_ref<fspp::OpenFile> open(int flags) const override;
|
cpputils::unique_ref<fspp::OpenFile> open(int flags) override;
|
||||||
void truncate(off_t size) const override;
|
void truncate(off_t size) override;
|
||||||
fspp::Dir::EntryType getType() const override;
|
fspp::Dir::EntryType getType() const override;
|
||||||
void remove() override;
|
void remove() override;
|
||||||
|
|
||||||
|
@ -52,6 +52,11 @@ shared_ptr<const DirBlobRef> CryNode::parent() const {
|
|||||||
return *_parent;
|
return *_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<DirBlobRef> CryNode::parent() {
|
||||||
|
ASSERT(_parent != none, "We are the root directory and can't get the parent of the root directory");
|
||||||
|
return *_parent;
|
||||||
|
}
|
||||||
|
|
||||||
void CryNode::rename(const bf::path &to) {
|
void CryNode::rename(const bf::path &to) {
|
||||||
device()->callFsActionCallbacks();
|
device()->callFsActionCallbacks();
|
||||||
if (_parent == none) {
|
if (_parent == none) {
|
||||||
|
@ -29,6 +29,7 @@ protected:
|
|||||||
const CryDevice *device() const;
|
const CryDevice *device() const;
|
||||||
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob() const;
|
cpputils::unique_ref<parallelaccessfsblobstore::FsBlobRef> LoadBlob() const;
|
||||||
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent() const;
|
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent() const;
|
||||||
|
std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> parent();
|
||||||
|
|
||||||
virtual fspp::Dir::EntryType getType() const = 0;
|
virtual fspp::Dir::EntryType getType() const = 0;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ using fspp::fuse::FuseErrnoException;
|
|||||||
|
|
||||||
namespace cryfs {
|
namespace cryfs {
|
||||||
|
|
||||||
CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr<const DirBlobRef> parent, unique_ref<FileBlobRef> fileBlob)
|
CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr<DirBlobRef> parent, unique_ref<FileBlobRef> fileBlob)
|
||||||
: _device(device), _parent(parent), _fileBlob(std::move(fileBlob)) {
|
: _device(device), _parent(parent), _fileBlob(std::move(fileBlob)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,15 +41,18 @@ void CryOpenFile::stat(struct ::stat *result) const {
|
|||||||
void CryOpenFile::truncate(off_t size) const {
|
void CryOpenFile::truncate(off_t size) const {
|
||||||
_device->callFsActionCallbacks();
|
_device->callFsActionCallbacks();
|
||||||
_fileBlob->resize(size);
|
_fileBlob->resize(size);
|
||||||
|
_parent->updateModificationTimestampForChild(_fileBlob->key());
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CryOpenFile::read(void *buf, size_t count, off_t offset) const {
|
size_t CryOpenFile::read(void *buf, size_t count, off_t offset) const {
|
||||||
_device->callFsActionCallbacks();
|
_device->callFsActionCallbacks();
|
||||||
|
_parent->updateAccessTimestampForChild(_fileBlob->key());
|
||||||
return _fileBlob->read(buf, offset, count);
|
return _fileBlob->read(buf, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CryOpenFile::write(const void *buf, size_t count, off_t offset) {
|
void CryOpenFile::write(const void *buf, size_t count, off_t offset) {
|
||||||
_device->callFsActionCallbacks();
|
_device->callFsActionCallbacks();
|
||||||
|
_parent->updateModificationTimestampForChild(_fileBlob->key());
|
||||||
_fileBlob->write(buf, offset, count);
|
_fileBlob->write(buf, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ class CryDevice;
|
|||||||
|
|
||||||
class CryOpenFile final: public fspp::OpenFile {
|
class CryOpenFile final: public fspp::OpenFile {
|
||||||
public:
|
public:
|
||||||
explicit CryOpenFile(const CryDevice *device, std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> parent, cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> fileBlob);
|
explicit CryOpenFile(const CryDevice *device, std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> parent, cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> fileBlob);
|
||||||
~CryOpenFile();
|
~CryOpenFile();
|
||||||
|
|
||||||
void stat(struct ::stat *result) const override;
|
void stat(struct ::stat *result) const override;
|
||||||
@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const CryDevice *_device;
|
const CryDevice *_device;
|
||||||
std::shared_ptr<const parallelaccessfsblobstore::DirBlobRef> _parent;
|
std::shared_ptr<parallelaccessfsblobstore::DirBlobRef> _parent;
|
||||||
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> _fileBlob;
|
cpputils::unique_ref<parallelaccessfsblobstore::FileBlobRef> _fileBlob;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CryOpenFile);
|
DISALLOW_COPY_AND_ASSIGN(CryOpenFile);
|
||||||
|
@ -60,6 +60,14 @@ public:
|
|||||||
return _base->statChildExceptSize(key, result);
|
return _base->statChildExceptSize(key, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||||
|
return _base->updateAccessTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||||
|
return _base->updateModificationTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
||||||
return _base->chmodChild(key, mode);
|
return _base->chmodChild(key, mode);
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,16 @@ void DirBlob::statChildExceptSize(const Key &key, struct ::stat *result) const {
|
|||||||
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
|
result->st_blksize = _fsBlobStore->virtualBlocksizeBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DirBlob::updateAccessTimestampForChild(const Key &key) {
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_entries.updateAccessTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirBlob::updateModificationTimestampForChild(const Key &key) {
|
||||||
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
|
_entries.updateModificationTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
void DirBlob::chmodChild(const Key &key, mode_t mode) {
|
void DirBlob::chmodChild(const Key &key, mode_t mode) {
|
||||||
std::unique_lock<std::mutex> lock(_mutex);
|
std::unique_lock<std::mutex> lock(_mutex);
|
||||||
_entries.setMode(key, mode);
|
_entries.setMode(key, mode);
|
||||||
|
@ -59,6 +59,10 @@ namespace cryfs {
|
|||||||
|
|
||||||
void statChildExceptSize(const blockstore::Key &key, struct ::stat *result) const;
|
void statChildExceptSize(const blockstore::Key &key, struct ::stat *result) const;
|
||||||
|
|
||||||
|
void updateAccessTimestampForChild(const blockstore::Key &key);
|
||||||
|
|
||||||
|
void updateModificationTimestampForChild(const blockstore::Key &key);
|
||||||
|
|
||||||
void chmodChild(const blockstore::Key &key, mode_t mode);
|
void chmodChild(const blockstore::Key &key, mode_t mode);
|
||||||
|
|
||||||
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
|
void chownChild(const blockstore::Key &key, uid_t uid, gid_t gid);
|
||||||
|
@ -228,5 +228,15 @@ void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAcces
|
|||||||
found->setLastModificationTime(lastModificationTime);
|
found->setLastModificationTime(lastModificationTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DirEntryList::updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||||
|
auto found = _findByKey(key);
|
||||||
|
found->setLastAccessTime(cpputils::time::now());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirEntryList::updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||||
|
auto found = _findByKey(key);
|
||||||
|
found->setLastModificationTime(cpputils::time::now());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,8 @@ namespace cryfs {
|
|||||||
void setMode(const blockstore::Key &key, mode_t mode);
|
void setMode(const blockstore::Key &key, mode_t mode);
|
||||||
bool setUidGid(const blockstore::Key &key, uid_t uid, gid_t gid);
|
bool setUidGid(const blockstore::Key &key, uid_t uid, gid_t gid);
|
||||||
void setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime);
|
void setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime);
|
||||||
|
void updateAccessTimestampForChild(const blockstore::Key &key);
|
||||||
|
void updateModificationTimestampForChild(const blockstore::Key &key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t _serializedSize() const;
|
uint64_t _serializedSize() const;
|
||||||
|
@ -56,6 +56,14 @@ public:
|
|||||||
return _base->statChildExceptSize(key, result);
|
return _base->statChildExceptSize(key, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateAccessTimestampForChild(const blockstore::Key &key) {
|
||||||
|
return _base->updateAccessTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateModificationTimestampForChild(const blockstore::Key &key) {
|
||||||
|
return _base->updateModificationTimestampForChild(key);
|
||||||
|
}
|
||||||
|
|
||||||
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
void chmodChild(const blockstore::Key &key, mode_t mode) {
|
||||||
return _base->chmodChild(key, mode);
|
return _base->chmodChild(key, mode);
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ class File: public virtual Node {
|
|||||||
public:
|
public:
|
||||||
virtual ~File() {}
|
virtual ~File() {}
|
||||||
|
|
||||||
virtual cpputils::unique_ref<OpenFile> open(int flags) const = 0;
|
virtual cpputils::unique_ref<OpenFile> open(int flags) = 0;
|
||||||
virtual void truncate(off_t size) const = 0;
|
virtual void truncate(off_t size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,10 @@
|
|||||||
#include "FsppSymlinkTest.h"
|
#include "FsppSymlinkTest.h"
|
||||||
#include "FsppNodeTest_Rename.h"
|
#include "FsppNodeTest_Rename.h"
|
||||||
#include "FsppNodeTest_Stat.h"
|
#include "FsppNodeTest_Stat.h"
|
||||||
#include "FsppNodeTest_Timestamps.h"
|
|
||||||
#include "FsppOpenFileTest.h"
|
#include "FsppOpenFileTest.h"
|
||||||
#include "FsppDeviceTest_Timestamps.h"
|
#include "FsppDeviceTest_Timestamps.h"
|
||||||
|
#include "FsppNodeTest_Timestamps.h"
|
||||||
|
#include "FsppOpenFileTest_Timestamps.h"
|
||||||
|
|
||||||
#define FSPP_ADD_FILESYTEM_TESTS(FS_NAME, FIXTURE) \
|
#define FSPP_ADD_FILESYTEM_TESTS(FS_NAME, FIXTURE) \
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppDeviceTest, FIXTURE); \
|
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppDeviceTest, FIXTURE); \
|
||||||
@ -26,5 +27,7 @@
|
|||||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_DirOnly, FIXTURE); \
|
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_DirOnly, FIXTURE); \
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_SymlinkOnly, FIXTURE); \
|
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppNodeTest_Stat_SymlinkOnly, FIXTURE); \
|
||||||
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest, FIXTURE); \
|
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest, FIXTURE); \
|
||||||
|
INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest_Timestamps, FIXTURE); \
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,54 +24,54 @@ public:
|
|||||||
|
|
||||||
void Test_Truncate_DontChange1(fspp::File *file) {
|
void Test_Truncate_DontChange1(fspp::File *file) {
|
||||||
file->truncate(0);
|
file->truncate(0);
|
||||||
this->EXPECT_SIZE(0, *file);
|
this->EXPECT_SIZE(0, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Truncate_GrowTo1(fspp::File *file) {
|
void Test_Truncate_GrowTo1(fspp::File *file) {
|
||||||
file->truncate(1);
|
file->truncate(1);
|
||||||
this->EXPECT_SIZE(1, *file);
|
this->EXPECT_SIZE(1, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Truncate_Grow(fspp::File *file) {
|
void Test_Truncate_Grow(fspp::File *file) {
|
||||||
file->truncate(10*1024*1024);
|
file->truncate(10*1024*1024);
|
||||||
this->EXPECT_SIZE(10*1024*1024, *file);
|
this->EXPECT_SIZE(10*1024*1024, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Truncate_DontChange2(fspp::File *file) {
|
void Test_Truncate_DontChange2(fspp::File *file) {
|
||||||
file->truncate(10*1024*1024);
|
file->truncate(10*1024*1024);
|
||||||
file->truncate(10*1024*1024);
|
file->truncate(10*1024*1024);
|
||||||
this->EXPECT_SIZE(10*1024*1024, *file);
|
this->EXPECT_SIZE(10*1024*1024, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Truncate_Shrink(fspp::File *file) {
|
void Test_Truncate_Shrink(fspp::File *file) {
|
||||||
file->truncate(10*1024*1024);
|
file->truncate(10*1024*1024);
|
||||||
file->truncate(5*1024*1024);
|
file->truncate(5*1024*1024);
|
||||||
this->EXPECT_SIZE(5*1024*1024, *file);
|
this->EXPECT_SIZE(5*1024*1024, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Truncate_ShrinkTo0(fspp::File *file) {
|
void Test_Truncate_ShrinkTo0(fspp::File *file) {
|
||||||
file->truncate(10*1024*1024);
|
file->truncate(10*1024*1024);
|
||||||
file->truncate(0);
|
file->truncate(0);
|
||||||
this->EXPECT_SIZE(0, *file);
|
this->EXPECT_SIZE(0, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Chown_Uid(fspp::File *file) {
|
void Test_Chown_Uid(fspp::File *file) {
|
||||||
file->chown(100, 200);
|
file->chown(100, 200);
|
||||||
this->IN_STAT(*file, [] (struct stat st){
|
this->IN_STAT(file, [] (struct stat st){
|
||||||
EXPECT_EQ(100u, st.st_uid);
|
EXPECT_EQ(100u, st.st_uid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Chown_Gid(fspp::File *file) {
|
void Test_Chown_Gid(fspp::File *file) {
|
||||||
file->chown(100, 200);
|
file->chown(100, 200);
|
||||||
this->IN_STAT(*file, [] (struct stat st){
|
this->IN_STAT(file, [] (struct stat st){
|
||||||
EXPECT_EQ(200u, st.st_gid);
|
EXPECT_EQ(200u, st.st_gid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Test_Chmod(fspp::File *file) {
|
void Test_Chmod(fspp::File *file) {
|
||||||
file->chmod(S_IFREG | S_IRUSR | S_IWOTH);
|
file->chmod(S_IFREG | S_IRUSR | S_IWOTH);
|
||||||
this->IN_STAT(*file, [] (struct stat st){
|
this->IN_STAT(file, [] (struct stat st){
|
||||||
EXPECT_EQ((mode_t)(S_IFREG | S_IRUSR | S_IWOTH), st.st_mode);
|
EXPECT_EQ((mode_t)(S_IFREG | S_IRUSR | S_IWOTH), st.st_mode);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
struct timespec ATIME; ATIME.tv_sec = 1458086400; ATIME.tv_nsec = 34525;
|
struct timespec ATIME; ATIME.tv_sec = 1458086400; ATIME.tv_nsec = 34525;
|
||||||
struct timespec MTIME; MTIME.tv_sec = 1458086300; MTIME.tv_nsec = 48293;
|
struct timespec MTIME; MTIME.tv_sec = 1458086300; MTIME.tv_nsec = 48293;
|
||||||
file->utimens(ATIME, MTIME);
|
file->utimens(ATIME, MTIME);
|
||||||
this->IN_STAT(*file, [this, ATIME, MTIME] (struct stat st) {
|
this->IN_STAT(file, [this, ATIME, MTIME] (struct stat st) {
|
||||||
this->EXPECT_ATIME_EQ(ATIME, st);
|
this->EXPECT_ATIME_EQ(ATIME, st);
|
||||||
this->EXPECT_MTIME_EQ(MTIME, st);
|
this->EXPECT_MTIME_EQ(MTIME, st);
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ class FsppNodeTest_Stat: public FsppNodeTest<ConcreteFileSystemTestFixture> {
|
|||||||
public:
|
public:
|
||||||
void Test_Nlink() {
|
void Test_Nlink() {
|
||||||
auto node = this->CreateNode("/mynode");
|
auto node = this->CreateNode("/mynode");
|
||||||
this->IN_STAT(*node, [] (struct stat st) {
|
this->IN_STAT(node.get(), [] (struct stat st) {
|
||||||
EXPECT_EQ(1u, st.st_nlink);
|
EXPECT_EQ(1u, st.st_nlink);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -24,12 +24,12 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_FileOnly);
|
|||||||
|
|
||||||
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, CreatedFileIsEmpty) {
|
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, CreatedFileIsEmpty) {
|
||||||
auto file = this->CreateFile("/myfile");
|
auto file = this->CreateFile("/myfile");
|
||||||
this->EXPECT_SIZE(0, *file);
|
this->EXPECT_SIZE(0, file.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, FileIsFile) {
|
TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, FileIsFile) {
|
||||||
auto file = this->CreateFile("/myfile");
|
auto file = this->CreateFile("/myfile");
|
||||||
this->IN_STAT(*file, [] (struct stat st) {
|
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||||
EXPECT_TRUE(S_ISREG(st.st_mode));
|
EXPECT_TRUE(S_ISREG(st.st_mode));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_DirOnly);
|
|||||||
|
|
||||||
TYPED_TEST_P(FsppNodeTest_Stat_DirOnly, DirIsDir) {
|
TYPED_TEST_P(FsppNodeTest_Stat_DirOnly, DirIsDir) {
|
||||||
auto file = this->CreateDir("/mydir");
|
auto file = this->CreateDir("/mydir");
|
||||||
this->IN_STAT(*file, [] (struct stat st) {
|
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||||
EXPECT_TRUE(S_ISDIR(st.st_mode));
|
EXPECT_TRUE(S_ISDIR(st.st_mode));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_SymlinkOnly);
|
|||||||
|
|
||||||
TYPED_TEST_P(FsppNodeTest_Stat_SymlinkOnly, SymlinkIsSymlink) {
|
TYPED_TEST_P(FsppNodeTest_Stat_SymlinkOnly, SymlinkIsSymlink) {
|
||||||
auto file = this->CreateSymlink("/mysymlink");
|
auto file = this->CreateSymlink("/mysymlink");
|
||||||
this->IN_STAT(*file, [] (struct stat st) {
|
this->IN_STAT(file.get(), [] (struct stat st) {
|
||||||
EXPECT_TRUE(S_ISLNK(st.st_mode));
|
EXPECT_TRUE(S_ISLNK(st.st_mode));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
149
src/fspp/fstest/FsppOpenFileTest_Timestamps.h
Normal file
149
src/fspp/fstest/FsppOpenFileTest_Timestamps.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef MESSMER_FSPP_FSTEST_FSPPOPENFILETEST_TIMESTAMPS_H_
|
||||||
|
#define MESSMER_FSPP_FSTEST_FSPPOPENFILETEST_TIMESTAMPS_H_
|
||||||
|
|
||||||
|
#include "testutils/TimestampTestUtils.h"
|
||||||
|
|
||||||
|
template<class ConcreteFileSystemTestFixture>
|
||||||
|
class FsppOpenFileTest_Timestamps: public FileSystemTest<ConcreteFileSystemTestFixture>, public TimestampTestUtils<fspp::OpenFile> {
|
||||||
|
public:
|
||||||
|
cpputils::unique_ref<fspp::OpenFile> CreateAndOpenFile(const boost::filesystem::path &path) {
|
||||||
|
return this->CreateFile(path)->open(O_RDWR);
|
||||||
|
}
|
||||||
|
cpputils::unique_ref<fspp::OpenFile> CreateAndOpenFileWithSize(const boost::filesystem::path &path, off_t size) {
|
||||||
|
auto file = this->CreateFile(path);
|
||||||
|
file->truncate(size);
|
||||||
|
auto openFile = file->open(O_RDWR);
|
||||||
|
assert(stat(*openFile).st_size == size);
|
||||||
|
return openFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TYPED_TEST_CASE_P(FsppOpenFileTest_Timestamps);
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, stat) {
|
||||||
|
auto openFile = this->CreateAndOpenFile("/mynode");
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
struct ::stat st;
|
||||||
|
openFile->stat(&st);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_empty_to_empty) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->truncate(0);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_empty_to_nonempty) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->truncate(10);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_empty) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->truncate(0);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_nonempty_shrink) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->truncate(5);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, truncate_nonempty_to_nonempty_grow) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->truncate(20);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, read_inbounds) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
char buffer[5];
|
||||||
|
openFile->read(buffer, 5, 0);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectUpdatesAccessTimestamp, this->ExpectDoesntUpdateModificationTimestamp, this->ExpectDoesntUpdateMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, read_outofbounds) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
char buffer[5];
|
||||||
|
openFile->read(buffer, 5, 2);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectUpdatesAccessTimestamp, this->ExpectDoesntUpdateModificationTimestamp, this->ExpectDoesntUpdateMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, write_inbounds) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->write("content", 7, 0);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, write_outofbounds) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->write("content", 7, 2);
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAccessTimestamp, this->ExpectUpdatesModificationTimestamp, this->ExpectUpdatesMetadataTimestamp});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, flush) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
openFile->write("content", 7, 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->flush();
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, fsync) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
openFile->write("content", 7, 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->fsync();
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST_P(FsppOpenFileTest_Timestamps, fdatasync) {
|
||||||
|
auto openFile = this->CreateAndOpenFileWithSize("/myfile", 10);
|
||||||
|
openFile->write("content", 7, 0);
|
||||||
|
auto operation = [&openFile] () {
|
||||||
|
openFile->fdatasync();
|
||||||
|
};
|
||||||
|
this->EXPECT_OPERATION_UPDATES_TIMESTAMPS_AS(*openFile, operation, {this->ExpectDoesntUpdateAnyTimestamps});
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_TYPED_TEST_CASE_P(FsppOpenFileTest_Timestamps,
|
||||||
|
stat,
|
||||||
|
truncate_empty_to_empty,
|
||||||
|
truncate_empty_to_nonempty,
|
||||||
|
truncate_nonempty_to_empty,
|
||||||
|
truncate_nonempty_to_nonempty_shrink,
|
||||||
|
truncate_nonempty_to_nonempty_grow,
|
||||||
|
read_inbounds,
|
||||||
|
read_outofbounds,
|
||||||
|
write_inbounds,
|
||||||
|
write_outofbounds,
|
||||||
|
flush,
|
||||||
|
fsync,
|
||||||
|
fdatasync
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
@ -24,15 +24,15 @@ public:
|
|||||||
std::unique_ptr<fspp::File> file_nested;
|
std::unique_ptr<fspp::File> file_nested;
|
||||||
|
|
||||||
//TODO IN_STAT still needed after moving it to FsppNodeTest?
|
//TODO IN_STAT still needed after moving it to FsppNodeTest?
|
||||||
void IN_STAT(const fspp::File &file, std::function<void (struct stat)> callback) {
|
void IN_STAT(fspp::File *file, std::function<void (struct stat)> callback) {
|
||||||
struct stat st1, st2;
|
struct stat st1, st2;
|
||||||
file.stat(&st1);
|
file->stat(&st1);
|
||||||
callback(st1);
|
callback(st1);
|
||||||
file.open(O_RDONLY)->stat(&st2);
|
file->open(O_RDONLY)->stat(&st2);
|
||||||
callback(st2);
|
callback(st2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::File &file) {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::File *file) {
|
||||||
IN_STAT(file, [expectedSize] (struct stat st) {
|
IN_STAT(file, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||||
});
|
});
|
||||||
@ -40,8 +40,8 @@ public:
|
|||||||
EXPECT_NUMBYTES_READABLE(expectedSize, file);
|
EXPECT_NUMBYTES_READABLE(expectedSize, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) {
|
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) {
|
||||||
auto openFile = file.open(O_RDONLY);
|
auto openFile = file->open(O_RDONLY);
|
||||||
cpputils::Data data(expectedSize);
|
cpputils::Data data(expectedSize);
|
||||||
//Try to read one byte more than the expected size
|
//Try to read one byte more than the expected size
|
||||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
class FsppNodeTestBase {
|
class FsppNodeTestBase {
|
||||||
public:
|
public:
|
||||||
virtual void IN_STAT(const fspp::Node &node, std::function<void (struct stat)> callback) = 0;
|
virtual void IN_STAT(fspp::Node *node, std::function<void (struct stat)> callback) = 0;
|
||||||
virtual void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) = 0;
|
virtual void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,24 +29,24 @@ public:
|
|||||||
|
|
||||||
class FsppNodeTest_File_Helper: public virtual FsppNodeTestBase {
|
class FsppNodeTest_File_Helper: public virtual FsppNodeTestBase {
|
||||||
public:
|
public:
|
||||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||||
struct stat st1, st2;
|
struct stat st1, st2;
|
||||||
file.stat(&st1);
|
file->stat(&st1);
|
||||||
callback(st1);
|
callback(st1);
|
||||||
dynamic_cast<const fspp::File &>(file).open(O_RDONLY)->stat(&st2);
|
dynamic_cast<fspp::File &>(*file).open(O_RDONLY)->stat(&st2);
|
||||||
callback(st2);
|
callback(st2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||||
});
|
});
|
||||||
|
|
||||||
EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast<const fspp::File&>(node));
|
EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast<fspp::File*>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) {
|
void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) {
|
||||||
auto openFile = file.open(O_RDONLY);
|
auto openFile = file->open(O_RDONLY);
|
||||||
cpputils::Data data(expectedSize);
|
cpputils::Data data(expectedSize);
|
||||||
//Try to read one byte more than the expected size
|
//Try to read one byte more than the expected size
|
||||||
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0);
|
||||||
@ -57,13 +57,13 @@ public:
|
|||||||
|
|
||||||
class FsppNodeTest_Dir_Helper: public virtual FsppNodeTestBase {
|
class FsppNodeTest_Dir_Helper: public virtual FsppNodeTestBase {
|
||||||
public:
|
public:
|
||||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
file.stat(&st);
|
file->stat(&st);
|
||||||
callback(st);
|
callback(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||||
});
|
});
|
||||||
@ -72,13 +72,13 @@ public:
|
|||||||
|
|
||||||
class FsppNodeTest_Symlink_Helper: public virtual FsppNodeTestBase {
|
class FsppNodeTest_Symlink_Helper: public virtual FsppNodeTestBase {
|
||||||
public:
|
public:
|
||||||
void IN_STAT(const fspp::Node &file, std::function<void (struct stat)> callback) override {
|
void IN_STAT(fspp::Node *file, std::function<void (struct stat)> callback) override {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
file.stat(&st);
|
file->stat(&st);
|
||||||
callback(st);
|
callback(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) override {
|
void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) override {
|
||||||
IN_STAT(node, [expectedSize] (struct stat st) {
|
IN_STAT(node, [expectedSize] (struct stat st) {
|
||||||
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
EXPECT_EQ(expectedSize, (uint64_t)st.st_size);
|
||||||
});
|
});
|
||||||
|
@ -151,12 +151,12 @@ unique_ref<Node> FilesystemImpl::LoadFileOrSymlink(const bf::path &path) {
|
|||||||
|
|
||||||
int FilesystemImpl::openFile(const bf::path &path, int flags) {
|
int FilesystemImpl::openFile(const bf::path &path, int flags) {
|
||||||
auto file = LoadFile(path);
|
auto file = LoadFile(path);
|
||||||
return openFile(*file, flags);
|
return openFile(file.get(), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FilesystemImpl::openFile(const File &file, int flags) {
|
int FilesystemImpl::openFile(File *file, int flags) {
|
||||||
PROFILE(_openFileNanosec);
|
PROFILE(_openFileNanosec);
|
||||||
return _open_files.open(file.open(flags));
|
return _open_files.open(file->open(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FilesystemImpl::flush(int descriptor) {
|
void FilesystemImpl::flush(int descriptor) {
|
||||||
|
@ -54,7 +54,7 @@ private:
|
|||||||
cpputils::unique_ref<Dir> LoadDir(const boost::filesystem::path &path);
|
cpputils::unique_ref<Dir> LoadDir(const boost::filesystem::path &path);
|
||||||
cpputils::unique_ref<Symlink> LoadSymlink(const boost::filesystem::path &path);
|
cpputils::unique_ref<Symlink> LoadSymlink(const boost::filesystem::path &path);
|
||||||
cpputils::unique_ref<Node> LoadFileOrSymlink(const boost::filesystem::path &path);
|
cpputils::unique_ref<Node> LoadFileOrSymlink(const boost::filesystem::path &path);
|
||||||
int openFile(const File &file, int flags);
|
int openFile(File *file, int flags);
|
||||||
|
|
||||||
#ifdef FSPP_PROFILE
|
#ifdef FSPP_PROFILE
|
||||||
std::atomic<uint64_t> _loadFileNanosec;
|
std::atomic<uint64_t> _loadFileNanosec;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user