Refactor filesystem & stl code

This commit is contained in:
EnderIce2
2024-05-18 07:42:01 +03:00
parent 77a291d08b
commit 6801475243
186 changed files with 15784 additions and 9746 deletions

0
syscalls/native/.gitkeep Normal file
View File

View File

@ -1,39 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/close.html */
int sys_close(SysFrm *,
int fildes)
{
function("%d", fildes);
PCB *pcb = thisProcess;
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_close(fildes);
}

View File

@ -1,200 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <limits.h>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using vfs::RefNode;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html */
int sys_execve(SysFrm *Frame, const char *path,
char *const argv[], char *const envp[])
{
PCB *pcb = thisProcess;
Virtual vmm = Virtual(pcb->PageTable);
if (path == nullptr ||
!vmm.Check((void *)path, US) ||
!vmm.Check((void *)argv, US) ||
!vmm.Check((void *)envp, US))
return -ENOENT;
const char *safe_path;
char **safe_argv;
char **safe_envp;
safe_path = (const char *)pcb->vma->RequestPages(1);
safe_argv = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
safe_envp = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
{
SwapPT swap(pcb->PageTable);
size_t len = strlen(path);
memset((void *)safe_path, 0, PAGE_SIZE);
memcpy((void *)safe_path, path, len);
const char *arg;
char *n_arg;
for (int i = 0; argv[i] != nullptr; i++)
{
arg = argv[i];
size_t len = strlen(arg);
n_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)n_arg, arg, len);
n_arg[len] = '\0';
safe_argv[i] = n_arg;
if (likely(i < MAX_ARG - 1))
safe_argv[i + 1] = nullptr;
}
for (int i = 0; envp[i] != nullptr; i++)
{
arg = envp[i];
size_t len = strlen(arg);
n_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)n_arg, arg, len);
n_arg[len] = '\0';
safe_envp[i] = n_arg;
if (likely(i < MAX_ARG - 1))
safe_envp[i + 1] = nullptr;
}
}
function("%s %#lx %#lx", safe_path, safe_argv, safe_envp);
#ifdef DEBUG
for (int i = 0; safe_argv[i] != nullptr; i++)
debug("safe_argv[%d]: %s", i, safe_argv[i]);
for (int i = 0; safe_envp[i] != nullptr; i++)
debug("safe_envp[%d]: %s", i, safe_envp[i]);
#endif
RefNode *File = fs->Open(safe_path,
pcb->CurrentWorkingDirectory);
if (!File)
{
error("File not found");
return -ENOENT;
}
char shebang_magic[2];
File->read((uint8_t *)shebang_magic, 2);
if (shebang_magic[0] == '#' && shebang_magic[1] == '!')
{
char *orig_path = (char *)pcb->vma->RequestPages(TO_PAGES(strlen(path) + 1));
memcpy(orig_path, path, strlen(path) + 1);
char *shebang = (char *)safe_path;
size_t shebang_len = 0;
constexpr int shebang_len_max = 255;
File->seek(2, SEEK_SET);
off_t shebang_off = 2;
while (true)
{
char c;
if (File->node->read((uint8_t *)&c, 1, shebang_off) == 0)
break;
if (c == '\n' || shebang_len == shebang_len_max)
break;
shebang[shebang_len++] = c;
shebang_off++;
}
shebang[shebang_len] = '\0';
debug("Shebang: %s", shebang);
char **c_safe_argv = (char **)pcb->vma->RequestPages(TO_PAGES(MAX_ARG));
int i = 0;
for (; safe_argv[i] != nullptr; i++)
{
size_t arg_len = strlen(safe_argv[i]);
char *c_arg = (char *)pcb->vma->RequestPages(TO_PAGES(arg_len));
memcpy((void *)c_arg, safe_argv[i], arg_len);
c_arg[arg_len] = '\0';
c_safe_argv[i] = c_arg;
debug("c_safe_argv[%d]: %s", i, c_safe_argv[i]);
}
c_safe_argv[i] = nullptr;
char *token = strtok(shebang, " ");
i = 0;
while (token != nullptr)
{
size_t len = strlen(token);
char *t_arg = (char *)pcb->vma->RequestPages(TO_PAGES(len));
memcpy((void *)t_arg, token, len);
t_arg[len] = '\0';
safe_argv[i++] = t_arg;
token = strtok(nullptr, " ");
}
safe_argv[i++] = orig_path;
for (int j = 1; c_safe_argv[j] != nullptr; j++)
{
safe_argv[i++] = c_safe_argv[j];
debug("clone: safe_argv[%d]: %s",
i, safe_argv[i - 1]);
}
safe_argv[i] = nullptr;
delete File;
return sys_execve(Frame, safe_argv[0],
(char *const *)safe_argv,
(char *const *)safe_envp);
}
int ret = Execute::Spawn((char *)safe_path,
(const char **)safe_argv,
(const char **)safe_envp,
pcb->Parent, true,
pcb->Info.Compatibility);
if (ret < 0)
{
error("Failed to spawn");
delete File;
return ret;
}
delete File;
Tasking::Task *ctx = pcb->GetContext();
ctx->Sleep(1000);
pcb->SetState(Tasking::Zombie);
pcb->SetExitCode(0); /* FIXME: get process exit code */
while (true)
ctx->Yield();
__builtin_unreachable();
}

