Refactor DirEntries
This commit is contained in:
parent
5f8bf4cea4
commit
52d85f4de3
@ -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
|
||||||
|
@ -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() {
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
22
src/cryfs/filesystem/fsblobstore/utils/time.h
Normal file
22
src/cryfs/filesystem/fsblobstore/utils/time.h
Normal 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
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user