VFS mount/umount + sys_open/close/read/fake write
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#define PROCESS_NAME_MAX 64
|
#define PROCESS_NAME_MAX 64
|
||||||
#define PROCESS_STACK_SIZE 0x10000 // 64kb
|
#define PROCESS_STACK_SIZE 0x10000 // 64kb
|
||||||
#define PROCESS_STACK_TOP 0x80000000
|
#define PROCESS_STACK_TOP 0x80000000
|
||||||
|
#define PROCESS_FD_MAX 32
|
||||||
|
|
||||||
/* sched */
|
/* sched */
|
||||||
// 1 tick = 1 ms => quantum = 10ms
|
// 1 tick = 1 ms => quantum = 10ms
|
||||||
@@ -47,6 +48,7 @@
|
|||||||
|
|
||||||
/* fs */
|
/* fs */
|
||||||
#define CALYXFS_FILES_MAX 10
|
#define CALYXFS_FILES_MAX 10
|
||||||
|
#define TAR_OPEN_FILES_MAX 64
|
||||||
|
|
||||||
/* paging */
|
/* paging */
|
||||||
#define PAGING_MAX_PHYS 0x200000000
|
#define PAGING_MAX_PHYS 0x200000000
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
struct tar_header
|
struct tar_header
|
||||||
{
|
{
|
||||||
@@ -33,4 +34,9 @@ int tar_init_fs(struct limine_file* file);
|
|||||||
struct tar_header* tar_file_lookup(const char* filename);
|
struct tar_header* tar_file_lookup(const char* filename);
|
||||||
void tar_file_read(struct tar_header* header, uint8_t* buf);
|
void tar_file_read(struct tar_header* header, uint8_t* buf);
|
||||||
|
|
||||||
|
int tar_open(const char* path, int flags);
|
||||||
|
int tar_close(int fd);
|
||||||
|
int64_t tar_read(int fd, char* buf, size_t count);
|
||||||
|
int64_t tar_write(int fd, char* buf, size_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Virtual filesystem layer
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
PepperOS will not work like the Unix-based mountpoint approach,
|
||||||
|
but rather like what Windows does. Filesystems will be separated
|
||||||
|
into "drives", and each drive will have a number assigned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VFS_H
|
||||||
|
#define VFS_H
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DRIVE_TAR
|
||||||
|
} DriveType;
|
||||||
|
|
||||||
|
struct drive
|
||||||
|
{
|
||||||
|
unsigned int id;
|
||||||
|
DriveType type;
|
||||||
|
struct fs_operations* operations;
|
||||||
|
|
||||||
|
struct drive* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fs_operations
|
||||||
|
{
|
||||||
|
int (*open)(const char* path, int flags);
|
||||||
|
int (*close)(int fd);
|
||||||
|
int64_t (*read)(int fd, char* buf, size_t count);
|
||||||
|
int64_t (*write)(int fd, char* buf, size_t count);
|
||||||
|
};
|
||||||
|
|
||||||
|
int vfs_mount(struct limine_file* file, DriveType type);
|
||||||
|
int vfs_umount(unsigned int drive_id);
|
||||||
|
|
||||||
|
int vfs_open(const char* path, int flags);
|
||||||
|
int vfs_close(int fd);
|
||||||
|
int64_t vfs_read(int fd, char* buf, size_t count);
|
||||||
|
int64_t vfs_write(int fd, const char* buf, size_t count);
|
||||||
|
|
||||||
|
#endif
|
||||||
+7
-1
@@ -10,7 +10,13 @@
|
|||||||
#include "limine.h"
|
#include "limine.h"
|
||||||
enum ErrorCodes {
|
enum ErrorCodes {
|
||||||
ENOMEM,
|
ENOMEM,
|
||||||
EIO
|
EIO,
|
||||||
|
EINVAL,
|
||||||
|
ENOENT,
|
||||||
|
EFAULT,
|
||||||
|
EBADF,
|
||||||
|
EBUSY,
|
||||||
|
ENOSYS
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLEAR_INTERRUPTS __asm__ volatile("cli")
|
#define CLEAR_INTERRUPTS __asm__ volatile("cli")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
READY,
|
READY,
|
||||||
@@ -18,6 +19,12 @@ typedef enum {
|
|||||||
DEAD
|
DEAD
|
||||||
} status_t;
|
} status_t;
|
||||||
|
|
||||||
|
struct process_fd {
|
||||||
|
bool used;
|
||||||
|
unsigned int drive_id;
|
||||||
|
int fs_fd;
|
||||||
|
};
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
size_t pid;
|
size_t pid;
|
||||||
char name[PROCESS_NAME_MAX];
|
char name[PROCESS_NAME_MAX];
|
||||||
@@ -26,6 +33,7 @@ struct process {
|
|||||||
struct cpu_status* context;
|
struct cpu_status* context;
|
||||||
void* root_page_table; // Process PML4 (should contain kernel PML4 in higher half [256-511]
|
void* root_page_table; // Process PML4 (should contain kernel PML4 in higher half [256-511]
|
||||||
void* kernel_stack; // Used for interrupts (syscall: int 0x80), defines the TSS RSP0
|
void* kernel_stack; // Used for interrupts (syscall: int 0x80), defines the TSS RSP0
|
||||||
|
struct process_fd fds[PROCESS_FD_MAX];
|
||||||
struct process* next;
|
struct process* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,4 +48,9 @@ void process_display_list(struct process* processes_list);
|
|||||||
|
|
||||||
void process_create_user(struct limine_file* file, char* name);
|
void process_create_user(struct limine_file* file, char* name);
|
||||||
|
|
||||||
|
void process_fd_init(struct process* proc);
|
||||||
|
int process_fd_alloc(struct process* proc, unsigned int drive_id, int fs_fd);
|
||||||
|
int process_fd_get_fsfd(struct process* proc, int fd, unsigned int* drive_id, int* fs_fd);
|
||||||
|
int process_fd_release(struct process* proc, int fd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+31
-4
@@ -10,26 +10,45 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <io/term/term.h>
|
#include <io/term/term.h>
|
||||||
#include <sched/process.h>
|
#include <sched/process.h>
|
||||||
|
#include <fs/vfs.h>
|
||||||
|
|
||||||
extern struct process* current_process;
|
extern struct process* current_process;
|
||||||
|
|
||||||
void sys_write(unsigned int fd, const char* buf, size_t count)
|
int64_t sys_read(unsigned int fd, char* buf, size_t count)
|
||||||
|
{
|
||||||
|
return vfs_read((int)fd, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t sys_write(unsigned int fd, const char* buf, size_t count)
|
||||||
{
|
{
|
||||||
switch (fd) {
|
switch (fd) {
|
||||||
case 1: //stdout
|
case 1: //stdout
|
||||||
for (size_t i=0; i<count; i++) {
|
for (size_t i=0; i<count; i++) {
|
||||||
internal_putc(buf[i], NULL);
|
internal_putc(buf[i], NULL);
|
||||||
}
|
}
|
||||||
break;
|
return (int64_t)count;
|
||||||
|
|
||||||
case 2: //stderr
|
case 2: //stderr
|
||||||
for (size_t i=0; i<count; i++) {
|
for (size_t i=0; i<count; i++) {
|
||||||
internal_putc(buf[i], NULL);
|
internal_putc(buf[i], NULL);
|
||||||
}
|
}
|
||||||
break;
|
return (int64_t)count;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return vfs_write((int)fd, buf, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t sys_open(const char* path, int flags)
|
||||||
|
{
|
||||||
|
return vfs_open(path, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t sys_close(unsigned int fd)
|
||||||
|
{
|
||||||
|
return vfs_close((int)fd);
|
||||||
|
}
|
||||||
|
|
||||||
void sys_exit(int error_code)
|
void sys_exit(int error_code)
|
||||||
{
|
{
|
||||||
current_process->status = DEAD;
|
current_process->status = DEAD;
|
||||||
@@ -61,12 +80,20 @@ struct cpu_status* syscall_handler(struct cpu_status* regs)
|
|||||||
switch (regs->rax)
|
switch (regs->rax)
|
||||||
{
|
{
|
||||||
case 0: //sys_read
|
case 0: //sys_read
|
||||||
|
regs->rax = (uint64_t)sys_read((unsigned int)regs->rdi, (char*)regs->rsi, (size_t)regs->rdx);
|
||||||
break;
|
break;
|
||||||
case 1: //sys_write
|
case 1: //sys_write
|
||||||
sys_write(regs->rdi, (char*)regs->rsi, regs->rdx);
|
regs->rax = (uint64_t)sys_write((unsigned int)regs->rdi, (const char*)regs->rsi, (size_t)regs->rdx);
|
||||||
|
break;
|
||||||
|
case 2: //sys_open
|
||||||
|
regs->rax = (uint64_t)sys_open((const char*)regs->rdi, (int)regs->rsi);
|
||||||
|
break;
|
||||||
|
case 3: //sys_close
|
||||||
|
regs->rax = (uint64_t)sys_close((unsigned int)regs->rdi);
|
||||||
break;
|
break;
|
||||||
case 60: //sys_exit
|
case 60: //sys_exit
|
||||||
sys_exit(regs->rdi);
|
sys_exit(regs->rdi);
|
||||||
|
regs->rax = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
regs->rax = 0xbad515ca11;
|
regs->rax = 0xbad515ca11;
|
||||||
|
|||||||
+113
@@ -25,6 +25,14 @@
|
|||||||
|
|
||||||
struct tar_header* headers[CALYXFS_FILES_MAX] = {0};
|
struct tar_header* headers[CALYXFS_FILES_MAX] = {0};
|
||||||
|
|
||||||
|
struct tar_open_file {
|
||||||
|
bool used;
|
||||||
|
struct tar_header* header;
|
||||||
|
size_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tar_open_file open_files[TAR_OPEN_FILES_MAX] = {0};
|
||||||
|
|
||||||
struct tar_file archive;
|
struct tar_file archive;
|
||||||
|
|
||||||
#define TAR_BLOCK_SIZE 512
|
#define TAR_BLOCK_SIZE 512
|
||||||
@@ -101,6 +109,7 @@ int tar_init_fs(struct limine_file* file)
|
|||||||
DEBUG("calyxfs found at 0x%p (size=%u)", file->address, file->size);
|
DEBUG("calyxfs found at 0x%p (size=%u)", file->address, file->size);
|
||||||
archive.address = file->address;
|
archive.address = file->address;
|
||||||
archive.size = file->size;
|
archive.size = file->size;
|
||||||
|
memset(open_files, 0, sizeof(open_files));
|
||||||
tar_parse((uint64_t)archive.address);
|
tar_parse((uint64_t)archive.address);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -179,4 +188,108 @@ void tar_file_read(struct tar_header* header, uint8_t* buf)
|
|||||||
void* file_ptr = (void*)((uint8_t*)header + TAR_BLOCK_SIZE);
|
void* file_ptr = (void*)((uint8_t*)header + TAR_BLOCK_SIZE);
|
||||||
|
|
||||||
memcpy(buf, (void*)file_ptr, sz);
|
memcpy(buf, (void*)file_ptr, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_open(const char* path, int flags)
|
||||||
|
{
|
||||||
|
if (!path) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags != 0) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* lookup_path = path;
|
||||||
|
while (*lookup_path == '/') {
|
||||||
|
lookup_path++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*lookup_path == '\0') {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tar_header* header = tar_file_lookup(lookup_path);
|
||||||
|
if (!header) {
|
||||||
|
char prefixed[102] = {0};
|
||||||
|
prefixed[0] = '.';
|
||||||
|
prefixed[1] = '/';
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (lookup_path[i] != '\0' && i < sizeof(prefixed) - 3) {
|
||||||
|
prefixed[2 + i] = lookup_path[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
prefixed[2 + i] = '\0';
|
||||||
|
|
||||||
|
header = tar_file_lookup(prefixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!header) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int fd = 0; fd < TAR_OPEN_FILES_MAX; fd++) {
|
||||||
|
if (!open_files[fd].used) {
|
||||||
|
open_files[fd].used = true;
|
||||||
|
open_files[fd].header = header;
|
||||||
|
open_files[fd].offset = 0;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tar_close(int fd)
|
||||||
|
{
|
||||||
|
if (fd < 0 || fd >= TAR_OPEN_FILES_MAX) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open_files[fd].used) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
open_files[fd].used = false;
|
||||||
|
open_files[fd].header = NULL;
|
||||||
|
open_files[fd].offset = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t tar_read(int fd, char* buf, size_t count)
|
||||||
|
{
|
||||||
|
if (!buf || fd < 0 || fd >= TAR_OPEN_FILES_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!open_files[fd].used || !open_files[fd].header) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t file_size = tar_getsize(open_files[fd].header->size);
|
||||||
|
if (open_files[fd].offset >= file_size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remaining = (size_t)file_size - open_files[fd].offset;
|
||||||
|
size_t read_count = (count < remaining) ? count : remaining;
|
||||||
|
|
||||||
|
uint8_t* file_ptr = (uint8_t*)open_files[fd].header + TAR_BLOCK_SIZE + open_files[fd].offset;
|
||||||
|
memcpy(buf, file_ptr, read_count);
|
||||||
|
open_files[fd].offset += read_count;
|
||||||
|
return (int64_t)read_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tar_write - Write to file in TAR archive
|
||||||
|
*
|
||||||
|
* Not implemented.
|
||||||
|
*/
|
||||||
|
int64_t tar_write(int fd, char* buf, size_t count)
|
||||||
|
{
|
||||||
|
(void)fd;
|
||||||
|
(void)buf;
|
||||||
|
(void)count;
|
||||||
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
+308
-1
@@ -13,4 +13,311 @@ filesystem-dependent functions.
|
|||||||
|
|
||||||
That way we have a nice abstraction layer and can just do calls no matter
|
That way we have a nice abstraction layer and can just do calls no matter
|
||||||
the underlying fs.
|
the underlying fs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fs/tar.h>
|
||||||
|
#include <fs/vfs.h>
|
||||||
|
#include <mem/kheap.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <sched/process.h>
|
||||||
|
#include <string/string.h>
|
||||||
|
|
||||||
|
extern struct process* current_process;
|
||||||
|
|
||||||
|
struct drive* root_drive;
|
||||||
|
|
||||||
|
// Bump-allocated (much like PIDs)
|
||||||
|
unsigned int next_drive_id = 0;
|
||||||
|
|
||||||
|
static struct drive* vfs_find_drive(unsigned int drive_id)
|
||||||
|
{
|
||||||
|
struct drive* curr = root_drive;
|
||||||
|
while (curr != NULL) {
|
||||||
|
if (curr->id == drive_id) {
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vfs_resolve_path(const char* path, struct drive** drive, const char** inner_path)
|
||||||
|
{
|
||||||
|
if (!path || !drive || !inner_path) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path[0] >= '0' && path[0] <= '9') {
|
||||||
|
unsigned int drive_id = 0;
|
||||||
|
size_t idx = 0;
|
||||||
|
|
||||||
|
while (path[idx] >= '0' && path[idx] <= '9') {
|
||||||
|
drive_id = (drive_id * 10) + (unsigned int)(path[idx] - '0');
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path[idx] != ':' || path[idx + 1] != '/') {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*drive = vfs_find_drive(drive_id);
|
||||||
|
if (*drive == NULL) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*inner_path = &path[idx + 1];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root_drive == NULL) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*drive = root_drive;
|
||||||
|
*inner_path = path;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vfs_add_drive - Add a drive to the drive list
|
||||||
|
* @new: the new drive
|
||||||
|
*
|
||||||
|
* This function adds the @new drive at the end
|
||||||
|
* of the drive linked list.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* %0 - on success
|
||||||
|
*/
|
||||||
|
int vfs_add_drive(struct drive* new)
|
||||||
|
{
|
||||||
|
if (root_drive == NULL) {
|
||||||
|
root_drive = new;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
struct drive* curr = root_drive;
|
||||||
|
while (curr->next != NULL) {
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->next = new;
|
||||||
|
new->next = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vfs_mount - Mount a drive
|
||||||
|
* @file: Limine-loaded module file
|
||||||
|
* @type: Filesystem type
|
||||||
|
*
|
||||||
|
* This function creates a new drive object and then adds
|
||||||
|
* it to the drive linked list. It also initializes the
|
||||||
|
* filesystem driver corresponding to the drive type.
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* %0 - on success
|
||||||
|
* %-ENOMEM - not enough memory
|
||||||
|
*/
|
||||||
|
int vfs_mount(struct limine_file* file, DriveType type)
|
||||||
|
{
|
||||||
|
struct fs_operations* ops = NULL;
|
||||||
|
struct drive* new = kmalloc(sizeof(struct drive));
|
||||||
|
if (new == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
new->id = next_drive_id++;
|
||||||
|
new->type = type;
|
||||||
|
new->operations = NULL;
|
||||||
|
new->next = NULL;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DRIVE_TAR:
|
||||||
|
if (tar_init_fs(file) < 0) {
|
||||||
|
kfree(new);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ops = kmalloc(sizeof(struct fs_operations));
|
||||||
|
if (ops == NULL) {
|
||||||
|
kfree(new);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ops->open = tar_open;
|
||||||
|
ops->close = tar_close;
|
||||||
|
ops->read = tar_read;
|
||||||
|
ops->write = tar_write;
|
||||||
|
new->operations = ops;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kfree(new);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vfs_add_drive(new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vfs_remove_drive - Remove a drive from the drive list
|
||||||
|
* @old: Drive to remove
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* %0 - on success
|
||||||
|
*/
|
||||||
|
int vfs_remove_drive(struct drive* old)
|
||||||
|
{
|
||||||
|
if (!old || !root_drive) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root_drive == old) {
|
||||||
|
root_drive = old->next;
|
||||||
|
old->next = NULL;
|
||||||
|
if (old->operations) {
|
||||||
|
kfree(old->operations);
|
||||||
|
}
|
||||||
|
kfree(old);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drive* tmp = root_drive;
|
||||||
|
while (tmp->next != NULL && tmp->next != old) {
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp->next == NULL) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next is the one to remove
|
||||||
|
tmp->next = old->next;
|
||||||
|
old->next = NULL;
|
||||||
|
if (old->operations) {
|
||||||
|
kfree(old->operations);
|
||||||
|
}
|
||||||
|
kfree(old);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vfs_umount - Unmount a drive
|
||||||
|
* @drive_id: drive ID to unmount
|
||||||
|
*
|
||||||
|
* Return:
|
||||||
|
* %0 - on success
|
||||||
|
* %-ENOENT - drive not found
|
||||||
|
*/
|
||||||
|
int vfs_umount(unsigned int drive_id)
|
||||||
|
{
|
||||||
|
struct drive* tmp = root_drive;
|
||||||
|
while (tmp != NULL) {
|
||||||
|
if (tmp->id == drive_id) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
found:
|
||||||
|
return vfs_remove_drive(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_open(const char* path, int flags)
|
||||||
|
{
|
||||||
|
struct drive* drive = NULL;
|
||||||
|
const char* inner_path = NULL;
|
||||||
|
|
||||||
|
if (!current_process) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rc = vfs_resolve_path(path, &drive, &inner_path);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drive->operations || !drive->operations->open) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fs_fd = drive->operations->open(inner_path, flags);
|
||||||
|
if (fs_fd < 0) {
|
||||||
|
return fs_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int proc_fd = process_fd_alloc(current_process, drive->id, fs_fd);
|
||||||
|
if (proc_fd < 0) {
|
||||||
|
drive->operations->close(fs_fd);
|
||||||
|
return proc_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proc_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfs_close(int fd)
|
||||||
|
{
|
||||||
|
if (!current_process) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int drive_id = 0;
|
||||||
|
int fs_fd = -1;
|
||||||
|
int rc = process_fd_get_fsfd(current_process, fd, &drive_id, &fs_fd);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drive* drive = vfs_find_drive(drive_id);
|
||||||
|
if (!drive || !drive->operations || !drive->operations->close) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = drive->operations->close(fs_fd);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return process_fd_release(current_process, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t vfs_read(int fd, char* buf, size_t count)
|
||||||
|
{
|
||||||
|
if (!current_process || !buf) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int drive_id = 0;
|
||||||
|
int fs_fd = -1;
|
||||||
|
int rc = process_fd_get_fsfd(current_process, fd, &drive_id, &fs_fd);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drive* drive = vfs_find_drive(drive_id);
|
||||||
|
if (!drive || !drive->operations || !drive->operations->read) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int64_t)drive->operations->read(fs_fd, buf, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t vfs_write(int fd, const char* buf, size_t count)
|
||||||
|
{
|
||||||
|
if (!current_process || !buf) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int drive_id = 0;
|
||||||
|
int fs_fd = -1;
|
||||||
|
int rc = process_fd_get_fsfd(current_process, fd, &drive_id, &fs_fd);
|
||||||
|
if (rc < 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drive* drive = vfs_find_drive(drive_id);
|
||||||
|
if (!drive || !drive->operations || !drive->operations->write) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int64_t)drive->operations->write(fs_fd, (char*)buf, count);
|
||||||
|
}
|
||||||
+1
-6
@@ -4,6 +4,7 @@
|
|||||||
* @license GPL-3.0-only
|
* @license GPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fs/vfs.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
@@ -125,14 +126,8 @@ void kmain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
file = boot_ctx.module->modules[0];
|
file = boot_ctx.module->modules[0];
|
||||||
tar_init_fs(file);
|
|
||||||
|
|
||||||
/* DANGER ZONE (tests)*/
|
/* DANGER ZONE (tests)*/
|
||||||
struct tar_header* header = tar_file_lookup("./welcome.txt");
|
|
||||||
|
|
||||||
uint8_t buf[1000] = {0};
|
|
||||||
tar_file_read(header, buf);
|
|
||||||
DEBUG("-BEGIN BUFFER-%s-END BUFFER-", buf);
|
|
||||||
/* END DANGER ZONE */
|
/* END DANGER ZONE */
|
||||||
|
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
|||||||
@@ -26,6 +26,64 @@ extern uint64_t *kernel_pml4;
|
|||||||
|
|
||||||
size_t next_free_pid = 0;
|
size_t next_free_pid = 0;
|
||||||
|
|
||||||
|
void process_fd_init(struct process* proc)
|
||||||
|
{
|
||||||
|
if (!proc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(proc->fds, 0, sizeof(proc->fds));
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_fd_alloc(struct process* proc, unsigned int drive_id, int fs_fd)
|
||||||
|
{
|
||||||
|
if (!proc || fs_fd < 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int fd = 3; fd < PROCESS_FD_MAX; fd++) {
|
||||||
|
if (!proc->fds[fd].used) {
|
||||||
|
proc->fds[fd].used = true;
|
||||||
|
proc->fds[fd].drive_id = drive_id;
|
||||||
|
proc->fds[fd].fs_fd = fs_fd;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_fd_get_fsfd(struct process* proc, int fd, unsigned int* drive_id, int* fs_fd)
|
||||||
|
{
|
||||||
|
if (!proc || !drive_id || !fs_fd || fd < 0 || fd >= PROCESS_FD_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!proc->fds[fd].used) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
*drive_id = proc->fds[fd].drive_id;
|
||||||
|
*fs_fd = proc->fds[fd].fs_fd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_fd_release(struct process* proc, int fd)
|
||||||
|
{
|
||||||
|
if (!proc || fd < 0 || fd >= PROCESS_FD_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!proc->fds[fd].used) {
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->fds[fd].used = false;
|
||||||
|
proc->fds[fd].drive_id = 0;
|
||||||
|
proc->fds[fd].fs_fd = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process_init - Initializes process list
|
* process_init - Initializes process list
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +158,8 @@ struct process* process_create(char* name, void(*function)(void*), void* arg)
|
|||||||
|
|
||||||
proc->kernel_stack = kalloc_stack();
|
proc->kernel_stack = kalloc_stack();
|
||||||
|
|
||||||
|
process_fd_init(proc);
|
||||||
|
|
||||||
proc->next = 0;
|
proc->next = 0;
|
||||||
|
|
||||||
process_add(&processes_list, proc);
|
process_add(&processes_list, proc);
|
||||||
@@ -255,6 +315,7 @@ void process_create_user(struct limine_file* file, char* name)
|
|||||||
proc->context->iret_ss = USER_DATA_SEGMENT | 3;
|
proc->context->iret_ss = USER_DATA_SEGMENT | 3;
|
||||||
proc->context->iret_cs = USER_CODE_SEGMENT | 3;
|
proc->context->iret_cs = USER_CODE_SEGMENT | 3;
|
||||||
proc->context->iret_flags = 0x202; // Interrupt Flag set
|
proc->context->iret_flags = 0x202; // Interrupt Flag set
|
||||||
|
process_fd_init(proc);
|
||||||
|
|
||||||
void* exec_addr = file->address;
|
void* exec_addr = file->address;
|
||||||
uint64_t exec_size = file->size;
|
uint64_t exec_size = file->size;
|
||||||
|
|||||||
Reference in New Issue
Block a user