Skip to content
Snippets Groups Projects
Commit 0ad5f116 authored by Avi Kivity's avatar Avi Kivity
Browse files

fs: piece-wise path lookup

real filesystems (and /proc, our immediate target) look up files incrementally
by each component.  Apply that to our filesystem infrastructure.

A new object is introduced, dir, representing a directory.  Lookup operations
are deferred to this object.
parent 94e5a1be
No related branches found
No related tags found
No related merge requests found
......@@ -8,7 +8,12 @@ bootfs::bootfs()
{
}
fileref bootfs::open(std::string name)
dirref bootfs::root()
{
return new dir(*this, "/");
}
fileref bootfs::do_open(std::string name)
{
metadata *md = reinterpret_cast<metadata *>(_base);
......@@ -38,3 +43,29 @@ void bootfs::file::read(void* buffer, uint64_t offset, uint64_t len)
}
std::memcpy(buffer, _fs._base + _md.offset + offset, len);
}
bootfs::dir::dir(bootfs& fs, std::string path)
: _fs(fs)
, _path(path)
{
}
fileref bootfs::dir::open(std::string name)
{
return _fs.do_open(_path + name);
}
dirref bootfs::dir::subdir(std::string name)
{
return new dir(_fs, _path + name + "/");
}
uint64_t bootfs::dir::size()
{
return 0;
}
void bootfs::dir::read(void* buffer, uint64_t offset, uint64_t len)
{
throw -1; // FIXME
}
......@@ -6,12 +6,17 @@
class bootfs : public filesystem {
public:
bootfs();
virtual fileref open(std::string name);
virtual dirref root();
private:
class file;
class dir;
struct metadata;
private:
fileref do_open(std::string path);
private:
char* _base;
friend class file;
friend class dir;
};
class bootfs::file : public ::file {
......@@ -24,6 +29,18 @@ private:
metadata& _md;
};
class bootfs::dir : public ::dir {
public:
dir(bootfs& fs, std::string path);
virtual fileref open(std::string name);
virtual dirref subdir(std::string name);
virtual uint64_t size();
virtual void read(void* buffer, uint64_t offset, uint64_t len);
private:
bootfs& _fs;
std::string _path;
};
struct bootfs::metadata {
uint64_t size;
uint64_t offset;
......
......@@ -26,3 +26,25 @@ void file::unref()
filesystem::~filesystem()
{
}
fileref filesystem::open(std::string name)
{
dirref d = root();
size_t s = 0, e;
while (d && (e = name.find('/', s)) != name.npos) {
if (s != e) {
d = d->subdir(name.substr(s, e - s));
}
s = e + 1;
}
if (!d) {
return fileref();
}
return d->open(name.substr(s, name.npos));
}
dirref dir::subdir(std::string name)
{
// trivial implementation, can be overridden
return boost::dynamic_pointer_cast<dir>(open(name));
}
......@@ -6,8 +6,10 @@
#include <boost/intrusive_ptr.hpp>
class file;
class dir;
typedef boost::intrusive_ptr<file> fileref;
typedef boost::intrusive_ptr<dir> dirref;
class file {
public:
......@@ -24,10 +26,17 @@ private:
friend void intrusive_ptr_release(file* f) { f->unref(); }
};
class dir : public file {
public:
virtual fileref open(std::string name) = 0;
virtual dirref subdir(std::string name);
};
class filesystem {
public:
virtual ~filesystem();
virtual fileref open(std::string name) = 0;
virtual dirref root() = 0;
fileref open(std::string name);
};
extern filesystem* rootfs;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment