Compare commits

...

31 Commits

Author SHA1 Message Date
e19414a64e BuildSystem: Fix GCC compilation with new host GCC
Newer GCCs fail to compile GCC 15.2.0 because of how u8"" literals are
handled. This can be bypassed by compiling with -fno-char8_t
2026-06-07 03:20:50 +03:00
98fd86477a Kernel: Remove allocations from path lookup
this bumped looped /usr/bin/ls stat performance from 750k->1100k/s
2026-05-26 19:10:16 +03:00
16a442f473 Kernel: Fix Thread::will_exit_because_of_signal
I was not checking whether the signal handler has been overwritten to
ignore the signal leading to infinite busy loops :)
2026-05-26 03:31:20 +03:00
becfa228fe Kernel: fix signal handler block mask restoration 2026-05-26 03:31:20 +03:00
c0ce647c74 ports: Cleanup dependencies and configure flags 2026-05-26 03:31:20 +03:00
05250083b9 ports: Clenup toolchain files 2026-05-26 03:31:20 +03:00
bb170ba613 ports: Allow build scripts install to custom path
This will maybe allow packaging ports :)
2026-05-26 03:31:20 +03:00
c79e412215 resolver: Fix UB and resolve localhost 2026-05-25 03:19:20 +03:00
585e021c7f Kernel: Don't panic when stack trace leads to GPF
if there is was a uncanonical address in stack trace we ended up in an
infinite recursive loop trying to print stack trace
2026-05-25 02:19:56 +03:00
43d03eb4a9 LibC: Add shm_open/shm_unlink
These can just open files in /tmp/shm. no need for anything fancier
2026-05-25 02:14:04 +03:00
2a6792b44a LibC: Make mlock, munlock and madvice no-ops
These don't have to do anything as I don't swap processes to disk
2026-05-25 02:14:04 +03:00
954898b14d Kernel: Fix file backed mmap syncing, my if condition was inverted 2026-05-25 02:14:04 +03:00
d266d2ca88 Kernel: Allow network interface ioctls on interfaces
previously it was only on the sockets
2026-05-25 02:14:04 +03:00
c72f2f9b31 LibC: Fix posix_spawn
signal was checking for NULL instead of SIG_ERR

there is no need to do post fork waiting in posix_spawn, we just have to
exit with 127 on error
2026-05-25 02:14:04 +03:00
62e2f4896a LibC: reorder LOCK_SH and LOCK_EX
Some software im porting has static asserts for these :)
2026-05-25 02:14:04 +03:00
9ccdebcd96 LibC: Implement/fix mk{,o}stemp{,s} 2026-05-25 02:14:04 +03:00
fe533c2e62 LibC: Fix freopen to preserve file state :) 2026-05-25 02:14:04 +03:00
ee5c225954 LibC: Add __fseterr
This is used by some ports to not require internal FILE structure
2026-05-25 02:14:04 +03:00
8fccb74542 Kernel: Add indirect block cache to ext2 inode
This reduces indirect block lookup by a lot :)
2026-05-25 02:14:04 +03:00
bc8ecbd6fa Kernel: Add directory entry cache for ext2 inodes 2026-05-25 02:14:04 +03:00
60484b286f Kernel: Fix bugs in sys_pselect
I was not validating nfds passed from userspace. Also invalid fds are
supposed to return EBADF instead of ignoring those entries
2026-05-25 02:14:04 +03:00
12158d9208 Kernel: Add OpenFileDescriptorSet::get_max_open_fd 2026-05-21 14:59:35 +03:00
5c94c30e1b Kernel: Use spinlocks instead of mutexes for RWLock
All the operations are super fast, just checking or changing few
integers, there is no need for a yielding mutex :^)
2026-05-21 02:17:34 +03:00
81d8ab3d79 Kernel: Remove completely unnecessary lock on file lookup
Mount point lookup already does locking internally, there is no need for
a lock for the whole duration of the lookup :D
2026-05-21 01:59:36 +03:00
6a58c716bd Kernel: Make ext2 inode cache thread safe 2026-05-21 01:56:32 +03:00
c295af9bd5 BAN: Fix HashMaps with custom hashes and comparators 2026-05-20 23:10:25 +03:00
d5ee98708b TaskBar: Show CPU load in task bar! 2026-05-20 19:14:21 +03:00
f6679eb4b5 Kernel: Expose CPU load information under /proc/cpu/<index> 2026-05-20 19:13:25 +03:00
ed3924722e Kernel: Remove kernel CPU load printing
We still keep track of processor loads but the hacky printing is no
longer done in kernel space :)
2026-05-20 19:11:27 +03:00
4ef03eac97 Kernel: Allow ProcRO inode fail and pass arbitrary argument to it 2026-05-20 19:06:10 +03:00
7ce68b0488 LibGUI: Allow timeout with Window::wait_events 2026-05-20 19:03:11 +03:00
100 changed files with 922 additions and 584 deletions

View File

@@ -98,7 +98,8 @@ namespace BAN
struct EntryHash struct EntryHash
{ {
constexpr bool operator()(const Key& a) template<detail::HashMapFindable<Key, HASH, COMP> U>
constexpr bool operator()(const U& a)
{ {
return HASH()(a); return HASH()(a);
} }
@@ -110,7 +111,8 @@ namespace BAN
struct EntryComp struct EntryComp
{ {
constexpr bool operator()(const Entry& a, const Key& b) template<detail::HashMapFindable<Key, HASH, COMP> U>
constexpr bool operator()(const Entry& a, const U& b)
{ {
return COMP()(a.key, b); return COMP()(a.key, b);
} }

View File

@@ -59,7 +59,7 @@ signal_trampoline:
addl $24, %esp addl $24, %esp
// restore sigmask // restore sigmask
movl $83, %eax // SYS_SIGPROCMASK movl $79, %eax // SYS_SIGPROCMASK
movl $3, %ebx // SIG_SETMASK movl $3, %ebx // SIG_SETMASK
leal 72(%esp), %ecx // set leal 72(%esp), %ecx // set
xorl %edx, %edx // oset xorl %edx, %edx // oset

View File

@@ -61,7 +61,7 @@ signal_trampoline:
addq $40, %rsp addq $40, %rsp
// restore sigmask // restore sigmask
movq $83, %rdi // SYS_SIGPROCMASK movq $79, %rdi // SYS_SIGPROCMASK
movq $3, %rsi // SIG_SETMASK movq $3, %rsi // SIG_SETMASK
leaq 192(%rsp), %rdx // set leaq 192(%rsp), %rdx // set
xorq %r10, %r10 // oset xorq %r10, %r10 // oset

View File

@@ -99,7 +99,8 @@ namespace Kernel
BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd); BAN::ErrorOr<uint32_t> reserve_free_block(uint32_t primary_bgd);
BAN::ErrorOr<void> release_block(uint32_t block); BAN::ErrorOr<void> release_block(uint32_t block);
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>>& inode_cache() { return m_inode_cache; } BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> open_inode(ino_t);
void remove_from_cache(ino_t);
const Ext2::Superblock& superblock() const { return m_superblock; } const Ext2::Superblock& superblock() const { return m_superblock; }
@@ -155,6 +156,7 @@ namespace Kernel
BAN::RefPtr<Inode> m_root_inode; BAN::RefPtr<Inode> m_root_inode;
BAN::Vector<uint32_t> m_superblock_backups; BAN::Vector<uint32_t> m_superblock_backups;
Mutex m_inode_cache_lock;
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache; BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
BlockBufferManager m_buffer_manager; BlockBufferManager m_buffer_manager;

View File

@@ -55,7 +55,7 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView); BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
/* needs write end of the lock when allocate is true*/ /* needs write end of the lock when allocate is true*/
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate); BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate);
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate); BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate);
/* needs write end of the lock */ /* needs write end of the lock */
@@ -71,7 +71,13 @@ namespace Kernel
private: private:
Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino); Ext2Inode(Ext2FS& fs, Ext2::Inode inode, uint32_t ino);
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t); BAN::Optional<uint32_t> block_cache_find(uint32_t block, uint32_t index) const;
void block_cache_remove(uint32_t block, uint32_t index);
void block_cache_add(uint32_t block, uint32_t index, uint32_t target);
BAN::RefPtr<Inode> dir_cache_find(BAN::StringView) const;
void dir_cache_remove(BAN::StringView);
void dir_cache_add(BAN::StringView, BAN::RefPtr<Inode>);
private: private:
struct ScopedSync struct ScopedSync
@@ -107,6 +113,27 @@ namespace Kernel
const uint32_t m_og_faddr; const uint32_t m_og_faddr;
const Ext2::Osd2 m_og_osd2; const Ext2::Osd2 m_og_osd2;
struct BlockCacheEntry
{
mutable uint32_t freq;
uint32_t block;
uint32_t index;
uint32_t target;
};
mutable SpinLock m_block_cache_lock;
BAN::Array<BlockCacheEntry, 8> m_block_cache;
struct DirCacheEntry
{
mutable size_t freq { 0 };
BAN::RefPtr<Inode> inode;
size_t name_len { 0 };
char name[256];
};
static constexpr size_t dir_cache_size = 32;
mutable RWLock m_dir_cache_lock;
BAN::Vector<DirCacheEntry> m_dir_cache;
friend class Ext2FS; friend class Ext2FS;
friend class BAN::RefPtr<Ext2Inode>; friend class BAN::RefPtr<Ext2Inode>;
}; };

View File

@@ -13,6 +13,8 @@ namespace Kernel
static void initialize(); static void initialize();
static ProcFileSystem& get(); static ProcFileSystem& get();
void post_scheduler_initialize();
BAN::ErrorOr<void> on_process_create(Process&); BAN::ErrorOr<void> on_process_create(Process&);
void on_process_delete(Process&); void on_process_delete(Process&);

View File

@@ -76,7 +76,7 @@ namespace Kernel
class ProcROInode final : public TmpInode class ProcROInode final : public TmpInode
{ {
public: public:
static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, mode_t, uid_t, gid_t); static BAN::ErrorOr<BAN::RefPtr<ProcROInode>> create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, mode_t, uid_t, gid_t);
~ProcROInode() = default; ~ProcROInode() = default;
protected: protected:
@@ -92,10 +92,11 @@ namespace Kernel
virtual bool has_hungup_impl() const override { return false; } virtual bool has_hungup_impl() const override { return false; }
private: private:
ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem&, const TmpInodeInfo&); ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem&, void*, const TmpInodeInfo&);
private: private:
size_t (*m_callback)(off_t, BAN::ByteSpan); BAN::ErrorOr<size_t> (*m_callback)(off_t, BAN::ByteSpan, void*);
void* m_argument;
}; };
class ProcSymlinkInode final : public TmpInode class ProcSymlinkInode final : public TmpInode

View File

@@ -92,8 +92,9 @@ namespace Kernel
MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>); MountPoint* mount_from_root_inode(BAN::RefPtr<Inode>);
private: private:
Mutex m_mutex;
BAN::RefPtr<FileSystem> m_root_fs; BAN::RefPtr<FileSystem> m_root_fs;
Mutex m_mount_point_lock;
BAN::Vector<MountPoint> m_mount_points; BAN::Vector<MountPoint> m_mount_points;
friend class BAN::RefPtr<VirtualFileSystem>; friend class BAN::RefPtr<VirtualFileSystem>;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <kernel/Lock/Mutex.h> #include <kernel/Lock/SpinLock.h>
#include <kernel/Lock/LockGuard.h> #include <kernel/Lock/SpinLockAsMutex.h>
namespace Kernel namespace Kernel
{ {
@@ -15,15 +15,18 @@ namespace Kernel
void rd_lock() void rd_lock()
{ {
LockGuard _(m_mutex); SpinLockGuard _(m_lock);
while (m_writers_waiting > 0 || m_writer != -1) while (m_writers_waiting > 0 || m_writer != -1)
m_thread_blocker.block_indefinite(&m_mutex); {
SpinLockGuardAsMutex smutex(_);
m_thread_blocker.block_indefinite(&smutex);
}
m_readers_active++; m_readers_active++;
} }
void rd_unlock() void rd_unlock()
{ {
LockGuard _(m_mutex); SpinLockGuard _(m_lock);
if (--m_readers_active == 0) if (--m_readers_active == 0)
m_thread_blocker.unblock(); m_thread_blocker.unblock();
} }
@@ -36,11 +39,14 @@ namespace Kernel
return; return;
} }
LockGuard _(m_mutex); SpinLockGuard _(m_lock);
m_writers_waiting++; m_writers_waiting++;
while (m_readers_active > 0 || m_writer != -1) while (m_readers_active > 0 || m_writer != -1)
m_thread_blocker.block_indefinite(&m_mutex); {
SpinLockGuardAsMutex smutex(_);
m_thread_blocker.block_indefinite(&smutex);
}
m_writers_waiting--; m_writers_waiting--;
m_writer = Thread::current_tid(); m_writer = Thread::current_tid();
@@ -51,13 +57,13 @@ namespace Kernel
{ {
if (--m_writer_depth != 0) if (--m_writer_depth != 0)
return; return;
LockGuard _(m_mutex); SpinLockGuard _(m_lock);
m_writer = -1; m_writer = -1;
m_thread_blocker.unblock(); m_thread_blocker.unblock();
} }
private: private:
Mutex m_mutex; SpinLock m_lock;
ThreadBlocker m_thread_blocker; ThreadBlocker m_thread_blocker;
uint32_t m_readers_active { 0 }; uint32_t m_readers_active { 0 };
uint32_t m_writers_waiting { 0 }; uint32_t m_writers_waiting { 0 };

View File

