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
{
constexpr bool operator()(const Key& a)
template<detail::HashMapFindable<Key, HASH, COMP> U>
constexpr bool operator()(const U& a)
{
return HASH()(a);
}
@@ -110,7 +111,8 @@ namespace BAN
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);
}

View File

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

View File

@@ -61,7 +61,7 @@ signal_trampoline:
addq $40, %rsp
// restore sigmask
movq $83, %rdi // SYS_SIGPROCMASK
movq $79, %rdi // SYS_SIGPROCMASK
movq $3, %rsi // SIG_SETMASK
leaq 192(%rsp), %rdx // set
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<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; }
@@ -155,6 +156,7 @@ namespace Kernel
BAN::RefPtr<Inode> m_root_inode;
BAN::Vector<uint32_t> m_superblock_backups;
Mutex m_inode_cache_lock;
BAN::HashMap<ino_t, BAN::RefPtr<Ext2Inode>> m_inode_cache;
BlockBufferManager m_buffer_manager;

View File

@@ -55,7 +55,7 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_no_lock(BAN::StringView);
/* 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);
/* needs write end of the lock */
@@ -71,7 +71,13 @@ namespace Kernel
private:
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:
struct ScopedSync
@@ -107,6 +113,27 @@ namespace Kernel
const uint32_t m_og_faddr;
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 BAN::RefPtr<Ext2Inode>;
};

View File

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

View File

@@ -76,7 +76,7 @@ namespace Kernel
class ProcROInode final : public TmpInode
{
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;
protected:
@@ -92,10 +92,11 @@ namespace Kernel
virtual bool has_hungup_impl() const override { return false; }
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:
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

View File

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

View File

@@ -1,7 +1,7 @@
#pragma once
#include <kernel/Lock/Mutex.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/Lock/SpinLock.h>
#include <kernel/Lock/SpinLockAsMutex.h>
namespace Kernel
{
@@ -15,15 +15,18 @@ namespace Kernel
void rd_lock()
{
LockGuard _(m_mutex);
SpinLockGuard _(m_lock);
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++;
}
void rd_unlock()
{
LockGuard _(m_mutex);
SpinLockGuard _(m_lock);
if (--m_readers_active == 0)
m_thread_blocker.unblock();
}
@@ -36,11 +39,14 @@ namespace Kernel
return;
}
LockGuard _(m_mutex);
SpinLockGuard _(m_lock);
m_writers_waiting++;
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_writer = Thread::current_tid();
@@ -51,13 +57,13 @@ namespace Kernel
{
if (--m_writer_depth != 0)
return;
LockGuard _(m_mutex);
SpinLockGuard _(m_lock);
m_writer = -1;
m_thread_blocker.unblock();
}
private:
Mutex m_mutex;
SpinLock m_lock;
ThreadBlocker m_thread_blocker;
uint32_t m_readers_active { 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;
private:
BAN::ErrorOr<long> ioctl_impl(int, void*) override;
private:
const Type m_type;
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> sendmsg(int socket, const msghdr& message, int flags);
int get_max_open_fd() const;
BAN::ErrorOr<VirtualFileSystem::File> file_of(int) const;
BAN::ErrorOr<BAN::String> path_of(int) const;
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:
static Processor& create(ProcessorID id);
static Processor& initialize();
@@ -72,9 +78,6 @@ namespace Kernel
static void set_smp_enabled() { s_is_smp_enabled = true; }
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 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 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 Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
@@ -187,7 +192,6 @@ namespace Kernel
static ProcessorID s_bsp_id;
static BAN::Atomic<uint8_t> s_processor_count;
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 vaddr_t s_shared_page_vaddr;
@@ -207,10 +211,9 @@ namespace Kernel
Scheduler* m_scheduler { nullptr };
uint64_t m_start_ns { 0 };
uint64_t m_idle_ns { 0 };
uint64_t m_last_update_ns { 0 };
uint64_t m_next_update_ns { 0 };
BAN::Atomic<bool> m_load_stat_lock;
uint64_t m_load_start_ns { 0 };
LoadStats m_load_stats {};
BAN::Atomic<SMPMessage*> m_smp_pending { 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)
{
if (!Processor::get_should_print_cpu_load())
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);
}
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
}
private:

View File

