Compare commits

...

40 Commits

Author SHA1 Message Date
Bananymous 49133dce48 Kernel: Make pipe check data every 100ms
This prevents dead lock if read-end does not detect data before blocking
why write-end already notified.
2024-12-03 21:54:27 +02:00
Bananymous 3b7b6beca5 ports: Allow using banan-os cmake toolchain file for ports 2024-12-03 20:29:38 +02:00
Bananymous 0dd81328ff ports: Unconditionally compile banan-os before building ports
This allows ports to use any banan-os library cleanly. Ninja is fast on
when everything is already compiled, so it doesn't add too much
overhead.
2024-12-03 20:29:38 +02:00
Bananymous a668593e6b ports: Don't update ports on every build
This makes using ports much less painful :)
2024-12-03 20:29:38 +02:00
Bananymous 3a5a22511a aoc2024: Implement day3 solution 2024-12-03 20:29:38 +02:00
Bananymous 86859267f0 ports/curl: remove libcurl.la file and use /dev/urandom 2024-12-03 20:29:38 +02:00
Bananymous 88c9f6d233 LibC: Make environ a weak alias
If user program defines its own global `environ` variable it will still
work :)
2024-12-03 20:29:38 +02:00
Bananymous 176693dd5a LibC: Implement wcscmp and wcsncmp 2024-12-03 16:21:54 +02:00
Bananymous 62bee04fc0 LibC: Implement dummy utime that just checks file existance 2024-12-03 16:21:18 +02:00
Bananymous 0a5aacfd87 Kernel: Allow open with O_CREAT bypass file permission checks
call to open(path, O_CREAT|O_EXCL|O_RDWR, 0444) should open file as
read-write although file is created as read-only on filesystem.
2024-12-03 16:17:34 +02:00
Bananymous 2dec3a6c95 Kernel: Add some sanity checks for existanse of threads 2024-12-03 16:16:50 +02:00
Bananymous fcc2814199 Kernel: Remove process from alarm list after it dies 2024-12-03 16:16:08 +02:00
Bananymous bc93d238dd LibC: Fix fread argument order in gethostname 2024-12-03 16:15:16 +02:00
Bananymous 79e2c5d48c LibC: Make FILE* reading buffered
There was no reason to perform a syscall for every byte read
2024-12-03 16:13:48 +02:00
Bananymous 0fab7ad63b Kernel: Fix SYS_FCNTL command handling :)
I had misunderstood how these work
2024-12-03 16:12:26 +02:00
Bananymous e6a2f55a59 Kernel: Closing file backed mmap wont expand the file size 2024-12-03 16:12:26 +02:00
Bananymous 67e9ca56ac Kernel: Create /dev/urandom -> /dev/random symlink
Most software uses urandom instead of random so this allows it work
normally.
2024-12-03 16:12:26 +02:00
Bananymous 713daf6cd3 Kernel/LibC: Add support for creating hardlinks 2024-12-03 16:12:26 +02:00
Bananymous 12abe81c6d ports/openssl: Add support for shared libraries 2024-12-03 01:46:59 +02:00
Bananymous fbcf10c86d LibC: Implement closelog and make syslog print to stddbg 2024-12-03 01:45:54 +02:00
Bananymous 415b20f884 LibC: Remove errno EEXISTS
I don't know why I had added this. It doesn't seem to be a thing on
either POSIX or linux. This was literally equivalent to EXIST
2024-12-02 20:13:38 +02:00
Bananymous d58ca5f37a Kernel/LibC: Implement symlink{,at} 2024-12-02 20:13:38 +02:00
Bananymous 11b6ee423e LibC: Define timezone structure 2024-12-02 20:13:37 +02:00
Bananymous a10ca47657 Kernel/LibC: Implement {,f}statvfs 2024-12-02 20:13:37 +02:00
Bananymous ad1f175a39 Kernel/LibC: Implement getppid 2024-12-02 20:13:37 +02:00
Bananymous fd3246113a LibC: Implement missing execlp and cleanup exec code 2024-12-02 20:13:37 +02:00
Bananymous b8013c883c LibC: Implement getpass 2024-12-02 20:13:37 +02:00
Bananymous ffcc4fd03a init: Make tty owned by logged in user 2024-12-02 20:13:37 +02:00
Bananymous 9d97964998 LibC: Fix getpwend gid field :) 2024-12-02 20:13:37 +02:00
Bananymous f0e54cdd51 LibC: Implement {asctime,ctime,gmtime,localtime}_r
Old non _r prefixed functions are now just wrappers around these new
functions :)
2024-12-02 20:13:37 +02:00
Bananymous 0360fd1efe LibC: Implement mk{,d,s}temp 2024-12-02 20:13:37 +02:00
Bananymous 4508e099ff LibC: Implement getpagesize 2024-12-02 20:13:37 +02:00
Bananymous 6ed1435aeb Kernel/LibC: Implement tcgetpgrp 2024-12-02 20:13:37 +02:00
Bananymous 6346e288ad LibC: Implement getrlimit 2024-12-02 20:13:37 +02:00
Bananymous d2b503910f userspace: fix aoc2023 and aoc2024 linking
This patch makes aoc projects not link against system libc but the cmake
libc target. This allows compilation before libc is installed
2024-12-02 20:13:37 +02:00
Bananymous 747c3b2a4b Kernel/LibC: Implement fsync 2024-12-02 20:13:37 +02:00
Bananymous cccb4e6d5e LibC: Implement basename and dirname 2024-12-02 20:13:37 +02:00
Bananymous f4c6afbdae LibC: Add definitions to LibC that are used by some ports 2024-12-02 20:13:37 +02:00
Bananymous d1ef380e6b LibC: Add missing definitions for ifreq members 2024-12-02 20:13:37 +02:00
Bananymous c02de2580d Kernel: Add support for SIOCGIFNAME ioctl 2024-12-02 20:13:37 +02:00
72 changed files with 1318 additions and 331 deletions