@@ -65,6 +65,9 @@ namespace Kernel
} }
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0; virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
private:
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
private: private:
const Type m_type; const Type m_type;
char m_name[10]; char m_name[10];

View File

@@ -58,6 +58,8 @@ namespace Kernel
BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags); BAN::ErrorOr<size_t> recvmsg(int socket, msghdr& message, int flags);
BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags); BAN::ErrorOr<size_t> sendmsg(int socket, const msghdr& message, int flags);
int get_max_open_fd() const;
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const; BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
BAN::ErrorOr<BAN::String> path_of(int) const; BAN::ErrorOr<BAN::String> path_of(int) const;
BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int); BAN::ErrorOr<BAN::RefPtr<Inode>> inode_of(int);

View File

@@ -57,6 +57,12 @@ namespace Kernel
}; };
}; };
struct LoadStats
{
uint64_t ns_idle;
uint64_t ns_total;
};
public: public:
static Processor& create(ProcessorID id); static Processor& create(ProcessorID id);
static Processor& initialize(); static Processor& initialize();
@@ -72,9 +78,6 @@ namespace Kernel
static void set_smp_enabled() { s_is_smp_enabled = true; } static void set_smp_enabled() { s_is_smp_enabled = true; }
static void wait_until_processors_ready(); static void wait_until_processors_ready();
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }
static bool get_should_print_cpu_load() { return s_should_print_cpu_load; }
static ProcessorID bsp_id() { return s_bsp_id; } static ProcessorID bsp_id() { return s_bsp_id; }
static bool current_is_bsp() { return current_id() == bsp_id(); } static bool current_is_bsp() { return current_id() == bsp_id(); }
@@ -116,6 +119,8 @@ namespace Kernel
static void* get_current_page_table() { return read_gs_sized<void*>(offsetof(Processor, m_current_page_table)); } static void* get_current_page_table() { return read_gs_sized<void*>(offsetof(Processor, m_current_page_table)); }
static void set_current_page_table(void* page_table) { write_gs_sized<void*>(offsetof(Processor, m_current_page_table), page_table); } static void set_current_page_table(void* page_table) { write_gs_sized<void*>(offsetof(Processor, m_current_page_table), page_table); }
static LoadStats get_load_stats(size_t index);
static void yield(); static void yield();
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); } static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
@@ -187,7 +192,6 @@ namespace Kernel
static ProcessorID s_bsp_id; static ProcessorID s_bsp_id;
static BAN::Atomic<uint8_t> s_processor_count; static BAN::Atomic<uint8_t> s_processor_count;
static BAN::Atomic<bool> s_is_smp_enabled; static BAN::Atomic<bool> s_is_smp_enabled;
static BAN::Atomic<bool> s_should_print_cpu_load;
static paddr_t s_shared_page_paddr; static paddr_t s_shared_page_paddr;
static vaddr_t s_shared_page_vaddr; static vaddr_t s_shared_page_vaddr;
@@ -207,10 +211,9 @@ namespace Kernel
Scheduler* m_scheduler { nullptr }; Scheduler* m_scheduler { nullptr };
uint64_t m_start_ns { 0 }; BAN::Atomic<bool> m_load_stat_lock;
uint64_t m_idle_ns { 0 }; uint64_t m_load_start_ns { 0 };
uint64_t m_last_update_ns { 0 }; LoadStats m_load_stats {};
uint64_t m_next_update_ns { 0 };
BAN::Atomic<SMPMessage*> m_smp_pending { nullptr }; BAN::Atomic<SMPMessage*> m_smp_pending { nullptr };
BAN::Atomic<SMPMessage*> m_smp_free { nullptr }; BAN::Atomic<SMPMessage*> m_smp_free { nullptr };

View File

@@ -356,51 +356,7 @@ namespace Kernel
void do_msync(uint32_t first_pixel, uint32_t pixel_count) void do_msync(uint32_t first_pixel, uint32_t pixel_count)
{ {
if (!Processor::get_should_print_cpu_load()) m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
const uint32_t fb_width = m_framebuffer->width();
// If we are here (in FramebufferMemoryRegion), our terminal driver is FramebufferTerminalDriver
ASSERT(g_terminal_driver->has_font());
const auto& font = g_terminal_driver->font();
const uint32_t x = first_pixel % fb_width;
const uint32_t y = first_pixel / fb_width;
const uint32_t load_w = 16 * font.width();
const uint32_t load_h = Processor::count() * font.height();
if (y >= load_h || x + pixel_count <= fb_width - load_w)
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
if (x >= fb_width - load_w && x + pixel_count <= fb_width)
return;
if (x < fb_width - load_w)
m_framebuffer->sync_pixels_linear(first_pixel, fb_width - load_w - x);
if (x + pixel_count > fb_width)
{
const uint32_t past_last_pixel = first_pixel + pixel_count;
first_pixel = (y + 1) * fb_width;
pixel_count = past_last_pixel - first_pixel;
const uint32_t cpu_load_end = load_h * fb_width;
while (pixel_count && first_pixel < cpu_load_end)
{
m_framebuffer->sync_pixels_linear(first_pixel, BAN::Math::min(pixel_count, fb_width - load_w));
const uint32_t advance = BAN::Math::min(pixel_count, fb_width);
pixel_count -= advance;
first_pixel += advance;
}
if (pixel_count)
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
}
} }
private: private:

View File

@@ -167,10 +167,36 @@ namespace Kernel
BAN::ErrorOr<void> Ext2FS::initialize_root_inode() BAN::ErrorOr<void> Ext2FS::initialize_root_inode()
{ {
m_root_inode = TRY(Ext2Inode::create(*this, Ext2::Enum::ROOT_INO)); m_root_inode = TRY(open_inode(Ext2::Enum::ROOT_INO));
return {}; return {};
} }
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2FS::open_inode(ino_t ino)
{
LockGuard _(m_inode_cache_lock);
auto it = m_inode_cache.find(ino);
if (it != m_inode_cache.end())
return it->value;
auto inode_location = TRY(locate_inode(ino));
auto block_buffer = TRY(get_block_buffer());
TRY(read_block(inode_location.block, block_buffer));
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(*this, inode, ino));
TRY(m_inode_cache.insert(ino, result));
return result;
}
void Ext2FS::remove_from_cache(ino_t ino)
{
LockGuard _(m_inode_cache_lock);
m_inode_cache.remove(ino);
}
BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode) BAN::ErrorOr<uint32_t> Ext2FS::create_inode(const Ext2::Inode& ext2_inode)
{ {
auto bgd_buffer = TRY(m_buffer_manager.get_buffer()); auto bgd_buffer = TRY(m_buffer_manager.get_buffer());

View File

@@ -42,24 +42,6 @@ namespace Kernel
return (m_ino - 1) / m_fs.superblock().blocks_per_group; return (m_ino - 1) / m_fs.superblock().blocks_per_group;
} }
BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> Ext2Inode::create(Ext2FS& fs, uint32_t inode_ino)
{
auto it = fs.inode_cache().find(inode_ino);
if (it != fs.inode_cache().end())
return it->value;
auto inode_location = TRY(fs.locate_inode(inode_ino));
auto block_buffer = TRY(fs.get_block_buffer());
TRY(fs.read_block(inode_location.block, block_buffer));
auto& inode = block_buffer.span().slice(inode_location.offset).as<Ext2::Inode>();
auto result = TRY(BAN::RefPtr<Ext2Inode>::create(fs, inode, inode_ino));
TRY(fs.inode_cache().insert(inode_ino, result));
return result;
}
Ext2Inode::~Ext2Inode() Ext2Inode::~Ext2Inode()
{ {
if (m_nlink > 0) if (m_nlink > 0)
@@ -89,57 +71,53 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t& block, uint32_t index, uint32_t depth, bool allocate) BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block_no_lock(uint32_t block, uint32_t index, uint32_t depth, bool allocate)
{ {
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t); const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
if (block == 0 && !allocate) ASSERT(block != 0);
return BAN::Optional<uint32_t>();
if (depth == 0) if (depth == 0)
return BAN::Optional<uint32_t>(block);
uint32_t local_index = index;
for (uint32_t i = 1; i < depth; i++)
local_index /= indices_per_fs_block;
local_index %= indices_per_fs_block;
uint32_t next_block = 0;
if (auto cached = block_cache_find(block, local_index); cached.has_value())
next_block = cached.value();
if (next_block == 0)
{ {
if (block == 0) auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer));
auto block_span = block_buffer.span().as_span<uint32_t>();
next_block = block_span[local_index];
if (next_block == 0)
{ {
block = TRY(m_fs.reserve_free_block(block_group())); if (!allocate)
return BAN::Optional<uint32_t>();
auto zero_buffer = TRY(m_fs.get_block_buffer());
memset(zero_buffer.data(), 0, zero_buffer.size());
next_block = TRY(m_fs.reserve_free_block(block_group()));
TRY(m_fs.write_block(next_block, zero_buffer));
m_blocks++; m_blocks++;
auto block_buffer = TRY(m_fs.get_block_buffer()); block_span[local_index] = next_block;
memset(block_buffer.data(), 0x00, block_buffer.size());
TRY(m_fs.write_block(block, block_buffer)); TRY(m_fs.write_block(block, block_buffer));
} }
return BAN::Optional<uint32_t>(block); block_cache_add(block, local_index, next_block);
} }
auto block_buffer = TRY(m_fs.get_block_buffer()); return block_from_indirect_block_no_lock(next_block, index, depth - 1, allocate);
bool needs_write = false;
if (block != 0)
TRY(m_fs.read_block(block, block_buffer));
else
{
block = TRY(m_fs.reserve_free_block(block_group()));
m_blocks++;
memset(block_buffer.data(), 0, block_buffer.size());
needs_write = true;
}
uint32_t divisor = 1;
for (uint32_t i = 1; i < depth; i++)
divisor *= indices_per_fs_block;
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
const auto old_block = new_block;
const auto result = TRY(block_from_indirect_block_no_lock(new_block, index, depth - 1, allocate));
if (needs_write || old_block != new_block)
TRY(m_fs.write_block(block, block_buffer));
return result;
} }
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate) BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index_no_lock(uint32_t data_block_index, bool allocate)
@@ -166,16 +144,29 @@ namespace Kernel
} }
data_block_index -= 12; data_block_index -= 12;
if (data_block_index < indices_per_block) uint32_t depth_block_count = indices_per_block;
return block_from_indirect_block_no_lock(m_ext2_blocks.block[12], data_block_index, 1, allocate); for (size_t i = 0; i < 3; i++)
data_block_index -= indices_per_block; {
if (data_block_index < depth_block_count)
{
auto& block = m_ext2_blocks.block[12 + i];
if (block == 0)
{
if (!allocate)
return BAN::Optional<uint32_t>();
if (data_block_index < indices_per_block * indices_per_block) auto zero_buffer = TRY(m_fs.get_block_buffer());
return block_from_indirect_block_no_lock(m_ext2_blocks.block[13], data_block_index, 2, allocate); memset(zero_buffer.data(), 0, zero_buffer.size());
data_block_index -= indices_per_block * indices_per_block;
if (data_block_index < indices_per_block * indices_per_block * indices_per_block) block = TRY(m_fs.reserve_free_block(block_group()));
return block_from_indirect_block_no_lock(m_ext2_blocks.block[14], data_block_index, 3, allocate); TRY(m_fs.write_block(block, zero_buffer));
m_blocks++;
}
return block_from_indirect_block_no_lock(block, data_block_index, i + 1, allocate);
}
data_block_index -= indices_per_block;
depth_block_count *= indices_per_block;
}
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@@ -542,7 +533,7 @@ done:
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid))); const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
auto inode_or_error = Ext2Inode::create(m_fs, new_ino); auto inode_or_error = m_fs.open_inode(new_ino);
if (inode_or_error.is_error()) if (inode_or_error.is_error())
{ {
TRY(m_fs.delete_inode(new_ino)); TRY(m_fs.delete_inode(new_ino));
@@ -568,7 +559,7 @@ done:
const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid))); const uint32_t new_ino = TRY(m_fs.create_inode(initialize_new_inode_info(mode, uid, gid)));
auto inode_or_error = Ext2Inode::create(m_fs, new_ino); auto inode_or_error = m_fs.open_inode(new_ino);
if (inode_or_error.is_error()) if (inode_or_error.is_error())
{ {
TRY(m_fs.delete_inode(new_ino)); TRY(m_fs.delete_inode(new_ino));
@@ -814,7 +805,7 @@ needs_new_block:
} }
else if (entry_name == ".."_sv) else if (entry_name == ".."_sv)
{ {
auto parent = TRY(Ext2Inode::create(m_fs, entry.inode)); auto parent = TRY(m_fs.open_inode(entry.inode));
parent->m_nlink--; parent->m_nlink--;
TRY(parent->sync_inode_no_lock()); TRY(parent->sync_inode_no_lock());
} }
@@ -860,7 +851,7 @@ needs_new_block:
auto& entry = block_buffer.span().slice(offset).as<Ext2::LinkedDirectoryEntry>(); auto& entry = block_buffer.span().slice(offset).as<Ext2::LinkedDirectoryEntry>();
if (entry.inode && name == BAN::StringView(entry.name, entry.name_len)) if (entry.inode && name == BAN::StringView(entry.name, entry.name_len))
{ {
auto inode = TRY(Ext2Inode::create(m_fs, entry.inode)); auto inode = TRY(m_fs.open_inode(entry.inode));
if (cleanup_directory && inode->mode().ifdir()) if (cleanup_directory && inode->mode().ifdir())
{ {
if (!TRY(inode->is_directory_empty_no_lock())) if (!TRY(inode->is_directory_empty_no_lock()))
@@ -878,11 +869,7 @@ needs_new_block:
// NOTE: If this was the last link to inode we must // NOTE: If this was the last link to inode we must
// remove it from inode cache to trigger cleanup // remove it from inode cache to trigger cleanup
if (inode->nlink() == 0) if (inode->nlink() == 0)
{ m_fs.remove_from_cache(inode->ino());
auto& cache = m_fs.inode_cache();
if (cache.contains(inode->ino()))
cache.remove(inode->ino());
}
// FIXME: This should expand the last inode if exists // FIXME: This should expand the last inode if exists
entry.inode = 0; entry.inode = 0;
@@ -892,6 +879,8 @@ needs_new_block:
} }
} }
dir_cache_remove(name);
return {}; return {};
} }
@@ -948,6 +937,9 @@ needs_new_block:
{ {
ASSERT(mode().ifdir()); ASSERT(mode().ifdir());
if (auto cached = dir_cache_find(file_name))
return cached;
auto block_buffer = TRY(m_fs.get_block_buffer()); auto block_buffer = TRY(m_fs.get_block_buffer());
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
@@ -963,11 +955,129 @@ needs_new_block:
auto& entry = entry_span.as<const Ext2::LinkedDirectoryEntry>(); auto& entry = entry_span.as<const Ext2::LinkedDirectoryEntry>();
BAN::StringView entry_name(entry.name, entry.name_len); BAN::StringView entry_name(entry.name, entry.name_len);
if (entry.inode && entry_name == file_name) if (entry.inode && entry_name == file_name)
return BAN::RefPtr<Inode>(TRY(Ext2Inode::create(m_fs, entry.inode))); {
auto inode = BAN::RefPtr<Inode>(TRY(m_fs.open_inode(entry.inode)));
dir_cache_add(file_name, inode);
return inode;
}
entry_span = entry_span.slice(entry.rec_len); entry_span = entry_span.slice(entry.rec_len);
} }
} }
return BAN::Error::from_errno(ENOENT); return BAN::Error::from_errno(ENOENT);
} }
BAN::Optional<uint32_t> Ext2Inode::block_cache_find(uint32_t block, uint32_t index) const
{
SpinLockGuard _(m_block_cache_lock);
for (const auto& cache : m_block_cache)
{
if (cache.block != block || cache.index != index)
continue;
cache.freq++;
return cache.target;
}
return {};
}
void Ext2Inode::block_cache_remove(uint32_t block, uint32_t index)
{
SpinLockGuard _(m_block_cache_lock);
for (auto& cache : m_block_cache)
{
if (cache.block != block || cache.index != index)
continue;
cache = {};
return;
}
}
void Ext2Inode::block_cache_add(uint32_t block, uint32_t index, uint32_t target)
{
SpinLockGuard _(m_block_cache_lock);
size_t min_freq = BAN::numeric_limits<size_t>::max();
size_t min_index = 0;
for (size_t i = 0; i < m_block_cache.size(); i++)
{
const auto& cache = m_block_cache[i];
if (cache.block == block && cache.index == index)
{
ASSERT(cache.target == target);
cache.freq++;
return;
}
if (cache.freq < min_freq)
{
min_freq = cache.freq;
min_index = i;
}
}
m_block_cache[min_index] = {
.freq = 1,
.block = block,
.index = index,
.target = target,
};
}
BAN::RefPtr<Inode> Ext2Inode::dir_cache_find(BAN::StringView name) const
{
RWLockRDGuard _(m_dir_cache_lock);
for (const auto& cache : m_dir_cache)
{
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
continue;
BAN::atomic_add_fetch(cache.freq, 1);
return cache.inode;
}
return {};
}
void Ext2Inode::dir_cache_remove(BAN::StringView name)
{
RWLockWRGuard _(m_dir_cache_lock);
for (auto& cache : m_dir_cache)
{
if (!cache.inode || name != BAN::StringView(cache.name, cache.name_len))
continue;
cache.freq = 0;
cache.inode = {};
return;
}
}
void Ext2Inode::dir_cache_add(BAN::StringView name, BAN::RefPtr<Inode> inode)
{
RWLockWRGuard _(m_dir_cache_lock);
if (m_dir_cache.empty() && m_dir_cache.resize(dir_cache_size).is_error())
return;
size_t min_freq = BAN::numeric_limits<size_t>::max();
size_t min_index = 0;
for (size_t i = 0; i < m_dir_cache.size(); i++)
{
const auto& cache = m_dir_cache[i];
if (cache.inode && name == BAN::StringView(cache.name, cache.name_len))
{
ASSERT(cache.inode == inode);
cache.freq++;
return;
}
if (cache.freq < min_freq)
{
min_freq = cache.freq;
min_index = i;
}
}
auto& cache = m_dir_cache[min_index];
cache.freq = 1;
cache.inode = inode;
cache.name_len = name.size();
memcpy(cache.name, name.data(), name.size());
}
} }

