[ox/fs] Fix DirectoryEntry base size

This commit is contained in:
Gary Talent 2018-05-02 21:09:31 -05:00
parent 06013211d4
commit ad956ffd70

View File

@ -18,37 +18,55 @@ namespace ox::fs {
template<typename InodeId_t> template<typename InodeId_t>
struct __attribute__((packed)) DirectoryEntry { struct __attribute__((packed)) DirectoryEntry {
struct __attribute__((packed)) DirectoryEntryData {
// DirectoryEntry fields
LittleEndian<InodeId_t> inode = 0;
BString<MaxFileNameLength> name;
};
// NodeBuffer fields // NodeBuffer fields
LittleEndian<InodeId_t> prev = 0; LittleEndian<InodeId_t> prev = 0;
LittleEndian<InodeId_t> next = 0; LittleEndian<InodeId_t> next = 0;
// DirectoryEntry fields
LittleEndian<InodeId_t> inode = 0;
BString<MaxFileNameLength> name;
DirectoryEntry() = default; DirectoryEntry() = default;
explicit DirectoryEntry(const char *name) { explicit DirectoryEntry(InodeId_t inode, const char *name) {
this->name = name; auto d = data();
if (d.valid()) {
d->inode = inode;
d->name = name;
}
}
ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() {
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(this, this->fullSize(), sizeof(*this), this->size());
}
const ptrarith::Ptr<DirectoryEntryData, InodeId_t> data() const {
return ptrarith::Ptr<DirectoryEntryData, InodeId_t>(const_cast<DirectoryEntry*>(this), this->fullSize(), sizeof(*this), this->size());
} }
/** /**
* @return the size of the data + the size of the Item type * @return the size of the data + the size of the Item type
*/ */
InodeId_t fullSize() const { InodeId_t fullSize() const {
return offsetof(DirectoryEntry, name) + name.size(); auto d = data();
if (d.valid()) {
return sizeof(*this) + offsetof(DirectoryEntryData, name) + d->name.size();
}
return 0;
} }
InodeId_t size() const { InodeId_t size() const {
return fullSize() - offsetof(DirectoryEntry, inode); return fullSize() - offsetof(DirectoryEntryData, inode);
} }
void setSize(InodeId_t) { void setSize(InodeId_t) {
// ignore set value // ignore set value
} }
ptrarith::Ptr<uint8_t, InodeId_t> data() { static std::size_t spaceNeeded(std::size_t chars) {
return ptrarith::Ptr<uint8_t, InodeId_t>(this, this->size(), sizeof(*this), this->size() - sizeof(*this)); return sizeof(DirectoryEntry) + chars;
} }
}; };
@ -59,6 +77,8 @@ class Directory {
private: private:
using Buffer = ptrarith::NodeBuffer<InodeId_t, DirectoryEntry<InodeId_t>>; using Buffer = ptrarith::NodeBuffer<InodeId_t, DirectoryEntry<InodeId_t>>;
InodeId_t m_inodeId = 0;
std::size_t m_size = 0; std::size_t m_size = 0;
Buffer *m_buff = nullptr; Buffer *m_buff = nullptr;
FileStore *m_fs = nullptr; FileStore *m_fs = nullptr;
@ -80,16 +100,23 @@ class Directory {
}; };
template<typename InodeId_t> template<typename InodeId_t>
Directory<InodeId_t>::Directory(fs::FileStore *fs, InodeId_t) { Directory<InodeId_t>::Directory(fs::FileStore *fs, InodeId_t id) {
m_fs = fs; m_fs = fs;
//m_size = size; m_inodeId = id;
//m_buff = reinterpret_cast<decltype(m_buff)>(buff); auto buff = fs->read(id).template to<Buffer>();
if (buff.valid()) {
m_size = buff.size();
m_buff = buff;
}
} }
template<typename InodeId_t> template<typename InodeId_t>
Error Directory<InodeId_t>::init() noexcept { Error Directory<InodeId_t>::init() noexcept {
if (m_size >= sizeof(Buffer)) { constexpr auto Size = sizeof(Buffer);
new (m_buff) Buffer(m_size); m_fs->write(m_inodeId, nullptr, Size);
auto buff = m_fs->read(m_inodeId);
if (buff.valid()) {
new (buff) Buffer(Size);
return 0; return 0;
} }
return 1; return 1;
@ -100,17 +127,24 @@ Error Directory<InodeId_t>::write(PathIterator path, InodeId_t inode) noexcept {
// find existing entry and update if exists // find existing entry and update if exists
if (!path.hasNext()) { if (!path.hasNext()) {
Error err = 1;
BString<MaxFileNameLength> name; BString<MaxFileNameLength> name;
path.next(&name); path.next(&name);
auto val = m_buff->malloc(name.size()); // find existing version of directory
if (val.valid()) { auto old = m_fs->read(m_inodeId);
new (val) DirectoryEntry<InodeId_t>(name.data()); if (old.valid()) {
val->name = name; const auto newSize = m_size + DirectoryEntry<InodeId_t>::spaceNeeded(name.size());
val->inode = inode; auto cpy = new (ox_malloca(newSize)) Buffer(old);
return 0; cpy->setSize(newSize);
auto val = cpy->malloc(name.size());
if (val.valid()) {
new (val) DirectoryEntry<InodeId_t>(inode, name.data());
err = m_fs->write(m_inodeId, cpy, cpy->size());
}
ox_freea(newSize, cpy);
} }
return 1; return err;
} }
// TODO: get sub directory and call its write instead of recursing on this directory // TODO: get sub directory and call its write instead of recursing on this directory
@ -124,15 +158,18 @@ Error Directory<InodeId_t>::rm(PathIterator) noexcept {
template<typename InodeId_t> template<typename InodeId_t>
ValErr<InodeId_t> Directory<InodeId_t>::find(PathIterator it) const noexcept { ValErr<InodeId_t> Directory<InodeId_t>::find(PathIterator it) const noexcept {
ValErr<InodeId_t> retval = {0, 1};
auto size = it.nextSize(); auto size = it.nextSize();
char name[size + 1]; auto name = reinterpret_cast<char*>(ox_alloca(size + 1));
it.next(name, size); it.next(name, size);
for (auto i = m_buff->iterator(); i.hasNext(); i.next()) { auto buff = m_fs->read(m_inodeId).template to<Buffer>();
if (i->name == name) { for (auto i = buff->iterator(); i.hasNext(); i.next()) {
return static_cast<InodeId_t>(i->inode); auto data = i->data();
if (data.valid() && data->name == name) {
retval = static_cast<InodeId_t>(data->inode);
} }
} }
return {0, 1}; return retval;
} }