View File

@ -1,47 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::TCB;
using Tasking::TaskState::Zombie;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/exit.html */
__noreturn void sys_exit(SysFrm *, int status)
{
TCB *t = thisThread;
trace("Userspace thread %s(%d) exited with code %d (%#x)",
t->Name,
t->ID, status,
status < 0 ? -status : status);
t->SetState(Zombie);
t->SetExitCode(status);
while (true)
t->GetContext()->Yield();
__builtin_unreachable();
}

View File

@ -1,119 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using Tasking::TCB;
using Tasking::TaskState::Ready;
using namespace Memory;
void sys_fork_return()
{
#if defined(a64)
asmv("movq $0, %rax\n"); /* Return 0 */
asmv("movq %r8, %rsp\n"); /* Restore stack pointer */
asmv("movq %r8, %rbp\n"); /* Restore base pointer */
asmv("swapgs\n"); /* Swap GS back to the user GS */
asmv("sti\n"); /* Enable interrupts */
asmv("sysretq\n"); /* Return to rcx address in user mode */
#elif defined(a32)
#warning "sys_fork not implemented for i386"
#endif
__builtin_unreachable();
}
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/fork.html */
int sys_fork(SysFrm *Frame)
{
assert(Frame != nullptr);
#ifdef a32
return -ENOSYS;
#endif
PCB *Parent = thisThread->Parent;
TCB *Thread = thisThread;
PCB *NewProcess =
TaskManager->CreateProcess(Parent, Parent->Name,
Parent->Security.ExecutionMode,
true);
if (!NewProcess)
{
error("Failed to create process for fork");
return -EAGAIN;
}
NewProcess->PageTable = Parent->PageTable->Fork();
TCB *NewThread =
TaskManager->CreateThread(NewProcess,
0,
nullptr,
nullptr,
std::vector<AuxiliaryVector>(),
Thread->Info.Architecture,
Thread->Info.Compatibility,
true);
NewThread->Rename(Thread->Name);
if (!NewThread)
{
error("Failed to create thread for fork");
return -EAGAIN;
}
TaskManager->UpdateFrame();
NewThread->FPU = Thread->FPU;
NewThread->Stack->Fork(Thread->Stack);
NewThread->Info.Architecture = Thread->Info.Architecture;
NewThread->Info.Compatibility = Thread->Info.Compatibility;
NewThread->Security.IsCritical = Thread->Security.IsCritical;
NewThread->Registers = Thread->Registers;
#if defined(a64)
NewThread->Registers.rip = (uintptr_t)sys_fork_return;
/* For sysretq */
NewThread->Registers.rcx = Frame->ReturnAddress;
NewThread->Registers.r8 = Frame->StackPointer;
#endif
#ifdef a86
NewThread->GSBase = NewThread->ShadowGSBase;
NewThread->ShadowGSBase = Thread->ShadowGSBase;
NewThread->FSBase = Thread->FSBase;
#endif
debug("ret addr: %#lx, stack: %#lx ip: %#lx", Frame->ReturnAddress,
Frame->StackPointer, (uintptr_t)sys_fork_return);
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)",
Thread->Name, Thread->ID,
NewThread->Name, NewThread->ID);
NewThread->SetState(Ready);
return (int)NewProcess->ID;
}

View File

@ -1,39 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/lseek.html */
off_t sys_lseek(SysFrm *, int fildes,
off_t offset, int whence)
{
function("%d, %d, %d", fildes, offset, whence);
PCB *pcb = thisProcess;
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_lseek(fildes, offset, whence);
}

View File