View File

@@ -16,22 +16,23 @@ namespace Kernel
MUST(s_instance->TmpFileSystem::initialize(0555, 0, 0)); MUST(s_instance->TmpFileSystem::initialize(0555, 0, 0));
auto meminfo_inode = MUST(ProcROInode::create_new( auto meminfo_inode = MUST(ProcROInode::create_new(
[](off_t offset, BAN::ByteSpan buffer) -> size_t [](off_t offset, BAN::ByteSpan buffer, void*) -> BAN::ErrorOr<size_t>
{ {
ASSERT(offset >= 0); ASSERT(offset >= 0);
if ((size_t)offset >= sizeof(full_meminfo_t)) if ((size_t)offset >= sizeof(full_meminfo_t))
return 0; return 0;
full_meminfo_t meminfo; const full_meminfo_t meminfo {
meminfo.page_size = PAGE_SIZE; .page_size = PAGE_SIZE,
meminfo.free_pages = Heap::get().free_pages(); .free_pages = Heap::get().free_pages(),
meminfo.used_pages = Heap::get().used_pages(); .used_pages = Heap::get().used_pages(),
};
size_t bytes = BAN::Math::min<size_t>(sizeof(full_meminfo_t) - offset, buffer.size()); size_t bytes = BAN::Math::min<size_t>(sizeof(full_meminfo_t) - offset, buffer.size());
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes); memcpy(buffer.data(), (uint8_t*)&meminfo + offset, bytes);
return bytes; return bytes;
}, },
*s_instance, 0444, 0, 0 *s_instance, nullptr, 0444, 0, 0
)); ));
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv)); MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*meminfo_inode, "meminfo"_sv));
@@ -48,6 +49,35 @@ namespace Kernel
MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv)); MUST(static_cast<TmpDirectoryInode*>(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv));
} }
void ProcFileSystem::post_scheduler_initialize()
{
MUST(s_instance->root_inode()->create_directory("cpu"_sv, Inode::Mode::IFDIR | 0555, 0, 0));
auto cpu_directory = MUST(s_instance->root_inode()->find_inode("cpu"_sv));
for (size_t i = 0; i < Processor::count(); i++)
{
auto cpu_inode = MUST(ProcROInode::create_new(
[](off_t offset, BAN::ByteSpan buffer, void* index_ptr) -> BAN::ErrorOr<size_t>
{
ASSERT(offset >= 0);
const size_t index = reinterpret_cast<uintptr_t>(index_ptr);
const auto load_stats = Processor::get_load_stats(index);
auto string = TRY(BAN::String::formatted("{} {}", load_stats.ns_idle, load_stats.ns_total));
if (static_cast<size_t>(offset) >= string.size())
return 0;
const size_t bytes = BAN::Math::min<size_t>(string.size() - offset, buffer.size());
memcpy(buffer.data(), string.data() + offset, bytes);
return bytes;
},
*s_instance, reinterpret_cast<void*>(i), 0444, 0, 0
));
MUST(cpu_directory->link_inode(MUST(BAN::String::formatted("{}", i)), cpu_inode));
}
}
ProcFileSystem& ProcFileSystem::get() ProcFileSystem& ProcFileSystem::get()
{ {
ASSERT(s_instance); ASSERT(s_instance);

View File

@@ -95,19 +95,20 @@ namespace Kernel
return (m_process.*m_callback)(); return (m_process.*m_callback)();
} }
BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) BAN::ErrorOr<BAN::RefPtr<ProcROInode>> ProcROInode::create_new(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, mode_t mode, uid_t uid, gid_t gid)
{ {
auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid); auto inode_info = create_inode_info(Mode::IFREG | mode, uid, gid);
auto* inode_ptr = new ProcROInode(callback, fs, inode_info); auto* inode_ptr = new ProcROInode(callback, fs, argument, inode_info);
if (inode_ptr == nullptr) if (inode_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<ProcROInode>::adopt(inode_ptr); return BAN::RefPtr<ProcROInode>::adopt(inode_ptr);
} }
ProcROInode::ProcROInode(size_t (*callback)(off_t, BAN::ByteSpan), TmpFileSystem& fs, const TmpInodeInfo& inode_info) ProcROInode::ProcROInode(BAN::ErrorOr<size_t> (*callback)(off_t, BAN::ByteSpan, void*), TmpFileSystem& fs, void* argument, const TmpInodeInfo& inode_info)
: TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info) : TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info)
, m_callback(callback) , m_callback(callback)
, m_argument(argument)
{ {
m_mode |= Inode::Mode::IFREG; m_mode |= Inode::Mode::IFREG;
} }
@@ -116,7 +117,7 @@ namespace Kernel
{ {
if (offset < 0) if (offset < 0)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
return m_callback(offset, buffer); return TRY(m_callback(offset, buffer, m_argument));
} }
BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) BAN::ErrorOr<BAN::RefPtr<ProcSymlinkInode>> ProcSymlinkInode::create_new(BAN::ErrorOr<BAN::String> (*callback)(void*), void (*destructor)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)

View File

@@ -210,14 +210,14 @@ namespace Kernel
if (!file.inode->mode().ifdir()) if (!file.inode->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR); return BAN::Error::from_errno(ENOTDIR);
LockGuard _(m_mutex); LockGuard _(m_mount_point_lock);
TRY(m_mount_points.emplace_back(file_system, BAN::move(file))); TRY(m_mount_points.emplace_back(file_system, BAN::move(file)));
return {}; return {};
} }
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_host_inode(BAN::RefPtr<Inode> inode) VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_host_inode(BAN::RefPtr<Inode> inode)
{ {
LockGuard _(m_mutex); LockGuard _(m_mount_point_lock);
for (MountPoint& mount : m_mount_points) for (MountPoint& mount : m_mount_points)
if (*mount.host.inode == *inode) if (*mount.host.inode == *inode)
return &mount; return &mount;
@@ -226,53 +226,52 @@ namespace Kernel
VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_root_inode(BAN::RefPtr<Inode> inode) VirtualFileSystem::MountPoint* VirtualFileSystem::mount_from_root_inode(BAN::RefPtr<Inode> inode)
{ {
LockGuard _(m_mutex); LockGuard _(m_mount_point_lock);
for (MountPoint& mount : m_mount_points) for (MountPoint& mount : m_mount_points)
if (*mount.target->root_inode() == *inode) if (*mount.target->root_inode() == *inode)
return &mount; return &mount;
return nullptr; return nullptr;
} }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-usage="
BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags) BAN::ErrorOr<VirtualFileSystem::File> VirtualFileSystem::file_from_relative_path(BAN::RefPtr<Inode> root_inode, const File& parent, const Credentials& credentials, BAN::StringView path, int flags)
{ {
LockGuard _(m_mutex);
auto inode = parent.inode; auto inode = parent.inode;
ASSERT(inode); ASSERT(inode);
BAN::String canonical_path; char canonical_buf[PATH_MAX];
TRY(canonical_path.append(parent.canonical_path)); size_t canonical_len = parent.canonical_path.size();
if (!canonical_path.empty() && canonical_path.back() == '/') if (!parent.canonical_path.empty() && parent.canonical_path.back() == '/')
canonical_path.pop_back(); canonical_len--;
ASSERT(canonical_path.empty() || canonical_path.back() != '/'); memcpy(canonical_buf, parent.canonical_path.data(), canonical_len);
ASSERT(canonical_len == 0 || canonical_buf[canonical_len - 1] != '/');
BAN::Vector<BAN::String> path_parts; char path_storage[PATH_MAX];
const auto append_string_view_in_reverse =
[&path_parts](BAN::StringView path) -> BAN::ErrorOr<void>
{
auto split_path = TRY(path.split('/'));
TRY(path_parts.reserve(path_parts.size() + split_path.size()));
for (size_t i = split_path.size(); i > 0; i--)
{
TRY(path_parts.emplace_back());
TRY(path_parts.back().append(split_path[i - 1]));
}
return {};
};
TRY(append_string_view_in_reverse(path));
size_t link_depth = 0; size_t link_depth = 0;
for (;;)
while (!path_parts.empty())
{ {
BAN::String path_part = BAN::move(path_parts.back()); const auto path_part = [&path] {
path_parts.pop_back(); size_t off = 0;
while (off < path.size() && path[off] == '/')
off++;
if (path_part.empty() || path_part == "."_sv) size_t len = 0;
while (off + len < path.size() && path[off + len] != '/')
len++;
const auto result = path.substring(off, len);
path = path.substring(off + len);
return result;
}();
if (path_part.empty())
break;
if (path_part == "."_sv)
continue; continue;
auto orig = inode; auto orig_inode = inode;
// resolve file name // resolve file name
{ {
@@ -289,26 +288,26 @@ namespace Kernel
if (path_part == ".."_sv) if (path_part == ".."_sv)
{ {
if (!canonical_path.empty()) while (canonical_len && canonical_buf[canonical_len - 1] != '/')
{ canonical_len--;
ASSERT(canonical_path.front() == '/'); if (canonical_len)
while (canonical_path.back() != '/') canonical_len--;
canonical_path.pop_back();
canonical_path.pop_back();
}
} }
else else
{ {
if (auto* mount_point = mount_from_host_inode(inode)) if (auto* mount_point = mount_from_host_inode(inode))
inode = mount_point->target->root_inode(); inode = mount_point->target->root_inode();
TRY(canonical_path.push_back('/')); if (canonical_len + 1 + path_part.size() > sizeof(canonical_buf))
TRY(canonical_path.append(path_part)); return BAN::Error::from_errno(ENAMETOOLONG);
canonical_buf[canonical_len++] = '/';
memcpy(canonical_buf + canonical_len, path_part.data(), path_part.size());
canonical_len += path_part.size();
} }
} }
if (!inode->mode().iflnk()) if (!inode->mode().iflnk())
continue; continue;
if ((flags & O_NOFOLLOW) && path_parts.empty()) if ((flags & O_NOFOLLOW) && !path.find([](char ch) { return ch != '/'; }).has_value())
continue; continue;
// resolve symbolic links // resolve symbolic links
@@ -320,21 +319,26 @@ namespace Kernel
if (link_target.front() == '/') if (link_target.front() == '/')
{ {
inode = root_inode; inode = root_inode;
canonical_path.clear(); canonical_len = 0;
} }
else else
{ {
inode = orig; inode = orig_inode;
while (canonical_path.back() != '/') while (canonical_len && canonical_buf[canonical_len - 1] != '/')
canonical_path.pop_back(); canonical_len--;
canonical_path.pop_back(); if (canonical_len)
canonical_len--;
} }
TRY(append_string_view_in_reverse(link_target.sv())); if (link_target.size() + path.size() > sizeof(path_storage))
return BAN::Error::from_errno(ENAMETOOLONG);
memcpy(path_storage, link_target.data(), link_target.size());
memcpy(path_storage + link_target.size(), path.data(), path.size());
path = BAN::StringView(path_storage, link_target.size() + path.size());
link_depth++; link_depth++;
if (link_depth > 100) if (link_depth > SYMLOOP_MAX)
return BAN::Error::from_errno(ELOOP); return BAN::Error::from_errno(ELOOP);
} }
} }
@@ -342,17 +346,14 @@ namespace Kernel
if (!inode->can_access(credentials, flags)) if (!inode->can_access(credentials, flags))
return BAN::Error::from_errno(EACCES); return BAN::Error::from_errno(EACCES);
if (canonical_path.empty()) if (canonical_len == 0)
TRY(canonical_path.push_back('/')); canonical_buf[canonical_len++] = '/';
File file; BAN::String canonical_path;
file.inode = inode; TRY(canonical_path.append(BAN::StringView(canonical_buf, canonical_len)));
file.canonical_path = BAN::move(canonical_path);
if (file.canonical_path.empty()) return File(BAN::move(inode), BAN::move(canonical_path));
TRY(file.canonical_path.push_back('/'));
return file;
} }
#pragma GCC diagnostic pop
} }

