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: protected:
Device(mode_t, uid_t, gid_t); 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 class BlockDevice : public Device
@ -31,6 +33,7 @@ namespace Kernel
public: public:
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) = 0; 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> 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; virtual blksize_t blksize() const = 0;

View File

@ -11,6 +11,18 @@ namespace Kernel
class Ext2FS final : public FileSystem class Ext2FS final : public FileSystem
{ {
public: 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 class BlockBufferWrapper
{ {
BAN_NON_COPYABLE(BlockBufferWrapper); BAN_NON_COPYABLE(BlockBufferWrapper);
@ -67,6 +79,7 @@ namespace Kernel
BAN::ErrorOr<void> read_block(uint32_t, BlockBufferWrapper&); BAN::ErrorOr<void> read_block(uint32_t, BlockBufferWrapper&);
BAN::ErrorOr<void> write_block(uint32_t, const BlockBufferWrapper&); BAN::ErrorOr<void> write_block(uint32_t, const BlockBufferWrapper&);
BAN::ErrorOr<void> sync_superblock(); BAN::ErrorOr<void> sync_superblock();
BAN::ErrorOr<void> sync_block(uint32_t block);
BlockBufferWrapper get_block_buffer(); BlockBufferWrapper get_block_buffer();

View File

@ -29,19 +29,24 @@ namespace Kernel
virtual dev_t dev() const override { return 0; } virtual dev_t dev() const override { return 0; }
virtual dev_t rdev() const override { return 0; } virtual dev_t rdev() const override { return 0; }
virtual const FileSystem* filesystem() const override;
protected: protected:
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<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) 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_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> 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<void> unlink_impl(BAN::StringView) override;
virtual BAN::ErrorOr<BAN::String> link_target_impl() 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> read_impl(off_t, BAN::ByteSpan) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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> truncate_impl(size_t) override;
virtual BAN::ErrorOr<void> chmod_impl(mode_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_read_impl() const override { return true; }
virtual bool can_write_impl() const override { return true; } virtual bool can_write_impl() const override { return true; }

View File

@ -20,6 +20,18 @@ namespace Kernel
}; };
public: 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<bool> probe(BAN::RefPtr<BlockDevice>);
static BAN::ErrorOr<BAN::RefPtr<FATFS>> create(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 // 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 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 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 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; } 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: private:
BAN::RefPtr<BlockDevice> m_block_device; BAN::RefPtr<BlockDevice> m_block_device;
BAN::RefPtr<FATInode> m_root_inode; 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 dev() const override { return 0; }
virtual dev_t rdev() 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; } const FAT::DirectoryEntry& entry() const { return m_entry; }
protected: protected:
@ -42,6 +44,7 @@ namespace Kernel
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) 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> truncate_impl(size_t) override;
//virtual BAN::ErrorOr<void> chmod_impl(mode_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_read_impl() const override { return true; }
virtual bool can_write_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> class FileSystem : public BAN::RefCounted<FileSystem>
{ {
public: 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() {} virtual ~FileSystem() {}
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>); static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);

View File

@ -19,6 +19,8 @@
namespace Kernel namespace Kernel
{ {
class FileSystem;
class FileBackedRegion; class FileBackedRegion;
class SharedFileData; class SharedFileData;
@ -86,15 +88,19 @@ namespace Kernel
virtual bool is_pipe() const { return false; } virtual bool is_pipe() const { return false; }
virtual bool is_tty() const { return false; } virtual bool is_tty() const { return false; }
virtual const FileSystem* filesystem() const = 0;
// Directory API // Directory API
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView); 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<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_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> 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); BAN::ErrorOr<void> unlink(BAN::StringView);
// Link API // Link API
BAN::ErrorOr<BAN::String> link_target(); BAN::ErrorOr<BAN::String> link_target();
BAN::ErrorOr<void> set_link_target(BAN::StringView);
// Socket API // Socket API
BAN::ErrorOr<long> accept(sockaddr* address, socklen_t* address_len, int flags); 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> truncate(size_t);
BAN::ErrorOr<void> chmod(mode_t); BAN::ErrorOr<void> chmod(mode_t);
BAN::ErrorOr<void> chown(uid_t, gid_t); BAN::ErrorOr<void> chown(uid_t, gid_t);
BAN::ErrorOr<void> fsync();
// Select/Non blocking API // Select/Non blocking API
bool can_read() const; 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<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_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> 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); } virtual BAN::ErrorOr<void> unlink_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); }
virtual BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Socket API // Socket API
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) { return BAN::Error::from_errno(ENOTSUP); } 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> 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> 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> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> fsync_impl() = 0;
// Select/Non blocking API // Select/Non blocking API
virtual bool can_read_impl() const = 0; 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 dev() const override { return 0; } // FIXME
virtual dev_t rdev() const override { return 0; } // FIXME virtual dev_t rdev() const override { return 0; } // FIXME
virtual const FileSystem* filesystem() const override { return nullptr; }
protected: protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) 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<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_read_impl() const override { return m_buffer_size > 0; }
virtual bool can_write_impl() const override { return true; } 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 dev() const final override { ASSERT_NOT_REACHED(); }
dev_t rdev() const final override { ASSERT_NOT_REACHED(); } dev_t rdev() const final override { ASSERT_NOT_REACHED(); }
const FileSystem* filesystem() const final override { return nullptr; }
protected: protected:
Socket(const Info& info) Socket(const Info& info)
: m_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> 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<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: private:
const Info m_info; const Info m_info;

View File

@ -40,6 +40,19 @@ namespace Kernel
static constexpr size_t no_page_limit = SIZE_MAX; static constexpr size_t no_page_limit = SIZE_MAX;
public: 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); static BAN::ErrorOr<TmpFileSystem*> create(size_t max_pages, mode_t, uid_t, gid_t);
~TmpFileSystem(); ~TmpFileSystem();

View File

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

View File

@ -8,9 +8,22 @@
namespace Kernel namespace Kernel
{ {
class VirtualFileSystem : public FileSystem class VirtualFileSystem final : public FileSystem
{ {
public: 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 void initialize(BAN::StringView);
static VirtualFileSystem& get(); static VirtualFileSystem& get();

View File

@ -19,6 +19,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/statvfs.h>
#include <sys/time.h> #include <sys/time.h>
#include <termios.h> #include <termios.h>
@ -97,6 +98,7 @@ namespace Kernel
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); } BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
BAN::ErrorOr<long> sys_getpgid(pid_t); 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> sys_getpid() const { return pid(); }
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags); 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_write(int fd, const void* buffer, size_t count);
BAN::ErrorOr<long> sys_access(const char* path, int amode); BAN::ErrorOr<long> sys_access(const char* path, int amode);
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t); 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_unlink(const char*);
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize); 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_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); 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_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_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); 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_sigpending(sigset_t* set);
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset); 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_tcsetpgrp(int fd, pid_t pgid);
BAN::ErrorOr<long> sys_termid(char*); 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); 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_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_string_access(const char*);
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write); 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> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
BAN::ErrorOr<void> sync(); 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_clean_pages(size_t);
size_t release_pages(size_t); size_t release_pages(size_t);
void release_all_pages(); void release_all_pages();
private:
BAN::ErrorOr<void> sync_cache_index(size_t index);
private: private:
struct PageCache struct PageCache
{ {

View File

@ -15,13 +15,14 @@ namespace Kernel
const BAN::GUID& partition_guid() const { return m_guid; } const BAN::GUID& partition_guid() const { return m_guid; }
const BAN::RefPtr<BlockDevice> device() const { return m_device; } 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> 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); } 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> 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> 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; } 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> 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> 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> 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); 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 uint32_t sector_size() const = 0;
virtual uint64_t total_size() const = 0; virtual uint64_t total_size() const = 0;

View File

@ -30,6 +30,9 @@ namespace Kernel
Terminated, Terminated,
}; };
static constexpr size_t kernel_stack_size { PAGE_SIZE * 8 };
static constexpr size_t userspace_stack_size { PAGE_SIZE * 128 };
public: public:
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*); static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&); static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
@ -103,8 +106,6 @@ namespace Kernel
// {kernel,userspace}_stack has to be destroyed before page table // {kernel,userspace}_stack has to be destroyed before page table
BAN::UniqPtr<PageTable> m_keep_alive_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_kernel_stack;
BAN::UniqPtr<VirtualRange> m_userspace_stack; BAN::UniqPtr<VirtualRange> m_userspace_stack;
const pid_t m_tid { 0 }; 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(ZeroDevice::create(0666, 0, 0)));
s_instance->add_device(MUST(KeyboardDevice::create(0440, 0, 901))); s_instance->add_device(MUST(KeyboardDevice::create(0440, 0, 901)));
s_instance->add_device(MUST(MouseDevice::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() DevFileSystem& DevFileSystem::get()

View File

@ -32,6 +32,18 @@ namespace Kernel
return superblock.magic == Ext2::Enum::SUPER_MAGIC; 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) BAN::ErrorOr<BAN::RefPtr<Ext2FS>> Ext2FS::create(BAN::RefPtr<BlockDevice> block_device)
{ {
auto ext2fs = TRY(BAN::RefPtr<Ext2FS>::create(block_device)); auto ext2fs = TRY(BAN::RefPtr<Ext2FS>::create(block_device));
@ -346,6 +358,17 @@ namespace Kernel
return {}; 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() Ext2FS::BlockBufferWrapper Ext2FS::get_block_buffer()
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);

View File

@ -47,6 +47,11 @@ namespace Kernel
dwarnln("Could not cleanup inode from FS: {}", ret.error()); 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) BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth)
{ {
if (block == 0) if (block == 0)
@ -99,7 +104,27 @@ namespace Kernel
{ {
ASSERT(mode().iflnk()); ASSERT(mode().iflnk());
if (m_inode.size < sizeof(m_inode.block)) 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); return BAN::Error::from_errno(ENOTSUP);
} }
@ -259,6 +284,14 @@ namespace Kernel
return {}; 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) BAN::ErrorOr<void> Ext2Inode::cleanup_indirect_block(uint32_t block, uint32_t depth)
{ {
ASSERT(block); ASSERT(block);
@ -427,8 +460,15 @@ done:
if (!find_inode_impl(name).is_error()) if (!find_inode_impl(name).is_error())
return BAN::Error::from_errno(EEXIST); 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); return BAN::Error::from_errno(ENOTSUP);
}
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid))); const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
@ -478,6 +518,23 @@ done:
return {}; 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) BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
{ {
if (!this->mode().ifdir()) if (!this->mode().ifdir())
@ -494,7 +551,7 @@ done:
auto error_or = find_inode_impl(name); auto error_or = find_inode_impl(name);
if (!error_or.is_error()) 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) if (error_or.error().get_error_code() != ENOENT)
return error_or.error(); return error_or.error();

View File

@ -64,6 +64,18 @@ namespace Kernel
return validate_bpb(bpb_span.as<const FAT::BPB>()); 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) BAN::ErrorOr<BAN::RefPtr<FATFS>> FATFS::create(BAN::RefPtr<BlockDevice> block_device)
{ {
// support only block devices with sectors at least 512 bytes // support only block devices with sectors at least 512 bytes
@ -226,7 +238,7 @@ namespace Kernel
{ {
if (index >= root_sector_count()) if (index >= root_sector_count())
return BAN::Error::from_errno(ENOENT); 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)); TRY(m_block_device->read_blocks(first_root_sector + index, 1, buffer));
return {}; return {};
} }

