mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-28 16:17:51 +01:00
More reasonable pointers, file nodes
This commit is contained in:
2
run.sh
2
run.sh
@@ -2,7 +2,7 @@
|
||||
|
||||
POSITIONAL_ARGS=()
|
||||
|
||||
QEMU_OPTS=" -no-reboot "
|
||||
QEMU_OPTS=" -no-reboot -m 256M"
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
extern volatile struct limine_module_request module_request;
|
||||
|
||||
static constexpr unsigned max_saved_modules = 2;
|
||||
static constexpr unsigned max_saved_modules = 4;
|
||||
static constexpr unsigned max_saved_module_name = 256;
|
||||
|
||||
void limine_modules_remap();
|
||||
|
||||
@@ -88,32 +88,12 @@ uint64_t syscall_close(uint64_t FD) {
|
||||
|
||||
//FIXME:
|
||||
uint64_t syscall_read(uint64_t fd, char *buf, uint64_t len) {
|
||||
if (fd == 0) {
|
||||
auto c = buf;
|
||||
while ((c - buf) < len) {
|
||||
*c = GlobalTtyManager.get_tty(0)->readchar();
|
||||
if (*c == '\r') {
|
||||
*(c++) = '\n';
|
||||
break;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return (c - buf);
|
||||
}
|
||||
auto f = FDT::current()->get(fd);
|
||||
if (!f) return -1;
|
||||
return f->read(buf, len);
|
||||
}
|
||||
|
||||
uint64_t syscall_write(uint64_t fd, const char *buf, uint64_t len) {
|
||||
if (fd == 1) {
|
||||
auto c = buf;
|
||||
while (*c != '\0' && (c - buf) < len) {
|
||||
GlobalTtyManager.all_tty_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
auto f = FDT::current()->get(fd);
|
||||
if (!f) return -1;
|
||||
return f->write(buf, len);
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#define POINTERS_H
|
||||
|
||||
#include <atomic>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "asserts.hpp"
|
||||
#include "kmem.hpp"
|
||||
|
||||
class SharedPtrTester;
|
||||
@@ -55,6 +57,78 @@ private:
|
||||
T *ptr = nullptr;
|
||||
};
|
||||
|
||||
struct SharedPtr_Base {
|
||||
struct UsesBlock {
|
||||
int32_t _uses_ctl;
|
||||
int32_t _uses_obj;
|
||||
} __attribute__((packed));
|
||||
|
||||
std::atomic<UsesBlock> _uses;
|
||||
|
||||
static_assert(decltype(_uses)::is_always_lock_free);
|
||||
|
||||
// Increments control block use counter
|
||||
void weak_lock() {
|
||||
UsesBlock old_uses = _uses.load();
|
||||
UsesBlock new_uses;
|
||||
do {
|
||||
assert(old_uses._uses_ctl >= 1);
|
||||
new_uses = old_uses;
|
||||
new_uses._uses_ctl++;
|
||||
} while (!_uses.compare_exchange_weak(old_uses, new_uses));
|
||||
}
|
||||
|
||||
// Decrements control block use counter
|
||||
// Returns true if it was deleted
|
||||
bool weak_release() {
|
||||
UsesBlock old_uses = _uses.load();
|
||||
UsesBlock new_uses;
|
||||
do {
|
||||
new_uses = old_uses;
|
||||
new_uses._uses_ctl--;
|
||||
} while (!_uses.compare_exchange_weak(old_uses, new_uses));
|
||||
|
||||
if (new_uses._uses_ctl == 0)
|
||||
delete this;
|
||||
return new_uses._uses_ctl == 0;
|
||||
}
|
||||
|
||||
// Increments control and object use counter
|
||||
// Returns false if the object was already deleted
|
||||
bool strong_lock() {
|
||||
UsesBlock old_uses = _uses.load();
|
||||
UsesBlock new_uses;
|
||||
do {
|
||||
if (old_uses._uses_obj <= 0)
|
||||
return false;
|
||||
new_uses = old_uses;
|
||||
new_uses._uses_ctl++;
|
||||
new_uses._uses_obj++;
|
||||
} while (!_uses.compare_exchange_weak(old_uses, new_uses));
|
||||
|
||||
assert(new_uses._uses_obj > 0);
|
||||
assert(new_uses._uses_ctl >= new_uses._uses_obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Decrements control and object use counter
|
||||
// Returns true if the object is to be deleted (it was the last reference)
|
||||
bool strong_release() {
|
||||
UsesBlock old_uses = _uses.load();
|
||||
UsesBlock new_uses;
|
||||
do {
|
||||
new_uses = old_uses;
|
||||
new_uses._uses_obj--;
|
||||
new_uses._uses_ctl--;
|
||||
} while (!_uses.compare_exchange_weak(old_uses, new_uses));
|
||||
|
||||
if (new_uses._uses_ctl == 0)
|
||||
delete this;
|
||||
|
||||
return new_uses._uses_obj == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SharedPtr {
|
||||
friend SharedPtrTester;
|
||||
@@ -62,51 +136,146 @@ class SharedPtr {
|
||||
public:
|
||||
SharedPtr() = default;
|
||||
|
||||
explicit SharedPtr(T *data) : ptr(data), uses(new std::atomic<int>(1)) {}
|
||||
explicit SharedPtr(T *data) : _ptr(data), _base(new SharedPtr_Base{SharedPtr_Base::UsesBlock{1, 1}}) {}
|
||||
SharedPtr(std::nullptr_t a_nullptr) : _ptr(nullptr), _base(nullptr) {}
|
||||
|
||||
~SharedPtr() {
|
||||
if (ptr == nullptr || uses == nullptr) return;
|
||||
if (uses->fetch_sub(1) == 1) {
|
||||
delete ptr;
|
||||
delete uses;
|
||||
}
|
||||
unref();
|
||||
}
|
||||
|
||||
SharedPtr(SharedPtr const &other) : ptr(other.ptr), uses(other.uses) {
|
||||
++(*uses);
|
||||
SharedPtr(SharedPtr const &other) : _base(other._base), _ptr(other._ptr) {
|
||||
if (!_base) return;
|
||||
_base->strong_lock();
|
||||
}
|
||||
|
||||
SharedPtr(SharedPtr &&other) {
|
||||
if (ptr != nullptr && uses != nullptr)
|
||||
if (uses->fetch_sub(1) == 1) {
|
||||
delete ptr;
|
||||
delete uses;
|
||||
}
|
||||
uses = other.uses;
|
||||
ptr = other.ptr;
|
||||
other.uses = nullptr;
|
||||
other.ptr = nullptr;
|
||||
unref();
|
||||
|
||||
_base = other._base;
|
||||
_ptr = other._ptr;
|
||||
other._base = nullptr;
|
||||
other._ptr = nullptr;
|
||||
}
|
||||
|
||||
SharedPtr &operator=(SharedPtr other) {
|
||||
std::swap(ptr, other.ptr);
|
||||
std::swap(uses, other.uses);
|
||||
std::swap(_base, other._base);
|
||||
std::swap(_ptr, other._ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T *operator->() const { return ptr; }
|
||||
T *operator->() const {
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
T &operator*() const { return *ptr; }
|
||||
T &operator*() const {
|
||||
return *_ptr;
|
||||
}
|
||||
|
||||
T *get() const noexcept { return ptr; }
|
||||
T *get() const noexcept {
|
||||
return _ptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] int useCount() const { return *uses; }
|
||||
[[nodiscard]] int useCount() const {
|
||||
if (!_base) return 0;
|
||||
return _base->_uses.load()._uses_obj;
|
||||
}
|
||||
|
||||
template<typename Tgt, template<class> class Ptr, typename Orig>
|
||||
friend Ptr<Tgt> static_ptr_cast(const Ptr<Orig> &ptr);
|
||||
|
||||
private:
|
||||
T *ptr = nullptr;
|
||||
std::atomic<int> *uses = nullptr;
|
||||
template<typename U>
|
||||
friend class WeakPtr;
|
||||
|
||||
explicit SharedPtr(T *ptr, SharedPtr_Base *base) : _ptr(ptr), _base(base) {}
|
||||
|
||||
void unref() {
|
||||
if (!_base) return;
|
||||
if (_base->strong_release())
|
||||
delete _ptr;
|
||||
_ptr = nullptr;
|
||||
_base = nullptr;
|
||||
}
|
||||
|
||||
T *_ptr = nullptr;
|
||||
SharedPtr_Base *_base = nullptr;
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class WeakPtr {
|
||||
public:
|
||||
WeakPtr() = default;
|
||||
|
||||
WeakPtr(const SharedPtr<T> &shared) : _base(shared._base), _ptr(shared._ptr) { _base->weak_lock(); }
|
||||
WeakPtr(std::nullptr_t a_nullptr) : _ptr(nullptr), _base(nullptr) {}
|
||||
|
||||
~WeakPtr() {
|
||||
unref();
|
||||
}
|
||||
|
||||
WeakPtr(WeakPtr const &other) : _base(other._base), _ptr(other._ptr) {
|
||||
if (!_base) return;
|
||||
_base->weak_lock();
|
||||
}
|
||||
|
||||
WeakPtr(WeakPtr &&other) {
|
||||
unref();
|
||||
|
||||
_base = other._base;
|
||||
_ptr = other._ptr;
|
||||
other._base = nullptr;
|
||||
other._ptr = nullptr;
|
||||
}
|
||||
|
||||
WeakPtr &operator=(WeakPtr other) {
|
||||
std::swap(_ptr, other._ptr);
|
||||
std::swap(_base, other._base);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::optional<SharedPtr<T>> lock() {
|
||||
if (!_base) return std::nullopt;
|
||||
if (_base->strong_lock())
|
||||
return SharedPtr(_ptr, _base);
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
[[nodiscard]] int expired() const {
|
||||
if (!_base) return true;
|
||||
return _base->_uses.load()._uses_obj <= 0;
|
||||
}
|
||||
|
||||
template<typename Tgt, template<class> class Ptr, typename Orig>
|
||||
friend Ptr<Tgt> static_ptr_cast(const Ptr<Orig> &ptr);
|
||||
|
||||
private:
|
||||
void unref() {
|
||||
if (!_base) return;
|
||||
_base->weak_release();
|
||||
_base = nullptr;
|
||||
_ptr = nullptr;
|
||||
}
|
||||
|
||||
T *_ptr = nullptr;
|
||||
SharedPtr_Base *_base = nullptr;
|
||||
};
|
||||
|
||||
template<typename Tgt, template<class> class Ptr, typename Orig>
|
||||
static Ptr<Tgt> static_ptr_cast(const Ptr<Orig> &ptr) {
|
||||
static_assert(std::is_convertible_v<Orig *, Tgt *> || std::is_base_of_v<Orig, Tgt>);
|
||||
if constexpr (std::is_same_v<Ptr<Tgt>, SharedPtr<Tgt>>) {
|
||||
ptr._base->strong_lock();
|
||||
} else if constexpr (std::is_same_v<Ptr<Tgt>, WeakPtr<Tgt>>) {
|
||||
ptr._base->weak_lock();
|
||||
} else {
|
||||
static_assert(false);
|
||||
}
|
||||
return Ptr<Tgt>(static_cast<Tgt *>(ptr._ptr), ptr._base);
|
||||
}
|
||||
|
||||
|
||||
class COWTester;
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -11,4 +11,6 @@ target_sources(kernel.elf PRIVATE
|
||||
FDT.cpp
|
||||
VFSGlobals.cpp
|
||||
File.cpp
|
||||
PipeFs.cpp
|
||||
TtyPipe.cpp
|
||||
)
|
||||
@@ -7,12 +7,13 @@
|
||||
#include "File.hpp"
|
||||
#include "MountTable.hpp"
|
||||
#include "PointersCollection.hpp"
|
||||
#include "TtyPipe.hpp"
|
||||
#include "VFSApi.hpp"
|
||||
#include "VFSGlobals.hpp"
|
||||
#include "paging.hpp"
|
||||
|
||||
FDT::FD FDT::open(const Path &p, FileOpts opts) {
|
||||
if (auto n = VFSGlobals::root.traverse(p)) {
|
||||
if (auto n = VFSGlobals::root.traverse(p); n.get() != nullptr) {
|
||||
LockGuard l(_mtx);
|
||||
_files.add(_cur_fd++, UniquePtr<File>(new File(n, opts)));
|
||||
return _cur_fd - 1;
|
||||
@@ -44,6 +45,10 @@ File *FDT::get(FDT::FD fd) const {
|
||||
FDT *FDT::current() {
|
||||
return Scheduler::cur_task()->_addressSpace->getFdt();
|
||||
}
|
||||
FDT::FDT() {
|
||||
_files.add(0, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDONLY)));
|
||||
_files.add(1, UniquePtr(new File(static_ptr_cast<Node>(TtyPipe::create()), O_RDWR)));
|
||||
}
|
||||
FDHandle::FDHandle(FDT::FD fd) : _fd(fd) {
|
||||
}
|
||||
FDHandle::~FDHandle() {
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
class FDT {
|
||||
public:
|
||||
FDT();
|
||||
|
||||
using FD = int64_t;
|
||||
FD open(const Path &p, FileOpts opts);
|
||||
void close(FD fd);
|
||||
|
||||
@@ -4,23 +4,25 @@
|
||||
|
||||
#include "File.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Node.hpp"
|
||||
|
||||
File::File(Node *node, FileOpts opts) : _n(node), _opts(opts) {
|
||||
File::File(SharedPtr<Node> node, FileOpts opts) : _n(std::move(node)), _opts(opts) {
|
||||
if (opts & FileOpts::O_WRONLY)
|
||||
assert(opts & FileOpts::O_RDONLY);
|
||||
}
|
||||
File::~File() {
|
||||
}
|
||||
Node *File::node() {
|
||||
SharedPtr<Node> File::node() const {
|
||||
return _n;
|
||||
}
|
||||
NodeDir *File::dir() {
|
||||
if (_n && _n->type() == Node::DIR) return static_cast<NodeDir *>(_n);
|
||||
SharedPtr<NodeDir> File::dir() const {
|
||||
if (_n.get() && _n->type() == Node::DIR) return static_ptr_cast<NodeDir>(_n);
|
||||
return nullptr;
|
||||
}
|
||||
NodeFile *File::file() const {
|
||||
if (_n && _n->type() == Node::FILE) return static_cast<NodeFile *>(_n);
|
||||
SharedPtr<NodeFile> File::file() const {
|
||||
if (_n.get() && _n->type() == Node::FILE) return static_ptr_cast<NodeFile>(_n);
|
||||
return nullptr;
|
||||
}
|
||||
uint64_t File::seek(uint64_t pos) {
|
||||
@@ -28,7 +30,7 @@ uint64_t File::seek(uint64_t pos) {
|
||||
return pos;
|
||||
}
|
||||
uint64_t File::read(char *buf, uint64_t size) {
|
||||
if (file()) {
|
||||
if (file().get() != nullptr) {
|
||||
file()->read(buf, _pos, size);
|
||||
_pos += size;
|
||||
return size;
|
||||
@@ -36,12 +38,12 @@ uint64_t File::read(char *buf, uint64_t size) {
|
||||
}
|
||||
uint64_t File::write(const char *buf, uint64_t size) {
|
||||
if (!(_opts & FileOpts::O_WRONLY)) return -1;
|
||||
if (file()) {
|
||||
if (file().get() != nullptr) {
|
||||
file()->write(buf, _pos, size);
|
||||
_pos += size;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
uint64_t File::size() {
|
||||
if (file()) return file()->size();
|
||||
if (file().get() != nullptr) return file()->size();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#define FICUS_FILE_HPP
|
||||
|
||||
#include "FileOpts.h"
|
||||
#include "PointersCollection.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Node;
|
||||
@@ -14,24 +16,24 @@ class NodeFile;
|
||||
|
||||
class File {
|
||||
public:
|
||||
File(Node *n, FileOpts opts);
|
||||
File(SharedPtr<Node> n, FileOpts opts);
|
||||
~File();
|
||||
File(const File &f) = delete;
|
||||
File &operator=(const File &o) = delete;
|
||||
File(const File &f) = delete;
|
||||
File &operator=(const File &o) = delete;
|
||||
|
||||
Node *node();
|
||||
NodeDir *dir();
|
||||
NodeFile *file() const;
|
||||
SharedPtr<Node> node() const;
|
||||
SharedPtr<NodeDir> dir() const;
|
||||
SharedPtr<NodeFile> file() const;
|
||||
|
||||
uint64_t seek(uint64_t pos);
|
||||
uint64_t read(char *buf, uint64_t size);
|
||||
uint64_t write(const char *buf, uint64_t size);
|
||||
uint64_t size();
|
||||
uint64_t seek(uint64_t pos);
|
||||
uint64_t read(char *buf, uint64_t size);
|
||||
uint64_t write(const char *buf, uint64_t size);
|
||||
uint64_t size();
|
||||
|
||||
private:
|
||||
Node *const _n;
|
||||
uint64_t _pos = 0;
|
||||
FileOpts _opts;
|
||||
SharedPtr<Node> _n;
|
||||
uint64_t _pos = 0;
|
||||
FileOpts _opts;
|
||||
};
|
||||
|
||||
#endif //FICUS_FILE_HPP
|
||||
|
||||
@@ -5,28 +5,27 @@
|
||||
#include "MemFs.hpp"
|
||||
#include "LockGuard.hpp"
|
||||
|
||||
Vector<Node *> MemFs::MemFsNodeDir::children() {
|
||||
LockGuard l(_lock);
|
||||
Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() {
|
||||
LockGuard l(_lock);
|
||||
|
||||
Vector<Node *> out;
|
||||
Vector<SharedPtr<Node>> out;
|
||||
for (auto c: _children) {
|
||||
out.emplace_back(c.data);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
NodeDir *MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||
SharedPtr<NodeDir> MemFs::MemFsNodeDir::mkdir(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newnode = new MemFsNodeDir();
|
||||
newnode->_name = name;
|
||||
_children.add(name, newnode);
|
||||
return newnode;
|
||||
auto newnode = MemFsNodeDir::create(name);
|
||||
_children.add(name, static_ptr_cast<Node>(newnode));
|
||||
return static_ptr_cast<NodeDir>(newnode);
|
||||
}
|
||||
NodeFile *MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||
SharedPtr<NodeFile> MemFs::MemFsNodeDir::mkfile(const String &name) {
|
||||
LockGuard l(_lock);
|
||||
auto newfile = new MemFsNodeFile(name);
|
||||
_children.add(name, newfile);
|
||||
return newfile;
|
||||
auto newfile = MemFsNodeFile::create(name);
|
||||
_children.add(name, static_ptr_cast<Node>(newfile));
|
||||
return static_ptr_cast<NodeFile>(newfile);
|
||||
}
|
||||
bool MemFs::MemFsNodeFile::read(char *buf, size_t start, size_t num) {
|
||||
LockGuard l(_lock);
|
||||
|
||||
@@ -14,33 +14,46 @@
|
||||
class MemFs : public Filesystem {
|
||||
struct MemFsNodeDir : public NodeDir {
|
||||
public:
|
||||
Vector<Node *> children() override;
|
||||
NodeDir *mkdir(const String &name) override;
|
||||
NodeFile *mkfile(const String &name) override;
|
||||
Vector<SharedPtr<Node>> children() override;
|
||||
SharedPtr<NodeDir> mkdir(const String &name) override;
|
||||
SharedPtr<NodeFile> mkfile(const String &name) override;
|
||||
|
||||
static SharedPtr<MemFsNodeDir> create(const String &name) {
|
||||
auto shared = SharedPtr(new MemFsNodeDir(name));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
SkipList<String, Node *> _children;
|
||||
MemFsNodeDir(const String &name) { _name = name; }
|
||||
SkipList<String, SharedPtr<Node>> _children;
|
||||
};
|
||||
|
||||
struct MemFsNodeFile : public NodeFile {
|
||||
public:
|
||||
MemFsNodeFile(const String &name) { _name = name; }
|
||||
bool read(char *buf, size_t start, size_t num) override;
|
||||
bool write(const char *buf, size_t start, size_t num) override;
|
||||
size_t size() override;
|
||||
bool is_tty() override { return false; }
|
||||
|
||||
bool read(char *buf, size_t start, size_t num) override;
|
||||
bool write(const char *buf, size_t start, size_t num) override;
|
||||
size_t size() override;
|
||||
static SharedPtr<MemFsNodeFile> create(const String &name) {
|
||||
auto shared = SharedPtr(new MemFsNodeFile(name));
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
MemFsNodeFile(const String &name) { _name = name; }
|
||||
Vector<uint8_t> _bytes;
|
||||
};
|
||||
|
||||
public:
|
||||
MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) {}
|
||||
|
||||
NodeDir *root() override { return &_rootNode; }
|
||||
NodeDir *root() override { return _rootNode.get(); }
|
||||
|
||||
private:
|
||||
MemFsNodeDir _rootNode;
|
||||
SharedPtr<MemFsNodeDir> _rootNode = MemFsNodeDir::create("");
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -8,24 +8,25 @@
|
||||
#include "Filesystem.hpp"
|
||||
|
||||
Node::~Node() = default;
|
||||
Node *Node::traverse(const Path &path) {
|
||||
NodeDir &nodeDir = static_cast<NodeDir &>(*this);
|
||||
SharedPtr<Node> Node::traverse(const Path &path) {
|
||||
|
||||
Filesystem *mnt;
|
||||
{
|
||||
LockGuard l(_lock);
|
||||
mnt = nodeDir._mount;
|
||||
mnt = _mount;
|
||||
}
|
||||
if (mnt) return mnt->root()->traverse(path);
|
||||
|
||||
if (path.empty()) {
|
||||
return this;
|
||||
auto ret = _self_weak.lock();
|
||||
assert(ret != std::nullopt);
|
||||
return *ret;
|
||||
}
|
||||
|
||||
|
||||
if (type() == DIR) {
|
||||
// Horribly inefficient
|
||||
auto children = nodeDir.children();
|
||||
auto children = static_cast<NodeDir *>(this)->children();
|
||||
for (size_t i = 0; i < children.size(); i++) {
|
||||
if (children[i]->name() == path[0]) {
|
||||
return children[i]->traverse(path.subvector(1, path.size()));
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef FICUS_NODE_HPP
|
||||
#define FICUS_NODE_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "List.hpp"
|
||||
#include "LockGuard.hpp"
|
||||
#include "String.hpp"
|
||||
@@ -28,7 +30,7 @@ public:
|
||||
LockGuard l(_lock);
|
||||
return _name;
|
||||
}
|
||||
virtual Node *traverse(const Path &path);
|
||||
virtual SharedPtr<Node> traverse(const Path &path);
|
||||
|
||||
protected:
|
||||
Node(Type type) : _type(type) {}
|
||||
@@ -40,16 +42,17 @@ protected:
|
||||
|
||||
String _name;
|
||||
Filesystem *_mount = nullptr;
|
||||
WeakPtr<Node> _self_weak = nullptr;
|
||||
};
|
||||
|
||||
class NodeFile;
|
||||
|
||||
class NodeDir : public Node {
|
||||
public:
|
||||
virtual Vector<Node *> children() = 0;
|
||||
virtual NodeDir *mkdir(const String &name) = 0;
|
||||
virtual NodeFile *mkfile(const String &name) = 0;
|
||||
virtual void set_mounted(Filesystem *mount);
|
||||
virtual Vector<SharedPtr<Node>> children() = 0;
|
||||
virtual SharedPtr<NodeDir> mkdir(const String &name) = 0;
|
||||
virtual SharedPtr<NodeFile> mkfile(const String &name) = 0;
|
||||
virtual void set_mounted(Filesystem *mount);
|
||||
|
||||
protected:
|
||||
NodeDir() : Node(Type::DIR) {}
|
||||
@@ -60,6 +63,7 @@ public:
|
||||
virtual bool read(char *buf, size_t start, size_t num) = 0;
|
||||
virtual bool write(const char *buf, size_t start, size_t num) = 0;
|
||||
virtual size_t size() = 0;
|
||||
virtual bool is_tty() = 0;
|
||||
|
||||
protected:
|
||||
NodeFile() : Node(Type::FILE) {}
|
||||
|
||||
5
src/kernel/vfs/PipeFs.cpp
Normal file
5
src/kernel/vfs/PipeFs.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 05.04.2024.
|
||||
//
|
||||
|
||||
#include "PipeFs.hpp"
|
||||
13
src/kernel/vfs/PipeFs.hpp
Normal file
13
src/kernel/vfs/PipeFs.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 05.04.2024.
|
||||
//
|
||||
|
||||
#ifndef FICUS_PIPEFS_HPP
|
||||
#define FICUS_PIPEFS_HPP
|
||||
|
||||
|
||||
class PipeFs {
|
||||
};
|
||||
|
||||
|
||||
#endif //FICUS_PIPEFS_HPP
|
||||
29
src/kernel/vfs/TtyPipe.cpp
Normal file
29
src/kernel/vfs/TtyPipe.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 05.04.2024.
|
||||
//
|
||||
|
||||
#include "TtyPipe.hpp"
|
||||
#include "TtyManager.hpp"
|
||||
bool TtyPipe::read(char *buf, size_t start, size_t num) {
|
||||
auto c = buf;
|
||||
while ((c - buf) < num) {
|
||||
*c = GlobalTtyManager.get_tty(0)->readchar();
|
||||
if (*c == '\r') {
|
||||
*(c++) = '\n';
|
||||
break;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return (c - buf);
|
||||
}
|
||||
bool TtyPipe::write(const char *buf, size_t start, size_t num) {
|
||||
auto c = buf;
|
||||
while (*c != '\0' && (c - buf) < num) {
|
||||
GlobalTtyManager.all_tty_putchar(*c);
|
||||
c++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
size_t TtyPipe::size() {
|
||||
return 0;
|
||||
}
|
||||
28
src/kernel/vfs/TtyPipe.hpp
Normal file
28
src/kernel/vfs/TtyPipe.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// Created by Stepan Usatiuk on 05.04.2024.
|
||||
//
|
||||
|
||||
#ifndef FICUS_TTYPIPE_HPP
|
||||
#define FICUS_TTYPIPE_HPP
|
||||
|
||||
|
||||
#include "Node.hpp"
|
||||
class TtyPipe : public NodeFile {
|
||||
public:
|
||||
bool read(char *buf, size_t start, size_t num) override;
|
||||
bool write(const char *buf, size_t start, size_t num) override;
|
||||
size_t size() override;
|
||||
bool is_tty() override { return true; }
|
||||
|
||||
static SharedPtr<TtyPipe> create() {
|
||||
auto shared = SharedPtr(new TtyPipe());
|
||||
shared->_self_weak = static_ptr_cast<Node>(shared);
|
||||
return shared;
|
||||
}
|
||||
|
||||
private:
|
||||
TtyPipe() = default;
|
||||
};
|
||||
|
||||
|
||||
#endif //FICUS_TTYPIPE_HPP
|
||||
@@ -12,7 +12,7 @@ bool VFSApi::mkdir(const Path &path) {
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||
if (root_fd.get() == -1) return false;
|
||||
File *root_f = FDT::current()->get(root_fd.get());
|
||||
if (!root_f->dir()) return false;
|
||||
if (root_f->dir().get() == nullptr) return false;
|
||||
root_f->dir()->mkdir(path.back());
|
||||
return true;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ bool VFSApi::touch(const Path &path) {
|
||||
FDHandle root_fd = FDHandle(FDT::current()->open(root, O_RDWR));
|
||||
if (root_fd.get() == -1) return false;
|
||||
File *root_f = FDT::current()->get(root_fd.get());
|
||||
if (!root_f->dir()) return false;
|
||||
if (root_f->dir().get() == nullptr) return false;
|
||||
root_f->dir()->mkfile(path.back());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
//
|
||||
|
||||
#include "VFSGlobals.hpp"
|
||||
Vector<Node *> RootNode::children() {
|
||||
Vector<SharedPtr<Node>> RootNode::children() {
|
||||
assert(false);
|
||||
return {};
|
||||
}
|
||||
NodeDir *RootNode::mkdir(const String &name) {
|
||||
SharedPtr<NodeDir> RootNode::mkdir(const String &name) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
NodeFile *RootNode::mkfile(const String &name) {
|
||||
SharedPtr<NodeFile> RootNode::mkfile(const String &name) {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
|
||||
class RootNode : public NodeDir {
|
||||
public:
|
||||
Vector<Node *> children() override;
|
||||
NodeDir *mkdir(const String &name) override;
|
||||
NodeFile *mkfile(const String &name) override;
|
||||
Vector<SharedPtr<Node>> children() override;
|
||||
SharedPtr<NodeDir> mkdir(const String &name) override;
|
||||
SharedPtr<NodeFile> mkfile(const String &name) override;
|
||||
};
|
||||
|
||||
namespace VFSGlobals {
|
||||
|
||||
Reference in New Issue
Block a user