@ -1,99 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/mmap.html */
void *sys_mmap(SysFrm *,
void *addr, size_t len,
int prot, int flags,
int fildes, off_t off)
{
if (len == 0)
return (void *)-EINVAL;
if (fildes != -1)
return (void *)-ENOSYS;
bool p_None = prot & sc_PROT_NONE;
bool p_Read = prot & sc_PROT_READ;
bool p_Write = prot & sc_PROT_WRITE;
bool p_Exec = prot & sc_PROT_EXEC;
bool m_Shared = flags & sc_MAP_SHARED;
bool m_Private = flags & sc_MAP_PRIVATE;
bool m_Fixed = flags & sc_MAP_FIXED;
bool m_Anon = flags & sc_MAP_ANONYMOUS;
UNUSED(p_None);
UNUSED(m_Anon);
debug("N:%d R:%d W:%d E:%d",
p_None, p_Read, p_Write,
p_Exec);
debug("S:%d P:%d F:%d A:%d",
m_Shared, m_Private,
m_Fixed, m_Anon);
int UnknownFlags = flags & ~(sc_MAP_SHARED |
sc_MAP_PRIVATE |
sc_MAP_FIXED |
sc_MAP_ANONYMOUS);
if (UnknownFlags)
{
debug("Unknown flags: %x", UnknownFlags);
return (void *)-EINVAL;
}
if (len > PAGE_SIZE_2M)
fixme("large page 2 MiB (requested %d)",
TO_MiB(len));
else if (len > PAGE_SIZE_1G)
fixme("huge page 1 GiB (requested %d)",
TO_GiB(len));
if (off % PAGE_SIZE)
return (void *)-EINVAL;
if (uintptr_t(addr) % PAGE_SIZE && m_Fixed)
return (void *)-EINVAL;
if ((m_Shared && m_Private) ||
(!m_Shared && !m_Private))
return (void *)-EINVAL;
PCB *pcb = thisProcess;
VirtualMemoryArea *vma = pcb->vma;
intptr_t ret = (intptr_t)vma->CreateCoWRegion(addr, len,
p_Read, p_Write, p_Exec,
m_Fixed, m_Shared);
return (void *)ret;
}

View File

@ -1,93 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/mprotect.html */
int sys_mprotect(SysFrm *,
void *addr, size_t len, int prot)
{
if (len == 0)
return -EINVAL;
if (uintptr_t(addr) % PAGE_SIZE)
return -EINVAL;
bool p_None = prot & sc_PROT_NONE;
bool p_Read = prot & sc_PROT_READ;
bool p_Write = prot & sc_PROT_WRITE;
// bool p_Exec = prot & sc_PROT_EXEC;
PCB *pcb = thisProcess;
Virtual vmm = Virtual(pcb->PageTable);
for (uintptr_t i = uintptr_t(addr);
i < uintptr_t(addr) + len;
i += PAGE_SIZE)
{
if (likely(!vmm.Check((void *)i, G)))
{
PageTableEntry *pte = vmm.GetPTE(addr);
if (!pte->Present ||
(!pte->UserSupervisor && p_Read) ||
(!pte->ReadWrite && p_Write))
{
debug("Page %p is not mapped with the correct permissions",
(void *)i);
return -EACCES;
}
pte->Present = p_None;
pte->UserSupervisor = p_Read;
pte->ReadWrite = p_Write;
// pte->ExecuteDisable = p_Exec;
#if defined(a64)
CPU::x64::invlpg(addr);
#elif defined(a32)
CPU::x32::invlpg(addr);
#elif defined(aa64)
asmv("dsb sy");
asmv("tlbi vae1is, %0"
:
: "r"(addr)
: "memory");
asmv("dsb sy");
asmv("isb");
#endif
}
else
{
warn("%p is a global page", (void *)i);
return -ENOMEM;
}
}
return 0;
}

View File

@ -1,60 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/munmap.html */
int sys_munmap(SysFrm *,
void *addr, size_t len)
{
if (uintptr_t(addr) % PAGE_SIZE)
return -EINVAL;
if (len == 0)
return -EINVAL;
PCB *pcb = thisProcess;
VirtualMemoryArea *vma = pcb->vma;
Virtual vmm = Virtual(pcb->PageTable);
for (uintptr_t i = uintptr_t(addr);
i < uintptr_t(addr) + len;
i += PAGE_SIZE)
{
if (likely(!vmm.Check((void *)i, G)))
vmm.Remap((void *)i, (void *)i, P | RW);
else
warn("%p is a global page", (void *)i);
}
/* TODO: Check if the page is allocated
and not only mapped */
vma->FreePages((void *)addr, TO_PAGES(len) + 1);
return 0;
}