View File

@ -24,6 +24,8 @@ namespace Kernel
protected:
Device(mode_t, uid_t, gid_t);
virtual BAN::ErrorOr<void> fsync_impl() final override { return BAN::Error::from_errno(EINVAL); }
};
class BlockDevice : public Device
@ -31,6 +33,7 @@ namespace Kernel
public:
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) = 0;
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) = 0;
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) = 0;
virtual blksize_t blksize() const = 0;

View File

@ -11,6 +11,18 @@ namespace Kernel
class Ext2FS final : public FileSystem
{
public:
virtual unsigned long bsize() const override;
virtual unsigned long frsize() const override;
virtual fsblkcnt_t blocks() const override;
virtual fsblkcnt_t bfree() const override;
virtual fsblkcnt_t bavail() const override;
virtual fsfilcnt_t files() const override;
virtual fsfilcnt_t ffree() const override;
virtual fsfilcnt_t favail() const override;
virtual unsigned long fsid() const override;
virtual unsigned long flag() const override;
virtual unsigned long namemax() const override;
class BlockBufferWrapper
{
BAN_NON_COPYABLE(BlockBufferWrapper);
@ -67,6 +79,7 @@ namespace Kernel
BAN::ErrorOr<void> read_block(uint32_t, BlockBufferWrapper&);
BAN::ErrorOr<void> write_block(uint32_t, const BlockBufferWrapper&);
BAN::ErrorOr<void> sync_superblock();
BAN::ErrorOr<void> sync_block(uint32_t block);
BlockBufferWrapper get_block_buffer();

View File

@ -29,19 +29,24 @@ namespace Kernel
virtual dev_t dev() const override { return 0; }
virtual dev_t rdev() const override { return 0; }
virtual const FileSystem* filesystem() const override;
protected:
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
virtual BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> fsync_impl() override;
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }

View File

@ -20,6 +20,18 @@ namespace Kernel
};
public:
virtual unsigned long bsize() const override;
virtual unsigned long frsize() const override;
virtual fsblkcnt_t blocks() const override;
virtual fsblkcnt_t bfree() const override;
virtual fsblkcnt_t bavail() const override;
virtual fsfilcnt_t files() const override;
virtual fsfilcnt_t ffree() const override;
virtual fsfilcnt_t favail() const override;
virtual unsigned long fsid() const override;
virtual unsigned long flag() const override;
virtual unsigned long namemax() const override;
static BAN::ErrorOr<bool> probe(BAN::RefPtr<BlockDevice>);
static BAN::ErrorOr<BAN::RefPtr<FATFS>> create(BAN::RefPtr<BlockDevice>);
@ -45,13 +57,15 @@ namespace Kernel
// TODO: These probably should be constant variables
uint32_t root_sector_count() const { return BAN::Math::div_round_up<uint32_t>(m_bpb.root_entry_count * 32, m_bpb.bytes_per_sector); }
uint32_t fat_sector_count() const { return m_bpb.fat_size16 ? m_bpb.fat_size16 : m_bpb.ext_32.fat_size32; }
uint32_t fat_size() const { return m_bpb.fat_size16 ? m_bpb.fat_size16 : m_bpb.ext_32.fat_size32; }
uint32_t total_sector_count() const { return m_bpb.total_sectors16 ? m_bpb.total_sectors16 : m_bpb.total_sectors32; }
uint32_t data_sector_count() const { return total_sector_count() - (m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count()) + root_sector_count()); }
uint32_t data_sector_count() const { return total_sector_count() - (m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size()) + root_sector_count()); }
uint32_t cluster_count() const { return data_sector_count() / m_bpb.sectors_per_cluster; }
uint32_t first_data_sector() const { return m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count()) + root_sector_count(); }
uint32_t first_data_sector() const { return m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size()) + root_sector_count(); }
uint32_t first_fat_sector() const { return m_bpb.reserved_sector_count; }
uint8_t bits_per_fat_entry() const { return static_cast<uint8_t>(m_type); }
private:
BAN::RefPtr<BlockDevice> m_block_device;
BAN::RefPtr<FATInode> m_root_inode;

