Refactor DirEntries

This commit is contained in:
Sebastian Messmer 2016-03-15 21:06:12 +00:00
parent 5f8bf4cea4
commit 52d85f4de3
12 changed files with 257 additions and 128 deletions

View File

@ -82,15 +82,15 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
} }
const auto &entry = *optEntry; const auto &entry = *optEntry;
if (entry.type == fspp::Dir::EntryType::DIR) { switch(entry.type()) {
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), entry.key)); case fspp::Dir::EntryType::DIR:
} else if (entry.type == fspp::Dir::EntryType::FILE) { return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, std::move(parent), entry.key()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), entry.key)); case fspp::Dir::EntryType::FILE:
} else if (entry.type == fspp::Dir::EntryType::SYMLINK) { return optional<unique_ref<fspp::Node>>(make_unique_ref<CryFile>(this, std::move(parent), entry.key()));
return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), entry.key)); case fspp::Dir::EntryType::SYMLINK:
} else { return optional<unique_ref<fspp::Node>>(make_unique_ref<CrySymlink>(this, std::move(parent), entry.key()));
ASSERT(false, "Unknown entry type");
} }
ASSERT(false, "Switch/case not exhaustive");
} }
unique_ref<DirBlobRef> CryDevice::LoadDirBlob(const bf::path &path) { unique_ref<DirBlobRef> CryDevice::LoadDirBlob(const bf::path &path) {
@ -119,7 +119,7 @@ unique_ref<FsBlobRef> CryDevice::LoadBlob(const bf::path &path) {
if (childOpt == boost::none) { if (childOpt == boost::none) {
throw FuseErrnoException(ENOENT); // Child entry in directory not found throw FuseErrnoException(ENOENT); // Child entry in directory not found
} }
Key childKey = childOpt->key; Key childKey = childOpt->key();
currentBlob = _fsBlobStore->load(childKey); currentBlob = _fsBlobStore->load(childKey);
if (currentBlob == none) { if (currentBlob == none) {
throw FuseErrnoException(ENOENT); // Blob for directory entry not found throw FuseErrnoException(ENOENT); // Blob for directory entry not found

View File

@ -9,6 +9,7 @@
#include "CryDevice.h" #include "CryDevice.h"
#include "CryFile.h" #include "CryFile.h"
#include "CryOpenFile.h" #include "CryOpenFile.h"
#include "fsblobstore/utils/time.h"
//TODO Get rid of this in favor of exception hierarchy //TODO Get rid of this in favor of exception hierarchy
using fspp::fuse::CHECK_RETVAL; using fspp::fuse::CHECK_RETVAL;
@ -39,7 +40,8 @@ CryDir::~CryDir() {
unique_ref<fspp::OpenFile> CryDir::createAndOpenFile(const string &name, mode_t mode, uid_t uid, gid_t gid) { unique_ref<fspp::OpenFile> CryDir::createAndOpenFile(const string &name, mode_t mode, uid_t uid, gid_t gid) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
auto child = device()->CreateFileBlob(); auto child = device()->CreateFileBlob();
LoadBlob()->AddChildFile(name, child->key(), mode, uid, gid); auto now = fsblobstore::time::now();
LoadBlob()->AddChildFile(name, child->key(), mode, uid, gid, now, now);
return make_unique_ref<CryOpenFile>(device(), std::move(child)); return make_unique_ref<CryOpenFile>(device(), std::move(child));
} }
@ -47,7 +49,8 @@ void CryDir::createDir(const string &name, mode_t mode, uid_t uid, gid_t gid) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
auto blob = LoadBlob(); auto blob = LoadBlob();
auto child = device()->CreateDirBlob(); auto child = device()->CreateDirBlob();
blob->AddChildDir(name, child->key(), mode, uid, gid); auto now = fsblobstore::time::now();
blob->AddChildDir(name, child->key(), mode, uid, gid, now, now);
} }
unique_ref<DirBlobRef> CryDir::LoadBlob() const { unique_ref<DirBlobRef> CryDir::LoadBlob() const {
@ -76,7 +79,8 @@ void CryDir::createSymlink(const string &name, const bf::path &target, uid_t uid
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
auto blob = LoadBlob(); auto blob = LoadBlob();
auto child = device()->CreateSymlinkBlob(target); auto child = device()->CreateSymlinkBlob(target);
blob->AddChildSymlink(name, child->key(), uid, gid); auto now = fsblobstore::time::now();
blob->AddChildSymlink(name, child->key(), uid, gid, now, now);
} }
void CryDir::remove() { void CryDir::remove() {

View File

@ -56,13 +56,15 @@ void CryNode::rename(const bf::path &to) {
throw FuseErrnoException(ENOENT); throw FuseErrnoException(ENOENT);
} }
const auto &old = *optOld; const auto &old = *optOld;
auto mode = old.mode; auto mode = old.mode();
auto uid = old.uid; auto uid = old.uid();
auto gid = old.gid; auto gid = old.gid();
auto lastAccessTime = old.lastAccessTime();
auto lastModificationTime = old.lastModificationTime();
(*_parent)->RemoveChild(_key); (*_parent)->RemoveChild(_key);
(*_parent)->flush(); (*_parent)->flush();
auto targetDir = _device->LoadDirBlob(to.parent_path()); auto targetDir = _device->LoadDirBlob(to.parent_path());
targetDir->AddChild(to.filename().native(), _key, getType(), mode, uid, gid); targetDir->AddChild(to.filename().native(), _key, getType(), mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) { void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) {

View File

@ -39,8 +39,8 @@ public:
} }
void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type, void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
mode_t mode, uid_t uid, gid_t gid) { mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChild(name, blobKey, type, mode, uid, gid); return _base->AddChild(name, blobKey, type, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void statChild(const blockstore::Key &key, struct ::stat *result) const { void statChild(const blockstore::Key &key, struct ::stat *result) const {
@ -59,16 +59,16 @@ public:
return _base->utimensChild(key, lastAccessTime, lastModificationTime); return _base->utimensChild(key, lastAccessTime, lastModificationTime);
} }
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildDir(name, blobKey, mode, uid, gid); return _base->AddChildDir(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildFile(name, blobKey, mode, uid, gid); return _base->AddChildFile(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid) { void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildSymlink(name, blobKey, uid, gid); return _base->AddChildSymlink(name, blobKey, uid, gid, lastAccessTime, lastModificationTime);
} }
void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const { void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const {

View File

@ -64,22 +64,22 @@ void DirBlob::_readEntriesFromBlob() {
_entries.deserializeFrom(static_cast<uint8_t*>(data.data()), data.size()); _entries.deserializeFrom(static_cast<uint8_t*>(data.data()), data.size());
} }
void DirBlob::AddChildDir(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void DirBlob::AddChildDir(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
AddChild(name, blobKey, fspp::Dir::EntryType::DIR, mode, uid, gid); AddChild(name, blobKey, fspp::Dir::EntryType::DIR, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void DirBlob::AddChildFile(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void DirBlob::AddChildFile(const std::string &name, const Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
AddChild(name, blobKey, fspp::Dir::EntryType::FILE, mode, uid, gid); AddChild(name, blobKey, fspp::Dir::EntryType::FILE, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void DirBlob::AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid) { void DirBlob::AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
AddChild(name, blobKey, fspp::Dir::EntryType::SYMLINK, S_IFLNK | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH, uid, gid); AddChild(name, blobKey, fspp::Dir::EntryType::SYMLINK, S_IFLNK | S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH, uid, gid, lastAccessTime, lastModificationTime);
} }
void DirBlob::AddChild(const std::string &name, const Key &blobKey, void DirBlob::AddChild(const std::string &name, const Key &blobKey,
fspp::Dir::EntryType entryType, mode_t mode, uid_t uid, gid_t gid) { fspp::Dir::EntryType entryType, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
std::unique_lock<std::mutex> lock(_mutex); std::unique_lock<std::mutex> lock(_mutex);
_entries.add(name, blobKey, entryType, mode, uid, gid); _entries.add(name, blobKey, entryType, mode, uid, gid, lastAccessTime, lastModificationTime);
_changed = true; _changed = true;
} }
@ -103,7 +103,7 @@ void DirBlob::AppendChildrenTo(vector<fspp::Dir::Entry> *result) const {
std::unique_lock<std::mutex> lock(_mutex); std::unique_lock<std::mutex> lock(_mutex);
result->reserve(result->size() + _entries.size()); result->reserve(result->size() + _entries.size());
for (const auto &entry : _entries) { for (const auto &entry : _entries) {
result->emplace_back(entry.type, entry.name); result->emplace_back(entry.type(), entry.name());
} }
} }
@ -119,19 +119,19 @@ void DirBlob::statChild(const Key &key, struct ::stat *result) const {
const auto &child = *childOpt; const auto &child = *childOpt;
//TODO Loading the blob for only getting the size of the file/symlink is not very performant. //TODO Loading the blob for only getting the size of the file/symlink is not very performant.
// Furthermore, this is the only reason why DirBlob needs a pointer to _fsBlobStore, which is ugly // Furthermore, this is the only reason why DirBlob needs a pointer to _fsBlobStore, which is ugly
result->st_mode = child.mode; result->st_mode = child.mode();
result->st_uid = child.uid; result->st_uid = child.uid();
result->st_gid = child.gid; result->st_gid = child.gid();
//TODO If possible without performance loss, then for a directory, st_nlink should return number of dir entries (including "." and "..") //TODO If possible without performance loss, then for a directory, st_nlink should return number of dir entries (including "." and "..")
result->st_nlink = 1; result->st_nlink = 1;
#ifdef __APPLE__ #ifdef __APPLE__
result->st_atimespec = child.lastAccessTime; result->st_atimespec = child.lastAccessTime();
result->st_mtimespec = child.lastModificationTime; result->st_mtimespec = child.lastModificationTime();
result->st_ctimespec = child.lastMetadataChangeTime; result->st_ctimespec = child.lastMetadataChangeTime();
#else #else
result->st_atim = child.lastAccessTime; result->st_atim = child.lastAccessTime();
result->st_mtim = child.lastModificationTime; result->st_mtim = child.lastModificationTime();
result->st_ctim = child.lastMetadataChangeTime; result->st_ctim = child.lastMetadataChangeTime();
#endif #endif
result->st_size = _getLstatSize(key); result->st_size = _getLstatSize(key);
//TODO Move ceilDivision to general utils which can be used by cryfs as well //TODO Move ceilDivision to general utils which can be used by cryfs as well

View File

@ -36,16 +36,15 @@ namespace cryfs {
boost::optional<const DirEntry&> GetChild(const blockstore::Key &key) const; boost::optional<const DirEntry&> GetChild(const blockstore::Key &key) const;
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
gid_t gid); gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid,
gid_t gid); gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid); void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type, void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
mode_t mode, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
uid_t uid, gid_t gid);
void RemoveChild(const blockstore::Key &key); void RemoveChild(const blockstore::Key &key);

View File

@ -8,21 +8,22 @@ namespace cryfs {
namespace fsblobstore { namespace fsblobstore {
void DirEntry::serialize(uint8_t *dest) const { void DirEntry::serialize(uint8_t *dest) const {
ASSERT( ASSERT(
((type == fspp::Dir::EntryType::FILE) && S_ISREG(mode) && !S_ISDIR(mode) && !S_ISLNK(mode)) || ((_type == fspp::Dir::EntryType::FILE) && S_ISREG(_mode) && !S_ISDIR(_mode) && !S_ISLNK(_mode)) ||
((type == fspp::Dir::EntryType::DIR) && !S_ISREG(mode) && S_ISDIR(mode) && !S_ISLNK(mode)) || ((_type == fspp::Dir::EntryType::DIR) && !S_ISREG(_mode) && S_ISDIR(_mode) && !S_ISLNK(_mode)) ||
((type == fspp::Dir::EntryType::SYMLINK) && !S_ISREG(mode) && !S_ISDIR(mode) && S_ISLNK(mode)) ((_type == fspp::Dir::EntryType::SYMLINK) && !S_ISREG(_mode) && !S_ISDIR(_mode) && S_ISLNK(_mode))
, "Wrong mode bit set for this type: "+std::to_string(mode & S_IFREG)+", "+std::to_string(mode&S_IFDIR)+", "+std::to_string(mode&S_IFLNK)+", "+std::to_string(static_cast<uint8_t>(type)) , "Wrong mode bit set for this type: " + std::to_string(_mode & S_IFREG) + ", " + std::to_string(
_mode & S_IFDIR) + ", " + std::to_string(_mode & S_IFLNK) + ", " + std::to_string(static_cast<uint8_t>(_type))
); );
unsigned int offset = 0; unsigned int offset = 0;
offset += _serializeUint8(dest + offset, static_cast<uint8_t>(type)); offset += _serializeUint8(dest + offset, static_cast<uint8_t>(_type));
offset += _serializeUint32(dest + offset, mode); offset += _serializeUint32(dest + offset, _mode);
offset += _serializeUint32(dest + offset, uid); offset += _serializeUint32(dest + offset, _uid);
offset += _serializeUint32(dest + offset, gid); offset += _serializeUint32(dest + offset, _gid);
offset += _serializeTimeValue(dest + offset, lastAccessTime); offset += _serializeTimeValue(dest + offset, _lastAccessTime);
offset += _serializeTimeValue(dest + offset, lastModificationTime); offset += _serializeTimeValue(dest + offset, _lastModificationTime);
offset += _serializeTimeValue(dest + offset, lastMetadataChangeTime); offset += _serializeTimeValue(dest + offset, _lastMetadataChangeTime);
offset += _serializeString(dest + offset, name); offset += _serializeString(dest + offset, _name);
offset += _serializeKey(dest + offset, key); offset += _serializeKey(dest + offset, _key);
ASSERT(offset == serializedSize(), "Didn't write correct number of elements"); ASSERT(offset == serializedSize(), "Didn't write correct number of elements");
} }
@ -110,7 +111,8 @@ namespace cryfs {
} }
size_t DirEntry::serializedSize() const { size_t DirEntry::serializedSize() const {
return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (name.size() + 1) + key.BINARY_LENGTH; return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + (
_name.size() + 1) + _key.BINARY_LENGTH;
} }
} }
} }

View File

@ -4,36 +4,48 @@
#include <blockstore/utils/Key.h> #include <blockstore/utils/Key.h>
#include <fspp/fs_interface/Dir.h> #include <fspp/fs_interface/Dir.h>
#include "time.h"
namespace cryfs { namespace cryfs {
namespace fsblobstore { namespace fsblobstore {
struct DirEntry final { class DirEntry final {
DirEntry(fspp::Dir::EntryType type_, const std::string &name_, const blockstore::Key &key_, mode_t mode_, public:
uid_t uid_, gid_t gid_, timespec lastAccessTime_, timespec lastModificationTime_, DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::Key &key, mode_t mode,
timespec lastMetadataChangeTime_) : type(type_), name(name_), key(key_), mode(mode_), uid(uid_), uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
gid(gid_), lastAccessTime(lastAccessTime_), timespec lastMetadataChangeTime);
lastModificationTime(lastModificationTime_),
lastMetadataChangeTime(lastMetadataChangeTime_) {
switch (type) {
case fspp::Dir::EntryType::FILE:
mode |= S_IFREG;
break;
case fspp::Dir::EntryType::DIR:
mode |= S_IFDIR;
break;
case fspp::Dir::EntryType::SYMLINK:
mode |= S_IFLNK;
break;
}
ASSERT((S_ISREG(mode) && type == fspp::Dir::EntryType::FILE) ||
(S_ISDIR(mode) && type == fspp::Dir::EntryType::DIR) ||
(S_ISLNK(mode) && type == fspp::Dir::EntryType::SYMLINK), "Unknown mode in entry");
}
void serialize(uint8_t* dest) const; void serialize(uint8_t* dest) const;
size_t serializedSize() const; size_t serializedSize() const;
static const char *deserializeAndAddToVector(const char *pos, std::vector<DirEntry> *result); static const char *deserializeAndAddToVector(const char *pos, std::vector<DirEntry> *result);
fspp::Dir::EntryType type() const;
void setType(fspp::Dir::EntryType value);
const std::string &name() const;
void setName(const std::string &value);
const blockstore::Key &key() const;
mode_t mode() const;
void setMode(mode_t value);
uid_t uid() const;
void setUid(uid_t value);
gid_t gid() const;
void setGid(gid_t value);
timespec lastAccessTime() const;
void setLastAccessTime(timespec value);
timespec lastModificationTime() const;
void setLastModificationTime(timespec value);
timespec lastMetadataChangeTime() const;
void setLastMetadataChangeTime(timespec value);
private:
static size_t _serializedTimeValueSize(); static size_t _serializedTimeValueSize();
static unsigned int _serializeTimeValue(uint8_t *dest, timespec value); static unsigned int _serializeTimeValue(uint8_t *dest, timespec value);
static unsigned int _serializeUint8(uint8_t *dest, uint8_t value); static unsigned int _serializeUint8(uint8_t *dest, uint8_t value);
@ -46,17 +58,117 @@ namespace cryfs {
static std::string _deserializeString(const char **pos); static std::string _deserializeString(const char **pos);
static blockstore::Key _deserializeKey(const char **pos); static blockstore::Key _deserializeKey(const char **pos);
fspp::Dir::EntryType type; void _updateLastMetadataChangeTime();
std::string name;
blockstore::Key key; fspp::Dir::EntryType _type;
mode_t mode; std::string _name;
uid_t uid; blockstore::Key _key;
gid_t gid; mode_t _mode;
struct timespec lastAccessTime; uid_t _uid;
struct timespec lastModificationTime; gid_t _gid;
struct timespec lastMetadataChangeTime; timespec _lastAccessTime;
timespec _lastModificationTime;
timespec _lastMetadataChangeTime;
}; };
inline DirEntry::DirEntry(fspp::Dir::EntryType type, const std::string &name, const blockstore::Key &key, mode_t mode,
uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime,
timespec lastMetadataChangeTime)
: _type(type), _name(name), _key(key), _mode(mode), _uid(uid), _gid(gid), _lastAccessTime(lastAccessTime),
_lastModificationTime(lastModificationTime), _lastMetadataChangeTime(lastMetadataChangeTime) {
switch (_type) {
case fspp::Dir::EntryType::FILE:
_mode |= S_IFREG;
break;
case fspp::Dir::EntryType::DIR:
_mode |= S_IFDIR;
break;
case fspp::Dir::EntryType::SYMLINK:
_mode |= S_IFLNK;
break;
}
ASSERT((S_ISREG(_mode) && _type == fspp::Dir::EntryType::FILE) ||
(S_ISDIR(_mode) && _type == fspp::Dir::EntryType::DIR) ||
(S_ISLNK(_mode) && _type == fspp::Dir::EntryType::SYMLINK), "Unknown mode in entry");
}
inline fspp::Dir::EntryType DirEntry::type() const {
return _type;
}
inline const std::string &DirEntry::name() const {
return _name;
}
inline const blockstore::Key &DirEntry::key() const {
return _key;
}
inline mode_t DirEntry::mode() const {
return _mode;
}
inline uid_t DirEntry::uid() const {
return _uid;
}
inline gid_t DirEntry::gid() const {
return _gid;
}
inline timespec DirEntry::lastAccessTime() const {
return _lastAccessTime;
}
inline timespec DirEntry::lastModificationTime() const {
return _lastModificationTime;
}
inline timespec DirEntry::lastMetadataChangeTime() const {
return _lastMetadataChangeTime;
}
inline void DirEntry::setType(fspp::Dir::EntryType value) {
_type = value;
_updateLastMetadataChangeTime();
}
inline void DirEntry::setName(const std::string &value) {
_name = value;
_updateLastMetadataChangeTime();
}
inline void DirEntry::setMode(mode_t value) {
_mode = value;
_updateLastMetadataChangeTime();
}
inline void DirEntry::setUid(uid_t value) {
_uid = value;
_updateLastMetadataChangeTime();
}
inline void DirEntry::setGid(gid_t value) {
_gid = value;
_updateLastMetadataChangeTime();
}
inline void DirEntry::setLastAccessTime(timespec value) {
_lastAccessTime = value;
}
inline void DirEntry::setLastModificationTime(timespec value) {
_lastModificationTime = value;
}
inline void DirEntry::setLastMetadataChangeTime(timespec value) {
_lastMetadataChangeTime = value;
}
inline void DirEntry::_updateLastMetadataChangeTime() {
setLastMetadataChangeTime(time::now());
}
} }
} }

View File

@ -1,6 +1,6 @@
#include "DirEntryList.h" #include "DirEntryList.h"
#include <limits> #include <limits>
#include <cpp-utils/system/clock_gettime.h> #include "time.h"
//TODO Get rid of that in favor of better error handling //TODO Get rid of that in favor of better error handling
#include <fspp/fuse/FuseErrnoException.h> #include <fspp/fuse/FuseErrnoException.h>
@ -44,24 +44,23 @@ void DirEntryList::deserializeFrom(const void *data, uint64_t size) {
bool DirEntryList::_hasChild(const string &name) const { bool DirEntryList::_hasChild(const string &name) const {
auto found = std::find_if(_entries.begin(), _entries.end(), [&name] (const DirEntry &entry) { auto found = std::find_if(_entries.begin(), _entries.end(), [&name] (const DirEntry &entry) {
return entry.name == name; return entry.name() == name;
}); });
return found != _entries.end(); return found != _entries.end();
} }
void DirEntryList::add(const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode, void DirEntryList::add(const string &name, const Key &blobKey, fspp::Dir::EntryType entryType, mode_t mode,
uid_t uid, gid_t gid) { uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
if (_hasChild(name)) { if (_hasChild(name)) {
throw fspp::fuse::FuseErrnoException(EEXIST); throw fspp::fuse::FuseErrnoException(EEXIST);
} }
auto insert_pos = _findUpperBound(blobKey); auto insert_pos = _findUpperBound(blobKey);
auto now = _now(); _entries.emplace(insert_pos, entryType, name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime, time::now());
_entries.emplace(insert_pos, entryType, name, blobKey, mode, uid, gid, now, now, now);
} }
boost::optional<const DirEntry&> DirEntryList::get(const string &name) const { boost::optional<const DirEntry&> DirEntryList::get(const string &name) const {
auto found = std::find_if(_entries.begin(), _entries.end(), [&name] (const DirEntry &entry) { auto found = std::find_if(_entries.begin(), _entries.end(), [&name] (const DirEntry &entry) {
return entry.name == name; return entry.name() == name;
}); });
if (found == _entries.end()) { if (found == _entries.end()) {
return boost::none; return boost::none;
@ -84,7 +83,7 @@ void DirEntryList::remove(const Key &key) {
vector<DirEntry>::iterator DirEntryList::_find(const Key &key) { vector<DirEntry>::iterator DirEntryList::_find(const Key &key) {
auto found = _findLowerBound(key); auto found = _findLowerBound(key);
if (found == _entries.end() || found->key != key) { if (found == _entries.end() || found->key() != key) {
throw fspp::fuse::FuseErrnoException(ENOENT); throw fspp::fuse::FuseErrnoException(ENOENT);
} }
return found; return found;
@ -92,13 +91,13 @@ vector<DirEntry>::iterator DirEntryList::_find(const Key &key) {
vector<DirEntry>::iterator DirEntryList::_findLowerBound(const Key &key) { vector<DirEntry>::iterator DirEntryList::_findLowerBound(const Key &key) {
return _findFirst(key, [&key] (const DirEntry &entry) { return _findFirst(key, [&key] (const DirEntry &entry) {
return !std::less<Key>()(entry.key, key); return !std::less<Key>()(entry.key(), key);
}); });
} }
vector<DirEntry>::iterator DirEntryList::_findUpperBound(const Key &key) { vector<DirEntry>::iterator DirEntryList::_findUpperBound(const Key &key) {
return _findFirst(key, [&key] (const DirEntry &entry) { return _findFirst(key, [&key] (const DirEntry &entry) {
return std::less<Key>()(key, entry.key); return std::less<Key>()(key, entry.key());
}); });
} }
@ -137,38 +136,28 @@ DirEntryList::const_iterator DirEntryList::end() const {
void DirEntryList::setMode(const Key &key, mode_t mode) { void DirEntryList::setMode(const Key &key, mode_t mode) {
auto found = _find(key); auto found = _find(key);
ASSERT ((S_ISREG(mode) && S_ISREG(found->mode)) || (S_ISDIR(mode) && S_ISDIR(found->mode)) || (S_ISLNK(mode)), "Unknown mode in entry"); ASSERT ((S_ISREG(mode) && S_ISREG(found->mode())) || (S_ISDIR(mode) && S_ISDIR(found->mode())) || (S_ISLNK(mode)), "Unknown mode in entry");
found->mode = mode; found->setMode(mode);
found->lastMetadataChangeTime = _now();
} }
bool DirEntryList::setUidGid(const Key &key, uid_t uid, gid_t gid) { bool DirEntryList::setUidGid(const Key &key, uid_t uid, gid_t gid) {
auto found = _find(key); auto found = _find(key);
bool changed = false; bool changed = false;
if (uid != (uid_t)-1) { if (uid != (uid_t)-1) {
found->uid = uid; found->setUid(uid);
found->lastMetadataChangeTime = _now();
changed = true; changed = true;
} }
if (gid != (gid_t)-1) { if (gid != (gid_t)-1) {
found->gid = gid; found->setGid(gid);
found->lastMetadataChangeTime = _now();
changed = true; changed = true;
} }
return changed; return changed;
} }
timespec DirEntryList::_now() {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now;
}
void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime) { void DirEntryList::setAccessTimes(const blockstore::Key &key, timespec lastAccessTime, timespec lastModificationTime) {
auto found = _find(key); auto found = _find(key);
found->lastAccessTime = lastAccessTime; found->setLastAccessTime(lastAccessTime);
found->lastModificationTime = lastModificationTime; found->setLastModificationTime(lastModificationTime);
found->lastMetadataChangeTime = lastModificationTime;
} }
} }

View File

@ -20,7 +20,7 @@ namespace cryfs {
void deserializeFrom(const void *data, uint64_t size); void deserializeFrom(const void *data, uint64_t size);
void add(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType entryType, void add(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType entryType,
mode_t mode, uid_t uid, gid_t gid); mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime);
boost::optional<const DirEntry&> get(const std::string &name) const; boost::optional<const DirEntry&> get(const std::string &name) const;
boost::optional<const DirEntry&> get(const blockstore::Key &key) const; boost::optional<const DirEntry&> get(const blockstore::Key &key) const;
void remove(const blockstore::Key &key); void remove(const blockstore::Key &key);
@ -41,7 +41,6 @@ namespace cryfs {
std::vector<DirEntry>::iterator _findUpperBound(const blockstore::Key &key); std::vector<DirEntry>::iterator _findUpperBound(const blockstore::Key &key);
std::vector<DirEntry>::iterator _findLowerBound(const blockstore::Key &key); std::vector<DirEntry>::iterator _findLowerBound(const blockstore::Key &key);
std::vector<DirEntry>::iterator _findFirst(const blockstore::Key &hint, std::function<bool (const DirEntry&)> pred); std::vector<DirEntry>::iterator _findFirst(const blockstore::Key &hint, std::function<bool (const DirEntry&)> pred);
static timespec _now();
std::vector<DirEntry> _entries; std::vector<DirEntry> _entries;

View File

@ -0,0 +1,22 @@
#pragma once
#ifndef MESSMER_CRYFS_FILESYTEM_FSBLOBSTORE_UTILS_TIME_H
#define MESSMER_CRYFS_FILESYTEM_FSBLOBSTORE_UTILS_TIME_H
#include <sys/types.h>
#include <cpp-utils/system/clock_gettime.h>
namespace cryfs {
namespace fsblobstore {
namespace time {
inline timespec now() {
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);
return now;
}
}
}
}
#endif

View File

@ -35,8 +35,8 @@ public:
} }
void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type, void AddChild(const std::string &name, const blockstore::Key &blobKey, fspp::Dir::EntryType type,
mode_t mode, uid_t uid, gid_t gid) { mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChild(name, blobKey, type, mode, uid, gid); return _base->AddChild(name, blobKey, type, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void statChild(const blockstore::Key &key, struct ::stat *result) const { void statChild(const blockstore::Key &key, struct ::stat *result) const {
@ -55,16 +55,16 @@ public:
return _base->utimensChild(key, lastAccessTime, lastModificationTime); return _base->utimensChild(key, lastAccessTime, lastModificationTime);
} }
void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void AddChildDir(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildDir(name, blobKey, mode, uid, gid); return _base->AddChildDir(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid) { void AddChildFile(const std::string &name, const blockstore::Key &blobKey, mode_t mode, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildFile(name, blobKey, mode, uid, gid); return _base->AddChildFile(name, blobKey, mode, uid, gid, lastAccessTime, lastModificationTime);
} }
void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid) { void AddChildSymlink(const std::string &name, const blockstore::Key &blobKey, uid_t uid, gid_t gid, timespec lastAccessTime, timespec lastModificationTime) {
return _base->AddChildSymlink(name, blobKey, uid, gid); return _base->AddChildSymlink(name, blobKey, uid, gid, lastAccessTime, lastModificationTime);
} }
void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const { void AppendChildrenTo(std::vector<fspp::Dir::Entry> *result) const {