Compare commits
7 Commits
0720b3245b
...
bef9158450
Author | SHA1 | Date | |
---|---|---|---|
bef9158450 | |||
93207820b3 | |||
62fa773b27 | |||
6d7a8a0d0b | |||
bf026d0dea | |||
c8a37eaf70 | |||
fcf191aa7a |
@ -24,6 +24,11 @@ struct Descriptor
|
||||
m_is_open = false;
|
||||
}
|
||||
|
||||
VFS::Node* node()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
ssize_t read(size_t size, char* buffer);
|
||||
ssize_t write(size_t size, const char* buffer);
|
||||
|
||||
|
@ -30,6 +30,7 @@ namespace VFS
|
||||
node_finddir find_func;
|
||||
node_mkdir mkdir_func;
|
||||
node_write write_func;
|
||||
int tty = 0;
|
||||
Node* link;
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define EPERM 1
|
||||
#define ENOENT 2
|
||||
#define ESRCH 3
|
||||
#define EINTR 4
|
||||
#define ENOEXEC 8
|
||||
#define EBADF 9
|
||||
#define ENOMEM 12
|
||||
@ -12,6 +13,7 @@
|
||||
#define EISDIR 21
|
||||
#define EINVAL 22
|
||||
#define EMFILE 24
|
||||
#define ENOTTY 25
|
||||
#define ENOSPC 28
|
||||
#define ENOSYS 38
|
||||
#define ENOTSUP 95
|
@ -22,6 +22,9 @@
|
||||
#define SYS_fork 17
|
||||
#define SYS_waitpid 18
|
||||
#define SYS_access 19
|
||||
#define SYS_fstat 20
|
||||
|
||||
struct stat;
|
||||
|
||||
namespace Syscall
|
||||
{
|
||||
@ -47,4 +50,5 @@ void sys_clock(Context* context);
|
||||
void sys_mkdir(Context* context, const char* filename);
|
||||
void sys_fork(Context* context);
|
||||
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);
|
||||
|
@ -13,6 +13,7 @@ VFS::Node* ConsoleDevice::create_new(const char* devname)
|
||||
dev->length = 0;
|
||||
dev->type = VFS_DEVICE;
|
||||
dev->flags = 0;
|
||||
dev->tty = 1;
|
||||
strncpy(dev->name, devname, sizeof(dev->name));
|
||||
return dev;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ VFS::Node* KeyboardDevice::create_new(const char* devname)
|
||||
dev->length = 0;
|
||||
dev->type = VFS_DEVICE;
|
||||
dev->flags = 0;
|
||||
dev->tty = 1;
|
||||
strncpy(dev->name, devname, sizeof(dev->name));
|
||||
return dev;
|
||||
}
|
||||
|
@ -31,7 +31,8 @@ void Syscall::entry(Context* context)
|
||||
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_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;
|
||||
}
|
||||
VMM::exit_syscall_context();
|
||||
}
|
||||
}
|
||||
|
44
kernel/src/sys/stat.cpp
Normal file
44
kernel/src/sys/stat.cpp
Normal 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;
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
#define SEEK_CUR 1
|
||||
#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)
|
||||
{
|
||||
@ -35,7 +36,7 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg)
|
||||
return;
|
||||
}
|
||||
Descriptor& file = current_task->files[fd];
|
||||
if (command == FNCTL_DUPFD)
|
||||
if (command == FCNTL_DUPFD)
|
||||
{
|
||||
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);
|
||||
return;
|
||||
}
|
||||
else if (command == FCNTL_ISTTY)
|
||||
{
|
||||
VFS::Node* node = file.node();
|
||||
if (node->tty) { context->rax = 1; }
|
||||
else
|
||||
context->rax = -ENOTTY;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->rax = -EINVAL;
|
||||
|
@ -6,6 +6,8 @@ extern _fini
|
||||
extern initialize_libc
|
||||
extern exit
|
||||
|
||||
extern __argv
|
||||
|
||||
global _start
|
||||
_start:
|
||||
; Set up end of the stack frame linked list.
|
||||
@ -19,7 +21,7 @@ _start:
|
||||
call _init
|
||||
|
||||
mov rdi, 0 ; argc = 0
|
||||
mov rsi, 0 ; argv = 0
|
||||
mov rsi, __argv ; Dummy argv which is equal to {NULL}
|
||||
|
||||
call main
|
||||
|
||||
|
@ -7,6 +7,7 @@ extern int errno;
|
||||
#define EPERM 1 // Operation not permitted
|
||||
#define ENOENT 2 // No such file or directory
|
||||
#define ESRCH 3 // No such process
|
||||
#define EINTR 4 // Interrupted system call. Not implemented.
|
||||
#define ENOEXEC 8 // Exec format error
|
||||
#define EBADF 9 // Bad file descriptor
|
||||
#define ENOMEM 12 // Cannot allocate memory
|
||||
@ -16,6 +17,7 @@ extern int errno;
|
||||
#define EISDIR 21 // Is a directory
|
||||
#define EINVAL 22 // Invalid argument
|
||||
#define EMFILE 24 // Too many open files
|
||||
#define ENOTTY 25 // Inappropriate ioctl for device
|
||||
#define ENOSPC 28 // No space left on device
|
||||
#define EPIPE 32 // Broken pipe. Not implemented.
|
||||
#define ENOSYS 38 // Function not implemented
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
/* Duplicate a file descriptor. */
|
||||
#define F_DUPFD 0
|
||||
/* Is a file descriptor a TTY? */
|
||||
#define F_ISTTY 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
8
libs/libc/include/luna/vfs.h
Normal file
8
libs/libc/include/luna/vfs.h
Normal 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
|
@ -1,7 +1,9 @@
|
||||
#ifndef _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
|
||||
// use a proper atomic integer type.
|
||||
typedef int sig_atomic_t; // On the x86, writes to aligned 32-bit and 64-bit integers are always atomic. (Or that's what
|
||||
// I understood)
|
||||
|
||||
#define SIGINT 1 // Not implemented.
|
||||
|
||||
#endif
|
@ -30,6 +30,9 @@ extern "C"
|
||||
/* Returns an integer (of type long long) parsed from the string 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. */
|
||||
char* getenv(const char*);
|
||||
|
||||
|
@ -1,8 +1,18 @@
|
||||
#ifndef _SYS_STAT_H
|
||||
#define _SYS_STAT_H
|
||||
|
||||
#include <luna/vfs.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
|
||||
extern "C"
|
||||
{
|
||||
@ -11,6 +21,9 @@ extern "C"
|
||||
/* Creates a new directory at the path pathname. FIXME: For now, mode is ignored. */
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
@ -21,5 +21,6 @@
|
||||
#define SYS_fork 17
|
||||
#define SYS_waitpid 18
|
||||
#define SYS_access 19
|
||||
#define SYS_fstat 20
|
||||
|
||||
#endif
|
@ -16,4 +16,7 @@ typedef long int off_t;
|
||||
/* The type of a file's mode. */
|
||||
typedef unsigned short mode_t;
|
||||
|
||||
/* The type of a filesystem inode. */
|
||||
typedef unsigned long ino_t;
|
||||
|
||||
#endif
|
@ -15,6 +15,9 @@ extern "C"
|
||||
* get the value in seconds. */
|
||||
clock_t clock(void);
|
||||
|
||||
/* FIXME: For now, is an alias for clock(), but in seconds. */
|
||||
time_t time(time_t* tloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -66,6 +66,9 @@ extern "C"
|
||||
/* Checks if the current program can access the file or directory at path. */
|
||||
int access(const char* path, int amode);
|
||||
|
||||
/* Checks if the file descriptor fd refers to a terminal. */
|
||||
int isatty(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
__attribute__((used)) const char* __argv[] = {NULL}; // For now.
|
||||
|
||||
static void terminate_libc()
|
||||
{
|
||||
fclose(stdout);
|
||||
|
@ -46,9 +46,16 @@ extern "C"
|
||||
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*)
|
||||
{
|
||||
NOT_IMPLEMENTED("getenv");
|
||||
return NULL; // Not implemented :)
|
||||
}
|
||||
|
||||
__lc_noreturn void _Exit(int status)
|
||||
|
@ -8,4 +8,9 @@ extern "C"
|
||||
{
|
||||
return (int)syscall(SYS_mkdir, pathname);
|
||||
}
|
||||
|
||||
int fstat(int fd, struct stat* buf)
|
||||
{
|
||||
return (int)syscall(SYS_fstat, fd, buf);
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ extern "C" long syscall(long number, ...)
|
||||
case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break;
|
||||
case SYS_munmap:
|
||||
case SYS_access:
|
||||
case SYS_fstat:
|
||||
case SYS_open: {
|
||||
arg arg0 = va_arg(ap, arg);
|
||||
arg arg1 = va_arg(ap, arg);
|
||||
|
@ -8,4 +8,13 @@ extern "C"
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
@ -74,4 +74,11 @@ extern "C"
|
||||
{
|
||||
return (int)syscall(SYS_access, path, amode);
|
||||
}
|
||||
|
||||
int isatty(int fd)
|
||||
{
|
||||
int result = fcntl(fd, F_ISTTY);
|
||||
if (result < 0) return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user