View File

@ -29,6 +29,8 @@ namespace Kernel
virtual dev_t dev() const override { return 0; }
virtual dev_t rdev() const override { return 0; }
virtual const FileSystem* filesystem() const override;
const FAT::DirectoryEntry& entry() const { return m_entry; }
protected:
@ -42,6 +44,7 @@ namespace Kernel
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
virtual bool can_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; }

View File

@ -9,6 +9,18 @@ namespace Kernel
class FileSystem : public BAN::RefCounted<FileSystem>
{
public:
virtual unsigned long bsize() const = 0;
virtual unsigned long frsize() const = 0;
virtual fsblkcnt_t blocks() const = 0;
virtual fsblkcnt_t bfree() const = 0;
virtual fsblkcnt_t bavail() const = 0;
virtual fsfilcnt_t files() const = 0;
virtual fsfilcnt_t ffree() const = 0;
virtual fsfilcnt_t favail() const = 0;
virtual unsigned long fsid() const = 0;
virtual unsigned long flag() const = 0;
virtual unsigned long namemax() const = 0;
virtual ~FileSystem() {}
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);

View File

@ -19,6 +19,8 @@
namespace Kernel
{
class FileSystem;
class FileBackedRegion;
class SharedFileData;
@ -86,15 +88,19 @@ namespace Kernel
virtual bool is_pipe() const { return false; }
virtual bool is_tty() const { return false; }
virtual const FileSystem* filesystem() const = 0;
// Directory API
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
BAN::ErrorOr<size_t> list_next_inodes(off_t, struct dirent* list, size_t list_size);
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
BAN::ErrorOr<void> unlink(BAN::StringView);
// Link API
BAN::ErrorOr<BAN::String> link_target();
BAN::ErrorOr<void> set_link_target(BAN::StringView);
// Socket API
BAN::ErrorOr<long> accept(sockaddr* address, socklen_t* address_len, int flags);
@ -111,6 +117,7 @@ namespace Kernel
BAN::ErrorOr<void> truncate(size_t);
BAN::ErrorOr<void> chmod(mode_t);
BAN::ErrorOr<void> chown(uid_t, gid_t);
BAN::ErrorOr<void> fsync();
// Select/Non blocking API
bool can_read() const;
@ -125,10 +132,12 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, 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_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Link API
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Socket API
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) { return BAN::Error::from_errno(ENOTSUP); }
@ -145,6 +154,7 @@ namespace Kernel
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> fsync_impl() = 0;
// Select/Non blocking API
virtual bool can_read_impl() const = 0;

View File

@ -30,9 +30,12 @@ namespace Kernel
virtual dev_t dev() const override { return 0; } // FIXME
virtual dev_t rdev() const override { return 0; } // FIXME
virtual const FileSystem* filesystem() const override { return nullptr; }
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
virtual bool can_write_impl() const override { return true; }

View File

@ -44,6 +44,8 @@ namespace Kernel
dev_t dev() const final override { ASSERT_NOT_REACHED(); }
dev_t rdev() const final override { ASSERT_NOT_REACHED(); }
const FileSystem* filesystem() const final override { return nullptr; }
protected:
Socket(const Info& info)
: m_info(info)
@ -51,6 +53,7 @@ namespace Kernel
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
private:
const Info m_info;

View File

@ -40,6 +40,19 @@ namespace Kernel
static constexpr size_t no_page_limit = SIZE_MAX;
public:
// FIXME: basically all of these :)
virtual unsigned long bsize() const override { return PAGE_SIZE; }
virtual unsigned long frsize() const override { return PAGE_SIZE; }
virtual fsblkcnt_t blocks() const override { return m_max_pages; }
virtual fsblkcnt_t bfree() const override { return m_max_pages - m_used_pages; }
virtual fsblkcnt_t bavail() const override { return m_max_pages - m_used_pages; }
virtual fsfilcnt_t files() const override { return PAGE_SIZE * blocks() / sizeof(TmpDirectoryEntry); }
virtual fsfilcnt_t ffree() const override { return PAGE_SIZE * bfree() / sizeof(TmpDirectoryEntry); }
virtual fsfilcnt_t favail() const override { return PAGE_SIZE * bavail() / sizeof(TmpDirectoryEntry); }
virtual unsigned long fsid() const override { return reinterpret_cast<uintptr_t>(this); }
virtual unsigned long flag() const override { return 0; }
virtual unsigned long namemax() const override { return PAGE_SIZE; }
static BAN::ErrorOr<TmpFileSystem*> create(size_t max_pages, mode_t, uid_t, gid_t);
~TmpFileSystem();