View File

@@ -256,6 +256,18 @@ namespace Kernel
break; break;
} }
case ISR::GeneralProtectionFault:
{
const uint8_t* ip = reinterpret_cast<const uint8_t*>(interrupt_stack->ip);
for (const auto& safe_user : s_safe_user_page_faults)
{
if (ip < safe_user.ip_start || ip >= safe_user.ip_end)
continue;
interrupt_stack->ip = reinterpret_cast<vaddr_t>(safe_user.ip_fault);
return;
}
break;
}
case ISR::DeviceNotAvailable: case ISR::DeviceNotAvailable:
{ {
if (pid == 0 || !Thread::current().is_userspace()) if (pid == 0 || !Thread::current().is_userspace())

View File

@@ -197,9 +197,6 @@ namespace Kernel
} }
else switch (key_event.keycode) else switch (key_event.keycode)
{ {
case LibInput::keycode_function(1):
Processor::toggle_should_print_cpu_load();
break;
case LibInput::keycode_function(11): case LibInput::keycode_function(11):
DevFileSystem::get().initiate_disk_cache_drop(); DevFileSystem::get().initiate_disk_cache_drop();
break; break;

View File

@@ -93,7 +93,7 @@ namespace Kernel
void SharedFileData::sync_no_lock(size_t page_index) void SharedFileData::sync_no_lock(size_t page_index)
{ {
if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) == 0) if (pages[page_index] == 0 || BAN::atomic_load(writers[page_index]) > 0)
return; return;
uint8_t page_buffer[PAGE_SIZE]; uint8_t page_buffer[PAGE_SIZE];
@@ -108,8 +108,9 @@ namespace Kernel
BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags) BAN::ErrorOr<void> FileBackedRegion::msync(vaddr_t address, size_t size, int flags)
{ {
if (flags != MS_SYNC) // TODO: maybe do something with the flags :)
dprintln("async file backed mmap msync"); (void)flags;
if (m_type != Type::SHARED) if (m_type != Type::SHARED)
return {}; return {};

View File

@@ -3,6 +3,8 @@
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Networking/NetworkInterface.h> #include <kernel/Networking/NetworkInterface.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <string.h> #include <string.h>
@@ -25,7 +27,7 @@ namespace Kernel
} }
NetworkInterface::NetworkInterface(Type type) NetworkInterface::NetworkInterface(Type type)
: CharacterDevice(0400, 0, 0) : CharacterDevice(0664, 0, 0)
, m_type(type) , m_type(type)
{ {
m_rdev = get_rdev(type); m_rdev = get_rdev(type);
@@ -43,4 +45,95 @@ namespace Kernel
} }
} }
BAN::ErrorOr<long> NetworkInterface::ioctl_impl(int request, void* arg)
{
if (arg == nullptr)
{
dprintln("No argument provided");
return BAN::Error::from_errno(EINVAL);
}
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
switch (request)
{
case SIOCGIFADDR:
{
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
ifru_addr.sin_family = AF_INET;
ifru_addr.sin_addr.s_addr = get_ipv4_address().raw;
return 0;
}
case SIOCSIFADDR:
{
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
if (ifru_addr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
dprintln("IPv4 address set to {}", get_ipv4_address());
return 0;
}
case SIOCGIFNETMASK:
{
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
ifru_netmask.sin_family = AF_INET;
ifru_netmask.sin_addr.s_addr = get_netmask().raw;
return 0;
}
case SIOCSIFNETMASK:
{
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
if (ifru_netmask.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
dprintln("Netmask set to {}", get_netmask());
return 0;
}
case SIOCGIFGWADDR:
{
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
ifru_gwaddr.sin_family = AF_INET;
ifru_gwaddr.sin_addr.s_addr = get_gateway().raw;
return 0;
}
case SIOCSIFGWADDR:
{
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
if (ifru_gwaddr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
dprintln("Gateway set to {}", get_gateway());
return 0;
}
case SIOCGIFHWADDR:
{
auto mac_address = get_mac_address();
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
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(name().size() < sizeof(ifrn_name));
memcpy(ifrn_name, name().data(), name().size());
ifrn_name[name().size()] = '\0';
return 0;
}
case SIOCGIFFLAGS:
{
int flags = 0;
if (link_up())
flags |= IFF_UP | IFF_RUNNING;
if (m_type == Type::Loopback)
flags |= IFF_LOOPBACK;
ifreq->ifr_ifru.ifru_flags = flags;
return 0;
}
}
return CharacterDevice::ioctl_impl(request, arg);
}
} }

View File

@@ -110,83 +110,20 @@ namespace Kernel
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg) BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
{ {
if (!arg)
{
dprintln("No argument provided");
return BAN::Error::from_errno(EINVAL);
}
auto interface = TRY(this->interface(nullptr, 0));
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
switch (request) switch (request)
{ {
case SIOCGIFADDR: case SIOCGIFADDR:
{
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
ifru_addr.sin_family = AF_INET;
ifru_addr.sin_addr.s_addr = interface->get_ipv4_address().raw;
return 0;
}
case SIOCSIFADDR: case SIOCSIFADDR:
{
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
if (ifru_addr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
dprintln("IPv4 address set to {}", interface->get_ipv4_address());
return 0;
}
case SIOCGIFNETMASK: case SIOCGIFNETMASK:
{
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
ifru_netmask.sin_family = AF_INET;
ifru_netmask.sin_addr.s_addr = interface->get_netmask().raw;
return 0;
}
case SIOCSIFNETMASK: case SIOCSIFNETMASK:
{
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
if (ifru_netmask.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
dprintln("Netmask set to {}", interface->get_netmask());
return 0;
}
case SIOCGIFGWADDR: case SIOCGIFGWADDR:
{
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
ifru_gwaddr.sin_family = AF_INET;
ifru_gwaddr.sin_addr.s_addr = interface->get_gateway().raw;
return 0;
}
case SIOCSIFGWADDR: case SIOCSIFGWADDR:
{
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
if (ifru_gwaddr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
dprintln("Gateway set to {}", interface->get_gateway());
return 0;
}
case SIOCGIFHWADDR: case SIOCGIFHWADDR:
{
auto mac_address = interface->get_mac_address();
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
return 0;
}
case SIOCGIFNAME: case SIOCGIFNAME:
{ return TRY(interface(nullptr, 0))->ioctl(request, arg);
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
ASSERT(interface->name().size() < sizeof(ifrn_name));
memcpy(ifrn_name, interface->name().data(), interface->name().size());
ifrn_name[interface->name().size()] = '\0';
return 0;
}
default:
return BAN::Error::from_errno(EINVAL);
} }
return Socket::ioctl_impl(request, arg);
} }
BAN::ErrorOr<void> NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len) BAN::ErrorOr<void> NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len)

View File

@@ -853,6 +853,15 @@ namespace Kernel
return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0)); return inode->sendmsg(message, flags | (is_nonblock ? MSG_DONTWAIT : 0));
} }
int OpenFileDescriptorSet::get_max_open_fd() const
{
LockGuard _(m_mutex);
for (int fd = m_open_files.size() - 1; fd > 0; fd--)
if (m_open_files[fd])
return fd;
return -1;
}
BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const BAN::ErrorOr<VirtualFileSystem::File> OpenFileDescriptorSet::file_of(int fd) const
{ {
LockGuard _(m_mutex); LockGuard _(m_mutex);

View File

@@ -1862,25 +1862,22 @@ namespace Kernel
sys_pselect_t arguments; sys_pselect_t arguments;
TRY(read_from_user(user_arguments, &arguments, sizeof(sys_pselect_t))); TRY(read_from_user(user_arguments, &arguments, sizeof(sys_pselect_t)));
MemoryRegion* readfd_region = nullptr; const int max_nfds = BAN::Math::min(m_open_file_descriptors.get_max_open_fd(), FD_SETSIZE) + 1;
MemoryRegion* writefd_region = nullptr; if (arguments.nfds > max_nfds)
MemoryRegion* errorfd_region = nullptr; arguments.nfds = max_nfds;
BAN::ScopeGuard _([&] { const auto init_fd_set = [](fd_set* user, fd_set* target) -> BAN::ErrorOr<void> {
if (readfd_region) if (user == nullptr)
readfd_region->unpin(); FD_ZERO(target);
if (writefd_region) else
writefd_region->unpin(); TRY(read_from_user(user, target, sizeof(fd_set)));
if (errorfd_region) return {};
errorfd_region->unpin(); };
});
if (arguments.readfds) fd_set rfds, wfds, efds;
readfd_region = TRY(validate_and_pin_pointer_access(arguments.readfds, sizeof(fd_set), true)); TRY(init_fd_set(arguments.readfds, &rfds));
if (arguments.writefds) TRY(init_fd_set(arguments.writefds, &wfds));
writefd_region = TRY(validate_and_pin_pointer_access(arguments.writefds, sizeof(fd_set), true)); TRY(init_fd_set(arguments.errorfds, &efds));
if (arguments.errorfds)
errorfd_region = TRY(validate_and_pin_pointer_access(arguments.errorfds, sizeof(fd_set), true));
const auto old_sigmask = Thread::current().m_signal_block_mask; const auto old_sigmask = Thread::current().m_signal_block_mask;
if (arguments.sigmask) if (arguments.sigmask)
@@ -1902,36 +1899,39 @@ namespace Kernel
timeout.tv_nsec; timeout.tv_nsec;
} }
fd_set ret_rfds, ret_wfds, ret_efds;
FD_ZERO(&ret_rfds);
FD_ZERO(&ret_wfds);
FD_ZERO(&ret_efds);
{ {
fd_set rfds, wfds, efds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
size_t return_value = 0; size_t return_value = 0;
for (int fd = 0; fd < arguments.nfds; fd++) for (int fd = 0; fd < arguments.nfds; fd++)
{ {
auto inode_or_error = m_open_file_descriptors.inode_of(fd); const bool wantr = FD_ISSET(fd, &rfds);
if (inode_or_error.is_error()) const bool wantw = FD_ISSET(fd, &wfds);
const bool wante = FD_ISSET(fd, &efds);
if (!wantr && !wantw && !wante)
continue; continue;
auto inode = inode_or_error.release_value(); auto inode = TRY(m_open_file_descriptors.inode_of(fd));
if (arguments.readfds && FD_ISSET(fd, arguments.readfds) && inode->can_read()) if (wantr && inode->can_read())
{ FD_SET(fd, &rfds); return_value++; } { FD_SET(fd, &ret_rfds); return_value++; }
if (arguments.writefds && FD_ISSET(fd, arguments.writefds) && inode->can_write()) if (wantw && inode->can_write())
{ FD_SET(fd, &wfds); return_value++; } { FD_SET(fd, &ret_wfds); return_value++; }
if (arguments.errorfds && FD_ISSET(fd, arguments.errorfds) && inode->has_error()) if (wante && inode->has_error())
{ FD_SET(fd, &efds); return_value++; } { FD_SET(fd, &ret_efds); return_value++; }
} }
if (return_value || SystemTimer::get().ns_since_boot() >= waketime_ns) if (return_value || SystemTimer::get().ns_since_boot() >= waketime_ns)
{ {
if (arguments.readfds) if (arguments.readfds)
memcpy(arguments.readfds, &rfds, sizeof(fd_set)); TRY(write_to_user(arguments.readfds, &ret_rfds, sizeof(fd_set)));
if (arguments.writefds) if (arguments.writefds)
memcpy(arguments.writefds, &wfds, sizeof(fd_set)); TRY(write_to_user(arguments.writefds, &ret_wfds, sizeof(fd_set)));
if (arguments.errorfds) if (arguments.errorfds)
memcpy(arguments.errorfds, &efds, sizeof(fd_set)); TRY(write_to_user(arguments.errorfds, &ret_efds, sizeof(fd_set)));
return return_value; return return_value;
} }
} }
@@ -1940,20 +1940,17 @@ namespace Kernel
for (int fd = 0; fd < arguments.nfds; fd++) for (int fd = 0; fd < arguments.nfds; fd++)
{ {
uint32_t events = 0; uint32_t events = 0;
if (arguments.readfds && FD_ISSET(fd, arguments.readfds)) if (FD_ISSET(fd, &rfds))
events |= EPOLLIN; events |= EPOLLIN;
if (arguments.writefds && FD_ISSET(fd, arguments.writefds)) if (FD_ISSET(fd, &wfds))
events |= EPOLLOUT; events |= EPOLLOUT;
if (arguments.errorfds && FD_ISSET(fd, arguments.errorfds)) if (FD_ISSET(fd, &efds))
events |= EPOLLERR; events |= EPOLLERR;
if (events == 0) if (events == 0)
continue; continue;
auto inode_or_error = m_open_file_descriptors.inode_of(fd); auto inode = TRY(m_open_file_descriptors.inode_of(fd));
if (inode_or_error.is_error()) TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode, { .events = events, .data = { .fd = fd }}));
continue;
TRY(epoll->ctl(EPOLL_CTL_ADD, fd, inode_or_error.release_value(), { .events = events, .data = { .fd = fd }}));
} }
BAN::Vector<epoll_event> event_buffer; BAN::Vector<epoll_event> event_buffer;
@@ -1961,25 +1958,24 @@ namespace Kernel
const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns)); const size_t waited_events = TRY(epoll->wait(event_buffer.span(), waketime_ns));
if (arguments.readfds)
FD_ZERO(arguments.readfds);
if (arguments.writefds)
FD_ZERO(arguments.writefds);
if (arguments.errorfds)
FD_ZERO(arguments.errorfds);
size_t return_value = 0; size_t return_value = 0;
for (size_t i = 0; i < waited_events; i++) for (size_t i = 0; i < waited_events; i++)
{ {
const int fd = event_buffer[i].data.fd; const int fd = event_buffer[i].data.fd;
if (arguments.readfds && event_buffer[i].events & (EPOLLIN | EPOLLHUP)) if (FD_ISSET(fd, &rfds) && event_buffer[i].events & (EPOLLIN | EPOLLHUP))
{ FD_SET(fd, arguments.readfds); return_value++; } { FD_SET(fd, &ret_rfds); return_value++; }
if (arguments.writefds && event_buffer[i].events & (EPOLLOUT)) if (FD_ISSET(fd, &wfds) && event_buffer[i].events & (EPOLLOUT))
{ FD_SET(fd, arguments.writefds); return_value++; } { FD_SET(fd, &ret_wfds); return_value++; }
if (arguments.errorfds && event_buffer[i].events & (EPOLLERR)) if (FD_ISSET(fd, &efds) && event_buffer[i].events & (EPOLLERR))
{ FD_SET(fd, arguments.errorfds); return_value++; } { FD_SET(fd, &ret_efds); return_value++; }
} }
if (arguments.readfds)
TRY(write_to_user(arguments.readfds, &ret_rfds, sizeof(fd_set)));
if (arguments.writefds)
TRY(write_to_user(arguments.writefds, &ret_wfds, sizeof(fd_set)));
if (arguments.errorfds)
TRY(write_to_user(arguments.errorfds, &ret_efds, sizeof(fd_set)));
return return_value; return return_value;
} }

