Compare commits
11 Commits
3f164c6b82
...
762b7a4276
Author | SHA1 | Date |
---|---|---|
|
762b7a4276 | |
|
a511441f7e | |
|
cd61d710df | |
|
f88ad7efcd | |
|
38320018dc | |
|
d883d212b1 | |
|
dedb2a2399 | |
|
8604c55de8 | |
|
e949e8550c | |
|
eb5c6cf736 | |
|
94ce2c97be |
|
@ -102,22 +102,4 @@ namespace BAN::Math
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<integral T>
|
|
||||||
inline constexpr T little_endian_to_host(const uint8_t* bytes)
|
|
||||||
{
|
|
||||||
T result = 0;
|
|
||||||
for (size_t i = 0; i < sizeof(T); i++)
|
|
||||||
result |= (T)bytes[i] << (i * 8);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<integral T>
|
|
||||||
inline constexpr T big_endian_to_host(const uint8_t* bytes)
|
|
||||||
{
|
|
||||||
T result = 0;
|
|
||||||
for (size_t i = 0; i < sizeof(T); i++)
|
|
||||||
result |= (T)bytes[i] << (8 * (sizeof(T) - i - 1));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -124,6 +124,8 @@ namespace LibELF
|
||||||
dprintln("Invalid program header");
|
dprintln("Invalid program header");
|
||||||
return BAN::Error::from_errno(EINVAL);
|
return BAN::Error::from_errno(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace LibELF
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
|
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
|
||||||
|
|
||||||
|
size_t virtual_page_count() const { return m_virtual_page_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
|
||||||
BAN::ErrorOr<void> initialize();
|
BAN::ErrorOr<void> initialize();
|
||||||
|
@ -42,6 +44,7 @@ namespace LibELF
|
||||||
Kernel::PageTable& m_page_table;
|
Kernel::PageTable& m_page_table;
|
||||||
ElfNativeFileHeader m_file_header;
|
ElfNativeFileHeader m_file_header;
|
||||||
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
||||||
|
size_t m_virtual_page_count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
|
@ -24,6 +24,8 @@ set(KERNEL_SOURCES
|
||||||
kernel/FS/Ext2/Inode.cpp
|
kernel/FS/Ext2/Inode.cpp
|
||||||
kernel/FS/Inode.cpp
|
kernel/FS/Inode.cpp
|
||||||
kernel/FS/Pipe.cpp
|
kernel/FS/Pipe.cpp
|
||||||
|
kernel/FS/ProcFS/FileSystem.cpp
|
||||||
|
kernel/FS/ProcFS/Inode.cpp
|
||||||
kernel/FS/RamFS/FileSystem.cpp
|
kernel/FS/RamFS/FileSystem.cpp
|
||||||
kernel/FS/RamFS/Inode.cpp
|
kernel/FS/RamFS/Inode.cpp
|
||||||
kernel/FS/VirtualFileSystem.cpp
|
kernel/FS/VirtualFileSystem.cpp
|
||||||
|
|
|
@ -25,9 +25,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
BlockDevice(mode_t mode, uid_t uid, gid_t gid)
|
BlockDevice(mode_t mode, uid_t uid, gid_t gid)
|
||||||
: Device(Mode::IFBLK | mode, uid, gid)
|
: Device(mode, uid, gid)
|
||||||
{
|
{
|
||||||
ASSERT(Device::mode().ifblk());
|
m_inode_info.mode |= Inode::Mode::IFBLK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
CharacterDevice(mode_t mode, uid_t uid, gid_t gid)
|
CharacterDevice(mode_t mode, uid_t uid, gid_t gid)
|
||||||
: Device(Mode::IFCHR | mode, uid, gid)
|
: Device(mode, uid, gid)
|
||||||
{
|
{
|
||||||
ASSERT(Device::mode().ifchr());
|
m_inode_info.mode |= Inode::Mode::IFCHR;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
|
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
|
||||||
BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t);
|
BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t);
|
||||||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||||
|
BAN::ErrorOr<void> delete_inode(BAN::StringView);
|
||||||
|
|
||||||
// Link API
|
// Link API
|
||||||
BAN::ErrorOr<BAN::String> link_target();
|
BAN::ErrorOr<BAN::String> link_target();
|
||||||
|
@ -104,6 +105,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
virtual BAN::ErrorOr<void> delete_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
||||||
// Link API
|
// Link API
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/FS/RamFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
|
#include <kernel/Process.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class ProcFileSystem final : public RamFileSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void initialize();
|
||||||
|
static ProcFileSystem& get();
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> on_process_create(Process&);
|
||||||
|
void on_process_delete(Process&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProcFileSystem(size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAN::RefPtr<RamDirectoryInode> m_root_inode;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <kernel/FS/RamFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
|
#include <kernel/Process.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
class ProcPidInode final : public RamDirectoryInode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<ProcPidInode>> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t);
|
||||||
|
~ProcPidInode() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProcPidInode(Process&, RamFileSystem&, const FullInodeInfo&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Process& m_process;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProcMemInode final : public RamInode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<ProcMemInode>> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t);
|
||||||
|
~ProcMemInode() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
||||||
|
|
||||||
|
// You may not write here and this is always non blocking
|
||||||
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||||
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
|
||||||
|
virtual bool has_data_impl() const override { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ProcMemInode(Process&, RamFileSystem&, const FullInodeInfo&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Process& m_process;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ namespace Kernel
|
||||||
class RamInode : public Inode
|
class RamInode : public Inode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<RamInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
|
|
||||||
virtual ~RamInode() = default;
|
virtual ~RamInode() = default;
|
||||||
|
|
||||||
virtual ino_t ino() const override { return m_inode_info.ino; }
|
virtual ino_t ino() const override { return m_inode_info.ino; }
|
||||||
|
@ -31,16 +30,10 @@ namespace Kernel
|
||||||
|
|
||||||
void add_link() { m_inode_info.nlink++; }
|
void add_link() { m_inode_info.nlink++; }
|
||||||
|
|
||||||
protected:
|
|
||||||
RamInode(RamFileSystem& fs, mode_t, uid_t, gid_t);
|
|
||||||
|
|
||||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
|
||||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
|
||||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct FullInodeInfo
|
struct FullInodeInfo
|
||||||
{
|
{
|
||||||
|
FullInodeInfo(RamFileSystem&, mode_t, uid_t, gid_t);
|
||||||
ino_t ino;
|
ino_t ino;
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
nlink_t nlink;
|
nlink_t nlink;
|
||||||
|
@ -56,16 +49,38 @@ namespace Kernel
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RamInode(RamFileSystem& fs, const FullInodeInfo& inode_info)
|
||||||
|
: m_fs(fs)
|
||||||
|
, m_inode_info(inode_info)
|
||||||
|
{
|
||||||
|
ASSERT((inode_info.mode & Inode::Mode::TYPE_MASK) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RamFileSystem& m_fs;
|
RamFileSystem& m_fs;
|
||||||
FullInodeInfo m_inode_info;
|
FullInodeInfo m_inode_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RamFileInode : public RamInode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static BAN::ErrorOr<BAN::RefPtr<RamFileInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
|
||||||
|
~RamFileInode() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RamFileInode(RamFileSystem&, const FullInodeInfo&);
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
|
||||||
|
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
|
||||||
|
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||||
|
|
||||||
|
private:
|
||||||
BAN::Vector<uint8_t> m_data;
|
BAN::Vector<uint8_t> m_data;
|
||||||
|
|
||||||
friend class RamFileSystem;
|
friend class RamFileSystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RamDirectoryInode final : public RamInode
|
class RamDirectoryInode : public RamInode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
|
static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
|
||||||
|
@ -74,12 +89,12 @@ namespace Kernel
|
||||||
BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>);
|
BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
RamDirectoryInode(RamFileSystem&, const FullInodeInfo&, ino_t parent);
|
||||||
|
|
||||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
||||||
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override;
|
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override;
|
||||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||||
|
virtual BAN::ErrorOr<void> delete_inode_impl(BAN::StringView) override;
|
||||||
private:
|
|
||||||
RamDirectoryInode(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t m_name_max = NAME_MAX;
|
static constexpr size_t m_name_max = NAME_MAX;
|
||||||
|
@ -88,11 +103,12 @@ namespace Kernel
|
||||||
char name[m_name_max + 1];
|
char name[m_name_max + 1];
|
||||||
size_t name_len = 0;
|
size_t name_len = 0;
|
||||||
ino_t ino;
|
ino_t ino;
|
||||||
|
uint8_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Vector<Entry> m_entries;
|
BAN::Vector<Entry> m_entries;
|
||||||
ino_t m_parent;
|
const ino_t m_parent;
|
||||||
|
|
||||||
friend class RamFileSystem;
|
friend class RamFileSystem;
|
||||||
};
|
};
|
||||||
|
@ -111,7 +127,7 @@ namespace Kernel
|
||||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RamSymlinkInode(RamFileSystem&, mode_t, uid_t, gid_t);
|
RamSymlinkInode(RamFileSystem&, const FullInodeInfo&, BAN::String&&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::String m_target;
|
BAN::String m_target;
|
||||||
|
|
|
@ -37,6 +37,8 @@ namespace Kernel
|
||||||
size_t size() const { return m_size; }
|
size_t size() const { return m_size; }
|
||||||
vaddr_t vaddr() const { return m_vaddr; }
|
vaddr_t vaddr() const { return m_vaddr; }
|
||||||
|
|
||||||
|
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
|
||||||
|
|
||||||
// Returns error if no memory was available
|
// Returns error if no memory was available
|
||||||
// Returns true if page was succesfully allocated
|
// Returns true if page was succesfully allocated
|
||||||
// Returns false if page was already allocated
|
// Returns false if page was already allocated
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
|
#include <sys/banan-os.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
|
@ -138,6 +139,8 @@ namespace Kernel
|
||||||
|
|
||||||
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
|
||||||
|
|
||||||
|
void get_meminfo(proc_meminfo_t*) const;
|
||||||
|
|
||||||
bool is_userspace() const { return m_is_userspace; }
|
bool is_userspace() const { return m_is_userspace; }
|
||||||
const userspace_info_t& userspace_info() const { return m_userspace_info; }
|
const userspace_info_t& userspace_info() const { return m_userspace_info; }
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ namespace Kernel
|
||||||
|
|
||||||
bool is_userspace() const { return m_is_userspace; }
|
bool is_userspace() const { return m_is_userspace; }
|
||||||
|
|
||||||
|
size_t virtual_page_count() const { return m_stack->size() / PAGE_SIZE; }
|
||||||
|
|
||||||
#if __enable_sse
|
#if __enable_sse
|
||||||
void save_sse() { asm volatile("fxsave %0" :: "m"(m_sse_storage)); }
|
void save_sse() { asm volatile("fxsave %0" :: "m"(m_sse_storage)); }
|
||||||
void load_sse() { asm volatile("fxrstor %0" :: "m"(m_sse_storage)); }
|
void load_sse() { asm volatile("fxrstor %0" :: "m"(m_sse_storage)); }
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
Device::Device(mode_t mode, uid_t uid, gid_t gid)
|
Device::Device(mode_t mode, uid_t uid, gid_t gid)
|
||||||
: RamInode(DevFileSystem::get(), mode, uid, gid)
|
: RamInode(DevFileSystem::get(), FullInodeInfo(DevFileSystem::get(), mode, uid, gid))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ namespace Kernel
|
||||||
s_instance = new DevFileSystem(1024 * 1024);
|
s_instance = new DevFileSystem(1024 * 1024);
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
|
|
||||||
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, Inode::Mode::IFDIR | 0755, 0, 0));
|
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0755, 0, 0));
|
||||||
MUST(s_instance->set_root_inode(root_inode));
|
MUST(s_instance->set_root_inode(root_inode));
|
||||||
|
|
||||||
s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0)));
|
s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0)));
|
||||||
|
|
|
@ -291,6 +291,7 @@ namespace Kernel
|
||||||
if (entry.inode)
|
if (entry.inode)
|
||||||
{
|
{
|
||||||
ptr->dirent.d_ino = entry.inode;
|
ptr->dirent.d_ino = entry.inode;
|
||||||
|
ptr->dirent.d_type = entry.file_type;
|
||||||
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
|
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
|
||||||
memcpy(ptr->dirent.d_name, entry.name, entry.name_len);
|
memcpy(ptr->dirent.d_name, entry.name, entry.name_len);
|
||||||
ptr->dirent.d_name[entry.name_len] = '\0';
|
ptr->dirent.d_name[entry.name_len] = '\0';
|
||||||
|
|
|
@ -84,6 +84,15 @@ namespace Kernel
|
||||||
return create_file_impl(name, mode, uid, gid);
|
return create_file_impl(name, mode, uid, gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> Inode::delete_inode(BAN::StringView name)
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
Thread::TerminateBlocker blocker(Thread::current());
|
||||||
|
if (!mode().ifdir())
|
||||||
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
|
return delete_inode_impl(name);
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> Inode::link_target()
|
BAN::ErrorOr<BAN::String> Inode::link_target()
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/ProcFS/Inode.h>
|
||||||
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
|
#include <kernel/LockGuard.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
static ProcFileSystem* s_instance = nullptr;
|
||||||
|
|
||||||
|
void ProcFileSystem::initialize()
|
||||||
|
{
|
||||||
|
ASSERT(s_instance == nullptr);
|
||||||
|
s_instance = new ProcFileSystem(1024 * 1024);
|
||||||
|
ASSERT(s_instance);
|
||||||
|
|
||||||
|
s_instance->m_root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0555, 0, 0));
|
||||||
|
MUST(s_instance->set_root_inode(s_instance->m_root_inode));
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcFileSystem& ProcFileSystem::get()
|
||||||
|
{
|
||||||
|
ASSERT(s_instance);
|
||||||
|
return *s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcFileSystem::ProcFileSystem(size_t size)
|
||||||
|
: RamFileSystem(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> ProcFileSystem::on_process_create(Process& process)
|
||||||
|
{
|
||||||
|
auto path = BAN::String::formatted("{}", process.pid());
|
||||||
|
auto inode = TRY(ProcPidInode::create(process, *this, 0555, 0, 0));
|
||||||
|
TRY(m_root_inode->add_inode(path, inode));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcFileSystem::on_process_delete(Process& process)
|
||||||
|
{
|
||||||
|
auto path = BAN::String::formatted("{}", process.pid());
|
||||||
|
MUST(m_root_inode->delete_inode(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <kernel/FS/ProcFS/Inode.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<ProcPidInode>> ProcPidInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
|
|
||||||
|
auto* inode_ptr = new ProcPidInode(process, fs, inode_info);
|
||||||
|
if (inode_ptr == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
auto inode = BAN::RefPtr<ProcPidInode>::adopt(inode_ptr);
|
||||||
|
|
||||||
|
TRY(inode->add_inode("meminfo"sv, MUST(ProcMemInode::create(process, fs, 0755, 0, 0))));
|
||||||
|
|
||||||
|
return inode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcPidInode::ProcPidInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info)
|
||||||
|
: RamDirectoryInode(fs, inode_info, fs.root_inode()->ino())
|
||||||
|
, m_process(process)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<ProcMemInode>> ProcMemInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
|
|
||||||
|
auto* inode_ptr = new ProcMemInode(process, fs, inode_info);
|
||||||
|
if (inode_ptr == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return BAN::RefPtr<ProcMemInode>::adopt(inode_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcMemInode::ProcMemInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info)
|
||||||
|
: RamInode(fs, inode_info)
|
||||||
|
, m_process(process)
|
||||||
|
{
|
||||||
|
m_inode_info.mode |= Inode::Mode::IFREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> ProcMemInode::read_impl(off_t offset, void* buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
ASSERT(offset >= 0);
|
||||||
|
if ((size_t)offset >= sizeof(proc_meminfo_t))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
proc_meminfo_t meminfo;
|
||||||
|
m_process.get_meminfo(&meminfo);
|
||||||
|
|
||||||
|
size_t bytes = BAN::Math::min<size_t>(buffer_size, sizeof(meminfo) - offset);
|
||||||
|
memcpy(buffer, &meminfo, bytes);
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,42 +5,50 @@
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
RamInode::FullInodeInfo::FullInodeInfo(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
|
||||||
RAM INODE
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<RamInode>> RamInode::create(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
|
||||||
{
|
|
||||||
ASSERT(Mode(mode).ifreg());
|
|
||||||
auto* ram_inode = new RamInode(fs, mode, uid, gid);
|
|
||||||
if (ram_inode == nullptr)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
return BAN::RefPtr<RamInode>::adopt(ram_inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
RamInode::RamInode(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
|
||||||
: m_fs(fs)
|
|
||||||
{
|
{
|
||||||
timespec current_time = SystemTimer::get().real_time();
|
timespec current_time = SystemTimer::get().real_time();
|
||||||
|
|
||||||
m_inode_info.ino = fs.next_ino();
|
this->ino = fs.next_ino();
|
||||||
m_inode_info.mode = mode;
|
this->mode = mode;
|
||||||
m_inode_info.nlink = 1;
|
this->nlink = 1;
|
||||||
m_inode_info.uid = uid;
|
this->uid = uid;
|
||||||
m_inode_info.gid = gid;
|
this->gid = gid;
|
||||||
m_inode_info.size = 0;
|
this->size = 0;
|
||||||
m_inode_info.atime = current_time;
|
this->atime = current_time;
|
||||||
m_inode_info.mtime = current_time;
|
this->mtime = current_time;
|
||||||
m_inode_info.ctime = current_time;
|
this->ctime = current_time;
|
||||||
m_inode_info.blksize = fs.blksize();
|
this->blksize = fs.blksize();
|
||||||
m_inode_info.blocks = 0;
|
this->blocks = 0;
|
||||||
m_inode_info.dev = 0;
|
|
||||||
m_inode_info.rdev = 0;
|
// TODO
|
||||||
|
this->dev = 0;
|
||||||
|
this->rdev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> RamInode::read_impl(off_t offset, void* buffer, size_t bytes)
|
/*
|
||||||
|
|
||||||
|
RAM FILE INODE
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<RamFileInode>> RamFileInode::create(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
|
|
||||||
|
auto* ram_inode = new RamFileInode(fs, inode_info);
|
||||||
|
if (ram_inode == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
return BAN::RefPtr<RamFileInode>::adopt(ram_inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
RamFileInode::RamFileInode(RamFileSystem& fs, const FullInodeInfo& inode_info)
|
||||||
|
: RamInode(fs, inode_info)
|
||||||
|
{
|
||||||
|
m_inode_info.mode |= Inode::Mode::IFREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<size_t> RamFileInode::read_impl(off_t offset, void* buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
ASSERT(offset >= 0);
|
ASSERT(offset >= 0);
|
||||||
if (offset >= size())
|
if (offset >= size())
|
||||||
|
@ -50,7 +58,7 @@ namespace Kernel
|
||||||
return to_copy;
|
return to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> RamInode::write_impl(off_t offset, const void* buffer, size_t bytes)
|
BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, const void* buffer, size_t bytes)
|
||||||
{
|
{
|
||||||
ASSERT(offset >= 0);
|
ASSERT(offset >= 0);
|
||||||
if (offset + bytes > (size_t)size())
|
if (offset + bytes > (size_t)size())
|
||||||
|
@ -59,7 +67,7 @@ namespace Kernel
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> RamInode::truncate_impl(size_t new_size)
|
BAN::ErrorOr<void> RamFileInode::truncate_impl(size_t new_size)
|
||||||
{
|
{
|
||||||
TRY(m_data.resize(new_size, 0));
|
TRY(m_data.resize(new_size, 0));
|
||||||
m_inode_info.size = m_data.size();
|
m_inode_info.size = m_data.size();
|
||||||
|
@ -75,30 +83,31 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> RamDirectoryInode::create(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> RamDirectoryInode::create(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
ASSERT(Mode(mode).ifdir());
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
auto* ram_inode = new RamDirectoryInode(fs, parent, mode, uid, gid);
|
|
||||||
|
// "." links to this
|
||||||
|
inode_info.nlink++;
|
||||||
|
|
||||||
|
// ".." links to this or parent
|
||||||
|
if (parent)
|
||||||
|
TRY(fs.get_inode(parent))->add_link();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inode_info.nlink++;
|
||||||
|
parent = inode_info.ino;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* ram_inode = new RamDirectoryInode(fs, inode_info, parent);
|
||||||
if (ram_inode == nullptr)
|
if (ram_inode == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
return BAN::RefPtr<RamDirectoryInode>::adopt(ram_inode);
|
return BAN::RefPtr<RamDirectoryInode>::adopt(ram_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid)
|
RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, const FullInodeInfo& inode_info, ino_t parent)
|
||||||
: RamInode(fs, mode, uid, gid)
|
: RamInode(fs, inode_info)
|
||||||
|
, m_parent(parent)
|
||||||
{
|
{
|
||||||
// "." links to this
|
m_inode_info.mode |= Inode::Mode::IFDIR;
|
||||||
m_inode_info.nlink++;
|
|
||||||
|
|
||||||
// ".." links to this, if there is no parent
|
|
||||||
if (parent == 0)
|
|
||||||
{
|
|
||||||
m_inode_info.nlink++;
|
|
||||||
m_parent = ino();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MUST(fs.get_inode(parent))->add_link();
|
|
||||||
m_parent = parent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::find_inode_impl(BAN::StringView name)
|
BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::find_inode_impl(BAN::StringView name)
|
||||||
|
@ -151,6 +160,7 @@ namespace Kernel
|
||||||
// "."
|
// "."
|
||||||
{
|
{
|
||||||
ptr->dirent.d_ino = ino();
|
ptr->dirent.d_ino = ino();
|
||||||
|
ptr->dirent.d_type = DT_DIR;
|
||||||
ptr->rec_len = sizeof(DirectoryEntry) + 2;
|
ptr->rec_len = sizeof(DirectoryEntry) + 2;
|
||||||
strcpy(ptr->dirent.d_name, ".");
|
strcpy(ptr->dirent.d_name, ".");
|
||||||
ptr = ptr->next();
|
ptr = ptr->next();
|
||||||
|
@ -159,6 +169,7 @@ namespace Kernel
|
||||||
// ".."
|
// ".."
|
||||||
{
|
{
|
||||||
ptr->dirent.d_ino = m_parent;
|
ptr->dirent.d_ino = m_parent;
|
||||||
|
ptr->dirent.d_type = DT_DIR;
|
||||||
ptr->rec_len = sizeof(DirectoryEntry) + 3;
|
ptr->rec_len = sizeof(DirectoryEntry) + 3;
|
||||||
strcpy(ptr->dirent.d_name, "..");
|
strcpy(ptr->dirent.d_name, "..");
|
||||||
ptr = ptr->next();
|
ptr = ptr->next();
|
||||||
|
@ -167,6 +178,7 @@ namespace Kernel
|
||||||
for (auto& entry : m_entries)
|
for (auto& entry : m_entries)
|
||||||
{
|
{
|
||||||
ptr->dirent.d_ino = entry.ino;
|
ptr->dirent.d_ino = entry.ino;
|
||||||
|
ptr->dirent.d_type = entry.type;
|
||||||
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
|
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
|
||||||
strcpy(ptr->dirent.d_name, entry.name);
|
strcpy(ptr->dirent.d_name, entry.name);
|
||||||
ptr = ptr->next();
|
ptr = ptr->next();
|
||||||
|
@ -181,7 +193,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
BAN::RefPtr<RamInode> inode;
|
BAN::RefPtr<RamInode> inode;
|
||||||
if (Mode(mode).ifreg())
|
if (Mode(mode).ifreg())
|
||||||
inode = TRY(RamInode::create(m_fs, mode, uid, gid));
|
inode = TRY(RamFileInode::create(m_fs, mode, uid, gid));
|
||||||
else if (Mode(mode).ifdir())
|
else if (Mode(mode).ifdir())
|
||||||
inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid));
|
inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid));
|
||||||
else
|
else
|
||||||
|
@ -192,6 +204,25 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t get_type(Inode::Mode mode)
|
||||||
|
{
|
||||||
|
if (mode.ifreg())
|
||||||
|
return DT_REG;
|
||||||
|
if (mode.ifdir())
|
||||||
|
return DT_DIR;
|
||||||
|
if (mode.ifchr())
|
||||||
|
return DT_CHR;
|
||||||
|
if (mode.ifblk())
|
||||||
|
return DT_BLK;
|
||||||
|
if (mode.ififo())
|
||||||
|
return DT_FIFO;
|
||||||
|
if (mode.ifsock())
|
||||||
|
return DT_SOCK;
|
||||||
|
if (mode.iflnk())
|
||||||
|
return DT_LNK;
|
||||||
|
return DT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode)
|
BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode)
|
||||||
{
|
{
|
||||||
if (name.size() > m_name_max)
|
if (name.size() > m_name_max)
|
||||||
|
@ -206,6 +237,7 @@ namespace Kernel
|
||||||
strcpy(entry.name, name.data());
|
strcpy(entry.name, name.data());
|
||||||
entry.name_len = name.size();
|
entry.name_len = name.size();
|
||||||
entry.ino = inode->ino();
|
entry.ino = inode->ino();
|
||||||
|
entry.type = get_type(inode->mode());
|
||||||
|
|
||||||
if (auto ret = m_fs.add_inode(inode); ret.is_error())
|
if (auto ret = m_fs.add_inode(inode); ret.is_error())
|
||||||
{
|
{
|
||||||
|
@ -216,26 +248,44 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> RamDirectoryInode::delete_inode_impl(BAN::StringView name)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_entries.size(); i++)
|
||||||
|
{
|
||||||
|
if (name == m_entries[i].name)
|
||||||
|
{
|
||||||
|
m_entries.remove(i);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RAM SYMLINK INODE
|
RAM SYMLINK INODE
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::RefPtr<RamSymlinkInode>> RamSymlinkInode::create(RamFileSystem& fs, BAN::StringView target, mode_t mode, uid_t uid, gid_t gid)
|
BAN::ErrorOr<BAN::RefPtr<RamSymlinkInode>> RamSymlinkInode::create(RamFileSystem& fs, BAN::StringView target_sv, mode_t mode, uid_t uid, gid_t gid)
|
||||||
{
|
{
|
||||||
ASSERT(Mode(mode).iflnk());
|
FullInodeInfo inode_info(fs, mode, uid, gid);
|
||||||
auto* ram_inode = new RamSymlinkInode(fs, mode, uid, gid);
|
|
||||||
|
BAN::String target_str;
|
||||||
|
TRY(target_str.append(target_sv));
|
||||||
|
|
||||||
|
auto* ram_inode = new RamSymlinkInode(fs, inode_info, BAN::move(target_str));
|
||||||
if (ram_inode == nullptr)
|
if (ram_inode == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
auto ref_ptr = BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode);
|
return BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode);
|
||||||
TRY(ref_ptr->set_link_target(target));
|
|
||||||
return ref_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
|
RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, const FullInodeInfo& inode_info, BAN::String&& target)
|
||||||
: RamInode(fs, mode, uid, gid)
|
: RamInode(fs, inode_info)
|
||||||
{ }
|
, m_target(BAN::move(target))
|
||||||
|
{
|
||||||
|
m_inode_info.mode |= Inode::Mode::IFLNK;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl()
|
BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl()
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/FS/Ext2/FileSystem.h>
|
#include <kernel/FS/Ext2/FileSystem.h>
|
||||||
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
#include <kernel/FS/RamFS/FileSystem.h>
|
#include <kernel/FS/RamFS/FileSystem.h>
|
||||||
#include <kernel/FS/RamFS/Inode.h>
|
#include <kernel/FS/RamFS/Inode.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
|
@ -26,14 +27,12 @@ namespace Kernel
|
||||||
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
|
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
|
||||||
|
|
||||||
Credentials root_creds { 0, 0, 0, 0 };
|
Credentials root_creds { 0, 0, 0, 0 };
|
||||||
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"));
|
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"sv));
|
||||||
|
|
||||||
mode_t tmpfs_mode = Inode::Mode::IFDIR
|
MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"sv));
|
||||||
| Inode::Mode::IRUSR | Inode::Mode::IWUSR | Inode::Mode::IXUSR
|
|
||||||
| Inode::Mode::IRGRP | Inode::Mode::IWGRP | Inode::Mode::IXGRP
|
auto* tmpfs = MUST(RamFileSystem::create(1024 * 1024, 0777, 0, 0));
|
||||||
| Inode::Mode::IROTH | Inode::Mode::IWOTH | Inode::Mode::IXOTH;
|
MUST(s_instance->mount(root_creds, tmpfs, "/tmp"sv));
|
||||||
auto* tmpfs = MUST(RamFileSystem::create(1024 * 1024, tmpfs_mode, 0, 0));
|
|
||||||
MUST(s_instance->mount(root_creds, tmpfs, "/tmp"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualFileSystem& VirtualFileSystem::get()
|
VirtualFileSystem& VirtualFileSystem::get()
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <kernel/CriticalScope.h>
|
#include <kernel/CriticalScope.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
|
@ -81,6 +82,8 @@ namespace Kernel
|
||||||
auto* process = new Process(credentials, pid, parent, sid, pgrp);
|
auto* process = new Process(credentials, pid, parent, sid, pgrp);
|
||||||
ASSERT(process);
|
ASSERT(process);
|
||||||
|
|
||||||
|
MUST(ProcFileSystem::get().on_process_create(*process));
|
||||||
|
|
||||||
return process;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +197,8 @@ namespace Kernel
|
||||||
s_processes.remove(i);
|
s_processes.remove(i);
|
||||||
s_process_lock.unlock();
|
s_process_lock.unlock();
|
||||||
|
|
||||||
|
ProcFileSystem::get().on_process_delete(*this);
|
||||||
|
|
||||||
m_lock.lock();
|
m_lock.lock();
|
||||||
m_exit_status.exited = true;
|
m_exit_status.exited = true;
|
||||||
while (m_exit_status.waiting > 0)
|
while (m_exit_status.waiting > 0)
|
||||||
|
@ -247,6 +252,21 @@ namespace Kernel
|
||||||
thread->set_terminating();
|
thread->set_terminating();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Process::get_meminfo(proc_meminfo_t* out) const
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
|
out->page_size = PAGE_SIZE;
|
||||||
|
|
||||||
|
out->virt_pages = 0;
|
||||||
|
for (auto* thread : m_threads)
|
||||||
|
out->virt_pages += thread->virtual_page_count();
|
||||||
|
for (auto& region : m_mapped_regions)
|
||||||
|
out->virt_pages += region->virtual_page_count();
|
||||||
|
if (m_loadable_elf)
|
||||||
|
out->virt_pages += m_loadable_elf->virtual_page_count();
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_exit(int status)
|
BAN::ErrorOr<long> Process::sys_exit(int status)
|
||||||
{
|
{
|
||||||
exit(status, 0);
|
exit(status, 0);
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Kernel
|
||||||
if (inode_or_error.is_error())
|
if (inode_or_error.is_error())
|
||||||
{
|
{
|
||||||
if (inode_or_error.error().get_error_code() == ENOENT)
|
if (inode_or_error.error().get_error_code() == ENOENT)
|
||||||
DevFileSystem::get().add_device("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), S_IFLNK | 0666, 0, 0)));
|
DevFileSystem::get().add_device("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), 0666, 0, 0)));
|
||||||
else
|
else
|
||||||
dwarnln("{}", inode_or_error.error());
|
dwarnln("{}", inode_or_error.error());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <kernel/Arch.h>
|
#include <kernel/Arch.h>
|
||||||
#include <kernel/Debug.h>
|
#include <kernel/Debug.h>
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
|
#include <kernel/FS/ProcFS/FileSystem.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/GDT.h>
|
#include <kernel/GDT.h>
|
||||||
#include <kernel/IDT.h>
|
#include <kernel/IDT.h>
|
||||||
|
@ -131,6 +132,9 @@ extern "C" void kernel_main()
|
||||||
DevFileSystem::initialize();
|
DevFileSystem::initialize();
|
||||||
dprintln("devfs initialized");
|
dprintln("devfs initialized");
|
||||||
|
|
||||||
|
ProcFileSystem::initialize();
|
||||||
|
dprintln("procfs initialized");
|
||||||
|
|
||||||
if (Serial::has_devices())
|
if (Serial::has_devices())
|
||||||
{
|
{
|
||||||
Serial::initialize_devices();
|
Serial::initialize_devices();
|
||||||
|
|
|
@ -13,9 +13,19 @@ __BEGIN_DECLS
|
||||||
struct __DIR;
|
struct __DIR;
|
||||||
typedef struct __DIR DIR;
|
typedef struct __DIR DIR;
|
||||||
|
|
||||||
|
#define DT_UNKNOWN 0
|
||||||
|
#define DT_REG 1
|
||||||
|
#define DT_DIR 2
|
||||||
|
#define DT_CHR 3
|
||||||
|
#define DT_BLK 4
|
||||||
|
#define DT_FIFO 5
|
||||||
|
#define DT_SOCK 6
|
||||||
|
#define DT_LNK 7
|
||||||
|
|
||||||
struct dirent
|
struct dirent
|
||||||
{
|
{
|
||||||
ino_t d_ino; /* File serial number. */
|
ino_t d_ino; /* File serial number. */
|
||||||
|
unsigned char d_type; /* File type. One of DT_* definitions. */
|
||||||
char d_name[]; /* Filename string of entry. */
|
char d_name[]; /* Filename string of entry. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define __need_size_t 1
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define TTY_CMD_SET 0x01
|
#define TTY_CMD_SET 0x01
|
||||||
#define TTY_CMD_UNSET 0x02
|
#define TTY_CMD_UNSET 0x02
|
||||||
|
|
||||||
|
@ -14,6 +17,12 @@ __BEGIN_DECLS
|
||||||
#define POWEROFF_SHUTDOWN 0
|
#define POWEROFF_SHUTDOWN 0
|
||||||
#define POWEROFF_REBOOT 1
|
#define POWEROFF_REBOOT 1
|
||||||
|
|
||||||
|
struct proc_meminfo_t
|
||||||
|
{
|
||||||
|
size_t page_size;
|
||||||
|
size_t virt_pages;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fildes: refers to valid tty device
|
fildes: refers to valid tty device
|
||||||
command: one of TTY_CMD_* definitions
|
command: one of TTY_CMD_* definitions
|
||||||
|
|
|
@ -62,12 +62,18 @@ int strcmp(const char* s1, const char* s2)
|
||||||
return *u1 - *u2;
|
return *u1 - *u2;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* strcpy(char* __restrict__ dest, const char* __restrict__ src)
|
char* stpcpy(char* __restrict__ dest, const char* __restrict__ src)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i = 0;
|
||||||
for (i = 0; src[i]; i++)
|
for (; src[i]; i++)
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
dest[i] = '\0';
|
dest[i] = '\0';
|
||||||
|
return &dest[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char* strcpy(char* __restrict__ dest, const char* __restrict__ src)
|
||||||
|
{
|
||||||
|
stpcpy(dest, src);
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ set(USERSPACE_PROJECTS
|
||||||
id
|
id
|
||||||
init
|
init
|
||||||
ls
|
ls
|
||||||
|
meminfo
|
||||||
mmap-shared-test
|
mmap-shared-test
|
||||||
poweroff
|
poweroff
|
||||||
Shell
|
Shell
|
||||||
|
|
|
@ -700,12 +700,18 @@ BAN::String get_prompt()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
|
{
|
||||||
|
static char* username = nullptr;
|
||||||
|
if (username == nullptr)
|
||||||
{
|
{
|
||||||
auto* passwd = getpwuid(geteuid());
|
auto* passwd = getpwuid(geteuid());
|
||||||
if (passwd == nullptr)
|
if (passwd == nullptr)
|
||||||
break;
|
break;
|
||||||
MUST(prompt.append(passwd->pw_name));
|
username = new char[strlen(passwd->pw_name) + 1];
|
||||||
|
strcpy(username, passwd->pw_name);
|
||||||
endpwent();
|
endpwent();
|
||||||
|
}
|
||||||
|
MUST(prompt.append(username));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'h':
|
case 'h':
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
|
project(meminfo CXX)
|
||||||
|
|
||||||
|
set(SOURCES
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(meminfo ${SOURCES})
|
||||||
|
target_compile_options(meminfo PUBLIC -O2 -g)
|
||||||
|
target_link_libraries(meminfo PUBLIC libc)
|
||||||
|
|
||||||
|
add_custom_target(meminfo-install
|
||||||
|
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/meminfo ${BANAN_BIN}/
|
||||||
|
DEPENDS meminfo
|
||||||
|
USES_TERMINAL
|
||||||
|
)
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/banan-os.h>
|
||||||
|
|
||||||
|
bool is_only_digits(const char* str)
|
||||||
|
{
|
||||||
|
while (*str)
|
||||||
|
if (!isdigit(*str++))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
DIR* proc = opendir("/proc");
|
||||||
|
if (proc == nullptr)
|
||||||
|
{
|
||||||
|
perror("opendir");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char path_buffer[128] {};
|
||||||
|
while (dirent* proc_ent = readdir(proc))
|
||||||
|
{
|
||||||
|
if (proc_ent->d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
if (!is_only_digits(proc_ent->d_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
strcpy(path_buffer, proc_ent->d_name);
|
||||||
|
strcat(path_buffer, "/meminfo");
|
||||||
|
|
||||||
|
int fd = openat(dirfd(proc), path_buffer, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
perror("openat");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_meminfo_t meminfo;
|
||||||
|
if (read(fd, &meminfo, sizeof(meminfo)) == -1)
|
||||||
|
perror("read");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("process:\n");
|
||||||
|
printf(" pid: %s\n", proc_ent->d_name);
|
||||||
|
printf(" vmem: %zu pages (%zu bytes)\n", meminfo.virt_pages, meminfo.page_size * meminfo.virt_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(proc);
|
||||||
|
}
|
Loading…
Reference in New Issue