View File

@ -42,9 +42,13 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TmpInode>> create_from_existing(TmpFileSystem&, ino_t, const TmpInodeInfo&);
~TmpInode();
virtual const FileSystem* filesystem() const override;
protected:
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
void sync();
void free_all_blocks();
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };

View File

@ -8,9 +8,22 @@
namespace Kernel
{
class VirtualFileSystem : public FileSystem
class VirtualFileSystem final : public FileSystem
{
public:
virtual unsigned long bsize() const override { return 0; }
virtual unsigned long frsize() const override { return 0; }
virtual fsblkcnt_t blocks() const override { return 0; }
virtual fsblkcnt_t bfree() const override { return 0; }
virtual fsblkcnt_t bavail() const override { return 0; }
virtual fsfilcnt_t files() const override { return 0; }
virtual fsfilcnt_t ffree() const override { return 0; }
virtual fsfilcnt_t favail() const override { return 0; }
virtual unsigned long fsid() const override { return 0; }
virtual unsigned long flag() const override { return 0; }
virtual unsigned long namemax() const override { return 0; }
static void initialize(BAN::StringView);
static VirtualFileSystem& get();

View File

@ -19,6 +19,7 @@
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/statvfs.h>
#include <sys/time.h>
#include <termios.h>
@ -97,6 +98,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
BAN::ErrorOr<long> sys_getpgid(pid_t);
BAN::ErrorOr<long> sys_getppid() const { return m_parent; }
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
@ -108,9 +110,12 @@ namespace Kernel
BAN::ErrorOr<long> sys_write(int fd, const void* buffer, size_t count);
BAN::ErrorOr<long> sys_access(const char* path, int amode);
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
BAN::ErrorOr<long> sys_unlink(const char*);
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
BAN::ErrorOr<long> sys_fchmodat(int fd, const char* path, mode_t mode, int flag);
@ -143,7 +148,10 @@ namespace Kernel
BAN::ErrorOr<long> sys_truncate(int fd, off_t length);
BAN::ErrorOr<long> sys_fsync(int fd);
BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag);
BAN::ErrorOr<long> sys_fstatvfsat(int fd, const char* path, struct statvfs* buf);
BAN::ErrorOr<long> sys_realpath(const char* path, char* buffer);
@ -177,6 +185,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
BAN::ErrorOr<long> sys_termid(char*);
@ -215,6 +224,7 @@ namespace Kernel
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags);
BAN::ErrorOr<VirtualFileSystem::File> find_parent(int fd, const char* path);
BAN::ErrorOr<void> validate_string_access(const char*);
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);

View File

@ -20,10 +20,14 @@ namespace Kernel
BAN::ErrorOr<void> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
BAN::ErrorOr<void> sync();
BAN::ErrorOr<void> sync(uint64_t sector, size_t sector_count);
size_t release_clean_pages(size_t);
size_t release_pages(size_t);
void release_all_pages();
private:
BAN::ErrorOr<void> sync_cache_index(size_t index);
private:
struct PageCache
{

View File

@ -15,13 +15,14 @@ namespace Kernel
const BAN::GUID& partition_guid() const { return m_guid; }
const BAN::RefPtr<BlockDevice> device() const { return m_device; }
virtual blksize_t blksize() const { return m_device->blksize(); }
virtual blksize_t blksize() const override { return m_device->blksize(); }
BAN::ErrorOr<void> read_sectors(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer) { return read_blocks(first_block, block_count, buffer); }
BAN::ErrorOr<void> write_sectors(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer) { return write_blocks(first_block, block_count, buffer); }
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) override;
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) override;
virtual BAN::StringView name() const override { return m_name; }

View File

@ -21,11 +21,12 @@ namespace Kernel
virtual BAN::ErrorOr<void> read_blocks(uint64_t lba, size_t sector_count, BAN::ByteSpan buffer) override { return read_sectors(lba, sector_count, buffer); }
virtual BAN::ErrorOr<void> write_blocks(uint64_t lba, size_t sector_count, BAN::ConstByteSpan buffer) override { return write_sectors(lba, sector_count, buffer); }
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) override;
BAN::ErrorOr<void> read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan);
BAN::ErrorOr<void> write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan);
virtual blksize_t blksize() const { return sector_size(); }
virtual blksize_t blksize() const override { return sector_size(); }
virtual uint32_t sector_size() const = 0;
virtual uint64_t total_size() const = 0;