View File

@@ -23,7 +23,6 @@ namespace Kernel
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE }; ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 }; BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
BAN::Atomic<bool> Processor::s_is_smp_enabled { false }; BAN::Atomic<bool> Processor::s_is_smp_enabled { false };
BAN::Atomic<bool> Processor::s_should_print_cpu_load { false };
paddr_t Processor::s_shared_page_paddr { 0 }; paddr_t Processor::s_shared_page_paddr { 0 };
vaddr_t Processor::s_shared_page_vaddr { 0 }; vaddr_t Processor::s_shared_page_vaddr { 0 };
@@ -598,6 +597,26 @@ namespace Kernel
set_interrupt_state(state); set_interrupt_state(state);
} }
Processor::LoadStats Processor::get_load_stats(size_t index)
{
ASSERT(index < Processor::count());
auto& processor = s_processors[s_processor_ids[index].as_u32()];
bool expected = false;
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
{
Processor::pause();
expected = false;
}
const auto load_stats = processor.m_load_stats;
processor.m_load_stat_lock.store(false);
return load_stats;
}
void Processor::yield() void Processor::yield()
{ {
auto state = get_interrupt_state(); auto state = get_interrupt_state();
@@ -605,47 +624,32 @@ namespace Kernel
ASSERT(!Thread::current().has_spinlock()); ASSERT(!Thread::current().has_spinlock());
auto& processor_info = s_processors[current_id().as_u32()]; auto& processor = s_processors[current_id().as_u32()];
{ {
constexpr uint64_t load_update_interval_ns = 1'000'000'000; bool expected = false;
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
if (scheduler().is_idle())
processor_info.m_idle_ns += current_ns - processor_info.m_start_ns;
if (current_ns >= processor_info.m_next_update_ns)
{ {
if (s_should_print_cpu_load && g_terminal_driver) Processor::pause();
{ expected = false;
const uint64_t duration_ns = current_ns - processor_info.m_last_update_ns;
const uint64_t load_x1000 = 100'000 * (duration_ns - BAN::Math::min(processor_info.m_idle_ns, duration_ns)) / duration_ns;
uint32_t x = g_terminal_driver->width() - 16;
uint32_t y = current_id().as_u32();
const auto proc_putc =
[&x, y](char ch)
{
if (x < g_terminal_driver->width() && y < g_terminal_driver->height())
g_terminal_driver->putchar_at(ch, x++, y, TerminalColor::WHITE, TerminalColor::BLACK);
};
BAN::Formatter::print(proc_putc, "CPU { 2}: { 3}.{3}%", current_id(), load_x1000 / 1000, load_x1000 % 1000);
}
processor_info.m_idle_ns = 0;
processor_info.m_last_update_ns = current_ns;
processor_info.m_next_update_ns += load_update_interval_ns;
} }
const uint64_t elapsed_ns = SystemTimer::get().ns_since_boot() - processor.m_load_start_ns;
auto& load_stats = processor.m_load_stats;
if (scheduler().is_idle())
load_stats.ns_idle += elapsed_ns;
load_stats.ns_total += elapsed_ns;
processor.m_load_stat_lock.store(false);
} }
if (!scheduler().is_idle()) if (!scheduler().is_idle())
Thread::current().set_cpu_time_stop(); Thread::current().set_cpu_time_stop();
asm_yield_trampoline(processor_info.stack_top_vaddr()); asm_yield_trampoline(processor.stack_top_vaddr());
processor_info.m_start_ns = SystemTimer::get().ns_since_boot(); processor.m_load_start_ns = SystemTimer::get().ns_since_boot();
if (!scheduler().is_idle()) if (!scheduler().is_idle())
Thread::current().set_cpu_time_start(); Thread::current().set_cpu_time_start();

View File

@@ -1,5 +1,6 @@
#include <BAN/ScopeGuard.h> #include <BAN/ScopeGuard.h>
#include <kernel/BootInfo.h> #include <kernel/BootInfo.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/Storage/DiskCache.h> #include <kernel/Storage/DiskCache.h>

View File

@@ -10,10 +10,14 @@
#include <kernel/Thread.h> #include <kernel/Thread.h>
#include <kernel/Timer/Timer.h> #include <kernel/Timer/Timer.h>
#include <kernel/UserCopy.h> #include <kernel/UserCopy.h>
#include <sys/syscall.h>
namespace Kernel namespace Kernel
{ {
static_assert(SYS_SIGPROCMASK == 79, "this is hard coded in arch/*/Signal.S");
static_assert(SIG_SETMASK == 3, "this is hard coded in arch/*/Signal.S");
#if ARCH(x86_64) #if ARCH(x86_64)
static constexpr vaddr_t s_user_stack_addr_start = 0x0000700000000000; static constexpr vaddr_t s_user_stack_addr_start = 0x0000700000000000;
#elif ARCH(i686) #elif ARCH(i686)
@@ -582,9 +586,15 @@ namespace Kernel
const uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask(); const uint64_t full_pending_mask = m_signal_pending_mask | process().signal_pending_mask();
const uint64_t signals = full_pending_mask & ~m_signal_block_mask; const uint64_t signals = full_pending_mask & ~m_signal_block_mask;
for (size_t sig = _SIGMIN; sig <= _SIGMAX; sig++) for (size_t sig = _SIGMIN; sig <= _SIGMAX; sig++)
if (signals & (static_cast<uint64_t>(1) << sig)) {
if (is_terminating_signal(sig) || is_abnormal_terminating_signal(sig)) if (!(signals & (static_cast<uint64_t>(1) << sig)))
return true; continue;
if (!is_terminating_signal(sig) && !is_abnormal_terminating_signal(sig))
continue;
SpinLockGuard _(m_process->m_signal_lock);
if (m_process->m_signal_handlers[sig].sa_handler == SIG_DFL)
return true;
}
return false; return false;
} }

View File

@@ -211,6 +211,8 @@ static void init2(void*)
SystemTimer::get().initialize_tsc(); SystemTimer::get().initialize_tsc();
ProcFileSystem::get().post_scheduler_initialize();
auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console)); auto console = MUST(DevFileSystem::get().root_inode()->find_inode(cmdline.console));
ASSERT(console->is_tty()); ASSERT(console->is_tty());
static_cast<Kernel::TTY*>(console.ptr())->set_as_current(); static_cast<Kernel::TTY*>(console.ptr())->set_as_current();

View File

@@ -20,5 +20,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -19,5 +19,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -23,5 +23,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -19,5 +19,5 @@ build() {
} }
install() { install() {
cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$BANAN_SYSROOT/usr/bin/specseek" || exit 1 cp -v bin/gcc/$specseek_arch/specseek_$specseek_arch "$DESTDIR/usr/bin/specseek" || exit 1
} }

View File

@@ -24,5 +24,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -24,5 +24,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -16,7 +16,7 @@ CONFIGURE_OPTIONS=(
) )
post_install() { post_install() {
if [ ! -L $BANAN_SYSROOT/usr/bin/sh ]; then if [ ! -L $DESTDIR/usr/bin/sh ]; then
ln -s bash $BANAN_SYSROOT/usr/bin/sh ln -s bash $DESTDIR/usr/bin/sh
fi fi
} }

View File

@@ -13,14 +13,16 @@ build() {
} }
install() { install() {
cp -v libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/ || exit 1 mkdir -p "$DESTDIR/usr/lib"
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so || exit 1 cp -v libbz2.so.$VERSION "$DESTDIR/usr/lib/" || exit 1
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1 || exit 1 ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so" || exit 1
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1.0 || exit 1 ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so.1" || exit 1
ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so.1.0" || exit 1
cp -v bzlib.h $BANAN_SYSROOT/usr/include/ || exit 1 mkdir -p "$DESTDIR/usr/include"
cp -v bzlib.h "$DESTDIR/usr/include/" || exit 1
cat > $BANAN_SYSROOT/usr/lib/pkgconfig/bzip2.pc << EOF cat > $DESTDIR/usr/lib/pkgconfig/bzip2.pc << EOF
prefix=/usr prefix=/usr
exec_prefix=\${prefix} exec_prefix=\${prefix}
bindir=\${exec_prefix}/bin bindir=\${exec_prefix}/bin

View File

@@ -13,10 +13,10 @@ build() {
} }
install() { install() {
rm -rf "$BANAN_SYSROOT/etc/cacert/extracted" rm -rf "$DESTDIR/etc/cacert/extracted"
mkdir -p "$BANAN_SYSROOT/etc/cacert/extracted" mkdir -p "$DESTDIR/etc/cacert/extracted"
cp -vf "../cacert-${VERSION//./-}.pem" "$BANAN_SYSROOT/etc/cacert/cacert.pem" cp -vf "../cacert-${VERSION//./-}.pem" "$DESTDIR/etc/cacert/cacert.pem"
awk '/-----BEGIN CERTIFICATE-----/ {c=1;n++} c {print > sprintf("cert%03d.pem", n)} /-----END CERTIFICATE-----/ {c=0}' "../cacert-${VERSION//./-}.pem" awk '/-----BEGIN CERTIFICATE-----/ {c=1;n++} c {print > sprintf("cert%03d.pem", n)} /-----END CERTIFICATE-----/ {c=0}' "../cacert-${VERSION//./-}.pem"
mv cert*.pem "$BANAN_SYSROOT/etc/cacert/extracted/" mv cert*.pem "$DESTDIR/etc/cacert/extracted/"
} }

View File

@@ -22,5 +22,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -21,6 +21,6 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $BANAN_SYSROOT/usr/share/cmake-3.26/Modules/Platform/ cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $DESTDIR/usr/share/cmake-3.26/Modules/Platform/
} }

