Compare commits

...

7 Commits

Author SHA1 Message Date
bef9158450 Kernel, libc: Add isatty() and F_ISTTY to fcntl() 2022-10-21 18:34:31 +02:00
93207820b3 libc: Add a few errors to errno.h
As well as ino_t, which I forgot in the fstat() commit :)
2022-10-21 18:34:01 +02:00
62fa773b27 libc: Add dummy argv 2022-10-21 18:33:06 +02:00
6d7a8a0d0b libc: Add very basic strtoul()
As well as returning NULL in getenv() instead of aborting.
2022-10-21 18:32:46 +02:00
bf026d0dea libc: Add bad time() function
It's just an alias for clock(). Which is not good. But it's a stub, that's the point.
2022-10-21 18:32:01 +02:00
c8a37eaf70 libc: Add SIGINT define 2022-10-21 18:31:19 +02:00
fcf191aa7a Kernel, libc: Add fstat() 2022-10-21 18:31:09 +02:00
26 changed files with 149 additions and 8 deletions

View File

@ -24,6 +24,11 @@ struct Descriptor
m_is_open = false; m_is_open = false;
} }
VFS::Node* node()
{
return m_node;
}
ssize_t read(size_t size, char* buffer); ssize_t read(size_t size, char* buffer);
ssize_t write(size_t size, const char* buffer); ssize_t write(size_t size, const char* buffer);

View File

@ -30,6 +30,7 @@ namespace VFS
node_finddir find_func; node_finddir find_func;
node_mkdir mkdir_func; node_mkdir mkdir_func;
node_write write_func; node_write write_func;
int tty = 0;
Node* link; Node* link;
}; };

View File

@ -3,6 +3,7 @@
#define EPERM 1 #define EPERM 1
#define ENOENT 2 #define ENOENT 2
#define ESRCH 3 #define ESRCH 3
#define EINTR 4
#define ENOEXEC 8 #define ENOEXEC 8
#define EBADF 9 #define EBADF 9
#define ENOMEM 12 #define ENOMEM 12
@ -12,6 +13,7 @@
#define EISDIR 21 #define EISDIR 21
#define EINVAL 22 #define EINVAL 22
#define EMFILE 24 #define EMFILE 24
#define ENOTTY 25
#define ENOSPC 28 #define ENOSPC 28
#define ENOSYS 38 #define ENOSYS 38
#define ENOTSUP 95 #define ENOTSUP 95

View File

@ -22,6 +22,9 @@
#define SYS_fork 17 #define SYS_fork 17
#define SYS_waitpid 18 #define SYS_waitpid 18
#define SYS_access 19 #define SYS_access 19
#define SYS_fstat 20
struct stat;
namespace Syscall namespace Syscall
{ {
@ -47,4 +50,5 @@ void sys_clock(Context* context);
void sys_mkdir(Context* context, const char* filename); void sys_mkdir(Context* context, const char* filename);
void sys_fork(Context* context); void sys_fork(Context* context);
void sys_waitpid(Context* context, long pid, int* wstatus, int options); void sys_waitpid(Context* context, long pid, int* wstatus, int options);
void sys_access(Context* context, const char* path, int amode); void sys_access(Context* context, const char* path, int amode);
void sys_fstat(Context* context, int fd, struct stat* buf);

View File

@ -13,6 +13,7 @@ VFS::Node* ConsoleDevice::create_new(const char* devname)
dev->length = 0; dev->length = 0;
dev->type = VFS_DEVICE; dev->type = VFS_DEVICE;
dev->flags = 0; dev->flags = 0;
dev->tty = 1;
strncpy(dev->name, devname, sizeof(dev->name)); strncpy(dev->name, devname, sizeof(dev->name));
return dev; return dev;
} }

View File

@ -19,6 +19,7 @@ VFS::Node* KeyboardDevice::create_new(const char* devname)
dev->length = 0; dev->length = 0;
dev->type = VFS_DEVICE; dev->type = VFS_DEVICE;
dev->flags = 0; dev->flags = 0;
dev->tty = 1;
strncpy(dev->name, devname, sizeof(dev->name)); strncpy(dev->name, devname, sizeof(dev->name));
return dev; return dev;
} }

View File

@ -31,7 +31,8 @@ void Syscall::entry(Context* context)
case SYS_fork: sys_fork(context); break; case SYS_fork: sys_fork(context); break;
case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break; case SYS_waitpid: sys_waitpid(context, (long)context->rdi, (int*)context->rsi, (int)context->rdx); break;
case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break; case SYS_access: sys_access(context, (const char*)context->rdi, (int)context->rsi); break;
case SYS_fstat: sys_fstat(context, (int)context->rdi, (struct stat*)context->rsi); break;
default: context->rax = -ENOSYS; break; default: context->rax = -ENOSYS; break;
} }
VMM::exit_syscall_context(); VMM::exit_syscall_context();
} }

44
kernel/src/sys/stat.cpp Normal file
View File