View File

@ -30,6 +30,9 @@ namespace Kernel
Terminated,
};
static constexpr size_t kernel_stack_size { PAGE_SIZE * 8 };
static constexpr size_t userspace_stack_size { PAGE_SIZE * 128 };
public:
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
@ -103,8 +106,6 @@ namespace Kernel
// {kernel,userspace}_stack has to be destroyed before page table
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
static constexpr size_t m_kernel_stack_size { PAGE_SIZE * 8 };
static constexpr size_t m_userspace_stack_size { PAGE_SIZE * 128 };
BAN::UniqPtr<VirtualRange> m_kernel_stack;
BAN::UniqPtr<VirtualRange> m_userspace_stack;
const pid_t m_tid { 0 };

View File

@ -31,6 +31,10 @@ namespace Kernel
s_instance->add_device(MUST(ZeroDevice::create(0666, 0, 0)));
s_instance->add_device(MUST(KeyboardDevice::create(0440, 0, 901)));
s_instance->add_device(MUST(MouseDevice::create(0440, 0, 901)));
// create symlink urandom -> random
auto urandom = MUST(TmpSymlinkInode::create_new(DevFileSystem::get(), 0777, 0, 0, "random"_sv));
s_instance->add_inode("urandom"_sv, urandom);
}
DevFileSystem& DevFileSystem::get()

View File

@ -32,6 +32,18 @@ namespace Kernel
return superblock.magic == Ext2::Enum::SUPER_MAGIC;
}
unsigned long Ext2FS::bsize() const { return block_size(); }
unsigned long Ext2FS::frsize() const { return block_size(); }
fsblkcnt_t Ext2FS::blocks() const { return m_superblock.blocks_count; }
fsblkcnt_t Ext2FS::bfree() const { return m_superblock.free_blocks_count; }
fsblkcnt_t Ext2FS::bavail() const { return m_superblock.free_blocks_count; } // FIXME
fsfilcnt_t Ext2FS::files() const { return m_superblock.inodes_count; }
fsfilcnt_t Ext2FS::ffree() const { return m_superblock.free_inodes_count; }
fsfilcnt_t Ext2FS::favail() const { return m_superblock.free_inodes_count; } // FIXME
unsigned long Ext2FS::fsid() const { return *reinterpret_cast<const unsigned long*>(m_superblock.uuid); } // FIXME?
unsigned long Ext2FS::flag() const { return 0; }
unsigned long Ext2FS::namemax() const { return 0xFF; }
BAN::ErrorOr<BAN::RefPtr<Ext2FS>> Ext2FS::create(BAN::RefPtr<BlockDevice> block_device)
{
auto ext2fs = TRY(BAN::RefPtr<Ext2FS>::create(block_device));
@ -346,6 +358,17 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> Ext2FS::sync_block(uint32_t block)
{
LockGuard _(m_mutex);
const uint32_t sector_size = m_block_device->blksize();
const uint32_t block_size = this->block_size();
const uint32_t sectors_per_block = block_size / sector_size;
return m_block_device->sync_blocks(block * sectors_per_block, sectors_per_block);
}
Ext2FS::BlockBufferWrapper Ext2FS::get_block_buffer()
{
LockGuard _(m_mutex);

View File

@ -47,6 +47,11 @@ namespace Kernel
dwarnln("Could not cleanup inode from FS: {}", ret.error());
}
const FileSystem* Ext2Inode::filesystem() const
{
return &m_fs;
}
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth)
{
if (block == 0)
@ -99,7 +104,27 @@ namespace Kernel
{
ASSERT(mode().iflnk());
if (m_inode.size < sizeof(m_inode.block))
return BAN::String((const char*)m_inode.block);
{
BAN::String result;
TRY(result.append(BAN::StringView(reinterpret_cast<const char*>(m_inode.block), m_inode.size)));
return result;
}
dwarnln("TODO: ext2 get symlink target from {} byte inode", m_inode.size);
return BAN::Error::from_errno(ENOTSUP);
}
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
{
ASSERT(mode().iflnk());
if (m_inode.size < sizeof(m_inode.block) && target.size() < sizeof(m_inode.block))
{
memset(m_inode.block, 0, sizeof(m_inode.block));
memcpy(m_inode.block, target.data(), target.size());
m_inode.size = target.size();
TRY(sync());
return {};
}
dwarnln("TODO: ext2 set symlink target to {} bytes from {} byte inode", target.size(), m_inode.size);
return BAN::Error::from_errno(ENOTSUP);
}
@ -259,6 +284,14 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
{
for (size_t i = 0; i < max_used_data_block_count(); i++)
if (const auto fs_block = TRY(fs_block_of_data_block_index(i)); fs_block.has_value())
TRY(m_fs.sync_block(fs_block.value()));
return {};
}
BAN::ErrorOr<void> Ext2Inode::cleanup_indirect_block(uint32_t block, uint32_t depth)
{
ASSERT(block);
@ -427,8 +460,15 @@ done:
if (!find_inode_impl(name).is_error())
return BAN::Error::from_errno(EEXIST);
if (!(Mode(mode).ifreg()))
switch (mode & Inode::Mode::TYPE_MASK)
{
case Inode::Mode::IFLNK:
case Inode::Mode::IFREG:
case Inode::Mode::IFIFO:
case Inode::Mode::IFSOCK:
break;
return BAN::Error::from_errno(ENOTSUP);
}
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
@ -478,6 +518,23 @@ done:
return {};
}
BAN::ErrorOr<void> Ext2Inode::link_inode_impl(BAN::StringView name, BAN::RefPtr<Inode> inode)
{
ASSERT(this->mode().ifdir());
ASSERT(!inode->mode().ifdir());
if (&m_fs != inode->filesystem())
return BAN::Error::from_errno(EXDEV);
if (!find_inode_impl(name).is_error())
return BAN::Error::from_errno(EEXIST);
auto ext2_inode = static_cast<Ext2Inode*>(inode.ptr());
TRY(link_inode_to_directory(*ext2_inode, name));
return {};
}
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
{
if (!this->mode().ifdir())
@ -494,7 +551,7 @@ done:
auto error_or = find_inode_impl(name);
if (!error_or.is_error())
return BAN::Error::from_errno(EEXISTS);
return BAN::Error::from_errno(EEXIST);
if (error_or.error().get_error_code() != ENOENT)
return error_or.error();

View File

@ -64,6 +64,18 @@ namespace Kernel
return validate_bpb(bpb_span.as<const FAT::BPB>());
}
unsigned long FATFS::bsize() const { return m_bpb.bytes_per_sector; }
unsigned long FATFS::frsize() const { return m_bpb.bytes_per_sector; }
fsblkcnt_t FATFS::blocks() const { return data_sector_count(); }
fsblkcnt_t FATFS::bfree() const { return 0; } // FIXME
fsblkcnt_t FATFS::bavail() const { return 0; } // FIXME
fsfilcnt_t FATFS::files() const { return m_bpb.number_of_fats * fat_size() * 8 / bits_per_fat_entry(); }
fsfilcnt_t FATFS::ffree() const { return 0; } // FIXME
fsfilcnt_t FATFS::favail() const { return 0; } // FIXME
unsigned long FATFS::fsid() const { return m_type == Type::FAT32 ? m_bpb.ext_32.volume_id : m_bpb.ext_12_16.volume_id; }
unsigned long FATFS::flag() const { return 0; }
unsigned long FATFS::namemax() const { return 255; }
BAN::ErrorOr<BAN::RefPtr<FATFS>> FATFS::create(BAN::RefPtr<BlockDevice> block_device)
{
// support only block devices with sectors at least 512 bytes
@ -226,7 +238,7 @@ namespace Kernel
{
if (index >= root_sector_count())
return BAN::Error::from_errno(ENOENT);
const uint32_t first_root_sector = m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count());
const uint32_t first_root_sector = m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size());
TRY(m_block_device->read_blocks(first_root_sector + index, 1, buffer));
return {};
}

View File