View File

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

View File

@ -1,5 +1,6 @@
#include <kernel/FS/Inode.h> #include <kernel/FS/Inode.h>
#include <kernel/Lock/LockGuard.h> #include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/FileBackedRegion.h>
#include <fcntl.h> #include <fcntl.h>
@ -92,6 +93,16 @@ namespace Kernel
return create_directory_impl(name, mode, uid, gid); 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) BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);
@ -110,6 +121,14 @@ namespace Kernel
return link_target_impl(); 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) BAN::ErrorOr<long> Inode::accept(sockaddr* address, socklen_t* address_len, int flags)
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);
@ -203,6 +222,15 @@ namespace Kernel
return chown_impl(uid, gid); 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 bool Inode::can_read() const
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);

View File

@ -49,7 +49,7 @@ namespace Kernel
if (m_writing_count == 0) if (m_writing_count == 0)
return 0; return 0;
LockFreeGuard lock_free(m_mutex); 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); 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()) while (m_buffer.size() - m_buffer_size < buffer.size())
{ {
LockFreeGuard lock_free(m_mutex); 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(); const size_t to_copy = buffer.size();

View File

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

View File

@ -81,7 +81,8 @@ namespace Kernel
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE); 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()); dwarnln("{}", ret.error());
} }

View File

@ -95,6 +95,14 @@ namespace Kernel
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address)); memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
return 0; 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: default:
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }

View File