View File

@@ -25,5 +25,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -18,6 +18,9 @@ build() {
} }
install() { install() {
cp doomgeneric/doomgeneric "${BANAN_SYSROOT}/bin/doom" || exit 1 mkdir -p "$DESTDIR/usr/bin"
cp ../doom1.wad "$BANAN_SYSROOT/home/user/" || exit 1 cp -vf doomgeneric/doomgeneric "$DESTDIR/usr/bin/doom"
mkdir -p "$DESTDIR/home/user"
cp -vf ../doom1.wad "$DESTDIR/home/user/"
} }

View File

@@ -3,7 +3,7 @@
NAME='ffmpeg' NAME='ffmpeg'
VERSION='8.0.1' VERSION='8.0.1'
DOWNLOAD_URL="https://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz#05ee0b03119b45c0bdb4df654b96802e909e0a752f72e4fe3794f487229e5a41" DOWNLOAD_URL="https://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz#05ee0b03119b45c0bdb4df654b96802e909e0a752f72e4fe3794f487229e5a41"
DEPENDENCIES=('SDL2') DEPENDENCIES=('SDL2' 'openssl')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--prefix=/usr' '--prefix=/usr'
'--target-os=none' '--target-os=none'
@@ -13,6 +13,8 @@ CONFIGURE_OPTIONS=(
'--enable-cross-compile' '--enable-cross-compile'
'--enable-shared' '--enable-shared'
'--enable-gpl' '--enable-gpl'
'--enable-version3'
'--enable-openssl'
) )
configure() { configure() {

View File

@@ -23,7 +23,7 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }
post_install() { post_install() {
@@ -39,9 +39,9 @@ post_install() {
tar xf "$font_name.tar.bz2" || exit 1 tar xf "$font_name.tar.bz2" || exit 1
fi fi
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/TTF" || exit 1 mkdir -p "$DESTDIR/usr/share/fonts/TTF" || exit 1
cp "$font_name/ttf/"* "$BANAN_SYSROOT/usr/share/fonts/TTF/" || exit 1 cp "$font_name/ttf/"* "$DESTDIR/usr/share/fonts/TTF/" || exit 1
cp "$font_name/fontconfig/"* "$BANAN_SYSROOT/usr/share/fontconfig/conf.avail/" || exit 1 cp "$font_name/fontconfig/"* "$DESTDIR/usr/share/fontconfig/conf.avail/" || exit 1
popd &>/dev/null popd &>/dev/null
} }

View File

@@ -23,5 +23,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -22,5 +22,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -18,5 +18,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -17,5 +17,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -3,7 +3,7 @@
NAME='gtk' NAME='gtk'
VERSION='3.24.49' VERSION='3.24.49'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc" DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc"
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr') DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr' 'libXcursor' 'libXinerama')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dtests=false' '-Dtests=false'
@@ -26,5 +26,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -14,5 +14,5 @@ build() {
} }
install() { install() {
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1 ./waf install --destdir="$DESTDIR/home/user/halflife" || exit 1
} }

View File

@@ -3,7 +3,7 @@
NAME='harfbuzz' NAME='harfbuzz'
VERSION='12.2.0' VERSION='12.2.0'
DOWNLOAD_URL="https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/harfbuzz-$VERSION.tar.xz#ecb603aa426a8b24665718667bda64a84c1504db7454ee4cadbd362eea64e545" DOWNLOAD_URL="https://github.com/harfbuzz/harfbuzz/releases/download/$VERSION/harfbuzz-$VERSION.tar.xz#ecb603aa426a8b24665718667bda64a84c1504db7454ee4cadbd362eea64e545"
DEPENDENCIES=('glib' 'freetype') DEPENDENCIES=('glib' 'freetype' 'icu')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dtests=disabled' '-Dtests=disabled'
@@ -23,7 +23,7 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }
post_install() { post_install() {

View File

@@ -4,7 +4,6 @@ NAME='icu'
VERSION='78.1' VERSION='78.1'
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886" DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886"
TAR_CONTENT='icu' TAR_CONTENT='icu'
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('source/config.sub') CONFIG_SUB=('source/config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
"--with-cross-build=$BANAN_PORT_DIR/icu/icu-$VERSION-$BANAN_ARCH/source/build-host" "--with-cross-build=$BANAN_PORT_DIR/icu/icu-$VERSION-$BANAN_ARCH/source/build-host"

View File

@@ -43,8 +43,10 @@ export MESON_CROSS_FILE="$BANAN_PORT_DIR/$BANAN_ARCH-banan_os-meson.txt"
if [ ! -f "$MESON_CROSS_FILE" ] || [ "$MESON_CROSS_FILE" -ot "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" ]; then if [ ! -f "$MESON_CROSS_FILE" ] || [ "$MESON_CROSS_FILE" -ot "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" ]; then
cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$MESON_CROSS_FILE" cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$MESON_CROSS_FILE"
sed -i "s|ARCH|$BANAN_ARCH|" "$MESON_CROSS_FILE" sed -i "s|ARCH|$BANAN_ARCH|" "$MESON_CROSS_FILE"
sed -i "s|CMAKE|$BANAN_CMAKE|" "$MESON_CROSS_FILE"
sed -i "s|SYSROOT|$BANAN_SYSROOT|" "$MESON_CROSS_FILE" sed -i "s|SYSROOT|$BANAN_SYSROOT|" "$MESON_CROSS_FILE"
sed -i "s|PKG_CONFIG|$BANAN_PORT_DIR/pkg-config|" "$MESON_CROSS_FILE"
sed -i "s|CMAKE_BINARY|$BANAN_CMAKE|" "$MESON_CROSS_FILE"
sed -i "s|CMAKE_TOOLCHAIN|$BANAN_TOOLCHAIN_DIR/Toolchain.txt|" "$MESON_CROSS_FILE"
fi fi
MAKE_BUILD_TARGETS=('all') MAKE_BUILD_TARGETS=('all')
@@ -250,6 +252,7 @@ if (( $needs_compile )); then
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash" sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
fi fi
DESTDIR="$BANAN_SYSROOT"
pre_install pre_install
install install
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file" grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"

View File

@@ -19,5 +19,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -22,5 +22,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -23,5 +23,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -4,3 +4,6 @@ NAME='libffi'
VERSION='3.5.2' VERSION='3.5.2'
DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc" DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc"
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
)

View File

@@ -3,7 +3,6 @@
NAME='libsndfile' NAME='libsndfile'
VERSION='1.2.2' VERSION='1.2.2'
DOWNLOAD_URL="https://github.com/libsndfile/libsndfile/releases/download/$VERSION/libsndfile-$VERSION.tar.xz#3799ca9924d3125038880367bf1468e53a1b7e3686a934f098b7e1d286cdb80e" DOWNLOAD_URL="https://github.com/libsndfile/libsndfile/releases/download/$VERSION/libsndfile-$VERSION.tar.xz#3799ca9924d3125038880367bf1468e53a1b7e3686a934f098b7e1d286cdb80e"
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('build-aux/config.sub') CONFIG_SUB=('build-aux/config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'CFLAGS=-std=c11' 'CFLAGS=-std=c11'

View File

@@ -18,5 +18,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -23,5 +23,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -3,7 +3,7 @@
NAME='links' NAME='links'
VERSION='2.30' VERSION='2.30'
DOWNLOAD_URL="http://links.twibright.com/download/links-$VERSION.tar.gz#7f0d54f4f7d1f094c25c9cbd657f98bc998311122563b1d757c9aeb1d3423b9e" DOWNLOAD_URL="http://links.twibright.com/download/links-$VERSION.tar.gz#7f0d54f4f7d1f094c25c9cbd657f98bc998311122563b1d757c9aeb1d3423b9e"
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd' 'libpng' 'libjpeg' 'libtiff' 'libwebp') DEPENDENCIES=('openssl' 'zlib' 'zstd' 'libpng' 'libjpeg' 'libtiff' 'libwebp')
post_configure() { post_configure() {
config_defines=( config_defines=(
@@ -50,5 +50,6 @@ build() {
} }
install() { install() {
cp -v links "$BANAN_SYSROOT/usr/bin/" || exit 1 mkdir -p "$DESTDIR/usr/bin"
cp -v links "$DESTDIR/usr/bin/" || exit 1
} }

View File

@@ -13,5 +13,5 @@ build() {
} }
install() { install() {
make install PLAT=posix INSTALL_TOP="$BANAN_SYSROOT/usr" || exit 1 make install PLAT=posix INSTALL_TOP="$DESTDIR/usr" || exit 1
} }

View File

@@ -4,7 +4,7 @@ NAME='lynx'
VERSION='2.9.2' VERSION='2.9.2'
DOWNLOAD_URL="https://invisible-island.net/archives/lynx/tarballs/lynx$VERSION.tar.gz#99f8f28f860094c533100d1cedf058c27fb242ce25e991e2d5f30ece4457a3bf" DOWNLOAD_URL="https://invisible-island.net/archives/lynx/tarballs/lynx$VERSION.tar.gz#99f8f28f860094c533100d1cedf058c27fb242ce25e991e2d5f30ece4457a3bf"
TAR_CONTENT="lynx$VERSION" TAR_CONTENT="lynx$VERSION"
DEPENDENCIES=('ncurses' 'ca-certificates' 'openssl' 'zlib') DEPENDENCIES=('ncurses' 'openssl' 'zlib')
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--without-system-type' '--without-system-type'

View File

@@ -74,8 +74,9 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
ln -sf osmesa.pc $BANAN_SYSROOT/usr/lib/pkgconfig/opengl.pc mkdir -p "$DESTDIR/usr/lib/pkgconfig"
ln -sf libOSMesa.so $BANAN_SYSROOT/usr/lib/libGL.so ln -sf osmesa.pc $DESTDIR/usr/lib/pkgconfig/opengl.pc
ln -sf libOSMesa.so $DESTDIR/usr/lib/libGL.so
} }

View File

@@ -9,5 +9,6 @@ configure() {
} }
install() { install() {
cp src/nyancat "$BANAN_SYSROOT/usr/bin/" mkdir -p "$DESTDIR/usr/bin"
cp src/nyancat "$DESTDIR/usr/bin/"
} }

View File

@@ -21,5 +21,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -11,16 +11,16 @@ configure() {
} }
post_install() { post_install() {
rm -f "$BANAN_SYSROOT/etc/ssl/certs"/* rm -f "$DESTDIR/etc/ssl/certs"/*
ln -svf "../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/cert.pem" ln -svf "../cacert/cacert.pem" "$DESTDIR/etc/ssl/cert.pem"
ln -svf "../../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/certs/ca-certificates.crt" ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-certificates.crt"
ln -svf "../../cacert/cacert.pem" "$BANAN_SYSROOT/etc/ssl/certs/ca-bundle.crt" ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-bundle.crt"
openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted" openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted"
find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 | find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 |
while IFS= read -r -d '' link; do while IFS= read -r -d '' link; do
ln -s "../../cacert/extracted/$(readlink "$link")" "$BANAN_SYSROOT/etc/ssl/certs/${link##*/}" ln -s "../../cacert/extracted/$(readlink "$link")" "$DESTDIR/etc/ssl/certs/${link##*/}"
rm "$link" rm "$link"
done done
} }

View File

@@ -3,7 +3,7 @@
NAME='pango' NAME='pango'
VERSION='1.57.0' VERSION='1.57.0'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/pango/-/archive/$VERSION/pango-$VERSION.tar.gz#1b2e2f683dfb5adec3faf17087ade8c648f10a5d3d0e17e421e0ac1a39e6740e" DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/pango/-/archive/$VERSION/pango-$VERSION.tar.gz#1b2e2f683dfb5adec3faf17087ade8c648f10a5d3d0e17e421e0ac1a39e6740e"
DEPENDENCIES=('glib' 'fontconfig' 'cairo' 'fribidi') DEPENDENCIES=('glib' 'fontconfig' 'cairo' 'fribidi' 'libXft')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dbuild-testsuite=false' '-Dbuild-testsuite=false'
@@ -22,5 +22,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -4,3 +4,6 @@ NAME='pcre2'
VERSION='10.45' VERSION='10.45'
DOWNLOAD_URL="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$VERSION/pcre2-$VERSION.tar.gz#0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee" DOWNLOAD_URL="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$VERSION/pcre2-$VERSION.tar.gz#0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee"
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
)

View File

@@ -20,5 +20,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -21,5 +21,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -10,6 +10,7 @@ CONFIGURE_OPTIONS=(
'--target-list=x86_64-softmmu' '--target-list=x86_64-softmmu'
'--disable-tpm' '--disable-tpm'
'--disable-docs' '--disable-docs'
'--enable-slirp'
) )
pre_configure() { pre_configure() {

View File

@@ -31,9 +31,9 @@ build() {
} }
install() { install() {
cp -v build/quake2-soft "${BANAN_SYSROOT}/bin/quake2" || exit 1 mkdir -p "$DESTDIR/usr/bin"
cp -vf build/quake2-soft "$DESTDIR/usr/bin/quake2" || exit 1
baseq2_tar=$(realpath ../baseq2.tar.gz || exit 1) mkdir -p "$DESTDIR/home/user"
cd "$BANAN_SYSROOT/home/user/" tar xf ../baseq2.tar.gz -C "$DESTDIR/home/user/"
tar xf $baseq2_tar
} }

View File

@@ -20,5 +20,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -24,5 +24,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -26,5 +26,5 @@ configure() {
} }
post_install() { post_install() {
ln -sf $tcc_arch-tcc $BANAN_SYSROOT/usr/bin/tcc ln -sf $tcc_arch-tcc $DESTDIR/usr/bin/tcc
} }