@@ -167,10 +167,36 @@ namespace Kernel
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 {};
}
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)
{
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;
}
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()
{
if (m_nlink > 0)
@@ -89,57 +71,53 @@ namespace Kernel
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);
if (block == 0 && !allocate)
return BAN::Optional<uint32_t>();
ASSERT(block != 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++;
auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0x00, block_buffer.size());
block_span[local_index] = next_block;
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());
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;
return block_from_indirect_block_no_lock(next_block, index, depth - 1, 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;
if (data_block_index < indices_per_block)
return block_from_indirect_block_no_lock(m_ext2_blocks.block[12], data_block_index, 1, allocate);
data_block_index -= indices_per_block;
uint32_t depth_block_count = indices_per_block;
for (size_t i = 0; i < 3; i++)
{
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)
return block_from_indirect_block_no_lock(m_ext2_blocks.block[13], data_block_index, 2, allocate);
data_block_index -= indices_per_block * indices_per_block;
auto zero_buffer = TRY(m_fs.get_block_buffer());
memset(zero_buffer.data(), 0, zero_buffer.size());
if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
return block_from_indirect_block_no_lock(m_ext2_blocks.block[14], data_block_index, 3, allocate);
block = TRY(m_fs.reserve_free_block(block_group()));
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();
}
@@ -542,7 +533,7 @@ done:
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())
{
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)));
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())
{
TRY(m_fs.delete_inode(new_ino));
@@ -814,7 +805,7 @@ needs_new_block:
}
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--;
TRY(parent->sync_inode_no_lock());
}
@@ -860,7 +851,7 @@ needs_new_block:
auto& entry = block_buffer.span().slice(offset).as<Ext2::LinkedDirectoryEntry>();
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 (!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
// remove it from inode cache to trigger cleanup
if (inode->nlink() == 0)
{
auto& cache = m_fs.inode_cache();
if (cache.contains(inode->ino()))
cache.remove(inode->ino());
}
m_fs.remove_from_cache(inode->ino());
// FIXME: This should expand the last inode if exists
entry.inode = 0;
@@ -892,6 +879,8 @@ needs_new_block:
}
}
dir_cache_remove(name);
return {};
}
@@ -948,6 +937,9 @@ needs_new_block:
{
ASSERT(mode().ifdir());
if (auto cached = dir_cache_find(file_name))
return cached;
auto block_buffer = TRY(m_fs.get_block_buffer());
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>();
BAN::StringView entry_name(entry.name, entry.name_len);
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);
}
}
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));
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);
if ((size_t)offset >= sizeof(full_meminfo_t))
return 0;
full_meminfo_t meminfo;
meminfo.page_size = PAGE_SIZE;
meminfo.free_pages = Heap::get().free_pages();
meminfo.used_pages = Heap::get().used_pages();
const full_meminfo_t meminfo {
.page_size = PAGE_SIZE,
.free_pages = Heap::get().free_pages(),
.used_pages = Heap::get().used_pages(),
};
size_t bytes = BAN::Math::min<size_t>(sizeof(full_meminfo_t) - offset, buffer.size());
memcpy(buffer.data(), (uint8_t*)&meminfo + offset, 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));
@@ -48,6 +49,35 @@ namespace Kernel
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()
{
ASSERT(s_instance);

View File

@@ -95,19 +95,20 @@ namespace Kernel
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_ptr = new ProcROInode(callback, fs, inode_info);
auto* inode_ptr = new ProcROInode(callback, fs, argument, inode_info);
if (inode_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
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)
, m_callback(callback)
, m_argument(argument)
{
m_mode |= Inode::Mode::IFREG;
}
@@ -116,7 +117,7 @@ namespace Kernel
{
if (offset < 0)
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)

View File

@@ -210,14 +210,14 @@ namespace Kernel
if (!file.inode->mode().ifdir())
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)));
return {};
}
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)
if (*mount.host.inode == *inode)
return &mount;
@@ -226,53 +226,52 @@ namespace Kernel
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)
if (*mount.target->root_inode() == *inode)
return &mount;
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)
{
LockGuard _(m_mutex);
auto inode = parent.inode;
ASSERT(inode);
BAN::String canonical_path;
TRY(canonical_path.append(parent.canonical_path));
if (!canonical_path.empty() && canonical_path.back() == '/')
canonical_path.pop_back();
ASSERT(canonical_path.empty() || canonical_path.back() != '/');
char canonical_buf[PATH_MAX];
size_t canonical_len = parent.canonical_path.size();
if (!parent.canonical_path.empty() && parent.canonical_path.back() == '/')
canonical_len--;
memcpy(canonical_buf, parent.canonical_path.data(), canonical_len);
ASSERT(canonical_len == 0 || canonical_buf[canonical_len - 1] != '/');
BAN::Vector<BAN::String> path_parts;
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));
char path_storage[PATH_MAX];
size_t link_depth = 0;
while (!path_parts.empty())
for (;;)
{
BAN::String path_part = BAN::move(path_parts.back());
path_parts.pop_back();
const auto path_part = [&path] {
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;
auto orig = inode;
auto orig_inode = inode;
// resolve file name
{
@@ -289,26 +288,26 @@ namespace Kernel
if (path_part == ".."_sv)
{
if (!canonical_path.empty())
{
ASSERT(canonical_path.front() == '/');
while (canonical_path.back() != '/')
canonical_path.pop_back();
canonical_path.pop_back();
}
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
canonical_len--;
if (canonical_len)
canonical_len--;
}
else
{
if (auto* mount_point = mount_from_host_inode(inode))
inode = mount_point->target->root_inode();
TRY(canonical_path.push_back('/'));
TRY(canonical_path.append(path_part));
if (canonical_len + 1 + path_part.size() > sizeof(canonical_buf))
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())
continue;
if ((flags & O_NOFOLLOW) && path_parts.empty())
if ((flags & O_NOFOLLOW) && !path.find([](char ch) { return ch != '/'; }).has_value())
continue;
// resolve symbolic links
@@ -320,21 +319,26 @@ namespace Kernel
if (link_target.front() == '/')
{
inode = root_inode;
canonical_path.clear();
canonical_len = 0;
}
else
{
inode = orig;
inode = orig_inode;
while (canonical_path.back() != '/')
canonical_path.pop_back();
canonical_path.pop_back();
while (canonical_len && canonical_buf[canonical_len - 1] != '/')
canonical_len--;
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++;
if (link_depth > 100)
if (link_depth > SYMLOOP_MAX)
return BAN::Error::from_errno(ELOOP);
}
}
@@ -342,17 +346,14 @@ namespace Kernel
if (!inode->can_access(credentials, flags))
return BAN::Error::from_errno(EACCES);
if (canonical_path.empty())
TRY(canonical_path.push_back('/'));
if (canonical_len == 0)
canonical_buf[canonical_len++] = '/';
File file;
file.inode = inode;
file.canonical_path = BAN::move(canonical_path);
BAN::String canonical_path;
TRY(canonical_path.append(BAN::StringView(canonical_buf, canonical_len)));
if (file.canonical_path.empty())
TRY(file.canonical_path.push_back('/'));
return file;
return File(BAN::move(inode), BAN::move(canonical_path));
}
#pragma GCC diagnostic pop
}