@ -202,20 +202,23 @@ namespace Kernel
{ {
TRY(validate_fd(fd)); 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) switch (cmd)
{ {
case F_GETFD: case F_GETFD:
return m_open_files[fd]->flags; return m_open_files[fd]->flags & FD_CLOEXEC;
case F_SETFD: case F_SETFD:
// FIXME: validate permissions to set access flags m_open_files[fd]->flags &= ~FD_CLOEXEC;
m_open_files[fd]->flags = extra; m_open_files[fd]->flags |= extra & FD_CLOEXEC;
dprintln(" set CLOEXEC to {}", !!(m_open_files[fd]->flags & FD_CLOEXEC));
return 0; return 0;
case F_GETFL: 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: 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; return 0;
default: default:
break; break;

View File

@ -228,6 +228,13 @@ namespace Kernel
s_processes.remove(i); s_processes.remove(i);
break; 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); ProcFileSystem::get().on_process_delete(*this);
@ -286,6 +293,7 @@ namespace Kernel
child.exited = true; child.exited = true;
parent.add_pending_signal(SIGCHLD); parent.add_pending_signal(SIGCHLD);
if (!parent.m_threads.empty())
Processor::scheduler().unblock_thread(parent.m_threads.front()); Processor::scheduler().unblock_thread(parent.m_threads.front());
parent.m_child_exit_blocker.unblock(); parent.m_child_exit_blocker.unblock();
@ -300,6 +308,8 @@ namespace Kernel
while (!m_threads.empty()) while (!m_threads.empty())
m_threads.front()->on_exit(); m_threads.front()->on_exit();
ASSERT_NOT_REACHED();
} }
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const 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); 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) BAN::ErrorOr<VirtualFileSystem::File> Process::find_file(int fd, const char* path, int flags)
{ {
ASSERT(m_process_lock.is_locked()); ASSERT(m_process_lock.is_locked());
@ -375,14 +405,7 @@ namespace Kernel
if (path) if (path)
TRY(validate_string_access(path)); TRY(validate_string_access(path));
VirtualFileSystem::File parent_file; auto parent_file = TRY(find_parent(fd, path));
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 file = path auto file = path
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags)) ? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags))
: BAN::move(parent_file); : BAN::move(parent_file);
@ -834,6 +857,8 @@ namespace Kernel
break; break;
process->add_pending_signal(SIGALRM); process->add_pending_signal(SIGALRM);
ASSERT(!process->m_threads.empty());
Processor::scheduler().unblock_thread(process->m_threads.front()); Processor::scheduler().unblock_thread(process->m_threads.front());
s_alarm_processes.remove(s_alarm_processes.begin()); s_alarm_processes.remove(s_alarm_processes.begin());
@ -854,10 +879,12 @@ namespace Kernel
{ {
switch (mode & Inode::Mode::TYPE_MASK) switch (mode & Inode::Mode::TYPE_MASK)
{ {
case Inode::Mode::IFREG: break; case Inode::Mode::IFREG:
case Inode::Mode::IFDIR: break; case Inode::Mode::IFDIR:
case Inode::Mode::IFIFO: break; case Inode::Mode::IFLNK:
case Inode::Mode::IFSOCK: break; case Inode::Mode::IFIFO:
case Inode::Mode::IFSOCK:
break;
default: default:
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
} }
@ -925,21 +952,7 @@ namespace Kernel
TRY(validate_string_access(path)); TRY(validate_string_access(path));
VirtualFileSystem::File parent_file; auto parent_file = TRY(find_parent(fd, path));
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 file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags | O_NOFOLLOW); auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags | O_NOFOLLOW);
VirtualFileSystem::File file; VirtualFileSystem::File file;
@ -950,7 +963,7 @@ namespace Kernel
// FIXME: There is a race condition between next two lines // FIXME: There is a race condition between next two lines
TRY(create_file_or_dir(parent_file, path, (mode & 0777) | Inode::Mode::IFREG)); 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 else
{ {
@ -1041,6 +1054,40 @@ namespace Kernel
return 0; 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) BAN::ErrorOr<long> Process::sys_unlink(const char* path)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
@ -1077,6 +1124,25 @@ namespace Kernel
return byte_count; 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) BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
@ -1448,6 +1514,14 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_fsync(int fd)
{
LockGuard _(m_process_lock);
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
TRY(inode->fsync());
return 0;
}
BAN::ErrorOr<void> Process::mount(BAN::StringView source, BAN::StringView target) BAN::ErrorOr<void> Process::mount(BAN::StringView source, BAN::StringView target)
{ {
BAN::String absolute_source, absolute_target; BAN::String absolute_source, absolute_target;
@ -1488,6 +1562,35 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_fstatvfsat(int fd, const char* path, struct statvfs* buf)
{
LockGuard _(m_process_lock);
TRY(validate_pointer_access(buf, sizeof(struct statvfs), true));
auto inode = TRY(find_file(fd, path, 0)).inode;
auto* fs = inode->filesystem();
if (fs == nullptr)
{
ASSERT(inode->mode().ifsock() || inode->mode().ififo());
dwarnln("TODO: fstatvfs on sockets or pipe?");
return BAN::Error::from_errno(EINVAL);
}
buf->f_bsize = fs->bsize();
buf->f_frsize = fs->frsize();
buf->f_blocks = fs->blocks();
buf->f_bfree = fs->bfree();
buf->f_bavail = fs->bavail();
buf->f_files = fs->files();
buf->f_ffree = fs->ffree();
buf->f_favail = fs->favail();
buf->f_fsid = fs->fsid();
buf->f_flag = fs->flag();
buf->f_namemax = fs->namemax();
return 0;
}
BAN::ErrorOr<long> Process::sys_realpath(const char* path, char* buffer) BAN::ErrorOr<long> Process::sys_realpath(const char* path, char* buffer)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
@ -1906,6 +2009,7 @@ namespace Kernel
if (signal) if (signal)
{ {
process.add_pending_signal(signal); process.add_pending_signal(signal);
if (!process.m_threads.empty())
Processor::scheduler().unblock_thread(process.m_threads.front()); Processor::scheduler().unblock_thread(process.m_threads.front());
} }
return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue; return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue;
@ -2004,6 +2108,24 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<long> Process::sys_tcgetpgrp(int fd)
{
LockGuard _(m_process_lock);
if (!m_controlling_terminal)
return BAN::Error::from_errno(ENOTTY);
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
if (!inode->is_tty())
return BAN::Error::from_errno(ENOTTY);
auto* tty = static_cast<TTY*>(inode.ptr());
if (tty != m_controlling_terminal.ptr())
return BAN::Error::from_errno(ENOTTY);
return tty->foreground_pgrp();
}
BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgrp) BAN::ErrorOr<long> Process::sys_tcsetpgrp(int fd, pid_t pgrp)
{ {
LockGuard _(m_process_lock); LockGuard _(m_process_lock);

View File

@ -32,7 +32,7 @@ namespace Kernel
for (auto& cache : m_cache) for (auto& cache : m_cache)
{ {
if (cache.first_sector < page_cache_start) if (cache.first_sector + sectors_per_page <= page_cache_start)
continue; continue;
if (cache.first_sector > page_cache_start) if (cache.first_sector > page_cache_start)
break; break;
@ -64,7 +64,7 @@ namespace Kernel
{ {
auto& cache = m_cache[index]; auto& cache = m_cache[index];
if (cache.first_sector < page_cache_start) if (cache.first_sector + sectors_per_page <= page_cache_start)
continue; continue;
if (cache.first_sector > page_cache_start) if (cache.first_sector > page_cache_start)
break; break;
@ -104,15 +104,11 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> DiskCache::sync() BAN::ErrorOr<void> DiskCache::sync_cache_index(size_t index)
{
if (g_disable_disk_write)
return {};
for (auto& cache : m_cache)
{ {
auto& cache = m_cache[index];
if (cache.dirty_mask == 0) if (cache.dirty_mask == 0)
continue; return {};
PageTable::with_fast_page(cache.paddr, [&] { PageTable::with_fast_page(cache.paddr, [&] {
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE); memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
@ -145,6 +141,36 @@ namespace Kernel
} }
cache.dirty_mask = 0; cache.dirty_mask = 0;
return {};
}
BAN::ErrorOr<void> DiskCache::sync()
{
if (g_disable_disk_write)
return {};
for (size_t i = 0; i < m_cache.size(); i++)
TRY(sync_cache_index(i));
return {};
}
BAN::ErrorOr<void> DiskCache::sync(uint64_t sector, size_t block_count)
{
if (g_disable_disk_write)
return {};
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
uint64_t page_cache_offset = sector % sectors_per_page;
uint64_t page_cache_start = sector - page_cache_offset;
for (size_t i = 0; i < m_cache.size(); i++)
{
auto& cache = m_cache[i];
if (cache.first_sector + sectors_per_page <= page_cache_start)
continue;
if (cache.first_sector * sectors_per_page >= page_cache_start * sectors_per_page + block_count)
break;
TRY(sync_cache_index(i));
} }
return {}; return {};

View File

@ -48,6 +48,15 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> Partition::sync_blocks(uint64_t block, size_t block_count)
{
const uint32_t blocks_in_partition = m_last_block - m_first_block + 1;
if (block + block_count > blocks_in_partition)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
TRY(m_device->sync_blocks(m_first_block + block, block_count));
return {};
}
BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer) BAN::ErrorOr<size_t> Partition::read_impl(off_t offset, BAN::ByteSpan buffer)
{ {
ASSERT(offset >= 0); ASSERT(offset >= 0);

View File

@ -286,6 +286,13 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> StorageDevice::sync_blocks(uint64_t block, size_t block_count)
{
if (!m_disk_cache.has_value())
return {};
return m_disk_cache->sync(block, block_count);
}
BAN::ErrorOr<size_t> StorageDevice::read_impl(off_t offset, BAN::ByteSpan buffer) BAN::ErrorOr<size_t> StorageDevice::read_impl(off_t offset, BAN::ByteSpan buffer)
{ {
if (offset % sector_size()) if (offset % sector_size())

View File

@ -64,7 +64,7 @@ namespace Kernel
PageTable::kernel(), PageTable::kernel(),
KERNEL_OFFSET, KERNEL_OFFSET,
~(uintptr_t)0, ~(uintptr_t)0,
m_kernel_stack_size, kernel_stack_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true true
)); ));
@ -104,7 +104,7 @@ namespace Kernel
thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range( thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range(
page_table, page_table,
0x300000, KERNEL_OFFSET, 0x300000, KERNEL_OFFSET,
m_kernel_stack_size, kernel_stack_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true true
)); ));
@ -112,7 +112,7 @@ namespace Kernel
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range( thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
page_table, page_table,
0x300000, KERNEL_OFFSET, 0x300000, KERNEL_OFFSET,
m_userspace_stack_size, userspace_stack_size,
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true true
)); ));

View File

@ -158,7 +158,6 @@ const char* strerrordesc_np(int error)
case ETXTBSY: return "Text file busy."; case ETXTBSY: return "Text file busy.";
case EWOULDBLOCK: return "Operation would block."; case EWOULDBLOCK: return "Operation would block.";
case EXDEV: return "Cross-device link."; case EXDEV: return "Cross-device link.";
case EEXISTS: return "File exists";
case ENOTBLK: return "Block device required"; case ENOTBLK: return "Block device required";
case EUNKNOWN: return "Unknown error"; case EUNKNOWN: return "Unknown error";
} }

View File

@ -8,9 +8,14 @@ CONFIGURE_OPTIONS=(
'--disable-threaded-resolver' '--disable-threaded-resolver'
'--disable-ipv6' '--disable-ipv6'
'--disable-docs' '--disable-docs'
'--disable-ntlm'
'--with-openssl' '--with-openssl'
'--with-zlib' '--with-zlib'
'--with-random=/dev/random'
'--with-ca-bundle=/etc/ssl/certs/ca-certificates.crt' '--with-ca-bundle=/etc/ssl/certs/ca-certificates.crt'
'--without-ca-path' '--without-ca-path'
) )
install() {
make install DESTDIR="$BANAN_SYSROOT" || exit 1
rm -f $BANAN_SYSROOT/usr/lib/libcurl.la
}

View File

@ -6,7 +6,7 @@ if (( $# != 1 )); then
fi fi
if [[ -z $BANAN_ROOT_DIR ]]; then if [[ -z $BANAN_ROOT_DIR ]]; then
BANAN_ROOT_DIR="$(realpath $(dirname $(realpath $0))/..)" export BANAN_ROOT_DIR="$(realpath $(dirname $(realpath $0))/..)"
fi fi
source "$BANAN_ROOT_DIR/script/config.sh" source "$BANAN_ROOT_DIR/script/config.sh"
@ -29,12 +29,11 @@ export OBJDUMP="$BANAN_TOOLCHAIN_TRIPLE-objdump"
export STRIP="$BANAN_TOOLCHAIN_TRIPLE-strip" export STRIP="$BANAN_TOOLCHAIN_TRIPLE-strip"
export CXXFILT="$BANAN_TOOLCHAIN_TRIPLE-c++filt" export CXXFILT="$BANAN_TOOLCHAIN_TRIPLE-c++filt"
if [ ! -f "$BANAN_SYSROOT/usr/lib/libc.a" ]; then export CMAKE_TOOLCHAIN_FILE="$BANAN_TOOLCHAIN_DIR/Toolchain.txt"
pushd "$BANAN_ROOT_DIR" >/dev/null pushd "$BANAN_ROOT_DIR" >/dev/null
./bos libc || exit 1 ./bos all && ./bos install || exit 1
./bos install || exit 1
popd >/dev/null popd >/dev/null
fi
if [ "$BANAN_ARCH" = "i686" ]; then if [ "$BANAN_ARCH" = "i686" ]; then
export LDFLAGS="-shared-libgcc" export LDFLAGS="-shared-libgcc"

View File

@ -1,7 +1,7 @@
diff -ruN openssl-3.3.1/Configurations/10-main.conf openssl-3.3.1-banan_os/Configurations/10-main.conf diff -ruN openssl-3.3.1/Configurations/10-main.conf openssl-3.3.1-banan_os/Configurations/10-main.conf
--- openssl-3.3.1/Configurations/10-main.conf 2024-06-04 15:53:04.000000000 +0300 --- openssl-3.3.1/Configurations/10-main.conf 2024-06-04 15:53:04.000000000 +0300
+++ openssl-3.3.1-banan_os/Configurations/10-main.conf 2024-08-21 15:45:36.605293938 +0300 +++ openssl-3.3.1-banan_os/Configurations/10-main.conf 2024-12-03 01:31:59.218821407 +0200
@@ -668,6 +668,22 @@ @@ -668,6 +668,26 @@
shared_extension => ".so", shared_extension => ".so",
}, },
@ -19,8 +19,27 @@ diff -ruN openssl-3.3.1/Configurations/10-main.conf openssl-3.3.1-banan_os/Confi
+ cxxflags => "-std=c++11", + cxxflags => "-std=c++11",
+ lib_cppflags => "-DOPENSSL_USE_NODELETE", + lib_cppflags => "-DOPENSSL_USE_NODELETE",
+ bn_ops => "BN_LLONG RC4_CHAR", + bn_ops => "BN_LLONG RC4_CHAR",
+ shared_target => "banan_os-shared",
+ shared_cflag => "-fPIC",
+ shared_ldflag => sub { $disabled{pinshared} ? () : "-Wl,-znodelete" },
+ shared_extension => ".so.\$(SHLIB_VERSION_NUMBER)",
+ }, + },
+ +
#### ####
#### Variety of LINUX:-) #### Variety of LINUX:-)
#### ####
diff -ruN openssl-3.3.1/Configurations/shared-info.pl openssl-3.3.1-banan_os/Configurations/shared-info.pl
--- openssl-3.3.1/Configurations/shared-info.pl 2024-06-04 15:53:04.000000000 +0300
+++ openssl-3.3.1-banan_os/Configurations/shared-info.pl 2024-12-03 01:34:21.382067497 +0200
@@ -39,6 +39,11 @@
: '-Wl,-z,defs',
};
},
+ 'banan_os-shared' => {
+ shared_ldflag => '-shared',
+ shared_sonameflag => '-Wl,-soname=',
+ shared_defflag => '-Wl,--version-script=',
+ },
'bsd-gcc-shared' => sub { return $shared_info{'linux-shared'}; },
'bsd-gcc-nodef-shared' => sub {
return {

View File

@ -1,16 +0,0 @@
#!/bin/bash
if [ -z $BANAN_PORT_DIR ]; then
echo "You must set the BANAN_PORT_DIR environment variable" >&2
exit 1
fi
cd $(dirname $(realpath $0))
rm -f $BANAN_PORT_DIR/.installed
while IFS= read -r port; do
pushd $(dirname "$port") >/dev/null
./build.sh
popd >/dev/null
done < <(find $BANAN_PORT_DIR -name '.compile_hash')

View File

@ -49,8 +49,6 @@ create_image () {
build_target all build_target all
build_target install build_target install
$BANAN_ROOT_DIR/ports/update.sh
pushd $BANAN_SYSROOT >/dev/null pushd $BANAN_SYSROOT >/dev/null
run_fakeroot tar cf ${BANAN_SYSROOT_TAR} * run_fakeroot tar cf ${BANAN_SYSROOT_TAR} *
popd >/dev/null popd >/dev/null

View File

@ -13,12 +13,21 @@ if (NOT DEFINED ENV{BANAN_SYSROOT_TAR})
endif () endif ()
set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR}) set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR})
if (NOT DEFINED ENV{BANAN_ROOT_DIR})
set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/toolchain/local) message(FATAL_ERROR "environment variable BANAN_ROOT_DIR not defined")
endif ()
set(TOOLCHAIN_PREFIX $ENV{BANAN_ROOT_DIR}/toolchain/local)
set(CMAKE_SYSTEM_NAME banan-os) set(CMAKE_SYSTEM_NAME banan-os)
set(CMAKE_SYSTEM_PROCESSOR AMD64) set(CMAKE_SYSTEM_PROCESSOR AMD64)
set(CMAKE_SYSROOT ${BANAN_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++)

View File

@ -41,6 +41,9 @@ endforeach()
foreach(AOC2023_PROJECT ${AOC2023_PROJECTS}) foreach(AOC2023_PROJECT ${AOC2023_PROJECTS})
add_subdirectory(${AOC2023_PROJECT}) add_subdirectory(${AOC2023_PROJECT})
add_dependencies(aoc2023 aoc2023_${AOC2023_PROJECT}) add_dependencies(aoc2023 aoc2023_${AOC2023_PROJECT})
target_link_options(aoc2023_${AOC2023_PROJECT} PRIVATE -nolibc)
target_compile_options(aoc2023_${AOC2023_PROJECT} PRIVATE -g -O2 -Wall -Wextra -Werror)
endforeach() endforeach()
add_dependencies(userspace aoc2023) add_dependencies(userspace aoc2023)

View File

@ -1,6 +1,7 @@
set(AOC2024_PROJECTS set(AOC2024_PROJECTS
day1 day1
day2 day2
day3
full full
) )
@ -19,6 +20,9 @@ endforeach()
foreach(AOC2024_PROJECT ${AOC2024_PROJECTS}) foreach(AOC2024_PROJECT ${AOC2024_PROJECTS})
add_subdirectory(${AOC2024_PROJECT}) add_subdirectory(${AOC2024_PROJECT})
add_dependencies(aoc2024 aoc2024_${AOC2024_PROJECT}) add_dependencies(aoc2024 aoc2024_${AOC2024_PROJECT})
target_link_options(aoc2024_${AOC2024_PROJECT} PRIVATE -nolibc)
target_compile_options(aoc2024_${AOC2024_PROJECT} PRIVATE -g -O2 -Wall -Wextra -Werror)
endforeach() endforeach()
add_dependencies(userspace aoc2024) add_dependencies(userspace aoc2024)

View File

@ -0,0 +1,9 @@
set(SOURCES
main.cpp
)
add_executable(aoc2024_day3 ${SOURCES})
banan_include_headers(aoc2024_day3 ban)
banan_link_library(aoc2024_day3 libc)
install(TARGETS aoc2024_day3 OPTIONAL)

View File

@ -0,0 +1,152 @@
#include <BAN/String.h>
#include <inttypes.h>
#include <stdio.h>
#include <ctype.h>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
i64 part1(FILE* fp)
{
i64 result = 0;
BAN::String full_input;
{
char buffer[512];
while (fgets(buffer, sizeof(buffer), fp))
MUST(full_input.append(buffer));
}
result = 0;
for (size_t i = 0; i < full_input.size() - 4;)
{
if (!full_input.sv().substring(i).starts_with("mul("))
{
i++;
continue;
}
i += 4;
if (i >= full_input.size() || !isdigit(full_input[i]))
continue;
i64 lhs = atoll(&full_input[i]);
while (i < full_input.size() && isdigit(full_input[i]))
i++;
if (i >= full_input.size() || full_input[i] != ',')
continue;
i++;
if (i >= full_input.size() || !isdigit(full_input[i]))
continue;
int rhs = atoll(&full_input[i]);
while (i < full_input.size() && isdigit(full_input[i]))
i++;
if (i >= full_input.size() || full_input[i] != ')')
continue;
result += lhs * rhs;
}
return result;
}
i64 part2(FILE* fp)
{
i64 result = 0;
BAN::String full_input;
{
char buffer[512];
while (fgets(buffer, sizeof(buffer), fp))
MUST(full_input.append(buffer));
}
bool state = true;
result = 0;
for (size_t i = 0; i < full_input.size();)
{
if (full_input.sv().substring(i).starts_with("do()"_sv))
{
state = true;
i += 4;
continue;
}
if (full_input.sv().substring(i).starts_with("don't()"_sv))
{
state = false;
i += 6;
continue;
}
if (state == false || !full_input.sv().substring(i).starts_with("mul("))
{
i++;
continue;
}
i += 4;
if (i >= full_input.size() || !isdigit(full_input[i]))
continue;
i64 lhs = atoll(&full_input[i]);
while (i < full_input.size() && isdigit(full_input[i]))
i++;
if (i >= full_input.size() || full_input[i] != ',')
continue;
i++;
if (i >= full_input.size() || !isdigit(full_input[i]))
continue;
int rhs = atoll(&full_input[i]);
while (i < full_input.size() && isdigit(full_input[i]))
i++;
if (i >= full_input.size() || full_input[i] != ')')
continue;
result += lhs * rhs;
}
return result;
}
int main(int argc, char** argv)
{
const char* file_path = "/usr/share/aoc2024/day3_input.txt";
if (argc >= 2)
file_path = argv[1];
FILE* fp = fopen(file_path, "r");
if (fp == nullptr)
{
perror("fopen");
return 1;
}
printf("part1: %" PRId64 "\n", part1(fp));
fseek(fp, 0, SEEK_SET);
printf("part2: %" PRId64 "\n", part2(fp));
fclose(fp);
}

View File

@ -10,6 +10,7 @@ set(LIBC_SOURCES
ftw.cpp ftw.cpp
grp.cpp grp.cpp
inttypes.cpp inttypes.cpp
libgen.cpp
locale.cpp locale.cpp
malloc.cpp malloc.cpp
math.cpp math.cpp
@ -31,6 +32,7 @@ set(LIBC_SOURCES
sys/select.cpp sys/select.cpp
sys/socket.cpp sys/socket.cpp
sys/stat.cpp sys/stat.cpp
sys/statvfs.cpp
sys/time.cpp sys/time.cpp
sys/utsname.cpp sys/utsname.cpp
sys/wait.cpp sys/wait.cpp

View File

@ -89,7 +89,6 @@ __BEGIN_DECLS
#define EWOULDBLOCK 80 #define EWOULDBLOCK 80
#define EXDEV 81 #define EXDEV 81
#define ENOTBLK 82 #define ENOTBLK 82
#define EEXISTS 83
#define EUNKNOWN 0xFF #define EUNKNOWN 0xFF

View File

@ -27,8 +27,6 @@ __BEGIN_DECLS
#define F_GETOWN 10 #define F_GETOWN 10
#define F_SETOWN 11 #define F_SETOWN 11
#define FD_CLOEXEC 1
#define F_RDLCK 1 #define F_RDLCK 1
#define F_UNLCK 2 #define F_UNLCK 2
#define F_WRLCK 3 #define F_WRLCK 3
@ -38,6 +36,14 @@ __BEGIN_DECLS
#define SEEK_CUR 2 #define SEEK_CUR 2
#define SEEK_END 3 #define SEEK_END 3
/* bits 0-3 */
#define O_RDONLY 0x00001
#define O_WRONLY 0x00002
#define O_RDWR (O_RDONLY | O_WRONLY)
#define O_SEARCH 0x00004
#define O_EXEC 0x00008
#define O_ACCMODE 0x0000F
/* bits 4-11 */ /* bits 4-11 */
#define O_CLOEXEC 0x00010 #define O_CLOEXEC 0x00010
#define O_CREAT 0x00020 #define O_CREAT 0x00020
@ -47,6 +53,7 @@ __BEGIN_DECLS
#define O_NOFOLLOW 0x00200 #define O_NOFOLLOW 0x00200
#define O_TRUNC 0x00400 #define O_TRUNC 0x00400
#define O_TTY_INIT 0x00800 #define O_TTY_INIT 0x00800
#define FD_CLOEXEC O_CLOEXEC
/* bits 12-16 */ /* bits 12-16 */
#define O_APPEND 0x01000 #define O_APPEND 0x01000
@ -55,14 +62,6 @@ __BEGIN_DECLS
#define O_RSYNC 0x08000 #define O_RSYNC 0x08000
#define O_SYNC 0x10000 #define O_SYNC 0x10000
/* bits 0-3 */
#define O_RDONLY 0x00001
#define O_WRONLY 0x00002
#define O_RDWR (O_RDONLY | O_WRONLY)
#define O_SEARCH 0x00004
#define O_EXEC 0x00008
#define O_ACCMODE 0x0000F
/* bit 17 */ /* bit 17 */
#define AT_FDCWD 0x20000 #define AT_FDCWD 0x20000

View File

@ -60,6 +60,7 @@ __BEGIN_DECLS
#define OPEN_MAX 64 #define OPEN_MAX 64
#define NAME_MAX 255 #define NAME_MAX 255
#define PATH_MAX 256 #define PATH_MAX 256
#define PASS_MAX 256
#define LOGIN_NAME_MAX 256 #define LOGIN_NAME_MAX 256
#define HOST_NAME_MAX 255 #define HOST_NAME_MAX 255
#define TTY_NAME_MAX PATH_MAX #define TTY_NAME_MAX PATH_MAX

View File

@ -19,6 +19,10 @@ struct if_nameindex
struct ifreq struct ifreq
{ {
union {
char ifrn_name[IF_NAMESIZE];
} ifr_ifrn;
union { union {
struct sockaddr ifru_addr; struct sockaddr ifru_addr;
struct sockaddr ifru_netmask; struct sockaddr ifru_netmask;
@ -27,6 +31,11 @@ struct ifreq
unsigned char __min_storage[sizeof(struct sockaddr) + 6]; unsigned char __min_storage[sizeof(struct sockaddr) + 6];
} ifr_ifru; } ifr_ifru;
}; };
#define ifr_name ifr_ifrn.ifrn_name
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_netmask ifr_ifru.ifru_addrnetmask
#define ifr_gwaddr ifr_ifru.ifru_addrgwaddr
#define ifr_hwaddr ifr_ifru.ifru_addrhwaddr
#define SIOCGIFADDR 1 /* Get interface address */ #define SIOCGIFADDR 1 /* Get interface address */
#define SIOCSIFADDR 2 /* Set interface address */ #define SIOCSIFADDR 2 /* Set interface address */
@ -35,6 +44,7 @@ struct ifreq
#define SIOCGIFGWADDR 5 /* Get gateway address */ #define SIOCGIFGWADDR 5 /* Get gateway address */
#define SIOCSIFGWADDR 6 /* Set gateway address */ #define SIOCSIFGWADDR 6 /* Set gateway address */
#define SIOCGIFHWADDR 7 /* Get hardware address */ #define SIOCGIFHWADDR 7 /* Get hardware address */
#define SIOCGIFNAME 8 /* Get interface name */
void if_freenameindex(struct if_nameindex* ptr); void if_freenameindex(struct if_nameindex* ptr);
char* if_indextoname(unsigned ifindex, char* ifname); char* if_indextoname(unsigned ifindex, char* ifname);

View File

@ -42,6 +42,11 @@ __BEGIN_DECLS
#define EAI_SYSTEM 9 #define EAI_SYSTEM 9
#define EAI_OVERFLOW 10 #define EAI_OVERFLOW 10
#define HOST_NOT_FOUND 1
#define NO_DATA 2
#define NO_RECOVERY 3
#define TRY_AGAIN 4
struct hostent struct hostent
{ {
char* h_name; /* Official name of the host. */ char* h_name; /* Official name of the host. */

View File

@ -108,6 +108,8 @@ struct sigevent
#define SIGRTMIN 30 #define SIGRTMIN 30
#define SIGRTMAX (SIGRTMIN+32) #define SIGRTMAX (SIGRTMIN+32)
#define NSIG SIGRTMAX
#define SI_USER 10 #define SI_USER 10
#define SI_QUEUE 11 #define SI_QUEUE 11
#define SI_TIMER 12 #define SI_TIMER 12

View File

@ -39,13 +39,16 @@ __BEGIN_DECLS
O(SYS_DUP, dup) \ O(SYS_DUP, dup) \
O(SYS_DUP2, dup2) \ O(SYS_DUP2, dup2) \
O(SYS_KILL, kill) \ O(SYS_KILL, kill) \
O(SYS_TCGETPGRP, tcgetpgrp) \
O(SYS_TCSETPGRP, tcsetpgrp) \ O(SYS_TCSETPGRP, tcsetpgrp) \
O(SYS_GET_PPID, getppid) \
O(SYS_GET_PID, getpid) \ O(SYS_GET_PID, getpid) \
O(SYS_GET_PGID, getpgid) \ O(SYS_GET_PGID, getpgid) \
O(SYS_SET_PGID, setpgid) \ O(SYS_SET_PGID, setpgid) \
O(SYS_FCNTL, fcntl) \ O(SYS_FCNTL, fcntl) \
O(SYS_NANOSLEEP, nanosleep) \ O(SYS_NANOSLEEP, nanosleep) \
O(SYS_FSTATAT, fstatat) \ O(SYS_FSTATAT, fstatat) \
O(SYS_FSTATVFSAT, fstatvfsat) \
O(SYS_SYNC, sync) \ O(SYS_SYNC, sync) \
O(SYS_MMAP, mmap) \ O(SYS_MMAP, mmap) \
O(SYS_MUNMAP, munmap) \ O(SYS_MUNMAP, munmap) \
@ -85,6 +88,9 @@ __BEGIN_DECLS
O(SYS_SETITIMER, setitimer) \ O(SYS_SETITIMER, setitimer) \
O(SYS_POSIX_OPENPT, posix_openpt) \ O(SYS_POSIX_OPENPT, posix_openpt) \
O(SYS_PTSNAME, ptsname) \ O(SYS_PTSNAME, ptsname) \
O(SYS_FSYNC, fsync) \
O(SYS_SYMLINKAT, symlinkat) \
O(SYS_HARDLINKAT, hardlinkat) \
enum Syscall enum Syscall
{ {

View File

@ -22,6 +22,12 @@ struct itimerval
#define ITIMER_VIRTUAL 1 #define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2 #define ITIMER_PROF 2
struct timezone
{
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of DST correction */
};
int getitimer(int which, struct itimerval* value); int getitimer(int which, struct itimerval* value);
int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp); int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp);
int setitimer(int which, const struct itimerval* __restrict value, struct itimerval* __restrict ovalue); int setitimer(int which, const struct itimerval* __restrict value, struct itimerval* __restrict ovalue);

View File

@ -233,6 +233,9 @@ int unlinkat(int fd, const char* path, int flag);
int usleep(useconds_t usec); int usleep(useconds_t usec);
ssize_t write(int fildes, const void* buf, size_t nbyte); ssize_t write(int fildes, const void* buf, size_t nbyte);
int getpagesize(void);
char* getpass(const char* prompt);
extern char* optarg; extern char* optarg;
extern int opterr, optind, optopt; extern int opterr, optind, optopt;

View File

@ -0,0 +1,69 @@
#include <libgen.h>
#include <limits.h>
#include <string.h>
char* basename(char* path)
{
static char buffer[PATH_MAX];
constexpr auto prep_string =
[](const char* str) -> char*
{
strcpy(buffer, str);
return buffer;
};
if (path == nullptr || path[0] == '\0')
return prep_string(".");
char* endp = path + strlen(path);
while (endp > path && endp[-1] == '/')
endp--;
if (endp == path)
return prep_string("/");
char* startp = endp;
while (startp > path && startp[-1] != '/')
startp--;
memcpy(buffer, startp, endp - startp);
buffer[endp - startp] = '\0';
return buffer;
}
char* dirname(char* path)
{
static char buffer[PATH_MAX];
constexpr auto prep_string =
[](const char* str) -> char*
{
strcpy(buffer, str);
return buffer;
};
if (path == nullptr || path[0] == '\0')
return prep_string(".");
char* endp = path + strlen(path);
while (endp > path && endp[-1] == '/')
endp--;
if (endp == path)
return prep_string("/");
while (endp > path && endp[-1] != '/')
endp--;
if (endp == path)
return prep_string(".");
while (endp > path && endp[-1] == '/')
endp--;
if (endp == path)
return prep_string("/");
memcpy(buffer, path, endp - path);
buffer[endp - path] = '\0';
return buffer;
}

View File

@ -580,6 +580,7 @@ extern "C" int printf_impl(const char* format, va_list arguments, int (*putc_fun
case 'm': case 'm':
{ {
// NOTE: this is a glibc extension // NOTE: this is a glibc extension
// NOTE: syslog() requires %m to be handled
if (options.alternate_form) if (options.alternate_form)
string = strerrorname_np(errno); string = strerrorname_np(errno);
else else

View File

@ -88,7 +88,7 @@ struct passwd* getpwent(void)
ASSERT(1 <= field_len && field_len <= 9); ASSERT(1 <= field_len && field_len <= 9);
for (size_t j = 0; j < field_len; j++) for (size_t j = 0; j < field_len; j++)
ASSERT(isdigit(ptr[j])); ASSERT(isdigit(ptr[j]));
s_pwent_struct.pw_uid = atoi(ptr); s_pwent_struct.pw_gid = atoi(ptr);
break; break;
case 4: case 4:
break; break;

View File

@ -26,9 +26,13 @@ struct FILE
int unget_char; int unget_char;
unsigned char inline_buffer_storage[BUFSIZ]; unsigned char inline_buffer_storage[BUFSIZ];
unsigned char* buffer; unsigned char* write_buffer;
uint32_t buffer_size; uint32_t wr_buf_size;
uint32_t buffer_index; uint32_t wr_buf_index;
unsigned char read_buffer[BUFSIZ];
uint32_t rd_buf_size;
uint32_t rd_buf_index;
}; };
struct ScopeLock struct ScopeLock
@ -63,9 +67,11 @@ static void init_closed_file(FILE* file)
file->error = false; file->error = false;
file->pid = -1; file->pid = -1;
file->unget_char = EOF; file->unget_char = EOF;
file->buffer = file->inline_buffer_storage; file->write_buffer = file->inline_buffer_storage;
file->buffer_size = BUFSIZ; file->wr_buf_size = BUFSIZ;
file->buffer_index = 0; file->wr_buf_index = 0;
file->rd_buf_size = 0;
file->rd_buf_index = 0;
} }
void _init_stdio() void _init_stdio()
@ -156,8 +162,9 @@ FILE* fdopen(int fd, const char* mode_str)
continue; continue;
s_files[i].fd = fd; s_files[i].fd = fd;
s_files[i].mode = mode & O_ACCMODE; s_files[i].mode = mode & O_ACCMODE;
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage); ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
ASSERT(s_files[i].buffer_size == BUFSIZ); ASSERT(s_files[i].wr_buf_size == BUFSIZ);
ASSERT(s_files[i].rd_buf_size == 0);
return &s_files[i]; return &s_files[i];
} }
@ -190,16 +197,16 @@ int fflush(FILE* file)
file->unget_char = EOF; file->unget_char = EOF;
if (file->buffer_index == 0) if (file->wr_buf_index == 0)
return 0; return 0;
if (syscall(SYS_WRITE, file->fd, file->buffer, file->buffer_index) < 0) if (syscall(SYS_WRITE, file->fd, file->write_buffer, file->wr_buf_index) < 0)
{ {
file->error = true; file->error = true;
return EOF; return EOF;
} }
file->buffer_index = 0; file->wr_buf_index = 0;
return 0; return 0;
} }
@ -278,8 +285,9 @@ FILE* fopen(const char* pathname, const char* mode_str)
continue; continue;
s_files[i].fd = fd; s_files[i].fd = fd;
s_files[i].mode = mode & O_ACCMODE; s_files[i].mode = mode & O_ACCMODE;
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage); ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
ASSERT(s_files[i].buffer_size == BUFSIZ); ASSERT(s_files[i].wr_buf_size == BUFSIZ);
ASSERT(s_files[i].rd_buf_size == 0);
return &s_files[i]; return &s_files[i];
} }
@ -323,26 +331,15 @@ size_t fread(void* buffer, size_t size, size_t nitems, FILE* file)
size_t target = size * nitems; size_t target = size * nitems;
size_t nread = 0; size_t nread = 0;
if (file->unget_char != EOF) if (target == 0)
{ return 0;
*static_cast<unsigned char*>(buffer) = file->unget_char;
file->unget_char = EOF;
nread++;
}
while (nread < target) while (nread < target)
{ {
ssize_t ret = syscall(SYS_READ, file->fd, static_cast<unsigned char*>(buffer) + nread, target - nread); int ch = getc_unlocked(file);
if (ch == EOF)
if (ret < 0) break;
file->error = true; static_cast<unsigned char*>(buffer)[nread++] = ch;
else if (ret == 0)
file->eof = true;
if (ret <= 0)
return nread;
nread += ret;
} }
return nread / size; return nread / size;
@ -403,6 +400,8 @@ int fseeko(FILE* file, off_t offset, int whence)
if (ret < 0) if (ret < 0)
return -1; return -1;
file->eof = false; file->eof = false;
file->rd_buf_size = 0;
file->rd_buf_index = 0;
return 0; return 0;
} }
@ -422,7 +421,7 @@ off_t ftello(FILE* file)
long ret = syscall(SYS_TELL, file->fd); long ret = syscall(SYS_TELL, file->fd);
if (ret < 0) if (ret < 0)
return -1; return -1;
return ret - (file->unget_char != EOF); return ret - (file->unget_char != EOF) - (file->rd_buf_size - file->rd_buf_index);
} }
int ftrylockfile(FILE*) int ftrylockfile(FILE*)
@ -469,22 +468,28 @@ int getc_unlocked(FILE* file)
return (unsigned char)ch; return (unsigned char)ch;
} }
unsigned char c; if (file->rd_buf_index < file->rd_buf_size)
long ret = syscall(SYS_READ, file->fd, &c, 1); return file->read_buffer[file->rd_buf_index++];
file->rd_buf_size = 0;
file->rd_buf_index = 0;
if (ret < 0) ssize_t nread = read(file->fd, file->read_buffer, sizeof(file->read_buffer));
if (nread < 0)
{ {
file->error = true; file->error = true;
return EOF; return EOF;
} }
if (ret == 0) if (nread == 0)
{ {
file->eof = true; file->eof = true;
return EOF; return EOF;
} }
return c; file->rd_buf_size = nread;
file->rd_buf_index = 1;
return file->read_buffer[0];
} }
int getchar_unlocked(void) int getchar_unlocked(void)
@ -598,8 +603,9 @@ FILE* popen(const char* command, const char* mode_str)
s_files[i].fd = read ? fds[0] : fds[1]; s_files[i].fd = read ? fds[0] : fds[1];
s_files[i].mode = (unsigned)(read ? O_RDONLY : O_WRONLY); s_files[i].mode = (unsigned)(read ? O_RDONLY : O_WRONLY);
s_files[i].pid = pid; s_files[i].pid = pid;
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage); ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
ASSERT(s_files[i].buffer_size == BUFSIZ); ASSERT(s_files[i].wr_buf_size == BUFSIZ);
ASSERT(s_files[i].rd_buf_size == 0);
return &s_files[i]; return &s_files[i];
} }
@ -628,8 +634,8 @@ int putchar(int c)
int putc_unlocked(int c, FILE* file) int putc_unlocked(int c, FILE* file)
{ {
file->buffer[file->buffer_index++] = c; file->write_buffer[file->wr_buf_index++] = c;
if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->buffer_index >= file->buffer_size) if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->wr_buf_index >= file->wr_buf_size)
if (fflush(file) == EOF) if (fflush(file) == EOF)
return EOF; return EOF;
return (unsigned char)c; return (unsigned char)c;
@ -748,8 +754,8 @@ int setvbuf(FILE* file, char* buffer, int type, size_t size)
} }
file->buffer_type = type; file->buffer_type = type;
file->buffer_size = size; file->wr_buf_size = size;
file->buffer = reinterpret_cast<unsigned char*>(buffer); file->write_buffer = reinterpret_cast<unsigned char*>(buffer);
return 0; return 0;
} }

