diff --git a/src/cryfs/filesystem/CryFile.cpp b/src/cryfs/filesystem/CryFile.cpp index 84dc5404..16df5a36 100644 --- a/src/cryfs/filesystem/CryFile.cpp +++ b/src/cryfs/filesystem/CryFile.cpp @@ -34,7 +34,7 @@ unique_ref CryFile::LoadBlob() const { return std::move(*file_blob); } -unique_ref CryFile::open(int flags) const { +unique_ref CryFile::open(int flags) { // TODO Should we honor open flags? UNUSED(flags); device()->callFsActionCallbacks(); @@ -42,7 +42,7 @@ unique_ref CryFile::open(int flags) const { return make_unique_ref(device(), parent(), std::move(blob)); } -void CryFile::truncate(off_t size) const { +void CryFile::truncate(off_t size) { device()->callFsActionCallbacks(); auto blob = LoadBlob(); blob->resize(size); diff --git a/src/cryfs/filesystem/CryFile.h b/src/cryfs/filesystem/CryFile.h index 95777ff9..270578ba 100644 --- a/src/cryfs/filesystem/CryFile.h +++ b/src/cryfs/filesystem/CryFile.h @@ -14,8 +14,8 @@ public: CryFile(CryDevice *device, cpputils::unique_ref parent, const blockstore::Key &key); ~CryFile(); - cpputils::unique_ref open(int flags) const override; - void truncate(off_t size) const override; + cpputils::unique_ref open(int flags) override; + void truncate(off_t size) override; fspp::Dir::EntryType getType() const override; void remove() override; diff --git a/src/cryfs/filesystem/CryNode.cpp b/src/cryfs/filesystem/CryNode.cpp index 71e362b5..0d551bae 100644 --- a/src/cryfs/filesystem/CryNode.cpp +++ b/src/cryfs/filesystem/CryNode.cpp @@ -52,6 +52,11 @@ shared_ptr CryNode::parent() const { return *_parent; } +shared_ptr 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) { device()->callFsActionCallbacks(); if (_parent == none) { diff --git a/src/cryfs/filesystem/CryNode.h b/src/cryfs/filesystem/CryNode.h index 2b00cb39..1399d41b 100644 --- a/src/cryfs/filesystem/CryNode.h +++ b/src/cryfs/filesystem/CryNode.h @@ -29,6 +29,7 @@ protected: const CryDevice *device() const; cpputils::unique_ref LoadBlob() const; std::shared_ptr parent() const; + std::shared_ptr parent(); virtual fspp::Dir::EntryType getType() const = 0; diff --git a/src/cryfs/filesystem/CryOpenFile.cpp b/src/cryfs/filesystem/CryOpenFile.cpp index e0be9f08..8a03b2a8 100644 --- a/src/cryfs/filesystem/CryOpenFile.cpp +++ b/src/cryfs/filesystem/CryOpenFile.cpp @@ -19,7 +19,7 @@ using fspp::fuse::FuseErrnoException; namespace cryfs { -CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr parent, unique_ref fileBlob) +CryOpenFile::CryOpenFile(const CryDevice *device, shared_ptr parent, unique_ref 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 { _device->callFsActionCallbacks(); _fileBlob->resize(size); + _parent->updateModificationTimestampForChild(_fileBlob->key()); } size_t CryOpenFile::read(void *buf, size_t count, off_t offset) const { _device->callFsActionCallbacks(); + _parent->updateAccessTimestampForChild(_fileBlob->key()); return _fileBlob->read(buf, offset, count); } void CryOpenFile::write(const void *buf, size_t count, off_t offset) { _device->callFsActionCallbacks(); + _parent->updateModificationTimestampForChild(_fileBlob->key()); _fileBlob->write(buf, offset, count); } diff --git a/src/cryfs/filesystem/CryOpenFile.h b/src/cryfs/filesystem/CryOpenFile.h index b621e3be..b483f584 100644 --- a/src/cryfs/filesystem/CryOpenFile.h +++ b/src/cryfs/filesystem/CryOpenFile.h @@ -11,7 +11,7 @@ class CryDevice; class CryOpenFile final: public fspp::OpenFile { public: - explicit CryOpenFile(const CryDevice *device, std::shared_ptr parent, cpputils::unique_ref fileBlob); + explicit CryOpenFile(const CryDevice *device, std::shared_ptr parent, cpputils::unique_ref fileBlob); ~CryOpenFile(); void stat(struct ::stat *result) const override; @@ -24,7 +24,7 @@ public: private: const CryDevice *_device; - std::shared_ptr _parent; + std::shared_ptr _parent; cpputils::unique_ref _fileBlob; DISALLOW_COPY_AND_ASSIGN(CryOpenFile); diff --git a/src/cryfs/filesystem/cachingfsblobstore/DirBlobRef.h b/src/cryfs/filesystem/cachingfsblobstore/DirBlobRef.h index 7ef37f5f..b1efc983 100644 --- a/src/cryfs/filesystem/cachingfsblobstore/DirBlobRef.h +++ b/src/cryfs/filesystem/cachingfsblobstore/DirBlobRef.h @@ -60,6 +60,14 @@ public: 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) { return _base->chmodChild(key, mode); } diff --git a/src/cryfs/filesystem/fsblobstore/DirBlob.cpp b/src/cryfs/filesystem/fsblobstore/DirBlob.cpp index dc3a28da..194dd6fb 100644 --- a/src/cryfs/filesystem/fsblobstore/DirBlob.cpp +++ b/src/cryfs/filesystem/fsblobstore/DirBlob.cpp @@ -158,6 +158,16 @@ void DirBlob::statChildExceptSize(const Key &key, struct ::stat *result) const { result->st_blksize = _fsBlobStore->virtualBlocksizeBytes(); } +void DirBlob::updateAccessTimestampForChild(const Key &key) { + std::unique_lock lock(_mutex); + _entries.updateAccessTimestampForChild(key); +} + +void DirBlob::updateModificationTimestampForChild(const Key &key) { + std::unique_lock lock(_mutex); + _entries.updateModificationTimestampForChild(key); +} + void DirBlob::chmodChild(const Key &key, mode_t mode) { std::unique_lock lock(_mutex); _entries.setMode(key, mode); diff --git a/src/cryfs/filesystem/fsblobstore/DirBlob.h b/src/cryfs/filesystem/fsblobstore/DirBlob.h index 4875f197..0851f37d 100644 --- a/src/cryfs/filesystem/fsblobstore/DirBlob.h +++ b/src/cryfs/filesystem/fsblobstore/DirBlob.h @@ -59,6 +59,10 @@ namespace cryfs { 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 chownChild(const blockstore::Key &key, uid_t uid, gid_t gid); diff --git a/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.cpp b/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.cpp index 53025e01..8ca6f514 100644 --- a/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.cpp +++ b/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.cpp @@ -228,5 +228,15 @@ void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAcces 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()); +} + } } diff --git a/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.h b/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.h index c3cc32b3..8f3e98dc 100644 --- a/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.h +++ b/src/cryfs/filesystem/fsblobstore/utils/DirEntryList.h @@ -39,6 +39,8 @@ namespace cryfs { void setMode(const blockstore::Key &key, mode_t mode); bool setUidGid(const blockstore::Key &key, uid_t uid, gid_t gid); void setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime); + void updateAccessTimestampForChild(const blockstore::Key &key); + void updateModificationTimestampForChild(const blockstore::Key &key); private: uint64_t _serializedSize() const; diff --git a/src/cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h b/src/cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h index 9e596f93..46a42226 100644 --- a/src/cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h +++ b/src/cryfs/filesystem/parallelaccessfsblobstore/DirBlobRef.h @@ -56,6 +56,14 @@ public: 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) { return _base->chmodChild(key, mode); } diff --git a/src/fspp/fs_interface/File.h b/src/fspp/fs_interface/File.h index 74084303..7ca7551c 100644 --- a/src/fspp/fs_interface/File.h +++ b/src/fspp/fs_interface/File.h @@ -13,8 +13,8 @@ class File: public virtual Node { public: virtual ~File() {} - virtual cpputils::unique_ref open(int flags) const = 0; - virtual void truncate(off_t size) const = 0; + virtual cpputils::unique_ref open(int flags) = 0; + virtual void truncate(off_t size) = 0; }; } diff --git a/src/fspp/fstest/FsTest.h b/src/fspp/fstest/FsTest.h index fb9b5d9b..ee6900ad 100644 --- a/src/fspp/fstest/FsTest.h +++ b/src/fspp/fstest/FsTest.h @@ -9,9 +9,10 @@ #include "FsppSymlinkTest.h" #include "FsppNodeTest_Rename.h" #include "FsppNodeTest_Stat.h" -#include "FsppNodeTest_Timestamps.h" #include "FsppOpenFileTest.h" #include "FsppDeviceTest_Timestamps.h" +#include "FsppNodeTest_Timestamps.h" +#include "FsppOpenFileTest_Timestamps.h" #define FSPP_ADD_FILESYTEM_TESTS(FS_NAME, 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_SymlinkOnly, FIXTURE); \ INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest, FIXTURE); \ + INSTANTIATE_TYPED_TEST_CASE_P(FS_NAME, FsppOpenFileTest_Timestamps, FIXTURE); \ + #endif diff --git a/src/fspp/fstest/FsppFileTest.h b/src/fspp/fstest/FsppFileTest.h index 18b1f9b0..805ed6b3 100644 --- a/src/fspp/fstest/FsppFileTest.h +++ b/src/fspp/fstest/FsppFileTest.h @@ -24,54 +24,54 @@ public: void Test_Truncate_DontChange1(fspp::File *file) { file->truncate(0); - this->EXPECT_SIZE(0, *file); + this->EXPECT_SIZE(0, file); } void Test_Truncate_GrowTo1(fspp::File *file) { file->truncate(1); - this->EXPECT_SIZE(1, *file); + this->EXPECT_SIZE(1, file); } void Test_Truncate_Grow(fspp::File *file) { 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) { 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) { file->truncate(10*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) { file->truncate(10*1024*1024); file->truncate(0); - this->EXPECT_SIZE(0, *file); + this->EXPECT_SIZE(0, file); } void Test_Chown_Uid(fspp::File *file) { file->chown(100, 200); - this->IN_STAT(*file, [] (struct stat st){ + this->IN_STAT(file, [] (struct stat st){ EXPECT_EQ(100u, st.st_uid); }); } void Test_Chown_Gid(fspp::File *file) { file->chown(100, 200); - this->IN_STAT(*file, [] (struct stat st){ + this->IN_STAT(file, [] (struct stat st){ EXPECT_EQ(200u, st.st_gid); }); } void Test_Chmod(fspp::File *file) { 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); }); } @@ -80,7 +80,7 @@ public: struct timespec ATIME; ATIME.tv_sec = 1458086400; ATIME.tv_nsec = 34525; struct timespec MTIME; MTIME.tv_sec = 1458086300; MTIME.tv_nsec = 48293; 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_MTIME_EQ(MTIME, st); }); diff --git a/src/fspp/fstest/FsppNodeTest_Stat.h b/src/fspp/fstest/FsppNodeTest_Stat.h index e31996ef..0f82d209 100644 --- a/src/fspp/fstest/FsppNodeTest_Stat.h +++ b/src/fspp/fstest/FsppNodeTest_Stat.h @@ -10,7 +10,7 @@ class FsppNodeTest_Stat: public FsppNodeTest { public: void Test_Nlink() { 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); }); } @@ -24,12 +24,12 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_FileOnly); TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, CreatedFileIsEmpty) { auto file = this->CreateFile("/myfile"); - this->EXPECT_SIZE(0, *file); + this->EXPECT_SIZE(0, file.get()); } TYPED_TEST_P(FsppNodeTest_Stat_FileOnly, FileIsFile) { 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)); }); } @@ -42,7 +42,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_DirOnly); TYPED_TEST_P(FsppNodeTest_Stat_DirOnly, DirIsDir) { 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)); }); } @@ -55,7 +55,7 @@ TYPED_TEST_CASE_P(FsppNodeTest_Stat_SymlinkOnly); TYPED_TEST_P(FsppNodeTest_Stat_SymlinkOnly, SymlinkIsSymlink) { 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)); }); } diff --git a/src/fspp/fstest/FsppOpenFileTest_Timestamps.h b/src/fspp/fstest/FsppOpenFileTest_Timestamps.h new file mode 100644 index 00000000..02b4ef52 --- /dev/null +++ b/src/fspp/fstest/FsppOpenFileTest_Timestamps.h @@ -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 FsppOpenFileTest_Timestamps: public FileSystemTest, public TimestampTestUtils { +public: + cpputils::unique_ref CreateAndOpenFile(const boost::filesystem::path &path) { + return this->CreateFile(path)->open(O_RDWR); + } + cpputils::unique_ref 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 diff --git a/src/fspp/fstest/testutils/FileTest.h b/src/fspp/fstest/testutils/FileTest.h index 64119295..c0f282e4 100644 --- a/src/fspp/fstest/testutils/FileTest.h +++ b/src/fspp/fstest/testutils/FileTest.h @@ -24,15 +24,15 @@ public: std::unique_ptr file_nested; //TODO IN_STAT still needed after moving it to FsppNodeTest? - void IN_STAT(const fspp::File &file, std::function callback) { + void IN_STAT(fspp::File *file, std::function callback) { struct stat st1, st2; - file.stat(&st1); + file->stat(&st1); callback(st1); - file.open(O_RDONLY)->stat(&st2); + file->open(O_RDONLY)->stat(&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) { EXPECT_EQ(expectedSize, (uint64_t)st.st_size); }); @@ -40,8 +40,8 @@ public: EXPECT_NUMBYTES_READABLE(expectedSize, file); } - void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) { - auto openFile = file.open(O_RDONLY); + void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) { + auto openFile = file->open(O_RDONLY); cpputils::Data data(expectedSize); //Try to read one byte more than the expected size ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0); diff --git a/src/fspp/fstest/testutils/FsppNodeTest.h b/src/fspp/fstest/testutils/FsppNodeTest.h index ff731f10..cc1c764b 100644 --- a/src/fspp/fstest/testutils/FsppNodeTest.h +++ b/src/fspp/fstest/testutils/FsppNodeTest.h @@ -9,8 +9,8 @@ class FsppNodeTestBase { public: - virtual void IN_STAT(const fspp::Node &node, std::function callback) = 0; - virtual void EXPECT_SIZE(uint64_t expectedSize, const fspp::Node &node) = 0; + virtual void IN_STAT(fspp::Node *node, std::function callback) = 0; + virtual void EXPECT_SIZE(uint64_t expectedSize, fspp::Node *node) = 0; }; /** @@ -29,24 +29,24 @@ public: class FsppNodeTest_File_Helper: public virtual FsppNodeTestBase { public: - void IN_STAT(const fspp::Node &file, std::function callback) override { + void IN_STAT(fspp::Node *file, std::function callback) override { struct stat st1, st2; - file.stat(&st1); + file->stat(&st1); callback(st1); - dynamic_cast(file).open(O_RDONLY)->stat(&st2); + dynamic_cast(*file).open(O_RDONLY)->stat(&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) { EXPECT_EQ(expectedSize, (uint64_t)st.st_size); }); - EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast(node)); + EXPECT_NUMBYTES_READABLE(expectedSize, dynamic_cast(node)); } - void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, const fspp::File &file) { - auto openFile = file.open(O_RDONLY); + void EXPECT_NUMBYTES_READABLE(uint64_t expectedSize, fspp::File *file) { + auto openFile = file->open(O_RDONLY); cpputils::Data data(expectedSize); //Try to read one byte more than the expected size ssize_t readBytes = openFile->read(data.data(), expectedSize+1, 0); @@ -57,13 +57,13 @@ public: class FsppNodeTest_Dir_Helper: public virtual FsppNodeTestBase { public: - void IN_STAT(const fspp::Node &file, std::function callback) override { + void IN_STAT(fspp::Node *file, std::function callback) override { struct stat st; - file.stat(&st); + file->stat(&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) { EXPECT_EQ(expectedSize, (uint64_t)st.st_size); }); @@ -72,13 +72,13 @@ public: class FsppNodeTest_Symlink_Helper: public virtual FsppNodeTestBase { public: - void IN_STAT(const fspp::Node &file, std::function callback) override { + void IN_STAT(fspp::Node *file, std::function callback) override { struct stat st; - file.stat(&st); + file->stat(&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) { EXPECT_EQ(expectedSize, (uint64_t)st.st_size); }); diff --git a/src/fspp/impl/FilesystemImpl.cpp b/src/fspp/impl/FilesystemImpl.cpp index 1be269de..d9bff72f 100644 --- a/src/fspp/impl/FilesystemImpl.cpp +++ b/src/fspp/impl/FilesystemImpl.cpp @@ -151,12 +151,12 @@ unique_ref FilesystemImpl::LoadFileOrSymlink(const bf::path &path) { int FilesystemImpl::openFile(const bf::path &path, int flags) { 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); - return _open_files.open(file.open(flags)); + return _open_files.open(file->open(flags)); } void FilesystemImpl::flush(int descriptor) { diff --git a/src/fspp/impl/FilesystemImpl.h b/src/fspp/impl/FilesystemImpl.h index 8af1fab1..f0e21be6 100644 --- a/src/fspp/impl/FilesystemImpl.h +++ b/src/fspp/impl/FilesystemImpl.h @@ -54,7 +54,7 @@ private: cpputils::unique_ref LoadDir(const boost::filesystem::path &path); cpputils::unique_ref LoadSymlink(const boost::filesystem::path &path); cpputils::unique_ref LoadFileOrSymlink(const boost::filesystem::path &path); - int openFile(const File &file, int flags); + int openFile(File *file, int flags); #ifdef FSPP_PROFILE std::atomic _loadFileNanosec;