View File

@@ -18,5 +18,5 @@ build() {
} }
install() { install() {
make -C unix install "DESTDIR=$BANAN_SYSROOT" || exit 1 make -C unix install "DESTDIR=$DESTDIR" || exit 1
} }

View File

@@ -19,9 +19,10 @@ post_install() {
fi fi
eawpats_dir="/usr/share/eawpats" eawpats_dir="/usr/share/eawpats"
mkdir -p "$BANAN_SYSROOT/$eawpats_dir" mkdir -p "$DESTDIR/$eawpats_dir"
unzip -qod "$BANAN_SYSROOT/$eawpats_dir" ../eawpats.zip unzip -qod "$DESTDIR/$eawpats_dir" ../eawpats.zip
cp "$BANAN_SYSROOT/$eawpats_dir/timidity.cfg" "$BANAN_SYSROOT/etc/" mkdir -p "$DESTDIR/etc"
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$BANAN_SYSROOT/etc/timidity.cfg" cp "$DESTDIR/$eawpats_dir/timidity.cfg" "$DESTDIR/etc/"
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$DESTDIR/etc/timidity.cfg"
} }

View File

@@ -15,5 +15,5 @@ build() {
} }
install() { install() {
cp -v tinygb "$BANAN_SYSROOT"/usr/bin || exit 1 cp -v tinygb "$DESTDIR/usr/bin/" || exit 1
} }

View File