View File

@ -1,50 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/open.html */
int sys_open(SysFrm *,
const char *path,
int oflag, mode_t mode)
{
const char *safe_path = nullptr;
PCB *pcb = thisProcess;
SmartHeap sh(512, pcb->vma);
safe_path = (const char *)sh.Get();
{
SwapPT swap(pcb->PageTable);
size_t len = strlen(path);
memcpy((void *)safe_path, path, MAX(len, size_t(511)));
}
function("%s, %d, %d", safe_path, oflag, mode);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_open(safe_path, oflag, mode);
}

View File

@ -1,54 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/read.html */
ssize_t sys_read(SysFrm *, int fildes,
void *buf, size_t nbyte)
{
void *safe_buf = nullptr;
PCB *pcb = thisProcess;
SmartHeap sh(nbyte, pcb->vma);
safe_buf = sh.Get();
function("%d, %p, %d", fildes, buf, nbyte);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
ssize_t ret = fdt->_read(fildes, safe_buf, nbyte);
if (ret >= 0)
fdt->_lseek(fildes, ret, SEEK_CUR);
else
return ret;
{
SwapPT swap(pcb->PageTable);
memcpy(buf, safe_buf, nbyte);
}
return ret;
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <utsname.h>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html */
ssize_t sys_readlink(SysFrm *, const char *path, char *buf,
size_t bufsize)
{
if (!path || !buf)
return -EINVAL;
if (bufsize > PAGE_SIZE)
{
warn("bufsize is too large: %ld", bufsize);
return -EINVAL;
}
PCB *pcb = thisProcess;
Memory::Virtual vmm(pcb->PageTable);
if (!vmm.Check((void *)buf, Memory::US))
{
warn("Invalid address %#lx", buf);
return -EFAULT;
}
const char *pPath = pcb->PageTable->Get(path);
char *pBuf = pcb->PageTable->Get(buf);
function("%s %#lx %ld", pPath, buf, bufsize);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
int fd = fdt->_open(pPath, O_RDONLY, 0);
if (fd < 0)
return -ENOENT;
vfs::FileDescriptorTable::Fildes fildes = fdt->GetDescriptor(fd);
vfs::Node *node = fildes.Handle->node;
fdt->_close(fd);
if (node->Type != vfs::NodeType::SYMLINK)
return -EINVAL;
if (!node->Symlink)
{
warn("Symlink null for \"%s\"?", pPath);
return -EINVAL;
}
size_t len = strlen(node->Symlink);
if (len > bufsize)
len = bufsize;
strncpy(pBuf, node->Symlink, len);
return len;
}

View File

@ -1,69 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <utsname.h>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/9699919799/functions/uname.html */
int sys_uname(SysFrm *, struct utsname *buf)
{
assert(sizeof(struct utsname) < PAGE_SIZE);
Tasking::PCB *pcb = thisProcess;
Memory::Virtual vmm(pcb->PageTable);
if (!vmm.Check(buf, Memory::US))
{
warn("Invalid address %#lx", buf);
return -EFAULT;
}
auto pBuf = pcb->PageTable->Get(buf);
struct utsname uname =
{
/* TODO: This shouldn't be hardcoded */
.sysname = KERNEL_NAME,
.nodename = "fennix",
.release = KERNEL_VERSION,
.version = KERNEL_VERSION,
#if defined(a64)
.machine = "x86_64",
#elif defined(a32)
.machine = "i386",
#elif defined(aa64)
.machine = "arm64",
#elif defined(aa32)
.machine = "arm",
#endif
};
memcpy(pBuf, &uname, sizeof(struct utsname));
return 0;
}

View File

@ -1,51 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <memory.hpp>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
using namespace Memory;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/write.html */
ssize_t sys_write(SysFrm *, int fildes,
const void *buf, size_t nbyte)
{
const void *safe_buf = nullptr;
PCB *pcb = thisProcess;
SmartHeap sh(nbyte, pcb->vma);
safe_buf = sh.Get();
{
SwapPT swap(pcb->PageTable);
memcpy((void *)safe_buf, buf, nbyte);
}
function("%d, %p, %d", fildes, buf, nbyte);
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
ssize_t ret = fdt->_write(fildes, safe_buf, nbyte);
if (ret)
fdt->_lseek(fildes, ret, SEEK_CUR);
return ret;
}