@ -46,6 +46,11 @@ namespace Kernel
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
}
const FileSystem* FATInode::filesystem() const
{
return &m_fs;
}
BAN::ErrorOr<void> FATInode::for_each_directory_entry(BAN::ConstByteSpan entry_span, BAN::Function<BAN::Iteration(const FAT::DirectoryEntry&)> callback)
{
ASSERT(mode().ifdir());

View File

@ -1,5 +1,6 @@
#include <kernel/FS/Inode.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h>
#include <fcntl.h>
@ -92,6 +93,16 @@ namespace Kernel
return create_directory_impl(name, mode, uid, gid);
}
BAN::ErrorOr<void> Inode::link_inode(BAN::StringView name, BAN::RefPtr<Inode> inode)
{
LockGuard _(m_mutex);
if (!this->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
if (inode->mode().ifdir())
return BAN::Error::from_errno(EINVAL);
return link_inode_impl(name, inode);
}
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
{
LockGuard _(m_mutex);
@ -110,6 +121,14 @@ namespace Kernel
return link_target_impl();
}
BAN::ErrorOr<void> Inode::set_link_target(BAN::StringView target)
{
LockGuard _(m_mutex);
if (!mode().iflnk())
return BAN::Error::from_errno(EINVAL);
return set_link_target_impl(target);
}
BAN::ErrorOr<long> Inode::accept(sockaddr* address, socklen_t* address_len, int flags)
{
LockGuard _(m_mutex);
@ -203,6 +222,15 @@ namespace Kernel
return chown_impl(uid, gid);
}
BAN::ErrorOr<void> Inode::fsync()
{
LockGuard _(m_mutex);
if (auto shared = m_shared_region.lock())
for (size_t i = 0; i < shared->pages.size(); i++)
shared->sync(i);
return fsync_impl();
}
bool Inode::can_read() const
{
LockGuard _(m_mutex);

View File

@ -49,7 +49,7 @@ namespace Kernel
if (m_writing_count == 0)
return 0;
LockFreeGuard lock_free(m_mutex);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
}
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
@ -84,7 +84,7 @@ namespace Kernel
while (m_buffer.size() - m_buffer_size < buffer.size())
{
LockFreeGuard lock_free(m_mutex);
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
}
const size_t to_copy = buffer.size();

View File

@ -41,6 +41,11 @@ namespace Kernel
/* GENERAL INODE */
const FileSystem* TmpInode::filesystem() const
{
return &m_fs;
}
dev_t TmpInode::dev() const
{
return m_fs.dev();

View File

@ -81,7 +81,8 @@ namespace Kernel
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
});
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
const size_t write_size = BAN::Math::min<size_t>(PAGE_SIZE, inode->size() - page_index * PAGE_SIZE);
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer).slice(0, write_size)); ret.is_error())
dwarnln("{}", ret.error());
}

View File

@ -95,6 +95,14 @@ namespace Kernel
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
return 0;
}
case SIOCGIFNAME:
{
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
ASSERT(m_interface->name().size() < sizeof(ifrn_name));
memcpy(ifrn_name, m_interface->name().data(), m_interface->name().size());
ifrn_name[m_interface->name().size()] = '\0';
return 0;
}
default:
return BAN::Error::from_errno(EINVAL);
}

View File

