#include #include "DirEntry.h" #include using std::vector; using std::string; using blockstore::BlockId; namespace cryfs { namespace fsblobstore { namespace { template size_t _serialize(void* dst, const DataType& obj) { cpputils::serialize(dst, obj); return sizeof(DataType); } template DataType _deserialize(const char** src) { DataType result = cpputils::deserialize(*src); *src += sizeof(DataType); return result; } constexpr size_t _serializedTimeValueSize() { return sizeof(uint64_t) + sizeof(uint32_t); } unsigned int _serializeTimeValue(uint8_t *dest, timespec value) { unsigned int offset = 0; offset += _serialize(dest + offset, value.tv_sec); offset += _serialize(dest + offset, value.tv_nsec); ASSERT(offset == _serializedTimeValueSize(), "serialized to wrong size"); return offset; } timespec _deserializeTimeValue(const char **pos) { timespec value{}; value.tv_sec = _deserialize(pos); value.tv_nsec = _deserialize(pos); return value; } unsigned int _serializeString(uint8_t *dest, const string &value) { std::memcpy(dest, value.c_str(), value.size()+1); return value.size() + 1; } string _deserializeString(const char **pos) { size_t length = strlen(*pos); string value(*pos, length); *pos += length + 1; return value; } unsigned int _serializeBlockId(uint8_t *dest, const BlockId &blockId) { blockId.ToBinary(dest); return blockId.BINARY_LENGTH; } BlockId _deserializeBlockId(const char **pos) { BlockId blockId = BlockId::FromBinary(*pos); *pos += BlockId::BINARY_LENGTH; return blockId; } } void DirEntry::serialize(uint8_t *dest) const { ASSERT( ((_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::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(_type)) ); unsigned int offset = 0; offset += _serialize(dest + offset, static_cast(_type)); offset += _serialize(dest + offset, _mode); offset += _serialize(dest + offset, _uid); offset += _serialize(dest + offset, _gid); offset += _serializeTimeValue(dest + offset, _lastAccessTime); offset += _serializeTimeValue(dest + offset, _lastModificationTime); offset += _serializeTimeValue(dest + offset, _lastMetadataChangeTime); offset += _serializeString(dest + offset, _name); offset += _serializeBlockId(dest + offset, _blockId); ASSERT(offset == serializedSize(), "Didn't write correct number of elements"); } const char *DirEntry::deserializeAndAddToVector(const char *pos, vector *result) { fspp::Dir::EntryType type = static_cast(_deserialize(&pos)); mode_t mode = _deserialize(&pos); uid_t uid = _deserialize(&pos); gid_t gid = _deserialize(&pos); timespec lastAccessTime = _deserializeTimeValue(&pos); timespec lastModificationTime = _deserializeTimeValue(&pos); timespec lastMetadataChangeTime = _deserializeTimeValue(&pos); string name = _deserializeString(&pos); BlockId blockId = _deserializeBlockId(&pos); result->emplace_back(type, name, blockId, mode, uid, gid, lastAccessTime, lastModificationTime, lastMetadataChangeTime); return pos; } size_t DirEntry::serializedSize() const { return 1 + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + 3*_serializedTimeValueSize() + ( _name.size() + 1) + _blockId.BINARY_LENGTH; } } }