View File

@@ -256,6 +256,18 @@ namespace Kernel
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:
{
if (pid == 0 || !Thread::current().is_userspace())

View File

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

View File

@@ -93,7 +93,7 @@ namespace Kernel
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;
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)
{
if (flags != MS_SYNC)
dprintln("async file backed mmap msync");
// TODO: maybe do something with the flags :)
(void)flags;
if (m_type != Type::SHARED)
return {};

View File

@@ -3,6 +3,8 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Networking/NetworkInterface.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/sysmacros.h>
#include <string.h>
@@ -25,7 +27,7 @@ namespace Kernel
}
NetworkInterface::NetworkInterface(Type type)
: CharacterDevice(0400, 0, 0)
: CharacterDevice(0664, 0, 0)
, m_type(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)
{
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)
{
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:
{
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:
{
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:
{
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:
{
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:
{
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:
{
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:
{
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 TRY(interface(nullptr, 0))->ioctl(request, arg);
}
return Socket::ioctl_impl(request, arg);
}
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));
}
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
{
LockGuard _(m_mutex);

View File

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

View File

@@ -23,7 +23,6 @@ namespace Kernel
ProcessorID Processor::s_bsp_id { PROCESSOR_NONE };
BAN::Atomic<uint8_t> Processor::s_processor_count { 0 };
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 };
vaddr_t Processor::s_shared_page_vaddr { 0 };
@@ -598,6 +597,26 @@ namespace Kernel
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()
{
auto state = get_interrupt_state();
@@ -605,47 +624,32 @@ namespace Kernel
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;
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)
bool expected = false;
while (!processor.m_load_stat_lock.compare_exchange(expected, true))
{
if (s_should_print_cpu_load && g_terminal_driver)
{
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;
Processor::pause();
expected = false;
}
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())
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())
Thread::current().set_cpu_time_start();

View File

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

View File

@@ -10,10 +10,14 @@
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
#include <kernel/UserCopy.h>
#include <sys/syscall.h>
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)
static constexpr vaddr_t s_user_stack_addr_start = 0x0000700000000000;
#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 signals = full_pending_mask & ~m_signal_block_mask;
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))
return true;
{
if (!(signals & (static_cast<uint64_t>(1) << sig)))
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;
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,5 +19,5 @@ build() {
}
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() {
cmake --install build || exit 1
DESTDIR="$DESTDIR" cmake --install build || exit 1
}

View File

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

View File

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

View File

@@ -13,14 +13,16 @@ build() {
}
install() {
cp -v libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/ || exit 1
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so || exit 1
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1 || exit 1
ln -svf libbz2.so.$VERSION $BANAN_SYSROOT/usr/lib/libbz2.so.1.0 || exit 1
mkdir -p "$DESTDIR/usr/lib"
cp -v libbz2.so.$VERSION "$DESTDIR/usr/lib/" || exit 1
ln -svf libbz2.so.$VERSION "$DESTDIR/usr/lib/libbz2.so" || 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
exec_prefix=\${prefix}
bindir=\${exec_prefix}/bin

View File

@@ -13,10 +13,10 @@ build() {
}
install() {
rm -rf "$BANAN_SYSROOT/etc/cacert/extracted"
mkdir -p "$BANAN_SYSROOT/etc/cacert/extracted"
rm -rf "$DESTDIR/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"
mv cert*.pem "$BANAN_SYSROOT/etc/cacert/extracted/"
mv cert*.pem "$DESTDIR/etc/cacert/extracted/"
}

View File

@@ -22,5 +22,5 @@ build() {
}
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() {
cmake --install build || exit 1
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $BANAN_SYSROOT/usr/share/cmake-3.26/Modules/Platform/
DESTDIR="$DESTDIR" cmake --install build || exit 1
cp $BANAN_TOOLCHAIN_DIR/cmake-platform/* $DESTDIR/usr/share/cmake-3.26/Modules/Platform/
}

View File

@@ -25,5 +25,5 @@ build() {
}
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() {
cp doomgeneric/doomgeneric "${BANAN_SYSROOT}/bin/doom" || exit 1
cp ../doom1.wad "$BANAN_SYSROOT/home/user/" || exit 1
mkdir -p "$DESTDIR/usr/bin"
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'
VERSION='8.0.1'
DOWNLOAD_URL="https://ffmpeg.org/releases/ffmpeg-$VERSION.tar.xz#05ee0b03119b45c0bdb4df654b96802e909e0a752f72e4fe3794f487229e5a41"
DEPENDENCIES=('SDL2')
DEPENDENCIES=('SDL2' 'openssl')
CONFIGURE_OPTIONS=(
'--prefix=/usr'
'--target-os=none'
@@ -13,6 +13,8 @@ CONFIGURE_OPTIONS=(
'--enable-cross-compile'
'--enable-shared'
'--enable-gpl'
'--enable-version3'
'--enable-openssl'
)
configure() {

View File

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

View File

@@ -23,5 +23,5 @@ build() {
}
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() {
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() {
cmake --install build || exit 1
DESTDIR="$DESTDIR" cmake --install build || exit 1
}

View File

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

View File

@@ -4,7 +4,6 @@ NAME='icu'
VERSION='78.1'
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886"
TAR_CONTENT='icu'
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('source/config.sub')
CONFIGURE_OPTIONS=(
"--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
cp "$BANAN_TOOLCHAIN_DIR/meson-cross-file.in" "$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|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
MAKE_BUILD_TARGETS=('all')
@@ -250,6 +252,7 @@ if (( $needs_compile )); then
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"
fi
DESTDIR="$BANAN_SYSROOT"
pre_install
install
grep -qsxF "$NAME-$VERSION" "$installed_file" || echo "$NAME-$VERSION" >> "$installed_file"

View File

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

View File

@@ -22,5 +22,5 @@ build() {
}
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() {
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'
DOWNLOAD_URL="https://github.com/libffi/libffi/releases/download/v$VERSION/libffi-$VERSION.tar.gz#f3a3082a23b37c293a4fcd1053147b371f2ff91fa7ea1b2a52e335676bac82dc"
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
)

View File

@@ -3,7 +3,6 @@
NAME='libsndfile'
VERSION='1.2.2'
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')
CONFIGURE_OPTIONS=(
'CFLAGS=-std=c11'

View File

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

View File

@@ -23,5 +23,5 @@ build() {
}
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'
VERSION='2.30'
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() {
config_defines=(
@@ -50,5 +50,6 @@ build() {
}
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() {
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'
DOWNLOAD_URL="https://invisible-island.net/archives/lynx/tarballs/lynx$VERSION.tar.gz#99f8f28f860094c533100d1cedf058c27fb242ce25e991e2d5f30ece4457a3bf"
TAR_CONTENT="lynx$VERSION"
DEPENDENCIES=('ncurses' 'ca-certificates' 'openssl' 'zlib')
DEPENDENCIES=('ncurses' 'openssl' 'zlib')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--without-system-type'

View File

@@ -74,8 +74,9 @@ build() {
}
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
ln -sf libOSMesa.so $BANAN_SYSROOT/usr/lib/libGL.so
mkdir -p "$DESTDIR/usr/lib/pkgconfig"
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() {
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() {
cmake --install build || exit 1
DESTDIR="$DESTDIR" cmake --install build || exit 1
}

View File

@@ -11,16 +11,16 @@ configure() {
}
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" "$BANAN_SYSROOT/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/cert.pem"
ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-certificates.crt"
ln -svf "../../cacert/cacert.pem" "$DESTDIR/etc/ssl/certs/ca-bundle.crt"
openssl rehash "$BANAN_SYSROOT/etc/cacert/extracted"
find "$BANAN_SYSROOT/etc/cacert/extracted" -type l -print0 |
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"
done
}

View File

@@ -3,7 +3,7 @@
NAME='pango'
VERSION='1.57.0'
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=(
'-Dprefix=/usr'
'-Dbuild-testsuite=false'
@@ -22,5 +22,5 @@ build() {
}
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'
DOWNLOAD_URL="https://github.com/PCRE2Project/pcre2/releases/download/pcre2-$VERSION/pcre2-$VERSION.tar.gz#0e138387df7835d7403b8351e2226c1377da804e0737db0e071b48f07c9d12ee"
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-static'
)

View File

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

View File

@@ -21,5 +21,5 @@ build() {
}
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'
'--disable-tpm'
'--disable-docs'
'--enable-slirp'
)
pre_configure() {

View File

@@ -31,9 +31,9 @@ build() {
}
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)
cd "$BANAN_SYSROOT/home/user/"
tar xf $baseq2_tar
mkdir -p "$DESTDIR/home/user"
tar xf ../baseq2.tar.gz -C "$DESTDIR/home/user/"
}

View File

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

View File

@@ -24,5 +24,5 @@ build() {
}
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() {
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() {
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
eawpats_dir="/usr/share/eawpats"
mkdir -p "$BANAN_SYSROOT/$eawpats_dir"
unzip -qod "$BANAN_SYSROOT/$eawpats_dir" ../eawpats.zip
mkdir -p "$DESTDIR/$eawpats_dir"
unzip -qod "$DESTDIR/$eawpats_dir" ../eawpats.zip
cp "$BANAN_SYSROOT/$eawpats_dir/timidity.cfg" "$BANAN_SYSROOT/etc/"
sed -i "s|^dir .*$|dir $eawpats_dir|g" "$BANAN_SYSROOT/etc/timidity.cfg"
mkdir -p "$DESTDIR/etc"
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() {
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
fi
mkdir -p "$BANAN_SYSROOT/usr/share/tuxracer" || exit 1
cp -r "tuxracer-data-$VERSION"/* "$BANAN_SYSROOT/usr/share/tuxracer/" || exit 1
find "$BANAN_SYSROOT/usr/share/tuxracer" -type f -exec chmod 644 {} +
mkdir -p "$DESTDIR/usr/share/tuxracer" || exit 1
cp -r "tuxracer-data-$VERSION"/* "$DESTDIR/usr/share/tuxracer/" || exit 1
find "$DESTDIR/usr/share/tuxracer" -type f -exec chmod 644 {} +
popd
}

View File

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

View File

@@ -21,5 +21,5 @@ build() {
}
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() {
cmake --install build ||exit 1
DESTDIR="$DESTDIR" cmake --install build ||exit 1
}

View File

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

View File

@@ -16,5 +16,5 @@ build() {
}
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_PROCESSOR ${BANAN_ARCH})
set(CMAKE_SYSROOT ${BANAN_SYSROOT})
set(CMAKE_STAGING_PREFIX ${BANAN_SYSROOT}/usr)
set(CMAKE_FIND_ROOT_PATH ${BANAN_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

View File

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

View File

@@ -11,11 +11,12 @@ ar = 'ARCH-pc-banan_os-ar'
ld = 'ARCH-pc-banan_os-ld'
objcopy = 'ARCH-pc-banan_os-objcopy'
strip = 'ARCH-pc-banan_os-strip'
pkg-config = 'pkg-config'
cmake = 'CMAKE'
pkg-config = 'PKG_CONFIG'
cmake = 'CMAKE_BINARY'
glib-compile-schemas = '/usr/bin/glib-compile-schemas'
glib-compile-resources = '/usr/bin/glib-compile-resources'
[properties]
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 vsscanf(const char* __restrict s, const char* __restrict format, va_list arg);
void __fseterr(FILE* stream);
__END_DECLS
#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);
int mbtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n);
char* mkdtemp(char* _template);
char* mktemp(char* _template);
int mkstemp(char* _template);
int mkostemp(char* _template, int flags);
long mrand48(void);
long nrand48(unsigned short xsubi[3]);
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);
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
#endif

View File

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

View File

@@ -1,12 +1,8 @@
#include <BAN/Atomic.h>
#include <errno.h>
#include <fcntl.h>
#include <spawn.h>
#include <stdlib.h>
#include <string.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <unistd.h>
#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)
{
// 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();
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__; \
if (ret != (err)) \
break; \
child_status = errno; \
exit(127); \
} 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)
for (int sig = _SIGMIN; sig <= _SIGMAX; 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)
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
child_status = 0;
auto* func = do_path_resolution ? execvpe : execve;
func(path, argv, envp);
exit(127);
}
if (child_pid == -1)
{
munmap(addr, sizeof(int));
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)
*pid = child_pid;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,9 +4,10 @@
#include <dirent.h>
#include <fcntl.h>
#include <time.h>
#include <inttypes.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
static BAN::ErrorOr<long long> read_integer_from_file(const char* file)
{
@@ -63,6 +64,77 @@ static BAN::String get_battery_percentage()
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()
{
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));
}
static BAN::ErrorOr<BAN::String> get_task_bar_string()
static BAN::ErrorOr<BAN::String> get_task_bar_string(bool show_long)
{
BAN::String result;
TRY(result.append(get_cpu_load(show_long)));
TRY(result.append(get_battery_percentage()));
TRY(result.append(get_audio_volume()));
@@ -144,6 +218,12 @@ int main()
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->invalidate();
@@ -153,7 +233,7 @@ int main()
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())
return;
const auto text = text_or_error.release_value();
@@ -176,6 +256,8 @@ int main()
while (is_running)
{
window->poll_events();
update_string();
constexpr uint64_t ns_per_s = 1'000'000'000;
@@ -193,10 +275,10 @@ int main()
uint64_t sleep_ns = target_ns - current_ns;
timespec sleep_ts;
sleep_ts.tv_sec = sleep_ns / ns_per_s;
sleep_ts.tv_nsec = sleep_ns % ns_per_s;
timespec timeout_ts;
timeout_ts.tv_sec = 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)
{
*this = BAN::move(other);
initialize_no_clear(BAN::move(other));
}
~DNSEntry() { clear(); }
@@ -74,6 +74,12 @@ struct DNSEntry
DNSEntry& operator=(DNSEntry&& other)
{
clear();
initialize_no_clear(BAN::move(other));
return *this;
}
void initialize_no_clear(DNSEntry&& other)
{
valid_until = other.valid_until;
switch (type = other.type)
{
@@ -88,7 +94,6 @@ struct DNSEntry
ASSERT_NOT_REACHED();
}
other.clear();
return *this;
}
void clear()
@@ -448,6 +453,7 @@ int main(int, char**)
if (send(client.socket, &addr, sizeof(addr), 0) == -1)
dprintln("send: {}", strerror(errno));
dwarnln("{} -> {}", client.query.data(), inet_ntoa({ .s_addr = resolved->raw }));
client.close = true;
break;
}
@@ -460,14 +466,8 @@ int main(int, char**)
if (!client.query.empty())
{
static uint8_t buffer[4096];
ssize_t nrecv = recv(client.socket, buffer, sizeof(buffer), 0);
if (nrecv < 0)
dprintln("{}", strerror(errno));
if (nrecv <= 0)
client.close = true;
else
dprintln("Client already has a query");
dprintln("unexpected data from client");
client.close = true;
continue;
}
@@ -480,8 +480,11 @@ int main(int, char**)
BAN::Optional<BAN::IPv4Address> result;
// TODO: add and parse /etc/hosts
if (*hostname && strcmp(query->data(), hostname) == 0)
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())
result = resolved.release_value();