@ -202,20 +202,23 @@ namespace Kernel
{
TRY(validate_fd(fd));
constexpr int creation_flags = O_CLOEXEC | O_CREAT | O_DIRECTORY | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_TRUNC | O_TTY_INIT;
dprintln("fcntl({} ('{}'), {}, {H})", fd, m_open_files[fd]->path(), cmd, extra);
switch (cmd)
{
case F_GETFD:
return m_open_files[fd]->flags;
return m_open_files[fd]->flags & FD_CLOEXEC;
case F_SETFD:
// FIXME: validate permissions to set access flags
m_open_files[fd]->flags = extra;
m_open_files[fd]->flags &= ~FD_CLOEXEC;
m_open_files[fd]->flags |= extra & FD_CLOEXEC;
dprintln(" set CLOEXEC to {}", !!(m_open_files[fd]->flags & FD_CLOEXEC));
return 0;
case F_GETFL:
return m_open_files[fd]->flags & ~creation_flags;
return m_open_files[fd]->flags & ~(O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE);
case F_SETFL:
m_open_files[fd]->flags |= extra & ~(O_ACCMODE | creation_flags);
m_open_files[fd]->flags &= ~O_NONBLOCK;
m_open_files[fd]->flags |= extra & O_NONBLOCK;
dprintln(" set NONBLOCK to {}", !!(m_open_files[fd]->flags & O_NONBLOCK));
return 0;
default:
break;

View File

@ -228,6 +228,13 @@ namespace Kernel
s_processes.remove(i);
break;
}
for (auto it = s_alarm_processes.begin(); it != s_alarm_processes.end();)
{
if (*it == this)
it = s_alarm_processes.remove(it);
else
it++;
}
}
ProcFileSystem::get().on_process_delete(*this);
@ -286,7 +293,8 @@ namespace Kernel
child.exited = true;
parent.add_pending_signal(SIGCHLD);
Processor::scheduler().unblock_thread(parent.m_threads.front());
if (!parent.m_threads.empty())
Processor::scheduler().unblock_thread(parent.m_threads.front());
parent.m_child_exit_blocker.unblock();
@ -300,6 +308,8 @@ namespace Kernel
while (!m_threads.empty())
m_threads.front()->on_exit();
ASSERT_NOT_REACHED();
}
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
@ -368,6 +378,26 @@ namespace Kernel
return read_from_vec_of_str(m_environ, offset, buffer);
}
BAN::ErrorOr<VirtualFileSystem::File> Process::find_parent(int fd, const char* path)
{
ASSERT(m_process_lock.is_locked());
if (path)
TRY(validate_string_access(path));
if (path && path[0] == '/')
return VirtualFileSystem::get().root_file();
if (fd == AT_FDCWD)
return TRY(m_working_directory.clone());
int flags = TRY(m_open_file_descriptors.flags_of(fd));
if (!(flags & O_RDONLY) && !(flags & O_SEARCH))
return BAN::Error::from_errno(EBADF);
return TRY(m_open_file_descriptors.file_of(fd));
}
BAN::ErrorOr<VirtualFileSystem::File> Process::find_file(int fd, const char* path, int flags)
{
ASSERT(m_process_lock.is_locked());
@ -375,14 +405,7 @@ namespace Kernel
if (path)
TRY(validate_string_access(path));
VirtualFileSystem::File parent_file;
if (path && path[0] == '/')
parent_file = VirtualFileSystem::get().root_file();
else if (fd == AT_FDCWD)
parent_file = TRY(m_working_directory.clone());
else
parent_file = TRY(m_open_file_descriptors.file_of(fd));
auto parent_file = TRY(find_parent(fd, path));
auto file = path
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags))
: BAN::move(parent_file);
@ -834,6 +857,8 @@ namespace Kernel
break;
process->add_pending_signal(SIGALRM);
ASSERT(!process->m_threads.empty());
Processor::scheduler().unblock_thread(process->m_threads.front());
s_alarm_processes.remove(s_alarm_processes.begin());
@ -854,10 +879,12 @@ namespace Kernel
{
switch (mode & Inode::Mode::TYPE_MASK)
{
case Inode::Mode::IFREG: break;
case Inode::Mode::IFDIR: break;
case Inode::Mode::IFIFO: break;
case Inode::Mode::IFSOCK: break;
case Inode::Mode::IFREG:
case Inode::Mode::IFDIR:
case Inode::Mode::IFLNK:
case Inode::Mode::IFIFO:
case Inode::Mode::IFSOCK:
break;
default:
return BAN::Error::from_errno(ENOTSUP);
}
@ -925,21 +952,7 @@ namespace Kernel
TRY(validate_string_access(path));
VirtualFileSystem::File parent_file;
if (path[0] == '/')
parent_file = VirtualFileSystem::get().root_file();
else if (fd == AT_FDCWD)
parent_file = TRY(m_working_directory.clone());
else
{
int flags = TRY(m_open_file_descriptors.flags_of(fd));
if (!(flags & O_RDONLY) && !(flags & O_SEARCH))
return BAN::Error::from_errno(EBADF);
if (!TRY(m_open_file_descriptors.inode_of(fd))->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
parent_file = TRY(m_open_file_descriptors.file_of(fd));
}
auto parent_file = TRY(find_parent(fd, path));
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags | O_NOFOLLOW);
VirtualFileSystem::File file;
@ -950,7 +963,7 @@ namespace Kernel
// FIXME: There is a race condition between next two lines
TRY(create_file_or_dir(parent_file, path, (mode & 0777) | Inode::Mode::IFREG));
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags));
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags & ~O_RDWR));
}
else
{
@ -1041,6 +1054,40 @@ namespace Kernel
return 0;
}
BAN::ErrorOr<long> Process::sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
{
LockGuard _(m_process_lock);
TRY(validate_string_access(path1));
TRY(validate_string_access(path2));
auto inode = TRY(find_file(fd1, path1, flag)).inode;
if (inode->mode().ifdir())
return BAN::Error::from_errno(EISDIR);
auto parent = TRY(find_parent(fd2, path2));
BAN::RefPtr<Inode> parent_inode;
BAN::StringView file_name;
BAN::StringView path2_sv = path2;
if (auto index = path2_sv.rfind('/'); index.has_value())
{
parent_inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path2_sv.substring(0, index.value()), O_EXEC | O_WRONLY)).inode;
file_name = path2_sv.substring(index.value() + 1);
}
else
{
parent_inode = parent.inode;
file_name = path2_sv;
if (!parent_inode->can_access(m_credentials, O_WRONLY))
return BAN::Error::from_errno(EACCES);
}
ASSERT(parent_inode->mode().ifdir());
TRY(parent_inode->link_inode(file_name, inode));
return 0;
}
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
{
LockGuard _(m_process_lock);
@ -1077,6 +1124,25 @@ namespace Kernel
return byte_count;
}
BAN::ErrorOr<long> Process::sys_symlinkat(const char* path1, int fd, const char* path2)
{
LockGuard _(m_process_lock);
TRY(validate_string_access(path1));
TRY(validate_string_access(path2));
auto parent_file = TRY(find_parent(fd, path2));
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path2, O_NOFOLLOW);
if (!file_or_error.is_error())
return BAN::Error::from_errno(EEXIST);
TRY(create_file_or_dir(parent_file, path2, 0777 | Inode::Mode::IFLNK));
auto symlink = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path2, O_NOFOLLOW));
TRY(symlink.inode->set_link_target(path1));
return 0;
}
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
{
LockGuard _(m_process_lock);