View File

@ -5,6 +5,7 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@ -559,9 +560,86 @@ int putenv(char* string)
return 0; return 0;
} }
char* mktemp(char*) static size_t temp_template_count_x(const char* _template)
{ {
ASSERT_NOT_REACHED(); const size_t len = strlen(_template);
for (size_t i = 0; i < len; i++)
if (_template[len - i - 1] != 'X')
return i;
return len;
}
static void generate_temp_template(char* _template, size_t x_count)
{
const size_t len = strlen(_template);
for (size_t i = 0; i < x_count; i++)
{
const uint8_t nibble = rand() & 0xF;
_template[len - i - 1] = (nibble < 10)
? ('0' + nibble)
: ('a' + nibble - 10);
}
}
char* mktemp(char* _template)
{
const size_t x_count = temp_template_count_x(_template);
if (x_count < 6)
{
errno = EINVAL;
_template[0] = '\0';
return _template;
}
for (;;)
{
generate_temp_template(_template, x_count);
struct stat st;
if (stat(_template, &st) == 0)
return _template;
}
}
char* mkdtemp(char* _template)
{
const size_t x_count = temp_template_count_x(_template);
if (x_count < 6)
{
errno = EINVAL;
return nullptr;
}
for (;;)
{
generate_temp_template(_template, x_count);
if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1)
return _template;
if (errno != EEXIST)
return nullptr;
}
}
int mkstemp(char* _template)
{
const size_t x_count = temp_template_count_x(_template);
if (x_count < 6)
{
errno = EINVAL;
return -1;
}
for (;;)
{
generate_temp_template(_template, x_count);
int fd = open(_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd != -1)
return fd;
if (errno != EEXIST)
return -1;
}
} }
int posix_openpt(int oflag) int posix_openpt(int oflag)