@@ -31,9 +31,9 @@ post_install() {
tar xf "tuxracer-data-$VERSION.tar.gz" || exit 1 tar xf "tuxracer-data-$VERSION.tar.gz" || exit 1
fi fi
mkdir -p "$BANAN_SYSROOT/usr/share/tuxracer" || exit 1 mkdir -p "$DESTDIR/usr/share/tuxracer" || exit 1
cp -r "tuxracer-data-$VERSION"/* "$BANAN_SYSROOT/usr/share/tuxracer/" || exit 1 cp -r "tuxracer-data-$VERSION"/* "$DESTDIR/usr/share/tuxracer/" || exit 1
find "$BANAN_SYSROOT/usr/share/tuxracer" -type f -exec chmod 644 {} + find "$DESTDIR/usr/share/tuxracer" -type f -exec chmod 644 {} +
popd popd
} }

View File

@@ -3,7 +3,7 @@
NAME='xash3d-fwgs' NAME='xash3d-fwgs'
VERSION='git' VERSION='git'
DOWNLOAD_URL="https://github.com/FWGS/xash3d-fwgs.git#da1b9ad80d76156a5cbd54d3ce87edb32634ea87" DOWNLOAD_URL="https://github.com/FWGS/xash3d-fwgs.git#da1b9ad80d76156a5cbd54d3ce87edb32634ea87"
DEPENDENCIES=('SDL2' 'freetype') DEPENDENCIES=('SDL2' 'freetype' 'bzip2' 'libvorbis')
configure() { configure() {
git submodule update --init --recursive || exit 1 git submodule update --init --recursive || exit 1
@@ -22,13 +22,12 @@ build() {
} }
install() { install() {
./waf install --destdir=$BANAN_SYSROOT/home/user/halflife || exit 1 ./waf install --destdir="$DESTDIR/usr/share/games/halflife" || exit 1
patchelf --add-needed libxash.so $BANAN_SYSROOT/home/user/halflife/xash3d
cat > $BANAN_SYSROOT/home/user/halflife/start.sh << EOF cat > "$DESTDIR/home/user/halflife/start.sh" << EOF
#!/bin/Shell #!/bin/Shell
export LD_LIBRARY_PATH=/home/user/halflife export LD_LIBRARY_PATH=/home/user/halflife
./xash3d -console ./xash3d -console
EOF EOF
chmod +x $BANAN_SYSROOT/home/user/halflife/start.sh chmod +x $DESTDIR/home/user/halflife/start.sh
} }

View File

@@ -18,10 +18,11 @@ build() {
} }
install() { install() {
cp -v build/xbanan/xbanan "$BANAN_SYSROOT/usr/bin" || exit 1 mkdir -p "$DESTDIR/usr/bin"
cp -v build/xbanan/xbanan "$DESTDIR/usr/bin/" || exit 1
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/X11" mkdir -p "$DESTDIR/usr/share/fonts/X11"
cp -r fonts/misc "$BANAN_SYSROOT/usr/share/fonts/X11/" || exit 1 cp -r fonts/misc "$DESTDIR/usr/share/fonts/X11/" || exit 1
} }
post_install() { post_install() {

View File

@@ -21,5 +21,5 @@ build() {
} }
install() { install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1 meson install --destdir="$DESTDIR" -C build || exit 1
} }

View File

@@ -20,5 +20,5 @@ build() {
} }
install() { install() {
cmake --install build ||exit 1 DESTDIR="$DESTDIR" cmake --install build ||exit 1
} }

View File

@@ -17,5 +17,5 @@ build() {
} }
install() { install() {
cmake --install build || exit 1 DESTDIR="$DESTDIR" cmake --install build || exit 1
} }

View File

@@ -16,5 +16,5 @@ build() {
} }
install() { install() {
cmake --install _build ||exit 1 DESTDIR="$DESTDIR" cmake --install _build ||exit 1
} }

View File

@@ -16,13 +16,11 @@ set(TOOLCHAIN_PREFIX $ENV{BANAN_TOOLCHAIN_PREFIX})
set(CMAKE_SYSTEM_NAME banan-os) set(CMAKE_SYSTEM_NAME banan-os)
set(CMAKE_SYSTEM_PROCESSOR ${BANAN_ARCH}) set(CMAKE_SYSTEM_PROCESSOR ${BANAN_ARCH})
set(CMAKE_SYSROOT ${BANAN_SYSROOT}) set(CMAKE_FIND_ROOT_PATH ${BANAN_SYSROOT})
set(CMAKE_STAGING_PREFIX ${BANAN_SYSROOT}/usr)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)

View File

@@ -130,7 +130,8 @@ build_gcc () {
--enable-shared \ --enable-shared \
--enable-lto \ --enable-lto \
--disable-nls \ --disable-nls \
--enable-languages=c,c++ --enable-languages=c,c++ \
CXXFLAGS='-fno-char8_t'
XCFLAGS="" XCFLAGS=""
if [ $BANAN_ARCH = "x86_64" ]; then if [ $BANAN_ARCH = "x86_64" ]; then

View File

@@ -11,11 +11,12 @@ ar = 'ARCH-pc-banan_os-ar'
ld = 'ARCH-pc-banan_os-ld' ld = 'ARCH-pc-banan_os-ld'
objcopy = 'ARCH-pc-banan_os-objcopy' objcopy = 'ARCH-pc-banan_os-objcopy'
strip = 'ARCH-pc-banan_os-strip' strip = 'ARCH-pc-banan_os-strip'
pkg-config = 'pkg-config' pkg-config = 'PKG_CONFIG'
cmake = 'CMAKE' cmake = 'CMAKE_BINARY'
glib-compile-schemas = '/usr/bin/glib-compile-schemas' glib-compile-schemas = '/usr/bin/glib-compile-schemas'
glib-compile-resources = '/usr/bin/glib-compile-resources' glib-compile-resources = '/usr/bin/glib-compile-resources'
[properties] [properties]
sys_root='SYSROOT' sys_root='SYSROOT'
cmake_toolchain_file='CMAKE_TOOLCHAIN'

View File

@@ -127,6 +127,8 @@ int vsnprintf(char* __restrict s, size_t n, const char* __restrict format, va_l
int vsprintf(char* __restrict s, const char* __restrict format, va_list ap); int vsprintf(char* __restrict s, const char* __restrict format, va_list ap);
int vsscanf(const char* __restrict s, const char* __restrict format, va_list arg); int vsscanf(const char* __restrict s, const char* __restrict format, va_list arg);
void __fseterr(FILE* stream);
__END_DECLS __END_DECLS
#endif #endif

View File

@@ -75,8 +75,8 @@ int mblen(const char* s, size_t n);
size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n); size_t mbstowcs(wchar_t* __restrict pwcs, const char* __restrict s, size_t n);
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n); int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
char* mkdtemp(char* _template); char* mkdtemp(char* _template);
char* mktemp(char* _template);
int mkstemp(char* _template); int mkstemp(char* _template);
int mkostemp(char* _template, int flags);
long mrand48(void); long mrand48(void);
long nrand48(unsigned short xsubi[3]); long nrand48(unsigned short xsubi[3]);
int posix_memalign(void** memptr, size_t alignment, size_t size); int posix_memalign(void** memptr, size_t alignment, size_t size);
@@ -109,6 +109,10 @@ int unsetenv(const char* name);
size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n); size_t wcstombs(char* __restrict s, const wchar_t* __restrict pwcs, size_t n);
int wctomb(char* s, wchar_t wchar); int wctomb(char* s, wchar_t wchar);
char* mktemp(char* _template);
int mkstemps(char* _template, int suffixlen);
int mkostemps(char* _template, int suffixlen, int flags);
__END_DECLS __END_DECLS
#endif #endif

View File

@@ -6,9 +6,9 @@
__BEGIN_DECLS __BEGIN_DECLS
#define LOCK_UN 0 #define LOCK_UN 0
#define LOCK_EX 1 #define LOCK_SH 1
#define LOCK_SH 2 #define LOCK_EX 2
#define LOCK_NB 4 #define LOCK_NB (1 << 2)
int flock(int fd, int op); int flock(int fd, int op);

View File

@@ -1,12 +1,8 @@
#include <BAN/Atomic.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <spawn.h> #include <spawn.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#define TODO_FUNC(name, ...) int name(__VA_ARGS__) { dwarnln("TODO: " #name); errno = ENOTSUP; return -1; } #define TODO_FUNC(name, ...) int name(__VA_ARGS__) { dwarnln("TODO: " #name); errno = ENOTSUP; return -1; }
@@ -205,20 +201,6 @@ int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t* __restrict file
static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, const posix_spawn_file_actions_t* file_actions, const posix_spawnattr_t* __restrict attrp, char* const argv[], char* const envp[], bool do_path_resolution) static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, const posix_spawn_file_actions_t* file_actions, const posix_spawnattr_t* __restrict attrp, char* const argv[], char* const envp[], bool do_path_resolution)
{ {
// MAP_SHARED | MAP_ANONYMOUS is not supported :D
const auto smo_key = smo_create(sizeof(int), PROT_READ | PROT_WRITE);
if (smo_key == -1)
return errno;
void* addr = smo_map(smo_key);
smo_delete(smo_key);
if (addr == MAP_FAILED)
return errno;
auto& child_status = *static_cast<BAN::Atomic<int>*>(addr);
child_status = INT_MAX;
const pid_t child_pid = fork(); const pid_t child_pid = fork();
if (child_pid == 0) if (child_pid == 0)
{ {
@@ -227,7 +209,6 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
auto ret = __VA_ARGS__; \ auto ret = __VA_ARGS__; \
if (ret != (err)) \ if (ret != (err)) \
break; \ break; \
child_status = errno; \
exit(127); \ exit(127); \
} while (false) } while (false)
@@ -249,7 +230,7 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
if (attrp->flags & POSIX_SPAWN_SETSIGDEF) if (attrp->flags & POSIX_SPAWN_SETSIGDEF)
for (int sig = _SIGMIN; sig <= _SIGMAX; sig++) for (int sig = _SIGMIN; sig <= _SIGMAX; sig++)
if (attrp->sigdefault & (1ull << sig)) if (attrp->sigdefault & (1ull << sig))
DIE_ON_ERROR(NULL, signal(sig, SIG_DFL)); DIE_ON_ERROR(SIG_ERR, signal(sig, SIG_DFL));
if (attrp->flags & POSIX_SPAWN_SETSIGMASK) if (attrp->flags & POSIX_SPAWN_SETSIGMASK)
DIE_ON_ERROR(-1, sigprocmask(SIG_SETMASK, &attrp->sigmask, nullptr)); DIE_ON_ERROR(-1, sigprocmask(SIG_SETMASK, &attrp->sigmask, nullptr));
@@ -287,31 +268,13 @@ static int do_posix_spawn(pid_t* __restrict pid, const char* __restrict path, co
#undef DIE_ON_ERROR #undef DIE_ON_ERROR
child_status = 0;
auto* func = do_path_resolution ? execvpe : execve; auto* func = do_path_resolution ? execvpe : execve;
func(path, argv, envp); func(path, argv, envp);
exit(127); exit(127);
} }
if (child_pid == -1) if (child_pid == -1)
{
munmap(addr, sizeof(int));
return errno; return errno;
}
while (child_status == INT_MAX)
sched_yield();
const int child_status_copy = child_status;
munmap(addr, sizeof(int));
if (child_status_copy != 0)
{
while (waitpid(child_pid, nullptr, 0) == -1 && errno == EINTR)
continue;
return child_status_copy;
}
if (pid != nullptr) if (pid != nullptr)
*pid = child_pid; *pid = child_pid;

View File

@@ -134,6 +134,12 @@ void clearerr(FILE* file)
file->error = false; file->error = false;
} }
void __fseterr(FILE* file)
{
ScopeLock _(file);
file->error = true;
}
char* ctermid(char* buffer) char* ctermid(char* buffer)
{ {
static char s_buffer[L_ctermid]; static char s_buffer[L_ctermid];
@@ -398,7 +404,8 @@ FILE* freopen(const char* pathname, const char* mode_str, FILE* file)
if (pathname) if (pathname)
{ {
fclose(file); fflush(file);
close(file->fd);
file->fd = open(pathname, mode, 0666); file->fd = open(pathname, mode, 0666);
file->mode = mode & O_ACCMODE; file->mode = mode & O_ACCMODE;
if (file->fd == -1) if (file->fd == -1)

View File

@@ -475,31 +475,36 @@ int system(const char* command)
return stat_val; return stat_val;
} }
static size_t temp_template_count_x(const char* _template) static void randomize_temp(char* buffer)
{ {
const size_t len = strlen(_template); // FIXME: don't use rand()
for (size_t i = 0; i < len; i++) const uint32_t value = rand() & 0xFFFFFF;
if (_template[len - i - 1] != 'X') sprintf(buffer, "%06x", value);
return i;
return len;
} }
static void generate_temp_template(char* _template, size_t x_count) static char* validate_temp_template(char* _template, int suffixlen)
{ {
const size_t len = strlen(_template); const size_t length = strlen(_template);
for (size_t i = 0; i < x_count; i++) if (suffixlen < 0 || length < static_cast<size_t>(suffixlen + 6))
{ {
const uint8_t nibble = rand() & 0xF; errno = EINVAL;
_template[len - i - 1] = (nibble < 10) return nullptr;
? ('0' + nibble)
: ('a' + nibble - 10);
} }
char* xptr = _template + length - suffixlen - 6;
if (memcmp(xptr, "XXXXXX", 6) != 0)
{
errno = EINVAL;
return nullptr;
}
return xptr;
} }
char* mktemp(char* _template) char* mktemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); char* xptr = validate_temp_template(_template, 0);
if (x_count < 6) if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
_template[0] = '\0'; _template[0] = '\0';
@@ -508,18 +513,22 @@ char* mktemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
struct stat st; struct stat st;
if (stat(_template, &st) == 0) if (stat(_template, &st) == -1)
{
if (errno != ENOENT)
_template[0] = '\0';
return _template; return _template;
}
} }
} }
char* mkdtemp(char* _template) char* mkdtemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); char* xptr = validate_temp_template(_template, 0);
if (x_count < 6) if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
return nullptr; return nullptr;
@@ -527,8 +536,7 @@ char* mkdtemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1) if (mkdir(_template, S_IRUSR | S_IWUSR | S_IXUSR) != -1)
return _template; return _template;
if (errno != EEXIST) if (errno != EEXIST)
@@ -538,8 +546,26 @@ char* mkdtemp(char* _template)
int mkstemp(char* _template) int mkstemp(char* _template)
{ {
const size_t x_count = temp_template_count_x(_template); return mkostemps(_template, 0, 0);
if (x_count < 6) }
int mkostemp(char* _template, int flags)
{
return mkostemps(_template, 0, flags);
}
int mkstemps(char* _template, int suffixlen)
{
return mkostemps(_template, suffixlen, 0);
}
int mkostemps(char* _template, int suffixlen, int flags)
{
flags &= O_APPEND | O_CLOEXEC | O_SYNC;
flags |= O_RDWR | O_CREAT | O_EXCL;
char* xptr = validate_temp_template(_template, suffixlen);
if (xptr == nullptr)
{ {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@@ -547,10 +573,8 @@ int mkstemp(char* _template)
for (;;) for (;;)
{ {
generate_temp_template(_template, x_count); randomize_temp(xptr);
if (int fd = open(_template, flags, 0600); fd != -1)
int fd = open(_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd != -1)
return fd; return fd;
if (errno != EEXIST) if (errno != EEXIST)
return -1; return -1;

View File

@@ -1,5 +1,7 @@
#include <fcntl.h>
#include <pthread.h> #include <pthread.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
@@ -40,38 +42,35 @@ int posix_madvise(void* addr, size_t len, int advice)
(void)addr; (void)addr;
(void)len; (void)len;
(void)advice; (void)advice;
fprintf(stddbg, "TODO: posix_madvise");
return 0; return 0;
} }
#include <BAN/Assert.h> int mlock(const void* addr, size_t len)
#include <BAN/Debug.h>
#include <errno.h>
int mlock(const void*, size_t)
{ {
ASSERT_NOT_REACHED(); (void)addr;
(void)len;
return 0;
} }
int munlock(const void*, size_t) int munlock(const void* addr, size_t len)
{ {
ASSERT_NOT_REACHED(); (void)addr;
(void)len;
return 0;
} }
int shm_open(const char* name, int oflag, mode_t mode) int shm_open(const char* name, int oflag, mode_t mode)
{ {
(void)name; if (mkdir("/tmp/shm", 0777) == -1 && errno != EEXIST)
(void)oflag; return -1;
(void)mode; char path[PATH_MAX];
dwarnln("TODO: shm_open"); sprintf(path, "/tmp/shm%s", name);
errno = ENOTSUP; return open(path, oflag | O_CLOEXEC, mode);
return -1;
} }
int shm_unlink(const char* name) int shm_unlink(const char* name)
{ {
(void)name; char path[PATH_MAX];
dwarnln("TODO: shm_unlink"); sprintf(path, "/tmp/shm%s", name);
errno = ENOTSUP; return unlink(path);
return -1;
} }

View File

@@ -300,10 +300,10 @@ namespace LibGUI
return {}; return {};
} }
void Window::wait_events() void Window::wait_events(const timespec* timeout)
{ {
epoll_event dummy; epoll_event dummy;
epoll_wait(m_epoll_fd, &dummy, 1, -1); epoll_pwait2(m_epoll_fd, &dummy, 1, timeout, nullptr);
} }
void Window::poll_events() void Window::poll_events()

View File

@@ -66,7 +66,7 @@ namespace LibGUI
uint32_t width() const { return m_width; } uint32_t width() const { return m_width; }
uint32_t height() const { return m_height; } uint32_t height() const { return m_height; }
void wait_events(); void wait_events(const timespec* timeout = nullptr);
void poll_events(); void poll_events();
void set_socket_error_callback(BAN::Function<void()> callback) { m_socket_error_callback = callback; } void set_socket_error_callback(BAN::Function<void()> callback) { m_socket_error_callback = callback; }

View File

@@ -4,9 +4,10 @@
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <inttypes.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <time.h>
static BAN::ErrorOr<long long> read_integer_from_file(const char* file) static BAN::ErrorOr<long long> read_integer_from_file(const char* file)
{ {
@@ -63,6 +64,77 @@ static BAN::String get_battery_percentage()
return result; return result;
} }
static BAN::String get_cpu_load(bool show_long)
{
struct LoadStats
{
uint64_t idle_ns;
uint64_t total_ns;
};
static BAN::Vector<LoadStats> cpu_stats;
BAN::Vector<LoadStats> delta_stats;
(void)delta_stats.reserve(show_long ? cpu_stats.size() : 1);
for (size_t i = 0;; i++)
{
char buffer[PATH_MAX];
sprintf(buffer, "/proc/cpu/%zu", i);
FILE* fp = fopen(buffer, "r");
if (fp == nullptr)
break;
LoadStats stats;
if (fscanf(fp, "%" SCNu64 " %" SCNu64, &stats.idle_ns, &stats.total_ns) == 2)
{
if (i >= cpu_stats.size())
MUST(cpu_stats.resize(i + 1, {}));
const LoadStats delta {
.idle_ns = stats.idle_ns - cpu_stats[i].idle_ns,
.total_ns = stats.total_ns - cpu_stats[i].total_ns,
};
cpu_stats[i] = stats;
if (show_long)
(void)delta_stats.push_back(delta);
else
{
if (delta_stats.empty())
(void)delta_stats.push_back(delta);
else
{
delta_stats[0].idle_ns += delta.idle_ns;
delta_stats[0].total_ns += delta.total_ns;
}
}
}
fclose(fp);
}
BAN::String result;
(void)result.append("CPU");
for (size_t i = 0; i < delta_stats.size(); i++)
{
const uint64_t idle_10000 = 10'000 * delta_stats[i].idle_ns / delta_stats[i].total_ns;
const uint64_t load_10000 = 10'000 - idle_10000;
auto string = BAN::String::formatted(" {}.{2}%", load_10000 / 100, load_10000 % 100);
if (string.is_error())
continue;
(void)result.append(string.release_value());
}
(void)result.append(" | "_sv);
return result;
}
static int open_audio_server_fd() static int open_audio_server_fd()
{ {
int fd = socket(AF_UNIX, SOCK_STREAM, 0); int fd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -106,10 +178,12 @@ static BAN::String get_audio_volume()
return MUST(BAN::String::formatted("vol {}% | ", response / 10)); return MUST(BAN::String::formatted("vol {}% | ", response / 10));
} }
static BAN::ErrorOr<BAN::String> get_task_bar_string() static BAN::ErrorOr<BAN::String> get_task_bar_string(bool show_long)
{ {
BAN::String result; BAN::String result;
TRY(result.append(get_cpu_load(show_long)));
TRY(result.append(get_battery_percentage())); TRY(result.append(get_battery_percentage()));
TRY(result.append(get_audio_volume())); TRY(result.append(get_audio_volume()));
@@ -144,6 +218,12 @@ int main()
window->set_position(0, 0); window->set_position(0, 0);
bool show_long = false;
window->set_mouse_button_event_callback([&](auto event) {
if (event.pressed)
show_long = !show_long;
});
window->texture().fill(bg_color); window->texture().fill(bg_color);
window->invalidate(); window->invalidate();
@@ -153,7 +233,7 @@ int main()
const auto update_string = const auto update_string =
[&]() [&]()
{ {
auto text_or_error = get_task_bar_string(); auto text_or_error = get_task_bar_string(show_long);
if (text_or_error.is_error()) if (text_or_error.is_error())
return; return;
const auto text = text_or_error.release_value(); const auto text = text_or_error.release_value();
@@ -176,6 +256,8 @@ int main()
while (is_running) while (is_running)
{ {
window->poll_events();
update_string(); update_string();
constexpr uint64_t ns_per_s = 1'000'000'000; constexpr uint64_t ns_per_s = 1'000'000'000;
@@ -193,10 +275,10 @@ int main()
uint64_t sleep_ns = target_ns - current_ns; uint64_t sleep_ns = target_ns - current_ns;
timespec sleep_ts; timespec timeout_ts;
sleep_ts.tv_sec = sleep_ns / ns_per_s; timeout_ts.tv_sec = sleep_ns / ns_per_s;
sleep_ts.tv_nsec = sleep_ns % ns_per_s; timeout_ts.tv_nsec = sleep_ns % ns_per_s;
nanosleep(&sleep_ts, nullptr); window->wait_events(&timeout_ts);
} }
} }

View File

@@ -66,7 +66,7 @@ struct DNSEntry
DNSEntry(DNSEntry&& other) DNSEntry(DNSEntry&& other)
{ {
*this = BAN::move(other); initialize_no_clear(BAN::move(other));
} }
~DNSEntry() { clear(); } ~DNSEntry() { clear(); }
@@ -74,6 +74,12 @@ struct DNSEntry
DNSEntry& operator=(DNSEntry&& other) DNSEntry& operator=(DNSEntry&& other)
{ {
clear(); clear();
initialize_no_clear(BAN::move(other));
return *this;
}
void initialize_no_clear(DNSEntry&& other)
{
valid_until = other.valid_until; valid_until = other.valid_until;
switch (type = other.type) switch (type = other.type)
{ {
@@ -88,7 +94,6 @@ struct DNSEntry
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
other.clear(); other.clear();
return *this;
} }
void clear() void clear()
@@ -448,6 +453,7 @@ int main(int, char**)
if (send(client.socket, &addr, sizeof(addr), 0) == -1) if (send(client.socket, &addr, sizeof(addr), 0) == -1)
dprintln("send: {}", strerror(errno)); dprintln("send: {}", strerror(errno));
dwarnln("{} -> {}", client.query.data(), inet_ntoa({ .s_addr = resolved->raw }));
client.close = true; client.close = true;
break; break;
} }
@@ -460,14 +466,8 @@ int main(int, char**)
if (!client.query.empty()) if (!client.query.empty())
{ {
static uint8_t buffer[4096]; dprintln("unexpected data from client");
ssize_t nrecv = recv(client.socket, buffer, sizeof(buffer), 0); client.close = true;
if (nrecv < 0)
dprintln("{}", strerror(errno));
if (nrecv <= 0)
client.close = true;
else
dprintln("Client already has a query");
continue; continue;
} }
@@ -480,8 +480,11 @@ int main(int, char**)
BAN::Optional<BAN::IPv4Address> result; BAN::Optional<BAN::IPv4Address> result;
// TODO: add and parse /etc/hosts
if (*hostname && strcmp(query->data(), hostname) == 0) if (*hostname && strcmp(query->data(), hostname) == 0)
result = BAN::IPv4Address(ntohl(INADDR_LOOPBACK)); result = BAN::IPv4Address(ntohl(INADDR_LOOPBACK));
else if (strcmp(query->data(), "localhost") == 0)
result = BAN::IPv4Address(ntohl(INADDR_LOOPBACK));
else if (auto resolved = resolve_from_dns_cache(dns_cache, query.value()); resolved.has_value()) else if (auto resolved = resolve_from_dns_cache(dns_cache, query.value()); resolved.has_value())
result = resolved.release_value(); result = resolved.release_value();