@ -0,0 +1,44 @@
#include "fs/VFS.h"
#include "interrupts/Context.h"
#include "std/errno.h"
#include "sys/UserMemory.h"
#include "thread/Scheduler.h"
typedef unsigned long off_t;
typedef unsigned short mode_t;
typedef unsigned long ino_t;
struct stat // FIXME: This struct is quite stubbed out.
{
ino_t st_ino;
mode_t st_mode;
off_t st_size;
};
void sys_fstat(Context* context, int fd, struct stat* buf)
{
Task* current_task = Scheduler::current_task();
if (fd < 0 || fd >= TASK_MAX_FDS)
{
context->rax = -EBADF;
return;
}
Descriptor& file = current_task->files[fd];
if (!file.is_open())
{
context->rax = -EBADF;
return;
}
struct stat* kstat = obtain_user_ref(buf);
if (!kstat)
{
context->rax = -EFAULT; // FIXME: The manual doesn't say fstat can return EFAULT, but it seems logical here...
return;
}
VFS::Node* node = file.node();
kstat->st_ino = node->inode;
kstat->st_mode = (mode_t)node->type;
kstat->st_size = node->length;
release_user_ref(kstat);
context->rax = 0;
}

View File

@ -19,7 +19,8 @@
#define SEEK_CUR 1 #define SEEK_CUR 1
#define SEEK_END 2 #define SEEK_END 2
#define FNCTL_DUPFD 0 #define FCNTL_DUPFD 0
#define FCNTL_ISTTY 1
void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
{ {
@ -35,7 +36,7 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
return; return;
} }
Descriptor& file = current_task->files[fd]; Descriptor& file = current_task->files[fd];
if (command == FNCTL_DUPFD) if (command == FCNTL_DUPFD)
{ {
if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS) if ((int)arg < 0 || (int)arg >= TASK_MAX_FDS)
{ {
@ -53,6 +54,14 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd); kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd);
return; return;
} }
else if (command == FCNTL_ISTTY)
{
VFS::Node* node = file.node();
if (node->tty) { context->rax = 1; }
else
context->rax = -ENOTTY;
return;
}
else else
{ {
context->rax = -EINVAL; context->rax = -EINVAL;

View File

@ -6,6 +6,8 @@ extern _fini
extern initialize_libc extern initialize_libc
extern exit extern exit
extern __argv
global _start global _start
_start: _start:
; Set up end of the stack frame linked list. ; Set up end of the stack frame linked list.
@ -19,7 +21,7 @@ _start:
call _init call _init
mov rdi, 0 ; argc = 0 mov rdi, 0 ; argc = 0
mov rsi, 0 ; argv = 0 mov rsi, __argv ; Dummy argv which is equal to {NULL}
call main call main

View File

@ -7,6 +7,7 @@ extern int errno;
#define EPERM 1 // Operation not permitted #define EPERM 1 // Operation not permitted
#define ENOENT 2 // No such file or directory #define ENOENT 2 // No such file or directory
#define ESRCH 3 // No such process #define ESRCH 3 // No such process
#define EINTR 4 // Interrupted system call. Not implemented.
#define ENOEXEC 8 // Exec format error #define ENOEXEC 8 // Exec format error
#define EBADF 9 // Bad file descriptor #define EBADF 9 // Bad file descriptor
#define ENOMEM 12 // Cannot allocate memory #define ENOMEM 12 // Cannot allocate memory
@ -16,6 +17,7 @@ extern int errno;
#define EISDIR 21 // Is a directory #define EISDIR 21 // Is a directory
#define EINVAL 22 // Invalid argument #define EINVAL 22 // Invalid argument
#define EMFILE 24 // Too many open files #define EMFILE 24 // Too many open files
#define ENOTTY 25 // Inappropriate ioctl for device
#define ENOSPC 28 // No space left on device #define ENOSPC 28 // No space left on device
#define EPIPE 32 // Broken pipe. Not implemented. #define EPIPE 32 // Broken pipe. Not implemented.
#define ENOSYS 38 // Function not implemented #define ENOSYS 38 // Function not implemented

View File

@ -10,6 +10,8 @@
/* Duplicate a file descriptor. */ /* Duplicate a file descriptor. */
#define F_DUPFD 0 #define F_DUPFD 0
/* Is a file descriptor a TTY? */
#define F_ISTTY 1
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"

View File

@ -0,0 +1,8 @@
#ifndef _LUNA_VFS_H
#define _LUNA_VFS_H
#define __VFS_FILE 0x0
#define __VFS_DIRECTORY 0x1
#define __VFS_DEVICE 0x2
#endif

View File

@ -1,7 +1,9 @@
#ifndef _SIGNAL_H #ifndef _SIGNAL_H
#define _SIGNAL_H #define _SIGNAL_H
typedef int sig_atomic_t; // FIXME: Implement signals (I'm trying to build bc, this header is only to satisfy it) and typedef int sig_atomic_t; // On the x86, writes to aligned 32-bit and 64-bit integers are always atomic. (Or that's what
// use a proper atomic integer type. // I understood)
#define SIGINT 1 // Not implemented.
#endif #endif

View File

@ -30,6 +30,9 @@ extern "C"
/* Returns an integer (of type long long) parsed from the string str. */ /* Returns an integer (of type long long) parsed from the string str. */
long long atoll(const char* str); long long atoll(const char* str);
/* Returns an integer (of type unsigned long) parsed from the string str. */
unsigned long strtoul(const char* str, const char** endptr, int base);
/* Not implemented. */ /* Not implemented. */
char* getenv(const char*); char* getenv(const char*);

View File

@ -1,8 +1,18 @@
#ifndef _SYS_STAT_H #ifndef _SYS_STAT_H
#define _SYS_STAT_H #define _SYS_STAT_H
#include <luna/vfs.h>
#include <sys/types.h> #include <sys/types.h>
struct stat // FIXME: This struct is quite stubbed out.
{
ino_t st_ino;
mode_t st_mode;
off_t st_size;
};
#define S_ISDIR(mode) (((mode)&0xf) == __VFS_DIRECTORY)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
@ -11,6 +21,9 @@ extern "C"
/* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */ /* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */
int mkdir(const char* pathname, mode_t mode); int mkdir(const char* pathname, mode_t mode);
/* Returns information about the file pointed to by fd in buf. */
int fstat(int fd, struct stat* buf);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -21,5 +21,6 @@
#define SYS_fork 17 #define SYS_fork 17
#define SYS_waitpid 18 #define SYS_waitpid 18
#define SYS_access 19 #define SYS_access 19
#define SYS_fstat 20
#endif #endif

View File

@ -16,4 +16,7 @@ typedef long int off_t;
/* The type of a file's mode. */ /* The type of a file's mode. */
typedef unsigned short mode_t; typedef unsigned short mode_t;
/* The type of a filesystem inode. */
typedef unsigned long ino_t;
#endif #endif

View File

@ -15,6 +15,9 @@ extern "C"
* get the value in seconds. */ * get the value in seconds. */
clock_t clock(void); clock_t clock(void);
/* FIXME: For now, is an alias for clock(), but in seconds. */
time_t time(time_t* tloc);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -66,6 +66,9 @@ extern "C"
/* Checks if the current program can access the file or directory at path. */ /* Checks if the current program can access the file or directory at path. */
int access(const char* path, int amode); int access(const char* path, int amode);
/* Checks if the file descriptor fd refers to a terminal. */
int isatty(int fd);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -4,6 +4,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
__attribute__((used)) const char* __argv[] = {NULL}; // For now.
static void terminate_libc() static void terminate_libc()
{ {
fclose(stdout); fclose(stdout);

View File

@ -46,9 +46,16 @@ extern "C"
return string_to_integer_type<long long>(str); return string_to_integer_type<long long>(str);
} }
unsigned long strtoul(const char* str, const char** endptr, int base)
{
if (base != 0 && base != 10) NOT_IMPLEMENTED("strtoul with base not in (0,10)");
if (endptr) NOT_IMPLEMENTED("strtoul with non-null endptr");
return string_to_integer_type<unsigned long>(str);
}
char* getenv(const char*) char* getenv(const char*)
{ {
NOT_IMPLEMENTED("getenv"); return NULL; // Not implemented :)
} }
__lc_noreturn void _Exit(int status) __lc_noreturn void _Exit(int status)

View File

@ -8,4 +8,9 @@ extern "C"
{ {
return (int)syscall(SYS_mkdir, pathname); return (int)syscall(SYS_mkdir, pathname);
} }
int fstat(int fd, struct stat* buf)
{
return (int)syscall(SYS_fstat, fd, buf);
}
} }

View File

@ -23,6 +23,7 @@ extern "C" long syscall(long number, ...)
case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break; case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break;
case SYS_munmap: case SYS_munmap:
case SYS_access: case SYS_access:
case SYS_fstat:
case SYS_open: { case SYS_open: {
arg arg0 = va_arg(ap, arg); arg arg0 = va_arg(ap, arg);
arg arg1 = va_arg(ap, arg); arg arg1 = va_arg(ap, arg);

View File

@ -8,4 +8,13 @@ extern "C"
{ {
return syscall(SYS_clock); return syscall(SYS_clock);
} }
time_t time(
time_t* tloc) // Very big FIXME: This is not the time of day, this just returns the same as clock() but in
// seconds. This is definitely wrong, but I'm not implementing a whole time system right now.
{
time_t result = (time_t)(syscall(SYS_clock) / CLOCKS_PER_SEC);
if (tloc) { *tloc = result; }
return result;
}
} }

View File

@ -74,4 +74,11 @@ extern "C"
{ {
return (int)syscall(SYS_access, path, amode); return (int)syscall(SYS_access, path, amode);
} }
int isatty(int fd)
{
int result = fcntl(fd, F_ISTTY);
if (result < 0) return 0;
return 1;
}
} }