View File

@ -492,7 +492,6 @@ const char* strerrorname_np(int error)
case ETXTBSY: return "ETXTBSY"; case ETXTBSY: return "ETXTBSY";
case EWOULDBLOCK: return "EWOULDBLOCK"; case EWOULDBLOCK: return "EWOULDBLOCK";
case EXDEV: return "EXDEV"; case EXDEV: return "EXDEV";
case EEXISTS: return "EEXISTS";
case ENOTBLK: return "ENOTBLK"; case ENOTBLK: return "ENOTBLK";
case EUNKNOWN: return "EUNKNOWN"; case EUNKNOWN: return "EUNKNOWN";
} }
@ -587,7 +586,6 @@ const char* strerrordesc_np(int error)
case ETXTBSY: return "Text file busy."; case ETXTBSY: return "Text file busy.";
case EWOULDBLOCK: return "Operation would block."; case EWOULDBLOCK: return "Operation would block.";
case EXDEV: return "Cross-device link."; case EXDEV: return "Cross-device link.";
case EEXISTS: return "File exists";
case ENOTBLK: return "Block device required"; case ENOTBLK: return "Block device required";
case EUNKNOWN: return "Unknown error"; case EUNKNOWN: return "Unknown error";
} }

View File

@ -1,7 +1,50 @@
#include <BAN/Assert.h> #include <BAN/Assert.h>
#include <BAN/Limits.h>
#include <kernel/Thread.h>
#include <errno.h> #include <errno.h>
#include <limits.h>
#include <sys/resource.h> #include <sys/resource.h>
int getrlimit(int resource, struct rlimit* rlp)
{
switch (resource)
{
case RLIMIT_CORE:
rlp->rlim_cur = 0;
rlp->rlim_max = 0;
return 0;
case RLIMIT_CPU:
rlp->rlim_cur = BAN::numeric_limits<rlim_t>::max();
rlp->rlim_max = BAN::numeric_limits<rlim_t>::max();
return 0;
case RLIMIT_DATA:
rlp->rlim_cur = BAN::numeric_limits<rlim_t>::max();
rlp->rlim_max = BAN::numeric_limits<rlim_t>::max();
return 0;
case RLIMIT_FSIZE:
rlp->rlim_cur = BAN::numeric_limits<rlim_t>::max();
rlp->rlim_max = BAN::numeric_limits<rlim_t>::max();
return 0;
case RLIMIT_NOFILE:
rlp->rlim_cur = OPEN_MAX;
rlp->rlim_max = OPEN_MAX;
return 0;
case RLIMIT_STACK:
rlp->rlim_cur = Kernel::Thread::userspace_stack_size;
rlp->rlim_max = Kernel::Thread::userspace_stack_size;
return 0;
case RLIMIT_AS:
rlp->rlim_cur = BAN::numeric_limits<rlim_t>::max();
rlp->rlim_max = BAN::numeric_limits<rlim_t>::max();
return 0;
}
errno = EINVAL;
return -1;
}
int getrusage(int who, struct rusage* r_usage) int getrusage(int who, struct rusage* r_usage)
{ {
if (who != RUSAGE_CHILDREN && who != RUSAGE_SELF) if (who != RUSAGE_CHILDREN && who != RUSAGE_SELF)

View File

@ -0,0 +1,18 @@
#include <fcntl.h>
#include <sys/statvfs.h>
#include <sys/syscall.h>
static int fstatvfsat(int fildes, const char* path, struct statvfs* buf)
{
return syscall(SYS_FSTATVFSAT, fildes, path, buf);
}
int fstatvfs(int fildes, struct statvfs* buf)
{
return fstatvfsat(fildes, nullptr, buf);
}
int statvfs(const char* __restrict path, struct statvfs* __restrict buf)
{
return fstatvfsat(AT_FDCWD, path, buf);
}

View File

@ -6,7 +6,8 @@
int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp) int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp)
{ {
// If tzp is not a null pointer, the behavior is unspecified. // If tzp is not a null pointer, the behavior is unspecified.
(void)tzp; if (tzp != nullptr)
*static_cast<struct timezone*>(tzp) = {};
timespec ts; timespec ts;
clock_gettime(CLOCK_REALTIME, &ts); clock_gettime(CLOCK_REALTIME, &ts);

View File

@ -1,12 +1,30 @@
#include <BAN/Assert.h> #include <BAN/Assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <syslog.h> #include <syslog.h>
void openlog(const char*, int, int) static const char* s_ident = nullptr;
void openlog(const char* ident, int option, int facility)
{ {
ASSERT_NOT_REACHED(); (void)option;
(void)facility;
s_ident = ident;
} }
void syslog(int, const char*, ...) void syslog(int priority, const char* format, ...)
{ {
ASSERT_NOT_REACHED(); (void)priority;
if (s_ident)
fprintf(stddbg, "%s", s_ident);
va_list args;
va_start(args, format);
vfprintf(stddbg, format, args);
va_end(args);
}
void closelog()
{
s_ident = nullptr;
} }

View File

@ -7,37 +7,11 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
// sample implementation from https://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
char* asctime(const struct tm* timeptr)
{
static constexpr char wday_name[][4] {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static constexpr char mon_name[][4] {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static char result[128];
sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
wday_name[timeptr->tm_wday],
mon_name[timeptr->tm_mon],
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec,
1900 + timeptr->tm_year);
return result;
}
int clock_gettime(clockid_t clock_id, struct timespec* tp) int clock_gettime(clockid_t clock_id, struct timespec* tp)
{ {
return syscall(SYS_CLOCK_GETTIME, clock_id, tp); return syscall(SYS_CLOCK_GETTIME, clock_id, tp);
} }
char* ctime(const time_t* clock)
{
return asctime(localtime(clock));
}
int nanosleep(const struct timespec* rqtp, struct timespec* rmtp) int nanosleep(const struct timespec* rqtp, struct timespec* rmtp)
{ {
return syscall(SYS_NANOSLEEP, rqtp, rmtp); return syscall(SYS_NANOSLEEP, rqtp, rmtp);
@ -53,10 +27,45 @@ time_t time(time_t* tloc)
return tp.tv_sec; return tp.tv_sec;
} }
struct tm* gmtime(const time_t* timer) // sample implementation from https://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
char* asctime_r(const struct tm* __restrict tm, char* __restrict buf)
{ {
static struct tm tm; static constexpr char wday_name[][4] {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static constexpr char mon_name[][4] {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
sprintf(buf, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
wday_name[tm->tm_wday],
mon_name[tm->tm_mon],
tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec,
1900 + tm->tm_year);
return buf;
}
char* asctime(const struct tm* timeptr)
{
static char buf[26];
return asctime_r(timeptr, buf);
}
char* ctime_r(const time_t* clock, char* buf)
{
struct tm local;
return asctime_r(localtime_r(clock, &local), buf);
}
char* ctime(const time_t* clock)
{
static char buf[26];
return ctime_r(clock, buf);
}
struct tm* gmtime_r(const time_t* timer, struct tm* __restrict result)
{
constexpr auto is_leap_year = constexpr auto is_leap_year =
[](time_t year) -> bool [](time_t year) -> bool
{ {
@ -73,38 +82,50 @@ struct tm* gmtime(const time_t* timer)
time_t time = *timer; time_t time = *timer;
tm.tm_sec = time % 60; time /= 60; result->tm_sec = time % 60; time /= 60;
tm.tm_min = time % 60; time /= 60; result->tm_min = time % 60; time /= 60;
tm.tm_hour = time % 24; time /= 24; result->tm_hour = time % 24; time /= 24;
time_t total_days = time; time_t total_days = time;
tm.tm_wday = (total_days + 4) % 7; result->tm_wday = (total_days + 4) % 7;
tm.tm_year = 1970; result->tm_year = 1970;
while (total_days >= 365U + is_leap_year(tm.tm_year)) while (total_days >= 365U + is_leap_year(result->tm_year))
{ {
total_days -= 365U + is_leap_year(tm.tm_year); total_days -= 365U + is_leap_year(result->tm_year);
tm.tm_year++; result->tm_year++;
} }
bool is_leap_day = is_leap_year(tm.tm_year) && total_days == month_days[2]; bool is_leap_day = is_leap_year(result->tm_year) && total_days == month_days[2];
bool had_leap_day = is_leap_year(tm.tm_year) && total_days > month_days[2]; bool had_leap_day = is_leap_year(result->tm_year) && total_days > month_days[2];
for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) for (result->tm_mon = 0; result->tm_mon < 12; result->tm_mon++)
if (total_days < month_days[tm.tm_mon + 1] + (is_leap_day || had_leap_day)) if (total_days < month_days[result->tm_mon + 1] + (is_leap_day || had_leap_day))
break; break;
tm.tm_mday = total_days - month_days[tm.tm_mon] + !had_leap_day; result->tm_mday = total_days - month_days[result->tm_mon] + !had_leap_day;
tm.tm_yday = total_days; result->tm_yday = total_days;
tm.tm_year -= 1900; result->tm_year -= 1900;
tm.tm_isdst = 0; result->tm_isdst = 0;
return &tm; return result;
}
struct tm* gmtime(const time_t* timer)
{
static struct tm tm;
return gmtime_r(timer, &tm);
}
struct tm* localtime_r(const time_t* timer, struct tm* result)
{
// FIXME: support timezones
return gmtime_r(timer, result);
} }
struct tm* localtime(const time_t* timer) struct tm* localtime(const time_t* timer)
{ {
// FIXME: support timezones static struct tm tm;
return gmtime(timer); return localtime_r(timer, &tm);
} }
size_t strftime(char* __restrict s, size_t maxsize, const char* __restrict format, const struct tm* __restrict timeptr) size_t strftime(char* __restrict s, size_t maxsize, const char* __restrict format, const struct tm* __restrict timeptr)

View File

@ -1,5 +1,6 @@
#include <BAN/Assert.h> #include <BAN/Assert.h>
#include <BAN/Debug.h> #include <BAN/Debug.h>
#include <kernel/Memory/Types.h>
#include <kernel/Syscall.h> #include <kernel/Syscall.h>
#include <errno.h> #include <errno.h>
@ -12,9 +13,11 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/time.h> #include <sys/time.h>
#include <termios.h>
#include <unistd.h> #include <unistd.h>
char** environ; char** __environ;
extern char** environ __attribute__((weak, alias("__environ")));
extern void _init_malloc(); extern void _init_malloc();
extern void _init_stdio(); extern void _init_stdio();
@ -115,6 +118,11 @@ int ftruncate(int fildes, off_t length)
return syscall(SYS_TRUNCATE, fildes, length); return syscall(SYS_TRUNCATE, fildes, length);
} }
int fsync(int fildes)
{
return syscall(SYS_FSYNC, fildes);
}
int dup(int fildes) int dup(int fildes)
{ {
return syscall(SYS_DUP, fildes); return syscall(SYS_DUP, fildes);
@ -135,7 +143,7 @@ int gethostname(char* name, size_t namelen)
FILE* fp = fopen("/etc/hostname", "r"); FILE* fp = fopen("/etc/hostname", "r");
if (fp == NULL) if (fp == NULL)
return -1; return -1;
size_t nread = fread(name, namelen - 1, 1, fp); size_t nread = fread(name, 1, namelen - 1, fp);
while (nread > 0 && name[nread - 1] == '\n') while (nread > 0 && name[nread - 1] == '\n')
nread--; nread--;
name[nread] = '\0'; name[nread] = '\0';
@ -143,90 +151,11 @@ int gethostname(char* name, size_t namelen)
return 0; return 0;
} }
int execl(const char* pathname, const char* arg0, ...) static int exec_impl(const char* pathname, char* const* argv, char* const* envp, bool do_path_resolution)
{ {
if (arg0 == nullptr) char buffer[PATH_MAX];
{
char* temp = nullptr;
return execv(pathname, &temp);
}
va_list ap; if (do_path_resolution && strchr(pathname, '/') == nullptr)
va_start(ap, arg0);
int argc = 1;
while (va_arg(ap, const char*))
argc++;
va_end(ap);
char** argv = (char**)malloc(sizeof(char*) * (argc + 1));
if (argv == nullptr)
{
errno = ENOMEM;
return -1;
}
va_start(ap, arg0);
argv[0] = (char*)arg0;
for (int i = 1; i < argc; i++)
argv[i] = va_arg(ap, char*);
argv[argc] = nullptr;
va_end(ap);
return execv(pathname, argv);
}
int execle(const char* pathname, const char* arg0, ...)
{
va_list ap;
int argc = 0;
if (arg0)
{
va_start(ap, arg0);
argc = 1;
while (va_arg(ap, const char*))
argc++;
va_end(ap);
}
char** argv = (char**)malloc(sizeof(char*) * (argc + 1));
if (argv == nullptr)
{
errno = ENOMEM;
return -1;
}
char** envp = nullptr;
va_start(ap, arg0);
argv[0] = (char*)arg0;
for (int i = 1; i < argc; i++)
argv[i] = va_arg(ap, char*);
argv[argc] = nullptr;
envp = va_arg(ap, char**);
va_end(ap);
return execve(pathname, argv, envp);
}
int execv(const char* pathname, char* const argv[])
{
return execve(pathname, argv, environ);
}
int execve(const char* pathname, char* const argv[], char* const envp[])
{
return syscall(SYS_EXEC, pathname, argv, envp);
}
int execvp(const char* file, char* const argv[])
{
char buffer[1024];
const char* pathname = NULL;
// do path resolution if file doesn't contain /
if (strchr(file, '/') == nullptr)
{ {
const char* cur = getenv("PATH"); const char* cur = getenv("PATH");
if (!cur) if (!cur)
@ -235,21 +164,22 @@ int execvp(const char* file, char* const argv[])
return -1; return -1;
} }
char* resolved = nullptr;
while (*cur) while (*cur)
{ {
const char* end = strchrnul(cur, ':'); const char* end = strchrnul(cur, ':');
size_t len = end - cur; size_t len = end - cur;
ASSERT(strlen(file) + 1 + len < sizeof(buffer)); ASSERT(strlen(pathname) + 1 + len < sizeof(buffer));
strncpy(buffer, cur, len); strncpy(buffer, cur, len);
strcat(buffer, "/"); strcat(buffer, "/");
strcat(buffer, file); strcat(buffer, pathname);
struct stat st; struct stat st;
if (stat(buffer, &st) == 0) if (stat(buffer, &st) == 0)
{ {
pathname = buffer; resolved = buffer;
break; break;
} }
@ -257,19 +187,91 @@ int execvp(const char* file, char* const argv[])
if (*cur) if (*cur)
cur++; cur++;
} }
}
else
{
pathname = file;
}
if (!pathname) if (!resolved)
{ {
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
return execve(pathname, argv, environ); pathname = resolved;
}
return syscall(SYS_EXEC, pathname, argv, envp);
}
static int execl_impl(const char* pathname, const char* arg0, va_list ap, bool has_env, bool do_path_resolution)
{
int argc = 1;
va_list ap2;
va_copy(ap2, ap);
while (va_arg(ap2, char*))
argc++;
va_end(ap2);
char** argv = static_cast<char**>(malloc((argc + 1) * sizeof(char*)));
if (argv == nullptr)
{
errno = ENOMEM;
return -1;
}
argv[0] = const_cast<char*>(arg0);
for (int i = 1; i < argc; i++)
argv[i] = va_arg(ap, char*);
argv[argc] = nullptr;
char** envp = environ;
if (has_env)
{
va_arg(ap, char*);
envp = va_arg(ap, char**);;
}
return exec_impl(pathname, argv, envp, do_path_resolution);
}
int execl(const char* pathname, const char* arg0, ...)
{
va_list ap;
va_start(ap, arg0);
int ret = execl_impl(pathname, arg0, ap, false, false);
va_end(ap);
return ret;
}
int execlp(const char* pathname, const char* arg0, ...)
{
va_list ap;
va_start(ap, arg0);
int ret = execl_impl(pathname, arg0, ap, false, true);
va_end(ap);
return ret;
}
int execle(const char* pathname, const char* arg0, ...)
{
va_list ap;
va_start(ap, arg0);
int ret = execl_impl(pathname, arg0, ap, true, false);
va_end(ap);
return ret;
}
int execv(const char* pathname, char* const argv[])
{
return exec_impl(pathname, argv, environ, false);
}
int execve(const char* pathname, char* const argv[], char* const envp[])
{
return exec_impl(pathname, argv, envp, false);
}
int execvp(const char* pathname, char* const argv[])
{
return exec_impl(pathname, argv, environ, true);
} }
pid_t fork(void) pid_t fork(void)
@ -443,6 +445,56 @@ int getopt(int argc, char* const argv[], const char* optstring)
return '?'; return '?';
} }
int getpagesize(void)
{
return PAGE_SIZE;
}
char* getpass(const char* prompt)
{
static char buffer[PASS_MAX];
int fd = open("/dev/tty", O_RDWR);
if (fd == -1)
return NULL;
termios orig, temp;
tcgetattr(fd, &orig);
char* ret = nullptr;
ssize_t total_read = 0;
if (write(fd, prompt, strlen(prompt)) < 0)
goto error;
temp = orig;
temp.c_lflag &= ~ECHO;
tcsetattr(fd, TCSANOW, &temp);
while (total_read == 0 || buffer[total_read - 1] != '\n')
{
ssize_t nread = read(fd, buffer + total_read, sizeof(buffer) - total_read - 1);
if (nread < 0)
goto error;
total_read += nread;
}
buffer[total_read - 1] = '\0';
ret = buffer;
write(fd, "\n", 1);
error:
tcsetattr(fd, TCSANOW, &orig);
close(fd);
return ret;
}
pid_t getppid(void)
{
return syscall(SYS_GET_PPID);
}
pid_t getpid(void) pid_t getpid(void)
{ {
return syscall(SYS_GET_PID); return syscall(SYS_GET_PID);
@ -478,6 +530,11 @@ pid_t getpgid(pid_t pid)
return syscall(SYS_GET_PGID, pid); return syscall(SYS_GET_PGID, pid);
} }
int tcgetpgrp(int fildes)
{
return syscall(SYS_TCGETPGRP, fildes);
}
int seteuid(uid_t uid) int seteuid(uid_t uid)
{ {
return syscall(SYS_SET_EUID, uid); return syscall(SYS_SET_EUID, uid);
@ -567,6 +624,20 @@ unsigned alarm(unsigned seconds)
int symlink(const char* path1, const char* path2) int symlink(const char* path1, const char* path2)
{ {
dwarnln("FIXME: symlink({}, {})", path1, path2); return symlinkat(path1, AT_FDCWD, path2);
ASSERT_NOT_REACHED(); }
int symlinkat(const char* path1, int fd, const char* path2)
{
return syscall(SYS_SYMLINKAT, path1, fd, path2);
}
int link(const char* path1, const char* path2)
{
return linkat(AT_FDCWD, path1, AT_FDCWD, path2, 0);
}
int linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
{
return syscall(SYS_HARDLINKAT, fd1, path1, fd2, path2, flag);
} }

View File

@ -1,8 +1,11 @@
#include <BAN/Assert.h>
#include <utime.h> #include <utime.h>
#include <sys/stat.h>
#include <stdio.h>
int utime(const char*, const struct utimbuf*) int utime(const char* filename, const struct utimbuf* times)
{ {
ASSERT_NOT_REACHED(); fprintf(stddbg, "TODO: utime(\"%s\", %p)\n", filename, times);
struct stat st;
return stat(filename, &st);
} }

View File

@ -6,3 +6,21 @@ size_t mbrtowc(wchar_t* __restrict, const char* __restrict, size_t, mbstate_t* _
{ {
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
int wcscmp(const wchar_t* ws1, const wchar_t* ws2)
{
for (; *ws1 && *ws2; ws1++, ws2++)
if (*ws1 != *ws2)
break;
return *ws1 - *ws2;
}
int wcsncmp(const wchar_t* ws1, const wchar_t* ws2, size_t n)
{
if (n == 0)
return 0;
for (; --n && *ws1 && *ws2; ws1++, ws2++)
if (*ws1 != *ws2)
break;
return *ws1 - *ws2;
}

View File

@ -69,7 +69,7 @@ namespace LibGUI
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
BAN::ScopeGuard server_closer([server_fd] { close(server_fd); }); BAN::ScopeGuard server_closer([server_fd] { close(server_fd); });
if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_CLOEXEC) == -1) if (fcntl(server_fd, F_SETFD, fcntl(server_fd, F_GETFD) | FD_CLOEXEC) == -1)
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
timespec start_time; timespec start_time;

View File

@ -174,7 +174,6 @@ static const char* errno_to_string(int error)
case ETXTBSY: return "Text file busy."; case ETXTBSY: return "Text file busy.";
case EWOULDBLOCK: return "Operation would block."; case EWOULDBLOCK: return "Operation would block.";
case EXDEV: return "Cross-device link."; case EXDEV: return "Cross-device link.";
case EEXISTS: return "File exists";
case ENOTBLK: return "Block device required"; case ENOTBLK: return "Block device required";
case EUNKNOWN: return "Unknown error"; case EUNKNOWN: return "Unknown error";
} }

View File

@ -77,6 +77,9 @@ int main(int argc, char** argv)
if (pwd == nullptr) if (pwd == nullptr)
continue; continue;
if (chown(tty_name, pwd->pw_uid, 0) == -1)
perror("chown");
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0) if (pid == 0)
{ {
@ -124,6 +127,9 @@ int main(int argc, char** argv)
if (tcsetpgrp(0, getpgrp()) == -1) if (tcsetpgrp(0, getpgrp()) == -1)
perror("tcsetpgrp"); perror("tcsetpgrp");
if (chown(tty_name, 0, 0) == -1)
perror("chown");
} }
} }

View File

@ -202,7 +202,7 @@ void update()
int main() int main()
{ {
// Make stdin non blocking // Make stdin non blocking
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK)) if (fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK))
{ {
perror("fcntl"); perror("fcntl");
return 1; return 1;