2014-12-09 17:19:59 +01:00
|
|
|
#include "DirBlock.h"
|
2014-12-07 10:42:16 +01:00
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
//TODO Remove and replace with exception hierarchy
|
2015-02-17 01:02:15 +01:00
|
|
|
#include "messmer/fspp/fuse/FuseErrnoException.h"
|
2014-12-07 10:42:16 +01:00
|
|
|
|
2014-12-09 11:13:50 +01:00
|
|
|
#include "MagicNumbers.h"
|
|
|
|
|
2014-12-07 10:42:16 +01:00
|
|
|
using std::unique_ptr;
|
|
|
|
using std::make_unique;
|
|
|
|
using std::vector;
|
|
|
|
using std::string;
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
using blockstore::Block;
|
2014-12-09 20:36:32 +01:00
|
|
|
using blockstore::Key;
|
2014-12-07 10:42:16 +01:00
|
|
|
|
|
|
|
namespace cryfs {
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
DirBlock::DirBlock(unique_ptr<Block> block)
|
|
|
|
: _block(std::move(block)) {
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
DirBlock::~DirBlock() {
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
void DirBlock::InitializeEmptyDir() {
|
2014-12-09 11:13:50 +01:00
|
|
|
*magicNumber() = MagicNumbers::DIR;
|
2014-12-07 10:42:16 +01:00
|
|
|
*entryCounter() = 0;
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
unsigned char *DirBlock::magicNumber() {
|
|
|
|
return const_cast<unsigned char*>(magicNumber(const_cast<const Block&>(*_block)));
|
2014-12-09 11:13:50 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
const unsigned char *DirBlock::magicNumber(const blockstore::Block &block) {
|
|
|
|
return (unsigned char*)block.data();
|
2014-12-09 11:13:50 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
bool DirBlock::IsDir(const blockstore::Block &block) {
|
|
|
|
return *magicNumber(block) == MagicNumbers::DIR;
|
2014-12-09 11:13:50 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
unique_ptr<vector<string>> DirBlock::GetChildren() const {
|
2014-12-07 10:42:16 +01:00
|
|
|
auto result = make_unique<vector<string>>();
|
|
|
|
unsigned int entryCount = *entryCounter();
|
|
|
|
result->reserve(entryCount);
|
|
|
|
|
|
|
|
const char *pos = entriesBegin();
|
|
|
|
for (unsigned int i = 0; i < entryCount; ++i) {
|
|
|
|
pos = readAndAddNextChild(pos, result.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
const char *DirBlock::readAndAddNextChild(const char *pos, vector<string> *result) const {
|
2014-12-07 10:42:16 +01:00
|
|
|
size_t length = strlen(pos);
|
|
|
|
result->emplace_back(pos, length);
|
|
|
|
const char *posAfterName = pos + length + 1;
|
|
|
|
const char *posAfterKey = posAfterName + strlen(posAfterName) + 1;
|
|
|
|
return posAfterKey;
|
|
|
|
}
|
|
|
|
|
2014-12-09 20:36:32 +01:00
|
|
|
void DirBlock::AddChild(const std::string &name, const Key &blockKey) {
|
2014-12-13 11:59:48 +01:00
|
|
|
string blockKeyStr = blockKey.ToString();
|
2014-12-09 20:36:32 +01:00
|
|
|
|
2014-12-07 10:42:16 +01:00
|
|
|
char *insertPos = entriesEnd();
|
2014-12-09 20:36:32 +01:00
|
|
|
assertEnoughSpaceLeft(insertPos, name.size() + 1 + blockKeyStr.size() + 1);
|
2014-12-07 10:42:16 +01:00
|
|
|
|
|
|
|
memcpy(insertPos, name.c_str(), name.size()+1);
|
2014-12-09 20:36:32 +01:00
|
|
|
memcpy(insertPos + name.size()+1, blockKeyStr.c_str(), blockKeyStr.size()+1);
|
2014-12-07 10:42:16 +01:00
|
|
|
++(*entryCounter());
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
void DirBlock::assertEnoughSpaceLeft(char *insertPos, size_t insertSize) const {
|
|
|
|
size_t usedSize = insertPos - (char*)_block->data();
|
|
|
|
assert(usedSize + insertSize <= _block->size());
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 20:36:32 +01:00
|
|
|
Key DirBlock::GetBlockKeyForName(const string &name) const {
|
2014-12-07 10:42:16 +01:00
|
|
|
unsigned int entryCount = *entryCounter();
|
|
|
|
const char *pos = entriesBegin();
|
|
|
|
for(unsigned int i = 0; i < entryCount; ++i) {
|
|
|
|
size_t name_length = strlen(pos);
|
|
|
|
if (name_length == name.size() && 0==std::memcmp(pos, name.c_str(), name_length)) {
|
|
|
|
pos += strlen(pos) + 1; // Skip name
|
2014-12-09 20:36:32 +01:00
|
|
|
return Key::FromString(pos); // Return key
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
pos += strlen(pos) + 1; // Skip name
|
|
|
|
pos += strlen(pos) + 1; // Skip key
|
|
|
|
}
|
|
|
|
throw fspp::fuse::FuseErrnoException(ENOENT);
|
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
unsigned int *DirBlock::entryCounter() {
|
|
|
|
return const_cast<unsigned int*>(const_cast<const DirBlock*>(this)->entryCounter());
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
const unsigned int *DirBlock::entryCounter() const {
|
|
|
|
return (unsigned int*)((char*)_block->data() + sizeof(unsigned char));
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
char *DirBlock::entriesBegin() {
|
|
|
|
return const_cast<char*>(const_cast<const DirBlock*>(this)->entriesBegin());
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
const char *DirBlock::entriesBegin() const {
|
|
|
|
return (char *)(_block->data())+sizeof(unsigned char) + sizeof(unsigned int);
|
2014-12-07 10:42:16 +01:00
|
|
|
}
|
|
|
|
|
2014-12-09 17:19:59 +01:00
|
|
|
char *DirBlock::entriesEnd() {
|
2014-12-07 10:42:16 +01:00
|
|
|
unsigned int entryCount = *entryCounter();
|
|
|
|
char *pos = entriesBegin();
|
|
|
|
for(unsigned int i = 0; i < entryCount; ++i) {
|
|
|
|
pos += strlen(pos) + 1; // Skip entry name
|
|
|
|
pos += strlen(pos) + 1; // Skip entry key
|
|
|
|
}
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|