Compare commits
40 Commits
a231f8587e
...
49133dce48
Author | SHA1 | Date |
---|---|---|
Bananymous | 49133dce48 | |
Bananymous | 3b7b6beca5 | |
Bananymous | 0dd81328ff | |
Bananymous | a668593e6b | |
Bananymous | 3a5a22511a | |
Bananymous | 86859267f0 | |
Bananymous | 88c9f6d233 | |
Bananymous | 176693dd5a | |
Bananymous | 62bee04fc0 | |
Bananymous | 0a5aacfd87 | |
Bananymous | 2dec3a6c95 | |
Bananymous | fcc2814199 | |
Bananymous | bc93d238dd | |
Bananymous | 79e2c5d48c | |
Bananymous | 0fab7ad63b | |
Bananymous | e6a2f55a59 | |
Bananymous | 67e9ca56ac | |
Bananymous | 713daf6cd3 | |
Bananymous | 12abe81c6d | |
Bananymous | fbcf10c86d | |
Bananymous | 415b20f884 | |
Bananymous | d58ca5f37a | |
Bananymous | 11b6ee423e | |
Bananymous | a10ca47657 | |
Bananymous | ad1f175a39 | |
Bananymous | fd3246113a | |
Bananymous | b8013c883c | |
Bananymous | ffcc4fd03a | |
Bananymous | 9d97964998 | |
Bananymous | f0e54cdd51 | |
Bananymous | 0360fd1efe | |
Bananymous | 4508e099ff | |
Bananymous | 6ed1435aeb | |
Bananymous | 6346e288ad | |
Bananymous | d2b503910f | |
Bananymous | 747c3b2a4b | |
Bananymous | cccb4e6d5e | |
Bananymous | f4c6afbdae | |
Bananymous | d1ef380e6b | |
Bananymous | c02de2580d |
|
@ -24,6 +24,8 @@ namespace Kernel
|
|||
|
||||
protected:
|
||||
Device(mode_t, uid_t, gid_t);
|
||||
|
||||
virtual BAN::ErrorOr<void> fsync_impl() final override { return BAN::Error::from_errno(EINVAL); }
|
||||
};
|
||||
|
||||
class BlockDevice : public Device
|
||||
|
@ -31,6 +33,7 @@ namespace Kernel
|
|||
public:
|
||||
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) = 0;
|
||||
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) = 0;
|
||||
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) = 0;
|
||||
|
||||
virtual blksize_t blksize() const = 0;
|
||||
|
||||
|
|
|
@ -11,6 +11,18 @@ namespace Kernel
|
|||
class Ext2FS final : public FileSystem
|
||||
{
|
||||
public:
|
||||
virtual unsigned long bsize() const override;
|
||||
virtual unsigned long frsize() const override;
|
||||
virtual fsblkcnt_t blocks() const override;
|
||||
virtual fsblkcnt_t bfree() const override;
|
||||
virtual fsblkcnt_t bavail() const override;
|
||||
virtual fsfilcnt_t files() const override;
|
||||
virtual fsfilcnt_t ffree() const override;
|
||||
virtual fsfilcnt_t favail() const override;
|
||||
virtual unsigned long fsid() const override;
|
||||
virtual unsigned long flag() const override;
|
||||
virtual unsigned long namemax() const override;
|
||||
|
||||
class BlockBufferWrapper
|
||||
{
|
||||
BAN_NON_COPYABLE(BlockBufferWrapper);
|
||||
|
@ -67,6 +79,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> read_block(uint32_t, BlockBufferWrapper&);
|
||||
BAN::ErrorOr<void> write_block(uint32_t, const BlockBufferWrapper&);
|
||||
BAN::ErrorOr<void> sync_superblock();
|
||||
BAN::ErrorOr<void> sync_block(uint32_t block);
|
||||
|
||||
BlockBufferWrapper get_block_buffer();
|
||||
|
||||
|
|
|
@ -29,19 +29,24 @@ namespace Kernel
|
|||
virtual dev_t dev() const override { return 0; }
|
||||
virtual dev_t rdev() const override { return 0; }
|
||||
|
||||
virtual const FileSystem* filesystem() const override;
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
|
||||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) override;
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) override;
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) override;
|
||||
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
|
||||
virtual BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) override;
|
||||
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override;
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
|
|
|
@ -20,6 +20,18 @@ namespace Kernel
|
|||
};
|
||||
|
||||
public:
|
||||
virtual unsigned long bsize() const override;
|
||||
virtual unsigned long frsize() const override;
|
||||
virtual fsblkcnt_t blocks() const override;
|
||||
virtual fsblkcnt_t bfree() const override;
|
||||
virtual fsblkcnt_t bavail() const override;
|
||||
virtual fsfilcnt_t files() const override;
|
||||
virtual fsfilcnt_t ffree() const override;
|
||||
virtual fsfilcnt_t favail() const override;
|
||||
virtual unsigned long fsid() const override;
|
||||
virtual unsigned long flag() const override;
|
||||
virtual unsigned long namemax() const override;
|
||||
|
||||
static BAN::ErrorOr<bool> probe(BAN::RefPtr<BlockDevice>);
|
||||
static BAN::ErrorOr<BAN::RefPtr<FATFS>> create(BAN::RefPtr<BlockDevice>);
|
||||
|
||||
|
@ -45,13 +57,15 @@ namespace Kernel
|
|||
|
||||
// TODO: These probably should be constant variables
|
||||
uint32_t root_sector_count() const { return BAN::Math::div_round_up<uint32_t>(m_bpb.root_entry_count * 32, m_bpb.bytes_per_sector); }
|
||||
uint32_t fat_sector_count() const { return m_bpb.fat_size16 ? m_bpb.fat_size16 : m_bpb.ext_32.fat_size32; }
|
||||
uint32_t fat_size() const { return m_bpb.fat_size16 ? m_bpb.fat_size16 : m_bpb.ext_32.fat_size32; }
|
||||
uint32_t total_sector_count() const { return m_bpb.total_sectors16 ? m_bpb.total_sectors16 : m_bpb.total_sectors32; }
|
||||
uint32_t data_sector_count() const { return total_sector_count() - (m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count()) + root_sector_count()); }
|
||||
uint32_t data_sector_count() const { return total_sector_count() - (m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size()) + root_sector_count()); }
|
||||
uint32_t cluster_count() const { return data_sector_count() / m_bpb.sectors_per_cluster; }
|
||||
uint32_t first_data_sector() const { return m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count()) + root_sector_count(); }
|
||||
uint32_t first_data_sector() const { return m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size()) + root_sector_count(); }
|
||||
uint32_t first_fat_sector() const { return m_bpb.reserved_sector_count; }
|
||||
|
||||
uint8_t bits_per_fat_entry() const { return static_cast<uint8_t>(m_type); }
|
||||
|
||||
private:
|
||||
BAN::RefPtr<BlockDevice> m_block_device;
|
||||
BAN::RefPtr<FATInode> m_root_inode;
|
||||
|
|
|
@ -29,6 +29,8 @@ namespace Kernel
|
|||
virtual dev_t dev() const override { return 0; }
|
||||
virtual dev_t rdev() const override { return 0; }
|
||||
|
||||
virtual const FileSystem* filesystem() const override;
|
||||
|
||||
const FAT::DirectoryEntry& entry() const { return m_entry; }
|
||||
|
||||
protected:
|
||||
|
@ -42,6 +44,7 @@ namespace Kernel
|
|||
//virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
//virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
|
||||
//virtual BAN::ErrorOr<void> chmod_impl(mode_t) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
virtual bool can_read_impl() const override { return true; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
|
|
|
@ -9,6 +9,18 @@ namespace Kernel
|
|||
class FileSystem : public BAN::RefCounted<FileSystem>
|
||||
{
|
||||
public:
|
||||
virtual unsigned long bsize() const = 0;
|
||||
virtual unsigned long frsize() const = 0;
|
||||
virtual fsblkcnt_t blocks() const = 0;
|
||||
virtual fsblkcnt_t bfree() const = 0;
|
||||
virtual fsblkcnt_t bavail() const = 0;
|
||||
virtual fsfilcnt_t files() const = 0;
|
||||
virtual fsfilcnt_t ffree() const = 0;
|
||||
virtual fsfilcnt_t favail() const = 0;
|
||||
virtual unsigned long fsid() const = 0;
|
||||
virtual unsigned long flag() const = 0;
|
||||
virtual unsigned long namemax() const = 0;
|
||||
|
||||
virtual ~FileSystem() {}
|
||||
|
||||
static BAN::ErrorOr<BAN::RefPtr<FileSystem>> from_block_device(BAN::RefPtr<BlockDevice>);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
class FileSystem;
|
||||
|
||||
class FileBackedRegion;
|
||||
class SharedFileData;
|
||||
|
||||
|
@ -86,15 +88,19 @@ namespace Kernel
|
|||
virtual bool is_pipe() const { return false; }
|
||||
virtual bool is_tty() const { return false; }
|
||||
|
||||
virtual const FileSystem* filesystem() const = 0;
|
||||
|
||||
// Directory API
|
||||
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
|
||||
BAN::ErrorOr<size_t> list_next_inodes(off_t, struct dirent* list, size_t list_size);
|
||||
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> create_directory(BAN::StringView, mode_t, uid_t, gid_t);
|
||||
BAN::ErrorOr<void> link_inode(BAN::StringView, BAN::RefPtr<Inode>);
|
||||
BAN::ErrorOr<void> unlink(BAN::StringView);
|
||||
|
||||
// Link API
|
||||
BAN::ErrorOr<BAN::String> link_target();
|
||||
BAN::ErrorOr<void> set_link_target(BAN::StringView);
|
||||
|
||||
// Socket API
|
||||
BAN::ErrorOr<long> accept(sockaddr* address, socklen_t* address_len, int flags);
|
||||
|
@ -111,6 +117,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> truncate(size_t);
|
||||
BAN::ErrorOr<void> chmod(mode_t);
|
||||
BAN::ErrorOr<void> chown(uid_t, gid_t);
|
||||
BAN::ErrorOr<void> fsync();
|
||||
|
||||
// Select/Non blocking API
|
||||
bool can_read() const;
|
||||
|
@ -125,10 +132,12 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<size_t> list_next_inodes_impl(off_t, struct dirent*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> create_directory_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> link_inode_impl(BAN::StringView, BAN::RefPtr<Inode>) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> unlink_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// Link API
|
||||
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> set_link_target_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
||||
// Socket API
|
||||
virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
|
@ -145,6 +154,7 @@ namespace Kernel
|
|||
virtual BAN::ErrorOr<void> truncate_impl(size_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chmod_impl(mode_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
|
||||
virtual BAN::ErrorOr<void> fsync_impl() = 0;
|
||||
|
||||
// Select/Non blocking API
|
||||
virtual bool can_read_impl() const = 0;
|
||||
|
|
|
@ -30,9 +30,12 @@ namespace Kernel
|
|||
virtual dev_t dev() const override { return 0; } // FIXME
|
||||
virtual dev_t rdev() const override { return 0; } // FIXME
|
||||
|
||||
virtual const FileSystem* filesystem() const override { return nullptr; }
|
||||
|
||||
protected:
|
||||
virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
virtual bool can_read_impl() const override { return m_buffer_size > 0; }
|
||||
virtual bool can_write_impl() const override { return true; }
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace Kernel
|
|||
dev_t dev() const final override { ASSERT_NOT_REACHED(); }
|
||||
dev_t rdev() const final override { ASSERT_NOT_REACHED(); }
|
||||
|
||||
const FileSystem* filesystem() const final override { return nullptr; }
|
||||
|
||||
protected:
|
||||
Socket(const Info& info)
|
||||
: m_info(info)
|
||||
|
@ -51,6 +53,7 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan buffer) override { return recvfrom_impl(buffer, nullptr, nullptr); }
|
||||
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan buffer) override { return sendto_impl(buffer, nullptr, 0); }
|
||||
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
|
||||
|
||||
private:
|
||||
const Info m_info;
|
||||
|
|
|
@ -40,6 +40,19 @@ namespace Kernel
|
|||
static constexpr size_t no_page_limit = SIZE_MAX;
|
||||
|
||||
public:
|
||||
// FIXME: basically all of these :)
|
||||
virtual unsigned long bsize() const override { return PAGE_SIZE; }
|
||||
virtual unsigned long frsize() const override { return PAGE_SIZE; }
|
||||
virtual fsblkcnt_t blocks() const override { return m_max_pages; }
|
||||
virtual fsblkcnt_t bfree() const override { return m_max_pages - m_used_pages; }
|
||||
virtual fsblkcnt_t bavail() const override { return m_max_pages - m_used_pages; }
|
||||
virtual fsfilcnt_t files() const override { return PAGE_SIZE * blocks() / sizeof(TmpDirectoryEntry); }
|
||||
virtual fsfilcnt_t ffree() const override { return PAGE_SIZE * bfree() / sizeof(TmpDirectoryEntry); }
|
||||
virtual fsfilcnt_t favail() const override { return PAGE_SIZE * bavail() / sizeof(TmpDirectoryEntry); }
|
||||
virtual unsigned long fsid() const override { return reinterpret_cast<uintptr_t>(this); }
|
||||
virtual unsigned long flag() const override { return 0; }
|
||||
virtual unsigned long namemax() const override { return PAGE_SIZE; }
|
||||
|
||||
static BAN::ErrorOr<TmpFileSystem*> create(size_t max_pages, mode_t, uid_t, gid_t);
|
||||
~TmpFileSystem();
|
||||
|
||||
|
|
|
@ -42,9 +42,13 @@ namespace Kernel
|
|||
static BAN::ErrorOr<BAN::RefPtr<TmpInode>> create_from_existing(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
~TmpInode();
|
||||
|
||||
virtual const FileSystem* filesystem() const override;
|
||||
|
||||
protected:
|
||||
TmpInode(TmpFileSystem&, ino_t, const TmpInodeInfo&);
|
||||
|
||||
virtual BAN::ErrorOr<void> fsync_impl() override { return {}; }
|
||||
|
||||
void sync();
|
||||
void free_all_blocks();
|
||||
virtual BAN::ErrorOr<void> prepare_unlink() { return {}; };
|
||||
|
|
|
@ -8,9 +8,22 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
class VirtualFileSystem : public FileSystem
|
||||
class VirtualFileSystem final : public FileSystem
|
||||
{
|
||||
public:
|
||||
virtual unsigned long bsize() const override { return 0; }
|
||||
virtual unsigned long frsize() const override { return 0; }
|
||||
virtual fsblkcnt_t blocks() const override { return 0; }
|
||||
virtual fsblkcnt_t bfree() const override { return 0; }
|
||||
virtual fsblkcnt_t bavail() const override { return 0; }
|
||||
virtual fsfilcnt_t files() const override { return 0; }
|
||||
virtual fsfilcnt_t ffree() const override { return 0; }
|
||||
virtual fsfilcnt_t favail() const override { return 0; }
|
||||
virtual unsigned long fsid() const override { return 0; }
|
||||
virtual unsigned long flag() const override { return 0; }
|
||||
virtual unsigned long namemax() const override { return 0; }
|
||||
|
||||
|
||||
static void initialize(BAN::StringView);
|
||||
static VirtualFileSystem& get();
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
|
||||
|
@ -97,6 +98,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_getegid() const { return m_credentials.egid(); }
|
||||
BAN::ErrorOr<long> sys_getpgid(pid_t);
|
||||
|
||||
BAN::ErrorOr<long> sys_getppid() const { return m_parent; }
|
||||
BAN::ErrorOr<long> sys_getpid() const { return pid(); }
|
||||
|
||||
BAN::ErrorOr<long> open_inode(VirtualFileSystem::File&&, int flags);
|
||||
|
@ -108,9 +110,12 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_write(int fd, const void* buffer, size_t count);
|
||||
BAN::ErrorOr<long> sys_access(const char* path, int amode);
|
||||
BAN::ErrorOr<long> sys_create_dir(const char*, mode_t);
|
||||
BAN::ErrorOr<long> sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag);
|
||||
BAN::ErrorOr<long> sys_unlink(const char*);
|
||||
BAN::ErrorOr<long> sys_readlinkat(int fd, const char* path, char* buffer, size_t bufsize);
|
||||
|
||||
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
||||
|
||||
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
|
||||
|
||||
BAN::ErrorOr<long> sys_fchmodat(int fd, const char* path, mode_t mode, int flag);
|
||||
|
@ -143,7 +148,10 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<long> sys_truncate(int fd, off_t length);
|
||||
|
||||
BAN::ErrorOr<long> sys_fsync(int fd);
|
||||
|
||||
BAN::ErrorOr<long> sys_fstatat(int fd, const char* path, struct stat* buf, int flag);
|
||||
BAN::ErrorOr<long> sys_fstatvfsat(int fd, const char* path, struct statvfs* buf);
|
||||
|
||||
BAN::ErrorOr<long> sys_realpath(const char* path, char* buffer);
|
||||
|
||||
|
@ -177,6 +185,7 @@ namespace Kernel
|
|||
BAN::ErrorOr<long> sys_sigpending(sigset_t* set);
|
||||
BAN::ErrorOr<long> sys_sigprocmask(int how, const sigset_t* set, sigset_t* oset);
|
||||
|
||||
BAN::ErrorOr<long> sys_tcgetpgrp(int fd);
|
||||
BAN::ErrorOr<long> sys_tcsetpgrp(int fd, pid_t pgid);
|
||||
|
||||
BAN::ErrorOr<long> sys_termid(char*);
|
||||
|
@ -215,6 +224,7 @@ namespace Kernel
|
|||
static Process* create_process(const Credentials&, pid_t parent, pid_t sid = 0, pid_t pgrp = 0);
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_file(int fd, const char* path, int flags);
|
||||
BAN::ErrorOr<VirtualFileSystem::File> find_parent(int fd, const char* path);
|
||||
|
||||
BAN::ErrorOr<void> validate_string_access(const char*);
|
||||
BAN::ErrorOr<void> validate_pointer_access_check(const void*, size_t, bool needs_write);
|
||||
|
|
|
@ -20,10 +20,14 @@ namespace Kernel
|
|||
BAN::ErrorOr<void> write_to_cache(uint64_t sector, BAN::ConstByteSpan, bool dirty);
|
||||
|
||||
BAN::ErrorOr<void> sync();
|
||||
BAN::ErrorOr<void> sync(uint64_t sector, size_t sector_count);
|
||||
size_t release_clean_pages(size_t);
|
||||
size_t release_pages(size_t);
|
||||
void release_all_pages();
|
||||
|
||||
private:
|
||||
BAN::ErrorOr<void> sync_cache_index(size_t index);
|
||||
|
||||
private:
|
||||
struct PageCache
|
||||
{
|
||||
|
|
|
@ -15,13 +15,14 @@ namespace Kernel
|
|||
const BAN::GUID& partition_guid() const { return m_guid; }
|
||||
const BAN::RefPtr<BlockDevice> device() const { return m_device; }
|
||||
|
||||
virtual blksize_t blksize() const { return m_device->blksize(); }
|
||||
virtual blksize_t blksize() const override { return m_device->blksize(); }
|
||||
|
||||
BAN::ErrorOr<void> read_sectors(uint64_t first_block, size_t block_count, BAN::ByteSpan buffer) { return read_blocks(first_block, block_count, buffer); }
|
||||
BAN::ErrorOr<void> write_sectors(uint64_t first_block, size_t block_count, BAN::ConstByteSpan buffer) { return write_blocks(first_block, block_count, buffer); }
|
||||
|
||||
virtual BAN::ErrorOr<void> read_blocks(uint64_t first_block, size_t block_count, BAN::ByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> write_blocks(uint64_t first_block, size_t block_count, BAN::ConstByteSpan) override;
|
||||
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) override;
|
||||
|
||||
virtual BAN::StringView name() const override { return m_name; }
|
||||
|
||||
|
|
|
@ -21,11 +21,12 @@ namespace Kernel
|
|||
|
||||
virtual BAN::ErrorOr<void> read_blocks(uint64_t lba, size_t sector_count, BAN::ByteSpan buffer) override { return read_sectors(lba, sector_count, buffer); }
|
||||
virtual BAN::ErrorOr<void> write_blocks(uint64_t lba, size_t sector_count, BAN::ConstByteSpan buffer) override { return write_sectors(lba, sector_count, buffer); }
|
||||
virtual BAN::ErrorOr<void> sync_blocks(uint64_t block, size_t block_count) override;
|
||||
|
||||
BAN::ErrorOr<void> read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan);
|
||||
BAN::ErrorOr<void> write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan);
|
||||
|
||||
virtual blksize_t blksize() const { return sector_size(); }
|
||||
virtual blksize_t blksize() const override { return sector_size(); }
|
||||
virtual uint32_t sector_size() const = 0;
|
||||
virtual uint64_t total_size() const = 0;
|
||||
|
||||
|
|
|
@ -30,6 +30,9 @@ namespace Kernel
|
|||
Terminated,
|
||||
};
|
||||
|
||||
static constexpr size_t kernel_stack_size { PAGE_SIZE * 8 };
|
||||
static constexpr size_t userspace_stack_size { PAGE_SIZE * 128 };
|
||||
|
||||
public:
|
||||
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
|
||||
static BAN::ErrorOr<Thread*> create_userspace(Process*, PageTable&);
|
||||
|
@ -103,8 +106,6 @@ namespace Kernel
|
|||
// {kernel,userspace}_stack has to be destroyed before page table
|
||||
BAN::UniqPtr<PageTable> m_keep_alive_page_table;
|
||||
|
||||
static constexpr size_t m_kernel_stack_size { PAGE_SIZE * 8 };
|
||||
static constexpr size_t m_userspace_stack_size { PAGE_SIZE * 128 };
|
||||
BAN::UniqPtr<VirtualRange> m_kernel_stack;
|
||||
BAN::UniqPtr<VirtualRange> m_userspace_stack;
|
||||
const pid_t m_tid { 0 };
|
||||
|
|
|
@ -31,6 +31,10 @@ namespace Kernel
|
|||
s_instance->add_device(MUST(ZeroDevice::create(0666, 0, 0)));
|
||||
s_instance->add_device(MUST(KeyboardDevice::create(0440, 0, 901)));
|
||||
s_instance->add_device(MUST(MouseDevice::create(0440, 0, 901)));
|
||||
|
||||
// create symlink urandom -> random
|
||||
auto urandom = MUST(TmpSymlinkInode::create_new(DevFileSystem::get(), 0777, 0, 0, "random"_sv));
|
||||
s_instance->add_inode("urandom"_sv, urandom);
|
||||
}
|
||||
|
||||
DevFileSystem& DevFileSystem::get()
|
||||
|
|
|
@ -32,6 +32,18 @@ namespace Kernel
|
|||
return superblock.magic == Ext2::Enum::SUPER_MAGIC;
|
||||
}
|
||||
|
||||
unsigned long Ext2FS::bsize() const { return block_size(); }
|
||||
unsigned long Ext2FS::frsize() const { return block_size(); }
|
||||
fsblkcnt_t Ext2FS::blocks() const { return m_superblock.blocks_count; }
|
||||
fsblkcnt_t Ext2FS::bfree() const { return m_superblock.free_blocks_count; }
|
||||
fsblkcnt_t Ext2FS::bavail() const { return m_superblock.free_blocks_count; } // FIXME
|
||||
fsfilcnt_t Ext2FS::files() const { return m_superblock.inodes_count; }
|
||||
fsfilcnt_t Ext2FS::ffree() const { return m_superblock.free_inodes_count; }
|
||||
fsfilcnt_t Ext2FS::favail() const { return m_superblock.free_inodes_count; } // FIXME
|
||||
unsigned long Ext2FS::fsid() const { return *reinterpret_cast<const unsigned long*>(m_superblock.uuid); } // FIXME?
|
||||
unsigned long Ext2FS::flag() const { return 0; }
|
||||
unsigned long Ext2FS::namemax() const { return 0xFF; }
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<Ext2FS>> Ext2FS::create(BAN::RefPtr<BlockDevice> block_device)
|
||||
{
|
||||
auto ext2fs = TRY(BAN::RefPtr<Ext2FS>::create(block_device));
|
||||
|
@ -346,6 +358,17 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2FS::sync_block(uint32_t block)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
||||
const uint32_t sector_size = m_block_device->blksize();
|
||||
const uint32_t block_size = this->block_size();
|
||||
const uint32_t sectors_per_block = block_size / sector_size;
|
||||
|
||||
return m_block_device->sync_blocks(block * sectors_per_block, sectors_per_block);
|
||||
}
|
||||
|
||||
Ext2FS::BlockBufferWrapper Ext2FS::get_block_buffer()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
|
|
@ -47,6 +47,11 @@ namespace Kernel
|
|||
dwarnln("Could not cleanup inode from FS: {}", ret.error());
|
||||
}
|
||||
|
||||
const FileSystem* Ext2Inode::filesystem() const
|
||||
{
|
||||
return &m_fs;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth)
|
||||
{
|
||||
if (block == 0)
|
||||
|
@ -99,7 +104,27 @@ namespace Kernel
|
|||
{
|
||||
ASSERT(mode().iflnk());
|
||||
if (m_inode.size < sizeof(m_inode.block))
|
||||
return BAN::String((const char*)m_inode.block);
|
||||
{
|
||||
BAN::String result;
|
||||
TRY(result.append(BAN::StringView(reinterpret_cast<const char*>(m_inode.block), m_inode.size)));
|
||||
return result;
|
||||
}
|
||||
dwarnln("TODO: ext2 get symlink target from {} byte inode", m_inode.size);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::set_link_target_impl(BAN::StringView target)
|
||||
{
|
||||
ASSERT(mode().iflnk());
|
||||
if (m_inode.size < sizeof(m_inode.block) && target.size() < sizeof(m_inode.block))
|
||||
{
|
||||
memset(m_inode.block, 0, sizeof(m_inode.block));
|
||||
memcpy(m_inode.block, target.data(), target.size());
|
||||
m_inode.size = target.size();
|
||||
TRY(sync());
|
||||
return {};
|
||||
}
|
||||
dwarnln("TODO: ext2 set symlink target to {} bytes from {} byte inode", target.size(), m_inode.size);
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
|
@ -259,6 +284,14 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::fsync_impl()
|
||||
{
|
||||
for (size_t i = 0; i < max_used_data_block_count(); i++)
|
||||
if (const auto fs_block = TRY(fs_block_of_data_block_index(i)); fs_block.has_value())
|
||||
TRY(m_fs.sync_block(fs_block.value()));
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::cleanup_indirect_block(uint32_t block, uint32_t depth)
|
||||
{
|
||||
ASSERT(block);
|
||||
|
@ -427,8 +460,15 @@ done:
|
|||
if (!find_inode_impl(name).is_error())
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
if (!(Mode(mode).ifreg()))
|
||||
switch (mode & Inode::Mode::TYPE_MASK)
|
||||
{
|
||||
case Inode::Mode::IFLNK:
|
||||
case Inode::Mode::IFREG:
|
||||
case Inode::Mode::IFIFO:
|
||||
case Inode::Mode::IFSOCK:
|
||||
break;
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
|
||||
|
||||
|
@ -478,6 +518,23 @@ done:
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::link_inode_impl(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
ASSERT(this->mode().ifdir());
|
||||
ASSERT(!inode->mode().ifdir());
|
||||
|
||||
if (&m_fs != inode->filesystem())
|
||||
return BAN::Error::from_errno(EXDEV);
|
||||
|
||||
if (!find_inode_impl(name).is_error())
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
auto ext2_inode = static_cast<Ext2Inode*>(inode.ptr());
|
||||
TRY(link_inode_to_directory(*ext2_inode, name));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Ext2Inode::link_inode_to_directory(Ext2Inode& inode, BAN::StringView name)
|
||||
{
|
||||
if (!this->mode().ifdir())
|
||||
|
@ -494,7 +551,7 @@ done:
|
|||
|
||||
auto error_or = find_inode_impl(name);
|
||||
if (!error_or.is_error())
|
||||
return BAN::Error::from_errno(EEXISTS);
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
if (error_or.error().get_error_code() != ENOENT)
|
||||
return error_or.error();
|
||||
|
||||
|
|
|
@ -64,6 +64,18 @@ namespace Kernel
|
|||
return validate_bpb(bpb_span.as<const FAT::BPB>());
|
||||
}
|
||||
|
||||
unsigned long FATFS::bsize() const { return m_bpb.bytes_per_sector; }
|
||||
unsigned long FATFS::frsize() const { return m_bpb.bytes_per_sector; }
|
||||
fsblkcnt_t FATFS::blocks() const { return data_sector_count(); }
|
||||
fsblkcnt_t FATFS::bfree() const { return 0; } // FIXME
|
||||
fsblkcnt_t FATFS::bavail() const { return 0; } // FIXME
|
||||
fsfilcnt_t FATFS::files() const { return m_bpb.number_of_fats * fat_size() * 8 / bits_per_fat_entry(); }
|
||||
fsfilcnt_t FATFS::ffree() const { return 0; } // FIXME
|
||||
fsfilcnt_t FATFS::favail() const { return 0; } // FIXME
|
||||
unsigned long FATFS::fsid() const { return m_type == Type::FAT32 ? m_bpb.ext_32.volume_id : m_bpb.ext_12_16.volume_id; }
|
||||
unsigned long FATFS::flag() const { return 0; }
|
||||
unsigned long FATFS::namemax() const { return 255; }
|
||||
|
||||
BAN::ErrorOr<BAN::RefPtr<FATFS>> FATFS::create(BAN::RefPtr<BlockDevice> block_device)
|
||||
{
|
||||
// support only block devices with sectors at least 512 bytes
|
||||
|
@ -226,7 +238,7 @@ namespace Kernel
|
|||
{
|
||||
if (index >= root_sector_count())
|
||||
return BAN::Error::from_errno(ENOENT);
|
||||
const uint32_t first_root_sector = m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_sector_count());
|
||||
const uint32_t first_root_sector = m_bpb.reserved_sector_count + (m_bpb.number_of_fats * fat_size());
|
||||
TRY(m_block_device->read_blocks(first_root_sector + index, 1, buffer));
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -46,6 +46,11 @@ namespace Kernel
|
|||
return timespec { .tv_sec = epoch, .tv_nsec = 0 };
|
||||
}
|
||||
|
||||
const FileSystem* FATInode::filesystem() const
|
||||
{
|
||||
return &m_fs;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> FATInode::for_each_directory_entry(BAN::ConstByteSpan entry_span, BAN::Function<BAN::Iteration(const FAT::DirectoryEntry&)> callback)
|
||||
{
|
||||
ASSERT(mode().ifdir());
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <kernel/FS/Inode.h>
|
||||
#include <kernel/Lock/LockGuard.h>
|
||||
#include <kernel/Memory/FileBackedRegion.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
|
@ -92,6 +93,16 @@ namespace Kernel
|
|||
return create_directory_impl(name, mode, uid, gid);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::link_inode(BAN::StringView name, BAN::RefPtr<Inode> inode)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!this->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
if (inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return link_inode_impl(name, inode);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::unlink(BAN::StringView name)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
@ -110,6 +121,14 @@ namespace Kernel
|
|||
return link_target_impl();
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::set_link_target(BAN::StringView target)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (!mode().iflnk())
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
return set_link_target_impl(target);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Inode::accept(sockaddr* address, socklen_t* address_len, int flags)
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
@ -203,6 +222,15 @@ namespace Kernel
|
|||
return chown_impl(uid, gid);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Inode::fsync()
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
if (auto shared = m_shared_region.lock())
|
||||
for (size_t i = 0; i < shared->pages.size(); i++)
|
||||
shared->sync(i);
|
||||
return fsync_impl();
|
||||
}
|
||||
|
||||
bool Inode::can_read() const
|
||||
{
|
||||
LockGuard _(m_mutex);
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Kernel
|
|||
if (m_writing_count == 0)
|
||||
return 0;
|
||||
LockFreeGuard lock_free(m_mutex);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
||||
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
||||
}
|
||||
|
||||
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
|
||||
|
@ -84,7 +84,7 @@ namespace Kernel
|
|||
while (m_buffer.size() - m_buffer_size < buffer.size())
|
||||
{
|
||||
LockFreeGuard lock_free(m_mutex);
|
||||
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker));
|
||||
TRY(Thread::current().block_or_eintr_or_timeout_ms(m_thread_blocker, 100, false));
|
||||
}
|
||||
|
||||
const size_t to_copy = buffer.size();
|
||||
|
|
|
@ -41,6 +41,11 @@ namespace Kernel
|
|||
|
||||
/* GENERAL INODE */
|
||||
|
||||
const FileSystem* TmpInode::filesystem() const
|
||||
{
|
||||
return &m_fs;
|
||||
}
|
||||
|
||||
dev_t TmpInode::dev() const
|
||||
{
|
||||
return m_fs.dev();
|
||||
|
|
|
@ -81,7 +81,8 @@ namespace Kernel
|
|||
memcpy(page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
||||
});
|
||||
|
||||
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer)); ret.is_error())
|
||||
const size_t write_size = BAN::Math::min<size_t>(PAGE_SIZE, inode->size() - page_index * PAGE_SIZE);
|
||||
if (auto ret = inode->write(page_index * PAGE_SIZE, BAN::ConstByteSpan::from(page_buffer).slice(0, write_size)); ret.is_error())
|
||||
dwarnln("{}", ret.error());
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,14 @@ namespace Kernel
|
|||
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
|
||||
return 0;
|
||||
}
|
||||
case SIOCGIFNAME:
|
||||
{
|
||||
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
|
||||
ASSERT(m_interface->name().size() < sizeof(ifrn_name));
|
||||
memcpy(ifrn_name, m_interface->name().data(), m_interface->name().size());
|
||||
ifrn_name[m_interface->name().size()] = '\0';
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
}
|
||||
|
|
|
@ -202,20 +202,23 @@ namespace Kernel
|
|||
{
|
||||
TRY(validate_fd(fd));
|
||||
|
||||
constexpr int creation_flags = O_CLOEXEC | O_CREAT | O_DIRECTORY | O_EXCL | O_NOCTTY | O_NOFOLLOW | O_TRUNC | O_TTY_INIT;
|
||||
dprintln("fcntl({} ('{}'), {}, {H})", fd, m_open_files[fd]->path(), cmd, extra);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case F_GETFD:
|
||||
return m_open_files[fd]->flags;
|
||||
return m_open_files[fd]->flags & FD_CLOEXEC;
|
||||
case F_SETFD:
|
||||
// FIXME: validate permissions to set access flags
|
||||
m_open_files[fd]->flags = extra;
|
||||
m_open_files[fd]->flags &= ~FD_CLOEXEC;
|
||||
m_open_files[fd]->flags |= extra & FD_CLOEXEC;
|
||||
dprintln(" set CLOEXEC to {}", !!(m_open_files[fd]->flags & FD_CLOEXEC));
|
||||
return 0;
|
||||
case F_GETFL:
|
||||
return m_open_files[fd]->flags & ~creation_flags;
|
||||
return m_open_files[fd]->flags & ~(O_APPEND | O_DSYNC | O_NONBLOCK | O_RSYNC | O_SYNC | O_ACCMODE);
|
||||
case F_SETFL:
|
||||
m_open_files[fd]->flags |= extra & ~(O_ACCMODE | creation_flags);
|
||||
m_open_files[fd]->flags &= ~O_NONBLOCK;
|
||||
m_open_files[fd]->flags |= extra & O_NONBLOCK;
|
||||
dprintln(" set NONBLOCK to {}", !!(m_open_files[fd]->flags & O_NONBLOCK));
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -228,6 +228,13 @@ namespace Kernel
|
|||
s_processes.remove(i);
|
||||
break;
|
||||
}
|
||||
for (auto it = s_alarm_processes.begin(); it != s_alarm_processes.end();)
|
||||
{
|
||||
if (*it == this)
|
||||
it = s_alarm_processes.remove(it);
|
||||
else
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
ProcFileSystem::get().on_process_delete(*this);
|
||||
|
@ -286,6 +293,7 @@ namespace Kernel
|
|||
child.exited = true;
|
||||
|
||||
parent.add_pending_signal(SIGCHLD);
|
||||
if (!parent.m_threads.empty())
|
||||
Processor::scheduler().unblock_thread(parent.m_threads.front());
|
||||
|
||||
parent.m_child_exit_blocker.unblock();
|
||||
|
@ -300,6 +308,8 @@ namespace Kernel
|
|||
|
||||
while (!m_threads.empty())
|
||||
m_threads.front()->on_exit();
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
size_t Process::proc_meminfo(off_t offset, BAN::ByteSpan buffer) const
|
||||
|
@ -368,6 +378,26 @@ namespace Kernel
|
|||
return read_from_vec_of_str(m_environ, offset, buffer);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> Process::find_parent(int fd, const char* path)
|
||||
{
|
||||
ASSERT(m_process_lock.is_locked());
|
||||
|
||||
if (path)
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
if (path && path[0] == '/')
|
||||
return VirtualFileSystem::get().root_file();
|
||||
|
||||
if (fd == AT_FDCWD)
|
||||
return TRY(m_working_directory.clone());
|
||||
|
||||
int flags = TRY(m_open_file_descriptors.flags_of(fd));
|
||||
if (!(flags & O_RDONLY) && !(flags & O_SEARCH))
|
||||
return BAN::Error::from_errno(EBADF);
|
||||
|
||||
return TRY(m_open_file_descriptors.file_of(fd));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<VirtualFileSystem::File> Process::find_file(int fd, const char* path, int flags)
|
||||
{
|
||||
ASSERT(m_process_lock.is_locked());
|
||||
|
@ -375,14 +405,7 @@ namespace Kernel
|
|||
if (path)
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
VirtualFileSystem::File parent_file;
|
||||
if (path && path[0] == '/')
|
||||
parent_file = VirtualFileSystem::get().root_file();
|
||||
else if (fd == AT_FDCWD)
|
||||
parent_file = TRY(m_working_directory.clone());
|
||||
else
|
||||
parent_file = TRY(m_open_file_descriptors.file_of(fd));
|
||||
|
||||
auto parent_file = TRY(find_parent(fd, path));
|
||||
auto file = path
|
||||
? TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags))
|
||||
: BAN::move(parent_file);
|
||||
|
@ -834,6 +857,8 @@ namespace Kernel
|
|||
break;
|
||||
|
||||
process->add_pending_signal(SIGALRM);
|
||||
|
||||
ASSERT(!process->m_threads.empty());
|
||||
Processor::scheduler().unblock_thread(process->m_threads.front());
|
||||
|
||||
s_alarm_processes.remove(s_alarm_processes.begin());
|
||||
|
@ -854,10 +879,12 @@ namespace Kernel
|
|||
{
|
||||
switch (mode & Inode::Mode::TYPE_MASK)
|
||||
{
|
||||
case Inode::Mode::IFREG: break;
|
||||
case Inode::Mode::IFDIR: break;
|
||||
case Inode::Mode::IFIFO: break;
|
||||
case Inode::Mode::IFSOCK: break;
|
||||
case Inode::Mode::IFREG:
|
||||
case Inode::Mode::IFDIR:
|
||||
case Inode::Mode::IFLNK:
|
||||
case Inode::Mode::IFIFO:
|
||||
case Inode::Mode::IFSOCK:
|
||||
break;
|
||||
default:
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
@ -925,21 +952,7 @@ namespace Kernel
|
|||
|
||||
TRY(validate_string_access(path));
|
||||
|
||||
VirtualFileSystem::File parent_file;
|
||||
if (path[0] == '/')
|
||||
parent_file = VirtualFileSystem::get().root_file();
|
||||
else if (fd == AT_FDCWD)
|
||||
parent_file = TRY(m_working_directory.clone());
|
||||
else
|
||||
{
|
||||
int flags = TRY(m_open_file_descriptors.flags_of(fd));
|
||||
if (!(flags & O_RDONLY) && !(flags & O_SEARCH))
|
||||
return BAN::Error::from_errno(EBADF);
|
||||
if (!TRY(m_open_file_descriptors.inode_of(fd))->mode().ifdir())
|
||||
return BAN::Error::from_errno(ENOTDIR);
|
||||
parent_file = TRY(m_open_file_descriptors.file_of(fd));
|
||||
}
|
||||
|
||||
auto parent_file = TRY(find_parent(fd, path));
|
||||
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags | O_NOFOLLOW);
|
||||
|
||||
VirtualFileSystem::File file;
|
||||
|
@ -950,7 +963,7 @@ namespace Kernel
|
|||
|
||||
// FIXME: There is a race condition between next two lines
|
||||
TRY(create_file_or_dir(parent_file, path, (mode & 0777) | Inode::Mode::IFREG));
|
||||
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags));
|
||||
file = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path, flags & ~O_RDWR));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1041,6 +1054,40 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_hardlinkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path1));
|
||||
TRY(validate_string_access(path2));
|
||||
|
||||
auto inode = TRY(find_file(fd1, path1, flag)).inode;
|
||||
if (inode->mode().ifdir())
|
||||
return BAN::Error::from_errno(EISDIR);
|
||||
|
||||
auto parent = TRY(find_parent(fd2, path2));
|
||||
|
||||
BAN::RefPtr<Inode> parent_inode;
|
||||
BAN::StringView file_name;
|
||||
|
||||
BAN::StringView path2_sv = path2;
|
||||
if (auto index = path2_sv.rfind('/'); index.has_value())
|
||||
{
|
||||
parent_inode = TRY(VirtualFileSystem::get().file_from_relative_path(parent, m_credentials, path2_sv.substring(0, index.value()), O_EXEC | O_WRONLY)).inode;
|
||||
file_name = path2_sv.substring(index.value() + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent_inode = parent.inode;
|
||||
file_name = path2_sv;
|
||||
if (!parent_inode->can_access(m_credentials, O_WRONLY))
|
||||
return BAN::Error::from_errno(EACCES);
|
||||
}
|
||||
|
||||
ASSERT(parent_inode->mode().ifdir());
|
||||
TRY(parent_inode->link_inode(file_name, inode));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_unlink(const char* path)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
@ -1077,6 +1124,25 @@ namespace Kernel
|
|||
return byte_count;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_symlinkat(const char* path1, int fd, const char* path2)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
TRY(validate_string_access(path1));
|
||||
TRY(validate_string_access(path2));
|
||||
|
||||
auto parent_file = TRY(find_parent(fd, path2));
|
||||
auto file_or_error = VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path2, O_NOFOLLOW);
|
||||
if (!file_or_error.is_error())
|
||||
return BAN::Error::from_errno(EEXIST);
|
||||
|
||||
TRY(create_file_or_dir(parent_file, path2, 0777 | Inode::Mode::IFLNK));
|
||||
|
||||
auto symlink = TRY(VirtualFileSystem::get().file_from_relative_path(parent_file, m_credentials, path2, O_NOFOLLOW));
|
||||
TRY(symlink.inode->set_link_target(path1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
@ -1448,6 +1514,14 @@ namespace Kernel
|
|||
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::String absolute_source, absolute_target;
|
||||
|
@ -1488,6 +1562,35 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
@ -1906,6 +2009,7 @@ namespace Kernel
|
|||
if (signal)
|
||||
{
|
||||
process.add_pending_signal(signal);
|
||||
if (!process.m_threads.empty())
|
||||
Processor::scheduler().unblock_thread(process.m_threads.front());
|
||||
}
|
||||
return (pid > 0) ? BAN::Iteration::Break : BAN::Iteration::Continue;
|
||||
|
@ -2004,6 +2108,24 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
LockGuard _(m_process_lock);
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Kernel
|
|||
|
||||
for (auto& cache : m_cache)
|
||||
{
|
||||
if (cache.first_sector < page_cache_start)
|
||||
if (cache.first_sector + sectors_per_page <= page_cache_start)
|
||||
continue;
|
||||
if (cache.first_sector > page_cache_start)
|
||||
break;
|
||||
|
@ -64,7 +64,7 @@ namespace Kernel
|
|||
{
|
||||
auto& cache = m_cache[index];
|
||||
|
||||
if (cache.first_sector < page_cache_start)
|
||||
if (cache.first_sector + sectors_per_page <= page_cache_start)
|
||||
continue;
|
||||
if (cache.first_sector > page_cache_start)
|
||||
break;
|
||||
|
@ -104,15 +104,11 @@ namespace Kernel
|
|||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> DiskCache::sync()
|
||||
{
|
||||
if (g_disable_disk_write)
|
||||
return {};
|
||||
|
||||
for (auto& cache : m_cache)
|
||||
BAN::ErrorOr<void> DiskCache::sync_cache_index(size_t index)
|
||||
{
|
||||
auto& cache = m_cache[index];
|
||||
if (cache.dirty_mask == 0)
|
||||
continue;
|
||||
return {};
|
||||
|
||||
PageTable::with_fast_page(cache.paddr, [&] {
|
||||
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
||||
|
@ -145,6 +141,36 @@ namespace Kernel
|
|||
}
|
||||
|
||||
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 {};
|
||||
|
|
|
@ -48,6 +48,15 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
ASSERT(offset >= 0);
|
||||
|
|
|
@ -286,6 +286,13 @@ namespace Kernel
|
|||
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)
|
||||
{
|
||||
if (offset % sector_size())
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace Kernel
|
|||
PageTable::kernel(),
|
||||
KERNEL_OFFSET,
|
||||
~(uintptr_t)0,
|
||||
m_kernel_stack_size,
|
||||
kernel_stack_size,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
true
|
||||
));
|
||||
|
@ -104,7 +104,7 @@ namespace Kernel
|
|||
thread->m_kernel_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||
page_table,
|
||||
0x300000, KERNEL_OFFSET,
|
||||
m_kernel_stack_size,
|
||||
kernel_stack_size,
|
||||
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
true
|
||||
));
|
||||
|
@ -112,7 +112,7 @@ namespace Kernel
|
|||
thread->m_userspace_stack = TRY(VirtualRange::create_to_vaddr_range(
|
||||
page_table,
|
||||
0x300000, KERNEL_OFFSET,
|
||||
m_userspace_stack_size,
|
||||
userspace_stack_size,
|
||||
PageTable::Flags::UserSupervisor | PageTable::Flags::ReadWrite | PageTable::Flags::Present,
|
||||
true
|
||||
));
|
||||
|
|
|
@ -158,7 +158,6 @@ const char* strerrordesc_np(int error)
|
|||
case ETXTBSY: return "Text file busy.";
|
||||
case EWOULDBLOCK: return "Operation would block.";
|
||||
case EXDEV: return "Cross-device link.";
|
||||
case EEXISTS: return "File exists";
|
||||
case ENOTBLK: return "Block device required";
|
||||
case EUNKNOWN: return "Unknown error";
|
||||
}
|
||||
|
|
|
@ -8,9 +8,14 @@ CONFIGURE_OPTIONS=(
|
|||
'--disable-threaded-resolver'
|
||||
'--disable-ipv6'
|
||||
'--disable-docs'
|
||||
'--disable-ntlm'
|
||||
'--with-openssl'
|
||||
'--with-zlib'
|
||||
'--with-random=/dev/random'
|
||||
'--with-ca-bundle=/etc/ssl/certs/ca-certificates.crt'
|
||||
'--without-ca-path'
|
||||
)
|
||||
|
||||
install() {
|
||||
make install DESTDIR="$BANAN_SYSROOT" || exit 1
|
||||
rm -f $BANAN_SYSROOT/usr/lib/libcurl.la
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ if (( $# != 1 )); then
|
|||
fi
|
||||
|
||||
if [[ -z $BANAN_ROOT_DIR ]]; then
|
||||
BANAN_ROOT_DIR="$(realpath $(dirname $(realpath $0))/..)"
|
||||
export BANAN_ROOT_DIR="$(realpath $(dirname $(realpath $0))/..)"
|
||||
fi
|
||||
|
||||
source "$BANAN_ROOT_DIR/script/config.sh"
|
||||
|
@ -29,12 +29,11 @@ export OBJDUMP="$BANAN_TOOLCHAIN_TRIPLE-objdump"
|
|||
export STRIP="$BANAN_TOOLCHAIN_TRIPLE-strip"
|
||||
export CXXFILT="$BANAN_TOOLCHAIN_TRIPLE-c++filt"
|
||||
|
||||
if [ ! -f "$BANAN_SYSROOT/usr/lib/libc.a" ]; then
|
||||
pushd "$BANAN_ROOT_DIR" >/dev/null
|
||||
./bos libc || exit 1
|
||||
./bos install || exit 1
|
||||
popd >/dev/null
|
||||
fi
|
||||
export CMAKE_TOOLCHAIN_FILE="$BANAN_TOOLCHAIN_DIR/Toolchain.txt"
|
||||
|
||||
pushd "$BANAN_ROOT_DIR" >/dev/null
|
||||
./bos all && ./bos install || exit 1
|
||||
popd >/dev/null
|
||||
|
||||
if [ "$BANAN_ARCH" = "i686" ]; then
|
||||
export LDFLAGS="-shared-libgcc"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
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-banan_os/Configurations/10-main.conf 2024-08-21 15:45:36.605293938 +0300
|
||||
@@ -668,6 +668,22 @@
|
||||
+++ openssl-3.3.1-banan_os/Configurations/10-main.conf 2024-12-03 01:31:59.218821407 +0200
|
||||
@@ -668,6 +668,26 @@
|
||||
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",
|
||||
+ lib_cppflags => "-DOPENSSL_USE_NODELETE",
|
||||
+ 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:-)
|
||||
####
|
||||
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 {
|
||||
|
|
|
@ -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')
|
|
@ -49,8 +49,6 @@ create_image () {
|
|||
build_target all
|
||||
build_target install
|
||||
|
||||
$BANAN_ROOT_DIR/ports/update.sh
|
||||
|
||||
pushd $BANAN_SYSROOT >/dev/null
|
||||
run_fakeroot tar cf ${BANAN_SYSROOT_TAR} *
|
||||
popd >/dev/null
|
||||
|
|
|
@ -13,12 +13,21 @@ if (NOT DEFINED ENV{BANAN_SYSROOT_TAR})
|
|||
endif ()
|
||||
set(BANAN_SYSROOT_TAR $ENV{BANAN_SYSROOT_TAR})
|
||||
|
||||
|
||||
set(TOOLCHAIN_PREFIX ${CMAKE_SOURCE_DIR}/toolchain/local)
|
||||
if (NOT DEFINED ENV{BANAN_ROOT_DIR})
|
||||
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_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_REQUIRED True)
|
||||
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}/bin/${BANAN_ARCH}-banan_os-g++)
|
||||
|
|
|
@ -41,6 +41,9 @@ endforeach()
|
|||
foreach(AOC2023_PROJECT ${AOC2023_PROJECTS})
|
||||
add_subdirectory(${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()
|
||||
|
||||
add_dependencies(userspace aoc2023)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
set(AOC2024_PROJECTS
|
||||
day1
|
||||
day2
|
||||
day3
|
||||
full
|
||||
)
|
||||
|
||||
|
@ -19,6 +20,9 @@ endforeach()
|
|||
foreach(AOC2024_PROJECT ${AOC2024_PROJECTS})
|
||||
add_subdirectory(${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()
|
||||
|
||||
add_dependencies(userspace aoc2024)
|
||||
|
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -10,6 +10,7 @@ set(LIBC_SOURCES
|
|||
ftw.cpp
|
||||
grp.cpp
|
||||
inttypes.cpp
|
||||
libgen.cpp
|
||||
locale.cpp
|
||||
malloc.cpp
|
||||
math.cpp
|
||||
|
@ -31,6 +32,7 @@ set(LIBC_SOURCES
|
|||
sys/select.cpp
|
||||
sys/socket.cpp
|
||||
sys/stat.cpp
|
||||
sys/statvfs.cpp
|
||||
sys/time.cpp
|
||||
sys/utsname.cpp
|
||||
sys/wait.cpp
|
||||
|
|
|
@ -89,7 +89,6 @@ __BEGIN_DECLS
|
|||
#define EWOULDBLOCK 80
|
||||
#define EXDEV 81
|
||||
#define ENOTBLK 82
|
||||
#define EEXISTS 83
|
||||
|
||||
#define EUNKNOWN 0xFF
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@ __BEGIN_DECLS
|
|||
#define F_GETOWN 10
|
||||
#define F_SETOWN 11
|
||||
|
||||
#define FD_CLOEXEC 1
|
||||
|
||||
#define F_RDLCK 1
|
||||
#define F_UNLCK 2
|
||||
#define F_WRLCK 3
|
||||
|
@ -38,6 +36,14 @@ __BEGIN_DECLS
|
|||
#define SEEK_CUR 2
|
||||
#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 */
|
||||
#define O_CLOEXEC 0x00010
|
||||
#define O_CREAT 0x00020
|
||||
|
@ -47,6 +53,7 @@ __BEGIN_DECLS
|
|||
#define O_NOFOLLOW 0x00200
|
||||
#define O_TRUNC 0x00400
|
||||
#define O_TTY_INIT 0x00800
|
||||
#define FD_CLOEXEC O_CLOEXEC
|
||||
|
||||
/* bits 12-16 */
|
||||
#define O_APPEND 0x01000
|
||||
|
@ -55,14 +62,6 @@ __BEGIN_DECLS
|
|||
#define O_RSYNC 0x08000
|
||||
#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 */
|
||||
#define AT_FDCWD 0x20000
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ __BEGIN_DECLS
|
|||
#define OPEN_MAX 64
|
||||
#define NAME_MAX 255
|
||||
#define PATH_MAX 256
|
||||
#define PASS_MAX 256
|
||||
#define LOGIN_NAME_MAX 256
|
||||
#define HOST_NAME_MAX 255
|
||||
#define TTY_NAME_MAX PATH_MAX
|
||||
|
|
|
@ -19,6 +19,10 @@ struct if_nameindex
|
|||
|
||||
struct ifreq
|
||||
{
|
||||
union {
|
||||
char ifrn_name[IF_NAMESIZE];
|
||||
} ifr_ifrn;
|
||||
|
||||
union {
|
||||
struct sockaddr ifru_addr;
|
||||
struct sockaddr ifru_netmask;
|
||||
|
@ -27,6 +31,11 @@ struct ifreq
|
|||
unsigned char __min_storage[sizeof(struct sockaddr) + 6];
|
||||
} 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 SIOCSIFADDR 2 /* Set interface address */
|
||||
|
@ -35,6 +44,7 @@ struct ifreq
|
|||
#define SIOCGIFGWADDR 5 /* Get gateway address */
|
||||
#define SIOCSIFGWADDR 6 /* Set gateway address */
|
||||
#define SIOCGIFHWADDR 7 /* Get hardware address */
|
||||
#define SIOCGIFNAME 8 /* Get interface name */
|
||||
|
||||
void if_freenameindex(struct if_nameindex* ptr);
|
||||
char* if_indextoname(unsigned ifindex, char* ifname);
|
||||
|
|
|
@ -42,6 +42,11 @@ __BEGIN_DECLS
|
|||
#define EAI_SYSTEM 9
|
||||
#define EAI_OVERFLOW 10
|
||||
|
||||
#define HOST_NOT_FOUND 1
|
||||
#define NO_DATA 2
|
||||
#define NO_RECOVERY 3
|
||||
#define TRY_AGAIN 4
|
||||
|
||||
struct hostent
|
||||
{
|
||||
char* h_name; /* Official name of the host. */
|
||||
|
|
|
@ -108,6 +108,8 @@ struct sigevent
|
|||
#define SIGRTMIN 30
|
||||
#define SIGRTMAX (SIGRTMIN+32)
|
||||
|
||||
#define NSIG SIGRTMAX
|
||||
|
||||
#define SI_USER 10
|
||||
#define SI_QUEUE 11
|
||||
#define SI_TIMER 12
|
||||
|
|
|
@ -39,13 +39,16 @@ __BEGIN_DECLS
|
|||
O(SYS_DUP, dup) \
|
||||
O(SYS_DUP2, dup2) \
|
||||
O(SYS_KILL, kill) \
|
||||
O(SYS_TCGETPGRP, tcgetpgrp) \
|
||||
O(SYS_TCSETPGRP, tcsetpgrp) \
|
||||
O(SYS_GET_PPID, getppid) \
|
||||
O(SYS_GET_PID, getpid) \
|
||||
O(SYS_GET_PGID, getpgid) \
|
||||
O(SYS_SET_PGID, setpgid) \
|
||||
O(SYS_FCNTL, fcntl) \
|
||||
O(SYS_NANOSLEEP, nanosleep) \
|
||||
O(SYS_FSTATAT, fstatat) \
|
||||
O(SYS_FSTATVFSAT, fstatvfsat) \
|
||||
O(SYS_SYNC, sync) \
|
||||
O(SYS_MMAP, mmap) \
|
||||
O(SYS_MUNMAP, munmap) \
|
||||
|
@ -85,6 +88,9 @@ __BEGIN_DECLS
|
|||
O(SYS_SETITIMER, setitimer) \
|
||||
O(SYS_POSIX_OPENPT, posix_openpt) \
|
||||
O(SYS_PTSNAME, ptsname) \
|
||||
O(SYS_FSYNC, fsync) \
|
||||
O(SYS_SYMLINKAT, symlinkat) \
|
||||
O(SYS_HARDLINKAT, hardlinkat) \
|
||||
|
||||
enum Syscall
|
||||
{
|
||||
|
|
|
@ -22,6 +22,12 @@ struct itimerval
|
|||
#define ITIMER_VIRTUAL 1
|
||||
#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 gettimeofday(struct timeval* __restrict tp, void* __restrict tzp);
|
||||
int setitimer(int which, const struct itimerval* __restrict value, struct itimerval* __restrict ovalue);
|
||||
|
|
|
@ -233,6 +233,9 @@ int unlinkat(int fd, const char* path, int flag);
|
|||
int usleep(useconds_t usec);
|
||||
ssize_t write(int fildes, const void* buf, size_t nbyte);
|
||||
|
||||
int getpagesize(void);
|
||||
char* getpass(const char* prompt);
|
||||
|
||||
extern char* optarg;
|
||||
extern int opterr, optind, optopt;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -580,6 +580,7 @@ extern "C" int printf_impl(const char* format, va_list arguments, int (*putc_fun
|
|||
case 'm':
|
||||
{
|
||||
// NOTE: this is a glibc extension
|
||||
// NOTE: syslog() requires %m to be handled
|
||||
if (options.alternate_form)
|
||||
string = strerrorname_np(errno);
|
||||
else
|
||||
|
|
|
@ -88,7 +88,7 @@ struct passwd* getpwent(void)
|
|||
ASSERT(1 <= field_len && field_len <= 9);
|
||||
for (size_t j = 0; j < field_len; j++)
|
||||
ASSERT(isdigit(ptr[j]));
|
||||
s_pwent_struct.pw_uid = atoi(ptr);
|
||||
s_pwent_struct.pw_gid = atoi(ptr);
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
|
|
|
@ -26,9 +26,13 @@ struct FILE
|
|||
int unget_char;
|
||||
|
||||
unsigned char inline_buffer_storage[BUFSIZ];
|
||||
unsigned char* buffer;
|
||||
uint32_t buffer_size;
|
||||
uint32_t buffer_index;
|
||||
unsigned char* write_buffer;
|
||||
uint32_t wr_buf_size;
|
||||
uint32_t wr_buf_index;
|
||||
|
||||
unsigned char read_buffer[BUFSIZ];
|
||||
uint32_t rd_buf_size;
|
||||
uint32_t rd_buf_index;
|
||||
};
|
||||
|
||||
struct ScopeLock
|
||||
|
@ -63,9 +67,11 @@ static void init_closed_file(FILE* file)
|
|||
file->error = false;
|
||||
file->pid = -1;
|
||||
file->unget_char = EOF;
|
||||
file->buffer = file->inline_buffer_storage;
|
||||
file->buffer_size = BUFSIZ;
|
||||
file->buffer_index = 0;
|
||||
file->write_buffer = file->inline_buffer_storage;
|
||||
file->wr_buf_size = BUFSIZ;
|
||||
file->wr_buf_index = 0;
|
||||
file->rd_buf_size = 0;
|
||||
file->rd_buf_index = 0;
|
||||
}
|
||||
|
||||
void _init_stdio()
|
||||
|
@ -156,8 +162,9 @@ FILE* fdopen(int fd, const char* mode_str)
|
|||
continue;
|
||||
s_files[i].fd = fd;
|
||||
s_files[i].mode = mode & O_ACCMODE;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].wr_buf_size == BUFSIZ);
|
||||
ASSERT(s_files[i].rd_buf_size == 0);
|
||||
return &s_files[i];
|
||||
}
|
||||
|
||||
|
@ -190,16 +197,16 @@ int fflush(FILE* file)
|
|||
|
||||
file->unget_char = EOF;
|
||||
|
||||
if (file->buffer_index == 0)
|
||||
if (file->wr_buf_index == 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;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
file->buffer_index = 0;
|
||||
file->wr_buf_index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -278,8 +285,9 @@ FILE* fopen(const char* pathname, const char* mode_str)
|
|||
continue;
|
||||
s_files[i].fd = fd;
|
||||
s_files[i].mode = mode & O_ACCMODE;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].wr_buf_size == BUFSIZ);
|
||||
ASSERT(s_files[i].rd_buf_size == 0);
|
||||
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 nread = 0;
|
||||
|
||||
if (file->unget_char != EOF)
|
||||
{
|
||||
*static_cast<unsigned char*>(buffer) = file->unget_char;
|
||||
file->unget_char = EOF;
|
||||
nread++;
|
||||
}
|
||||
if (target == 0)
|
||||
return 0;
|
||||
|
||||
while (nread < target)
|
||||
{
|
||||
ssize_t ret = syscall(SYS_READ, file->fd, static_cast<unsigned char*>(buffer) + nread, target - nread);
|
||||
|
||||
if (ret < 0)
|
||||
file->error = true;
|
||||
else if (ret == 0)
|
||||
file->eof = true;
|
||||
|
||||
if (ret <= 0)
|
||||
return nread;
|
||||
|
||||
nread += ret;
|
||||
int ch = getc_unlocked(file);
|
||||
if (ch == EOF)
|
||||
break;
|
||||
static_cast<unsigned char*>(buffer)[nread++] = ch;
|
||||
}
|
||||
|
||||
return nread / size;
|
||||
|
@ -403,6 +400,8 @@ int fseeko(FILE* file, off_t offset, int whence)
|
|||
if (ret < 0)
|
||||
return -1;
|
||||
file->eof = false;
|
||||
file->rd_buf_size = 0;
|
||||
file->rd_buf_index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -422,7 +421,7 @@ off_t ftello(FILE* file)
|
|||
long ret = syscall(SYS_TELL, file->fd);
|
||||
if (ret < 0)
|
||||
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*)
|
||||
|
@ -469,22 +468,28 @@ int getc_unlocked(FILE* file)
|
|||
return (unsigned char)ch;
|
||||
}
|
||||
|
||||
unsigned char c;
|
||||
long ret = syscall(SYS_READ, file->fd, &c, 1);
|
||||
if (file->rd_buf_index < file->rd_buf_size)
|
||||
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;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
if (nread == 0)
|
||||
{
|
||||
file->eof = true;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
return c;
|
||||
file->rd_buf_size = nread;
|
||||
file->rd_buf_index = 1;
|
||||
return file->read_buffer[0];
|
||||
}
|
||||
|
||||
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].mode = (unsigned)(read ? O_RDONLY : O_WRONLY);
|
||||
s_files[i].pid = pid;
|
||||
ASSERT(s_files[i].buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].buffer_size == BUFSIZ);
|
||||
ASSERT(s_files[i].write_buffer == s_files[i].inline_buffer_storage);
|
||||
ASSERT(s_files[i].wr_buf_size == BUFSIZ);
|
||||
ASSERT(s_files[i].rd_buf_size == 0);
|
||||
return &s_files[i];
|
||||
}
|
||||
|
||||
|
@ -628,8 +634,8 @@ int putchar(int c)
|
|||
|
||||
int putc_unlocked(int c, FILE* file)
|
||||
{
|
||||
file->buffer[file->buffer_index++] = c;
|
||||
if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->buffer_index >= file->buffer_size)
|
||||
file->write_buffer[file->wr_buf_index++] = c;
|
||||
if (file->buffer_type == _IONBF || (file->buffer_type == _IOLBF && c == '\n') || file->wr_buf_index >= file->wr_buf_size)
|
||||
if (fflush(file) == EOF)
|
||||
return EOF;
|
||||
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_size = size;
|
||||
file->buffer = reinterpret_cast<unsigned char*>(buffer);
|
||||
file->wr_buf_size = size;
|
||||
file->write_buffer = reinterpret_cast<unsigned char*>(buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <locale.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -559,9 +560,86 @@ int putenv(char* string)
|
|||
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)
|
||||
|
|
|
@ -492,7 +492,6 @@ const char* strerrorname_np(int error)
|
|||
case ETXTBSY: return "ETXTBSY";
|
||||
case EWOULDBLOCK: return "EWOULDBLOCK";
|
||||
case EXDEV: return "EXDEV";
|
||||
case EEXISTS: return "EEXISTS";
|
||||
case ENOTBLK: return "ENOTBLK";
|
||||
case EUNKNOWN: return "EUNKNOWN";
|
||||
}
|
||||
|
@ -587,7 +586,6 @@ const char* strerrordesc_np(int error)
|
|||
case ETXTBSY: return "Text file busy.";
|
||||
case EWOULDBLOCK: return "Operation would block.";
|
||||
case EXDEV: return "Cross-device link.";
|
||||
case EEXISTS: return "File exists";
|
||||
case ENOTBLK: return "Block device required";
|
||||
case EUNKNOWN: return "Unknown error";
|
||||
}
|
||||
|
|
|
@ -1,7 +1,50 @@
|
|||
#include <BAN/Assert.h>
|
||||
#include <BAN/Limits.h>
|
||||
|
||||
#include <kernel/Thread.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.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)
|
||||
{
|
||||
if (who != RUSAGE_CHILDREN && who != RUSAGE_SELF)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -6,7 +6,8 @@
|
|||
int gettimeofday(struct timeval* __restrict tp, void* __restrict tzp)
|
||||
{
|
||||
// If tzp is not a null pointer, the behavior is unspecified.
|
||||
(void)tzp;
|
||||
if (tzp != nullptr)
|
||||
*static_cast<struct timezone*>(tzp) = {};
|
||||
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
|
|
|
@ -1,12 +1,30 @@
|
|||
#include <BAN/Assert.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.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;
|
||||
}
|
||||
|
|
|
@ -7,37 +7,11 @@
|
|||
#include <time.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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return syscall(SYS_NANOSLEEP, rqtp, rmtp);
|
||||
|
@ -53,10 +27,45 @@ time_t time(time_t* tloc)
|
|||
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 =
|
||||
[](time_t year) -> bool
|
||||
{
|
||||
|
@ -73,38 +82,50 @@ struct tm* gmtime(const time_t* timer)
|
|||
|
||||
time_t time = *timer;
|
||||
|
||||
tm.tm_sec = time % 60; time /= 60;
|
||||
tm.tm_min = time % 60; time /= 60;
|
||||
tm.tm_hour = time % 24; time /= 24;
|
||||
result->tm_sec = time % 60; time /= 60;
|
||||
result->tm_min = time % 60; time /= 60;
|
||||
result->tm_hour = time % 24; time /= 24;
|
||||
|
||||
time_t total_days = time;
|
||||
tm.tm_wday = (total_days + 4) % 7;
|
||||
tm.tm_year = 1970;
|
||||
while (total_days >= 365U + is_leap_year(tm.tm_year))
|
||||
result->tm_wday = (total_days + 4) % 7;
|
||||
result->tm_year = 1970;
|
||||
while (total_days >= 365U + is_leap_year(result->tm_year))
|
||||
{
|
||||
total_days -= 365U + is_leap_year(tm.tm_year);
|
||||
tm.tm_year++;
|
||||
total_days -= 365U + is_leap_year(result->tm_year);
|
||||
result->tm_year++;
|
||||
}
|
||||
|
||||
bool is_leap_day = is_leap_year(tm.tm_year) && total_days == month_days[2];
|
||||
bool had_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(result->tm_year) && total_days > month_days[2];
|
||||
|
||||
for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++)
|
||||
if (total_days < month_days[tm.tm_mon + 1] + (is_leap_day || had_leap_day))
|
||||
for (result->tm_mon = 0; result->tm_mon < 12; result->tm_mon++)
|
||||
if (total_days < month_days[result->tm_mon + 1] + (is_leap_day || had_leap_day))
|
||||
break;
|
||||
|
||||
tm.tm_mday = total_days - month_days[tm.tm_mon] + !had_leap_day;
|
||||
tm.tm_yday = total_days;
|
||||
tm.tm_year -= 1900;
|
||||
tm.tm_isdst = 0;
|
||||
result->tm_mday = total_days - month_days[result->tm_mon] + !had_leap_day;
|
||||
result->tm_yday = total_days;
|
||||
result->tm_year -= 1900;
|
||||
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)
|
||||
{
|
||||
// FIXME: support timezones
|
||||
return gmtime(timer);
|
||||
static struct tm tm;
|
||||
return localtime_r(timer, &tm);
|
||||
}
|
||||
|
||||
size_t strftime(char* __restrict s, size_t maxsize, const char* __restrict format, const struct tm* __restrict timeptr)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <BAN/Assert.h>
|
||||
#include <BAN/Debug.h>
|
||||
#include <kernel/Memory/Types.h>
|
||||
#include <kernel/Syscall.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
@ -12,9 +13,11 @@
|
|||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char** environ;
|
||||
char** __environ;
|
||||
extern char** environ __attribute__((weak, alias("__environ")));
|
||||
|
||||
extern void _init_malloc();
|
||||
extern void _init_stdio();
|
||||
|
@ -115,6 +118,11 @@ int ftruncate(int fildes, off_t length)
|
|||
return syscall(SYS_TRUNCATE, fildes, length);
|
||||
}
|
||||
|
||||
int fsync(int fildes)
|
||||
{
|
||||
return syscall(SYS_FSYNC, fildes);
|
||||
}
|
||||
|
||||
int dup(int fildes)
|
||||
{
|
||||
return syscall(SYS_DUP, fildes);
|
||||
|
@ -135,7 +143,7 @@ int gethostname(char* name, size_t namelen)
|
|||
FILE* fp = fopen("/etc/hostname", "r");
|
||||
if (fp == NULL)
|
||||
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')
|
||||
nread--;
|
||||
name[nread] = '\0';
|
||||
|
@ -143,90 +151,11 @@ int gethostname(char* name, size_t namelen)
|
|||
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* temp = nullptr;
|
||||
return execv(pathname, &temp);
|
||||
}
|
||||
char buffer[PATH_MAX];
|
||||
|
||||
va_list ap;
|
||||
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)
|
||||
if (do_path_resolution && strchr(pathname, '/') == nullptr)
|
||||
{
|
||||
const char* cur = getenv("PATH");
|
||||
if (!cur)
|
||||
|
@ -235,21 +164,22 @@ int execvp(const char* file, char* const argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
char* resolved = nullptr;
|
||||
while (*cur)
|
||||
{
|
||||
const char* end = strchrnul(cur, ':');
|
||||
size_t len = end - cur;
|
||||
|
||||
ASSERT(strlen(file) + 1 + len < sizeof(buffer));
|
||||
ASSERT(strlen(pathname) + 1 + len < sizeof(buffer));
|
||||
|
||||
strncpy(buffer, cur, len);
|
||||
strcat(buffer, "/");
|
||||
strcat(buffer, file);
|
||||
strcat(buffer, pathname);
|
||||
|
||||
struct stat st;
|
||||
if (stat(buffer, &st) == 0)
|
||||
{
|
||||
pathname = buffer;
|
||||
resolved = buffer;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -257,19 +187,91 @@ int execvp(const char* file, char* const argv[])
|
|||
if (*cur)
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pathname = file;
|
||||
}
|
||||
|
||||
if (!pathname)
|
||||
if (!resolved)
|
||||
{
|
||||
errno = ENOENT;
|
||||
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)
|
||||
|
@ -443,6 +445,56 @@ int getopt(int argc, char* const argv[], const char* optstring)
|
|||
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)
|
||||
{
|
||||
return syscall(SYS_GET_PID);
|
||||
|
@ -478,6 +530,11 @@ pid_t getpgid(pid_t pid)
|
|||
return syscall(SYS_GET_PGID, pid);
|
||||
}
|
||||
|
||||
int tcgetpgrp(int fildes)
|
||||
{
|
||||
return syscall(SYS_TCGETPGRP, fildes);
|
||||
}
|
||||
|
||||
int seteuid(uid_t uid)
|
||||
{
|
||||
return syscall(SYS_SET_EUID, uid);
|
||||
|
@ -567,6 +624,20 @@ unsigned alarm(unsigned seconds)
|
|||
|
||||
int symlink(const char* path1, const char* path2)
|
||||
{
|
||||
dwarnln("FIXME: symlink({}, {})", path1, path2);
|
||||
ASSERT_NOT_REACHED();
|
||||
return symlinkat(path1, AT_FDCWD, path2);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include <BAN/Assert.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);
|
||||
}
|
||||
|
|
|
@ -6,3 +6,21 @@ size_t mbrtowc(wchar_t* __restrict, const char* __restrict, size_t, mbstate_t* _
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace LibGUI
|
|||
return BAN::Error::from_errno(errno);
|
||||
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);
|
||||
|
||||
timespec start_time;
|
||||
|
|
|
@ -174,7 +174,6 @@ static const char* errno_to_string(int error)
|
|||
case ETXTBSY: return "Text file busy.";
|
||||
case EWOULDBLOCK: return "Operation would block.";
|
||||
case EXDEV: return "Cross-device link.";
|
||||
case EEXISTS: return "File exists";
|
||||
case ENOTBLK: return "Block device required";
|
||||
case EUNKNOWN: return "Unknown error";
|
||||
}
|
||||
|
|
|
@ -77,6 +77,9 @@ int main(int argc, char** argv)
|
|||
if (pwd == nullptr)
|
||||
continue;
|
||||
|
||||
if (chown(tty_name, pwd->pw_uid, 0) == -1)
|
||||
perror("chown");
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
|
@ -124,6 +127,9 @@ int main(int argc, char** argv)
|
|||
|
||||
if (tcsetpgrp(0, getpgrp()) == -1)
|
||||
perror("tcsetpgrp");
|
||||
|
||||
if (chown(tty_name, 0, 0) == -1)
|
||||
perror("chown");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -202,7 +202,7 @@ void update()
|
|||
int main()
|
||||
{
|
||||
// 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");
|
||||
return 1;
|
||||
|
|
Loading…
Reference in New Issue