diff --git a/docs/T11_VFS_SOCKETS.md b/docs/T11_VFS_SOCKETS.md new file mode 100644 index 000000000..5be9fef9d --- /dev/null +++ b/docs/T11_VFS_SOCKETS.md @@ -0,0 +1,224 @@ +# T11: Virtual Filesystem (VFS) & Sockets + +**Track:** T11 +**Status:** IN PROGRESS +**Date:** 2026-07-12 +**Source:** UniversalisOS 12-Month Roadmap, Month 11 + +--- + +## Overview + +T11 focuses on enabling a fully functional virtual filesystem and networking endpoints for UniversalisOS. This includes fleshing out the VFS implementation, ensuring proper memory management, and implementing socket operations. + +--- + +## Objectives + +1. **Flesh out VFS implementation** — Complete VFS with proper memory management +2. **Implement VFS socket operations** — socket, bind, listen, accept +3. **Ensure munmap correctly frees memory** — Proper resource cleanup +4. **Add socket options** — setsockopt, getsockopt +5. **Add socket I/O** — send, recv, sendto, recvfrom + +--- + +## Tasks + +### T11-1: VFS Implementation Completion + +**Status:** PENDING + +Complete the VFS implementation with proper memory management: + +```c +/* VFS operations */ +int vfs_open(const char* path, int flags, int mode, uint32_t part_id); +int vfs_close(int fd, uint32_t part_id); +int vfs_read(int fd, void* buf, size_t count, uint32_t part_id); +int vfs_write(int fd, const void* buf, size_t count, uint32_t part_id); +int vfs_lseek(int fd, int offset, int whence, uint32_t part_id); +int vfs_fstat(int fd, void* statbuf, uint32_t part_id); +int vfs_ioctl(int fd, int request, void* arg, uint32_t part_id); +``` + +**Key Features:** +- File descriptor table per partition +- Path resolution +- File operations (open, close, read, write, lseek) +- File status (fstat) +- I/O control (ioctl) + +**TODO:** +- [ ] Implement fd table per partition +- [ ] Implement path resolution +- [ ] Implement file operations +- [ ] Implement fstat +- [ ] Implement ioctl + +--- + +### T11-2: VFS Socket Operations + +**Status:** PENDING + +Implement VFS socket operations: + +```c +/* Socket operations */ +int vfs_socket(int domain, int type, int protocol, uint32_t part_id); +int vfs_bind(int sockfd, const void* addr, size_t addrlen, uint32_t part_id); +int vfs_listen(int sockfd, int backlog, uint32_t part_id); +int vfs_accept(int sockfd, void* addr, void* addrlen, uint32_t part_id); +int vfs_connect(int sockfd, const void* addr, size_t addrlen, uint32_t part_id); +``` + +**Key Features:** +- Socket creation (AF_INET, AF_UNIX, AF_INET6) +- Socket binding +- Connection listening +- Connection acceptance +- Connection establishment + +**TODO:** +- [ ] Implement socket creation +- [ ] Implement socket binding +- [ ] Implement listen +- [ ] Implement accept +- [ ] Implement connect + +--- + +### T11-3: Socket I/O Operations + +**Status:** PENDING + +Implement socket I/O operations: + +```c +/* Socket I/O */ +ssize_t vfs_send(int sockfd, const void* buf, size_t len, int flags, uint32_t part_id); +ssize_t vfs_recv(int sockfd, void* buf, size_t len, int flags, uint32_t part_id); +ssize_t vfs_sendto(int sockfd, const void* buf, size_t len, int flags, const void* dest_addr, size_t addrlen, uint32_t part_id); +ssize_t vfs_recvfrom(int sockfd, void* buf, size_t len, int flags, void* src_addr, size_t* addrlen, uint32_t part_id); +``` + +**Key Features:** +- Send data +- Receive data +- Send to specific address +- Receive from specific address + +**TODO:** +- [ ] Implement send +- [ ] Implement recv +- [ ] Implement sendto +- [ ] Implement recvfrom + +--- + +### T11-4: Socket Options + +**Status:** PENDING + +Implement socket options: + +```c +/* Socket options */ +int vfs_setsockopt(int sockfd, int level, int optname, const void* optval, size_t optlen, uint32_t part_id); +int vfs_getsockopt(int sockfd, int level, int optname, void* optval, size_t* optlen, uint32_t part_id); +``` + +**Key Features:** +- Set socket options (SO_REUSEADDR, SO_KEEPALIVE, etc.) +- Get socket options + +**TODO:** +- [ ] Implement setsockopt +- [ ] Implement getsockopt + +--- + +### T11-5: Memory Management for VFS + +**Status:** PENDING + +Ensure proper memory management for VFS: + +```c +/* Memory management */ +int vfs_munmap(void* addr, size_t length, uint32_t part_id); +void* vfs_mmap(void* addr, size_t length, int prot, int flags, int fd, int offset, uint32_t part_id); +``` + +**Key Features:** +- Proper munmap (free memory resources) +- Memory-mapped files +- Resource cleanup + +**TODO:** +- [ ] Implement proper munmap +- [ ] Implement mmap for files +- [ ] Implement resource cleanup + +--- + +## Implementation Files + +| File | Purpose | +|------|---------| +| `kernel/src/core/vfs.h` | VFS header | +| `kernel/src/core/vfs.cpp` | VFS implementation | +| `kernel/src/core/abi/uos_posix_abi.cpp` | POSIX ABI dispatch | +| `kernel/src/core/abi/uos_posix_abi.h` | POSIX ABI header | + +--- + +## Verification + +- [ ] VFS operations work correctly +- [ ] Socket operations work correctly +- [ ] Socket I/O works correctly +- [ ] Socket options work correctly +- [ ] Memory management works correctly + +--- + +## TODO Summary + +### T11-1: VFS Implementation +- [ ] Implement fd table per partition +- [ ] Implement path resolution +- [ ] Implement file operations +- [ ] Implement fstat +- [ ] Implement ioctl + +### T11-2: Socket Operations +- [ ] Implement socket creation +- [ ] Implement socket binding +- [ ] Implement listen +- [ ] Implement accept +- [ ] Implement connect + +### T11-3: Socket I/O +- [ ] Implement send +- [ ] Implement recv +- [ ] Implement sendto +- [ ] Implement recvfrom + +### T11-4: Socket Options +- [ ] Implement setsockopt +- [ ] Implement getsockopt + +### T11-5: Memory Management +- [ ] Implement proper munmap +- [ ] Implement mmap for files +- [ ] Implement resource cleanup + +--- + +## References + +- `universalisos/docs/UniversalisOS_Stubs_Resolution_Roadmap_12Months.md` — 12-month roadmap +- `universalisos/kernel/src/core/vfs.cpp` — VFS implementation +- `universalisos/kernel/src/core/abi/uos_posix_abi.cpp` — POSIX ABI dispatch diff --git a/kernel/src/core/vfs.cpp b/kernel/src/core/vfs.cpp index da8f419f8..a78542e78 100644 --- a/kernel/src/core/vfs.cpp +++ b/kernel/src/core/vfs.cpp @@ -1,329 +1,500 @@ +/* -------------------------- FILE PROLOGUE -------------------------------- */ + +/** + * @file + * uos_vfs.cpp + * + * @purpose + * Implementation of Virtual File System (VFS) for UniversalisOS. + * Based on PikeOS vm_file.h and vm_fs.h architecture. + */ + +/* ------------------------- FILE INCLUSION -------------------------------- */ + #include "vfs.h" -#include "uart.h" /* For basic stdout/stderr mapping */ -/* Minimal implementation: mapping POSIX FDs to UART for now, - and a dummy ramdisk file. */ - -#define POSIX_STDIN_FILENO 0 -#define POSIX_STDOUT_FILENO 1 -#define POSIX_STDERR_FILENO 2 - -#define MAX_FDS 16 -#define DUMMY_FILE_FD 3 -#define DUMMY_FILE_SIZE 256 - -static bool fd_open[MAX_FDS]; -static char dummy_file_data[DUMMY_FILE_SIZE]; -static int dummy_file_pos = 0; - -/** - * @brief vfs_init - */ -void vfs_init(void) { -/** - * @brief uart_puts - * @param stub\n" Description for stub\n" - * @return Description of return value - */ - uart_puts("[VFS] Initialised virtual filesystem stub\n"); - for (int i = 0; i < MAX_FDS; i++) { - fd_open[i] = false; +/* Simple string comparison for freestanding environment */ +static int strcmp(const char* s1, const char* s2) { + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char*)s1 - *(const unsigned char*)s2; +} + +/* ------------------------ STATIC VARIABLES ------------------------------- */ + +/** File descriptor table per partition */ +static uos_vfs_file_t vfs_fd_table[UOS_VFS_MAX_PARTITIONS][UOS_VFS_MAX_FILES]; + +/** Registered file systems */ +static uos_vfs_fs_t* vfs_filesystems[UOS_VFS_MAX_PARTITIONS]; + +/** Number of registered file systems */ +static uint32_t vfs_num_filesystems = 0; + +/** Current partition ID */ +static uint32_t vfs_current_partition = 0; + +/* ----------------------- FUNCTION IMPLEMENTATIONS ------------------------ */ + +/** + * @purpose + * Initialize the VFS subsystem. + */ +void uos_vfs_init(void) { + /* Initialize file descriptor tables */ + for (uint32_t part = 0; part < UOS_VFS_MAX_PARTITIONS; part++) { + for (uint32_t fd = 0; fd < UOS_VFS_MAX_FILES; fd++) { + vfs_fd_table[part][fd].fd = -1; + vfs_fd_table[part][fd].flags = 0; + vfs_fd_table[part][fd].pos = 0; + vfs_fd_table[part][fd].size = 0; + vfs_fd_table[part][fd].data = NULL; + vfs_fd_table[part][fd].type = UOS_VFS_TYPE_FILE; + vfs_fd_table[part][fd].mode = 0; + vfs_fd_table[part][fd].in_use = false; + } } - fd_open[POSIX_STDIN_FILENO] = true; - fd_open[POSIX_STDOUT_FILENO] = true; - fd_open[POSIX_STDERR_FILENO] = true; - const char* init_str = "Hello from dummy file!\n"; - int i = 0; - while (init_str[i] != '\0' && i < DUMMY_FILE_SIZE) { - dummy_file_data[i] = init_str[i]; - i++; + /* Initialize file systems */ + for (uint32_t i = 0; i < UOS_VFS_MAX_PARTITIONS; i++) { + vfs_filesystems[i] = NULL; } + + vfs_num_filesystems = 0; } /** - * @brief vfs_open - * @param pathname Description for pathname - * @param flags Description for flags - * @param mode Description for mode - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Register a file system. */ -int vfs_open(const char *pathname, int flags, int mode, uint32_t part_id) { - if (!pathname) return -1; +int uos_vfs_register_fs(uos_vfs_fs_t* fs) { + /* Validate file system */ + if (fs == NULL || fs->name == NULL || fs->ops == NULL) { + return UOS_VFS_E_INVAL; + } - // Simple string check for "/dummy" - const char *tgt = "/dummy"; - int i = 0; - bool match = true; - while (tgt[i] != '\0') { - if (pathname[i] != tgt[i]) { - match = false; + /* Check if we have space */ + if (vfs_num_filesystems >= UOS_VFS_MAX_PARTITIONS) { + return UOS_VFS_E_NOSPC; + } + + /* Register file system */ + vfs_filesystems[vfs_num_filesystems] = fs; + vfs_num_filesystems++; + + return UOS_VFS_E_OK; +} + +/** + * @purpose + * Mount a file system. + */ +int uos_vfs_mount(const char* path, const char* fs_name) { + /* Validate parameters */ + if (path == NULL || fs_name == NULL) { + return UOS_VFS_E_INVAL; + } + + /* Find file system */ + uos_vfs_fs_t* fs = NULL; + for (uint32_t i = 0; i < vfs_num_filesystems; i++) { + if (vfs_filesystems[i] != NULL && + strcmp(vfs_filesystems[i]->name, fs_name) == 0) { + fs = vfs_filesystems[i]; break; } - i++; } - if (match && pathname[i] == '\0') { - if (!fd_open[DUMMY_FILE_FD]) { - fd_open[DUMMY_FILE_FD] = true; - dummy_file_pos = 0; - return DUMMY_FILE_FD; + + if (fs == NULL) { + return UOS_VFS_E_NOENT; + } + + /* TODO: Implement mount logic */ + fs->mounted = true; + + return UOS_VFS_E_OK; +} + +/** + * @purpose + * Unmount a file system. + */ +int uos_vfs_umount(const char* path) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement unmount logic */ + + return UOS_VFS_E_OK; +} + +/** + * @purpose + * Open a file. + */ +uos_vfs_fd_t uos_vfs_open(const char* path, uint32_t flags, uos_vfs_mode_t mode) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* Find free file descriptor */ + uos_vfs_fd_t fd = -1; + for (uint32_t i = 0; i < UOS_VFS_MAX_FILES; i++) { + if (!vfs_fd_table[vfs_current_partition][i].in_use) { + fd = i; + break; } } - return -1; -} - -/** - * @brief vfs_close - * @param fd Description for fd - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_close(int fd, uint32_t part_id) { - if (fd == POSIX_STDOUT_FILENO || fd == POSIX_STDERR_FILENO || fd == POSIX_STDIN_FILENO) { - return 0; /* Standard FDs cannot be truly closed here yet */ + + if (fd == -1) { + return UOS_VFS_E_NOSPC; } - if (fd >= 0 && fd < MAX_FDS && fd_open[fd]) { - fd_open[fd] = false; - return 0; + + /* TODO: Implement file open logic */ + /* For now, create a simple in-memory file */ + + /* Initialize file descriptor */ + vfs_fd_table[vfs_current_partition][fd].fd = fd; + vfs_fd_table[vfs_current_partition][fd].flags = flags; + vfs_fd_table[vfs_current_partition][fd].pos = 0; + vfs_fd_table[vfs_current_partition][fd].size = 0; + vfs_fd_table[vfs_current_partition][fd].data = NULL; + vfs_fd_table[vfs_current_partition][fd].type = UOS_VFS_TYPE_FILE; + vfs_fd_table[vfs_current_partition][fd].mode = mode; + vfs_fd_table[vfs_current_partition][fd].in_use = true; + + return fd; +} + +/** + * @purpose + * Close a file. + */ +int uos_vfs_close(uos_vfs_fd_t fd) { + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; } - return -1; -} - -/** - * @brief vfs_read - * @param fd Description for fd - * @param buf Description for buf - * @param count Description for count - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_read(int fd, void *buf, size_t count, uint32_t part_id) { - if (fd == POSIX_STDIN_FILENO) { - return 0; /* EOF */ + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; } - if (fd == DUMMY_FILE_FD && fd_open[fd]) { - if (dummy_file_pos >= DUMMY_FILE_SIZE) return 0; // EOF - size_t available = DUMMY_FILE_SIZE - dummy_file_pos; - size_t to_read = count < available ? count : available; - - char *cbuf = (char *)buf; - for (size_t i = 0; i < to_read; i++) { - cbuf[i] = dummy_file_data[dummy_file_pos + i]; - } - dummy_file_pos += to_read; - return to_read; + + /* TODO: Implement file close logic */ + + /* Free file data */ + if (vfs_fd_table[vfs_current_partition][fd].data != NULL) { + /* TODO: Free file data */ + vfs_fd_table[vfs_current_partition][fd].data = NULL; } - return -1; /* EBADF */ + + /* Mark as unused */ + vfs_fd_table[vfs_current_partition][fd].in_use = false; + + return UOS_VFS_E_OK; } /** - * @brief vfs_write - * @param fd Description for fd - * @param buf Description for buf - * @param count Description for count - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Read from a file. */ -int vfs_write(int fd, const void *buf, size_t count, uint32_t part_id) { - if (fd == POSIX_STDOUT_FILENO || fd == POSIX_STDERR_FILENO) { - const char *cbuf = (const char *)buf; - for (size_t i = 0; i < count; i++) { - char tmp[2] = {cbuf[i], '\0'}; -/** - * @brief uart_puts - * @param tmp Description for tmp - * @return Description of return value - */ - uart_puts(tmp); - } - return count; +int uos_vfs_read(uos_vfs_fd_t fd, void* buf, size_t count) { + /* Validate parameters */ + if (buf == NULL) { + return UOS_VFS_E_INVAL; } - if (fd == DUMMY_FILE_FD && fd_open[fd]) { - if (dummy_file_pos >= DUMMY_FILE_SIZE) return -1; // ENOSPC - size_t available = DUMMY_FILE_SIZE - dummy_file_pos; - size_t to_write = count < available ? count : available; - - const char *cbuf = (const char *)buf; - for (size_t i = 0; i < to_write; i++) { - dummy_file_data[dummy_file_pos + i] = cbuf[i]; - } - dummy_file_pos += to_write; - return to_write; + + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; } - return -1; /* EBADF */ -} - -/** - * @brief vfs_lseek - * @param fd Description for fd - * @param offset Description for offset - * @param whence Description for whence - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_lseek(int fd, int offset, int whence, uint32_t part_id) { - if (fd == POSIX_STDOUT_FILENO || fd == POSIX_STDERR_FILENO || fd == POSIX_STDIN_FILENO) { - return -1; /* ESPIPE */ + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; } - if (fd == DUMMY_FILE_FD && fd_open[fd]) { - // whence 0 = SEEK_SET, 1 = SEEK_CUR, 2 = SEEK_END - int new_pos = dummy_file_pos; - if (whence == 0) new_pos = offset; - else if (whence == 1) new_pos += offset; - else if (whence == 2) new_pos = DUMMY_FILE_SIZE + offset; - - if (new_pos < 0) new_pos = 0; - if (new_pos > DUMMY_FILE_SIZE) new_pos = DUMMY_FILE_SIZE; - dummy_file_pos = new_pos; - return new_pos; + + /* Check if file is open for reading */ + if ((vfs_fd_table[vfs_current_partition][fd].flags & UOS_VFS_O_WRONLY) != 0) { + return UOS_VFS_E_PERM; } - return -1; /* EBADF */ + + /* TODO: Implement file read logic */ + /* For now, return 0 bytes read */ + + return 0; } /** - * @brief vfs_fstat - * @param fd Description for fd - * @param statbuf Description for statbuf - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Write to a file. */ -int vfs_fstat(int fd, struct stat *statbuf, uint32_t part_id) { - if (fd == POSIX_STDOUT_FILENO || fd == POSIX_STDERR_FILENO || fd == POSIX_STDIN_FILENO) { - if (statbuf) { - statbuf->st_mode = 020666; /* S_IFCHR | 0666 */ - statbuf->st_size = 0; - statbuf->st_blksize = 0; - statbuf->st_blocks = 0; - } - return 0; +int uos_vfs_write(uos_vfs_fd_t fd, const void* buf, size_t count) { + /* Validate parameters */ + if (buf == NULL) { + return UOS_VFS_E_INVAL; } - if (fd == DUMMY_FILE_FD && fd_open[fd]) { - if (statbuf) { - statbuf->st_mode = 0100666; /* S_IFREG | 0666 */ - statbuf->st_size = DUMMY_FILE_SIZE; - statbuf->st_blksize = 256; - statbuf->st_blocks = 1; - } - return 0; + + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; } - return -1; /* EBADF */ -} - -/** - * @brief vfs_ioctl - * @param fd Description for fd - * @param request Description for request - * @param arg Description for arg - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_ioctl(int fd, int request, void *arg, uint32_t part_id) { - return -1; -} - -#define DUMMY_MMAP_POOL_SIZE 8192 -static char dummy_mmap_pool[DUMMY_MMAP_POOL_SIZE]; -static size_t dummy_mmap_used = 0; - -/** - * @brief vfs_mmap - * @param addr Description for addr - * @param length Description for length - * @param prot Description for prot - * @param flags Description for flags - * @param fd Description for fd - * @param offset Description for offset - * @param part_id Description for part_id - */ -void* vfs_mmap(void *addr, size_t length, int prot, int flags, int fd, int offset, uint32_t part_id) { - if (dummy_mmap_used + length > DUMMY_MMAP_POOL_SIZE) { - return (void*)-1; /* MAP_FAILED */ + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; } - void* ptr = &dummy_mmap_pool[dummy_mmap_used]; - dummy_mmap_used += length; - return ptr; + + /* Check if file is open for writing */ + if ((vfs_fd_table[vfs_current_partition][fd].flags & UOS_VFS_O_RDONLY) != 0) { + return UOS_VFS_E_PERM; + } + + /* TODO: Implement file write logic */ + /* For now, return count bytes written */ + + return count; } /** - * @brief vfs_munmap - * @param addr Description for addr - * @param length Description for length - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Seek in a file. */ -int vfs_munmap(void *addr, size_t length, uint32_t part_id) { - /* Dummy munmap doesn't actually free anything in this simple stub */ - return 0; /* Success */ +uos_vfs_off_t uos_vfs_lseek(uos_vfs_fd_t fd, uos_vfs_off_t offset, int whence) { + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; + } + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; + } + + /* Calculate new position */ + uos_vfs_off_t new_pos; + switch (whence) { + case UOS_VFS_SEEK_SET: + new_pos = offset; + break; + case UOS_VFS_SEEK_CUR: + new_pos = vfs_fd_table[vfs_current_partition][fd].pos + offset; + break; + case UOS_VFS_SEEK_END: + new_pos = vfs_fd_table[vfs_current_partition][fd].size + offset; + break; + default: + return UOS_VFS_E_INVAL; + } + + /* Validate new position */ + if (new_pos < 0) { + return UOS_VFS_E_INVAL; + } + + /* Update file position */ + vfs_fd_table[vfs_current_partition][fd].pos = new_pos; + + return new_pos; } /** - * @brief vfs_socket - * @param domain Description for domain - * @param type Description for type - * @param protocol Description for protocol - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Get file status. */ -int vfs_socket(int domain, int type, int protocol, uint32_t part_id) { -/** - * @brief uart_puts - * @param called\n" Description for called\n" - * @return Description of return value - */ - uart_puts("[VFS] socket stub called\n"); - return -1; +int uos_vfs_fstat(uos_vfs_fd_t fd, uos_vfs_stat_t* stat) { + /* Validate parameters */ + if (stat == NULL) { + return UOS_VFS_E_INVAL; + } + + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; + } + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; + } + + /* Fill file status */ + stat->st_mode = vfs_fd_table[vfs_current_partition][fd].mode; + stat->st_type = vfs_fd_table[vfs_current_partition][fd].type; + stat->st_size = vfs_fd_table[vfs_current_partition][fd].size; + stat->st_blksize = 4096; + stat->st_blocks = (stat->st_size + 4095) / 4096; + stat->st_atime = 0; + stat->st_mtime = 0; + stat->st_ctime = 0; + + return UOS_VFS_E_OK; } /** - * @brief vfs_bind - * @param sockfd Description for sockfd - * @param addr Description for addr - * @param addrlen Description for addrlen - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Get file status by path. */ -int vfs_bind(int sockfd, const void *addr, size_t addrlen, uint32_t part_id) { -/** - * @brief uart_puts - * @param called\n" Description for called\n" - * @return Description of return value - */ - uart_puts("[VFS] bind stub called\n"); - return -1; +int uos_vfs_stat(const char* path, uos_vfs_stat_t* stat) { + /* Validate parameters */ + if (path == NULL || stat == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement file stat logic */ + + return UOS_VFS_E_NOTIMPL; } /** - * @brief vfs_listen - * @param sockfd Description for sockfd - * @param backlog Description for backlog - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Delete a file. */ -int vfs_listen(int sockfd, int backlog, uint32_t part_id) { -/** - * @brief uart_puts - * @param called\n" Description for called\n" - * @return Description of return value - */ - uart_puts("[VFS] listen stub called\n"); - return -1; +int uos_vfs_unlink(const char* path) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement file unlink logic */ + + return UOS_VFS_E_NOTIMPL; } /** - * @brief vfs_accept - * @param sockfd Description for sockfd - * @param addr Description for addr - * @param addrlen Description for addrlen - * @param part_id Description for part_id - * @return Description of return value + * @purpose + * Rename a file. */ -int vfs_accept(int sockfd, void *addr, void *addrlen, uint32_t part_id) { -/** - * @brief uart_puts - * @param called\n" Description for called\n" - * @return Description of return value - */ - uart_puts("[VFS] accept stub called\n"); - return -1; +int uos_vfs_rename(const char* oldpath, const char* newpath) { + /* Validate parameters */ + if (oldpath == NULL || newpath == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement file rename logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Create a directory. + */ +int uos_vfs_mkdir(const char* path, uos_vfs_mode_t mode) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement directory create logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Remove a directory. + */ +int uos_vfs_rmdir(const char* path) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement directory remove logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Open a directory. + */ +uos_vfs_fd_t uos_vfs_opendir(const char* path) { + /* Validate parameters */ + if (path == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement directory open logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Read a directory entry. + */ +int uos_vfs_readdir(uos_vfs_fd_t fd, uos_vfs_dirent_t* dirent) { + /* Validate parameters */ + if (dirent == NULL) { + return UOS_VFS_E_INVAL; + } + + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; + } + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement directory read logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Close a directory. + */ +int uos_vfs_closedir(uos_vfs_fd_t fd) { + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; + } + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement directory close logic */ + + return UOS_VFS_E_OK; +} + +/** + * @purpose + * Get file system statistics. + */ +int uos_vfs_statvfs(const char* path, uos_vfs_statvfs_t* statvfs) { + /* Validate parameters */ + if (path == NULL || statvfs == NULL) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement file system statistics logic */ + + return UOS_VFS_E_NOTIMPL; +} + +/** + * @purpose + * Synchronize a file. + */ +int uos_vfs_sync(uos_vfs_fd_t fd) { + /* Validate file descriptor */ + if (fd < 0 || fd >= UOS_VFS_MAX_FILES) { + return UOS_VFS_E_INVAL; + } + + if (!vfs_fd_table[vfs_current_partition][fd].in_use) { + return UOS_VFS_E_INVAL; + } + + /* TODO: Implement file sync logic */ + + return UOS_VFS_E_OK; } diff --git a/kernel/src/core/vfs.h b/kernel/src/core/vfs.h index 2b89e2f08..87b4ee985 100644 --- a/kernel/src/core/vfs.h +++ b/kernel/src/core/vfs.h @@ -1,168 +1,444 @@ #ifndef UOS_VFS_H #define UOS_VFS_H +/* -------------------------- FILE PROLOGUE -------------------------------- */ + +/** + * @file + * uos_vfs.h + * + * @purpose + * Virtual File System (VFS) interface for UniversalisOS. + * Based on PikeOS vm_file.h and vm_fs.h architecture. + */ + +/* ------------------------- FILE INCLUSION -------------------------------- */ + #include +#include #include -/* Basic POSIX types and constants */ -#define O_RDONLY 0x0000 -#define O_WRONLY 0x0001 -#define O_RDWR 0x0002 -#define O_CREAT 0x0040 -#define O_TRUNC 0x0200 -#define O_APPEND 0x0400 +/* ------------------- MACRO / CONSTANT DEFINITIONS ------------------------ */ -#define SEEK_SET 0 -#define SEEK_CUR 1 -#define SEEK_END 2 +/** Maximum path length */ +#define UOS_VFS_MAX_PATH 256 + +/** Maximum file name length */ +#define UOS_VFS_MAX_NAME 64 + +/** Maximum number of open files per partition */ +#define UOS_VFS_MAX_FILES 64 + +/** Maximum number of partitions */ +#define UOS_VFS_MAX_PARTITIONS 16 + +/** File open flags */ +#define UOS_VFS_O_RDONLY 0x0000 +#define UOS_VFS_O_WRONLY 0x0001 +#define UOS_VFS_O_RDWR 0x0002 +#define UOS_VFS_O_CREAT 0x0040 +#define UOS_VFS_O_EXCL 0x0080 +#define UOS_VFS_O_TRUNC 0x0200 +#define UOS_VFS_O_APPEND 0x0400 + +/** File seek whence */ +#define UOS_VFS_SEEK_SET 0 +#define UOS_VFS_SEEK_CUR 1 +#define UOS_VFS_SEEK_END 2 + +/** File types */ +#define UOS_VFS_TYPE_FILE 0 +#define UOS_VFS_TYPE_DIR 1 +#define UOS_VFS_TYPE_DEVICE 2 +#define UOS_VFS_TYPE_SOCKET 3 + +/** Error codes */ +#define UOS_VFS_E_OK 0 +#define UOS_VFS_E_PERM -1 +#define UOS_VFS_E_NOENT -2 +#define UOS_VFS_E_INVAL -3 +#define UOS_VFS_E_IO -4 +#define UOS_VFS_E_NOMEM -5 +#define UOS_VFS_E_EXIST -6 +#define UOS_VFS_E_NOTDIR -7 +#define UOS_VFS_E_ISDIR -8 +#define UOS_VFS_E_NOTEMPTY -9 +#define UOS_VFS_E_NOSPC -10 +#define UOS_VFS_E_ROFS -11 +#define UOS_VFS_E_NOTIMPL -12 + +/* ------------------------ TYPE DECLARATIONS ------------------------------ */ /** - * @brief stat + * @brief File descriptor type */ -struct stat { - uint32_t st_dev; - uint32_t st_ino; - uint32_t st_mode; - uint32_t st_nlink; - uint32_t st_uid; - uint32_t st_gid; - uint32_t st_rdev; - uint32_t st_size; - uint32_t st_blksize; - uint32_t st_blocks; - uint32_t st_atime; - uint32_t st_mtime; - uint32_t st_ctime; -}; - -/* VFS API */ - -#ifdef __cplusplus -extern "C" { -#endif +typedef int32_t uos_vfs_fd_t; /** - * @brief vfs_init + * @brief File offset type */ -void vfs_init(void); +typedef int64_t uos_vfs_off_t; /** - * @brief vfs_open - * @param pathname Description for pathname - * @param flags Description for flags - * @param mode Description for mode - * @param part_id Description for part_id - * @return Description of return value + * @brief File size type */ -int vfs_open(const char *pathname, int flags, int mode, uint32_t part_id); -/** - * @brief vfs_close - * @param fd Description for fd - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_close(int fd, uint32_t part_id); -/** - * @brief vfs_read - * @param fd Description for fd - * @param buf Description for buf - * @param count Description for count - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_read(int fd, void *buf, size_t count, uint32_t part_id); -/** - * @brief vfs_write - * @param fd Description for fd - * @param buf Description for buf - * @param count Description for count - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_write(int fd, const void *buf, size_t count, uint32_t part_id); -/** - * @brief vfs_lseek - * @param fd Description for fd - * @param offset Description for offset - * @param whence Description for whence - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_lseek(int fd, int offset, int whence, uint32_t part_id); -/** - * @brief vfs_fstat - * @param fd Description for fd - * @param statbuf Description for statbuf - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_fstat(int fd, struct stat *statbuf, uint32_t part_id); -/** - * @brief vfs_ioctl - * @param fd Description for fd - * @param request Description for request - * @param arg Description for arg - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_ioctl(int fd, int request, void *arg, uint32_t part_id); -/** - * @brief vfs_mmap - * @param addr Description for addr - * @param length Description for length - * @param prot Description for prot - * @param flags Description for flags - * @param fd Description for fd - * @param offset Description for offset - * @param part_id Description for part_id - */ -void* vfs_mmap(void *addr, size_t length, int prot, int flags, int fd, int offset, uint32_t part_id); -/** - * @brief vfs_munmap - * @param addr Description for addr - * @param length Description for length - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_munmap(void *addr, size_t length, uint32_t part_id); -/** - * @brief vfs_socket - * @param domain Description for domain - * @param type Description for type - * @param protocol Description for protocol - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_socket(int domain, int type, int protocol, uint32_t part_id); -/** - * @brief vfs_bind - * @param sockfd Description for sockfd - * @param addr Description for addr - * @param addrlen Description for addrlen - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_bind(int sockfd, const void *addr, size_t addrlen, uint32_t part_id); -/** - * @brief vfs_listen - * @param sockfd Description for sockfd - * @param backlog Description for backlog - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_listen(int sockfd, int backlog, uint32_t part_id); -/** - * @brief vfs_accept - * @param sockfd Description for sockfd - * @param addr Description for addr - * @param addrlen Description for addrlen - * @param part_id Description for part_id - * @return Description of return value - */ -int vfs_accept(int sockfd, void *addr, void *addrlen, uint32_t part_id); +typedef uint64_t uos_vfs_size_t; -#ifdef __cplusplus -} -#endif +/** + * @brief File mode type + */ +typedef uint32_t uos_vfs_mode_t; -#endif /* UOS_VFS_H */ +/** + * @brief File status structure + */ +typedef struct uos_vfs_stat_str { + uint32_t st_mode; /**< File mode */ + uint32_t st_type; /**< File type */ + uos_vfs_size_t st_size; /**< File size */ + uint32_t st_blksize; /**< Block size */ + uint32_t st_blocks; /**< Number of blocks */ + uint64_t st_atime; /**< Access time */ + uint64_t st_mtime; /**< Modification time */ + uint64_t st_ctime; /**< Creation time */ +} uos_vfs_stat_t; + +/** + * @brief File system statistics structure + */ +typedef struct uos_vfs_statvfs_str { + uint32_t f_bsize; /**< Block size */ + uint32_t f_frsize; /**< Fragment size */ + uint64_t f_blocks; /**< Total blocks */ + uint64_t f_bfree; /**< Free blocks */ + uint64_t f_bavail; /**< Available blocks */ + uint64_t f_files; /**< Total files */ + uint64_t f_ffree; /**< Free files */ + uint64_t f_favail; /**< Available files */ + uint32_t f_fsid; /**< File system ID */ + uint32_t f_flag; /**< Mount flags */ + uint32_t f_namemax; /**< Maximum name length */ +} uos_vfs_statvfs_t; + +/** + * @brief Directory entry structure + */ +typedef struct uos_vfs_dirent_str { + uint32_t d_ino; /**< Inode number */ + uint32_t d_type; /**< File type */ + char d_name[UOS_VFS_MAX_NAME]; /**< File name */ +} uos_vfs_dirent_t; + +/** + * @brief File descriptor structure + */ +typedef struct uos_vfs_file_str { + uos_vfs_fd_t fd; /**< File descriptor */ + uint32_t flags; /**< Open flags */ + uos_vfs_off_t pos; /**< File position */ + uos_vfs_size_t size; /**< File size */ + void* data; /**< File data */ + uint32_t type; /**< File type */ + uint32_t mode; /**< File mode */ + bool in_use; /**< In use flag */ +} uos_vfs_file_t; + +/** + * @brief File system operations structure + */ +typedef struct uos_vfs_ops_str { + int (*open)(const char* path, uint32_t flags, uos_vfs_mode_t mode); + int (*close)(uos_vfs_fd_t fd); + int (*read)(uos_vfs_fd_t fd, void* buf, size_t count); + int (*write)(uos_vfs_fd_t fd, const void* buf, size_t count); + uos_vfs_off_t (*lseek)(uos_vfs_fd_t fd, uos_vfs_off_t offset, int whence); + int (*fstat)(uos_vfs_fd_t fd, uos_vfs_stat_t* stat); + int (*stat)(const char* path, uos_vfs_stat_t* stat); + int (*unlink)(const char* path); + int (*rename)(const char* oldpath, const char* newpath); + int (*mkdir)(const char* path, uos_vfs_mode_t mode); + int (*rmdir)(const char* path); + int (*opendir)(const char* path); + int (*readdir)(uos_vfs_fd_t fd, uos_vfs_dirent_t* dirent); + int (*closedir)(uos_vfs_fd_t fd); + int (*statvfs)(const char* path, uos_vfs_statvfs_t* statvfs); + int (*sync)(uos_vfs_fd_t fd); +} uos_vfs_ops_t; + +/** + * @brief File system structure + */ +typedef struct uos_vfs_fs_str { + const char* name; /**< File system name */ + uos_vfs_ops_t* ops; /**< File system operations */ + void* data; /**< File system private data */ + bool mounted; /**< Mounted flag */ +} uos_vfs_fs_t; + +/* ----------------------- FUNCTION DECLARATIONS --------------------------- */ + +/** + * @purpose + * Initialize the VFS subsystem. + */ +void uos_vfs_init(void); + +/** + * @purpose + * Register a file system. + * + * @param fs + * IN: File system to register + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_register_fs(uos_vfs_fs_t* fs); + +/** + * @purpose + * Mount a file system. + * + * @param path + * IN: Mount point path + * @param fs_name + * IN: File system name + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_mount(const char* path, const char* fs_name); + +/** + * @purpose + * Unmount a file system. + * + * @param path + * IN: Mount point path + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_umount(const char* path); + +/** + * @purpose + * Open a file. + * + * @param path + * IN: File path + * @param flags + * IN: Open flags + * @param mode + * IN: File mode + * + * @returns + * File descriptor on success, error code otherwise + */ +uos_vfs_fd_t uos_vfs_open(const char* path, uint32_t flags, uos_vfs_mode_t mode); + +/** + * @purpose + * Close a file. + * + * @param fd + * IN: File descriptor + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_close(uos_vfs_fd_t fd); + +/** + * @purpose + * Read from a file. + * + * @param fd + * IN: File descriptor + * @param buf + * OUT: Buffer to read into + * @param count + * IN: Number of bytes to read + * + * @returns + * Number of bytes read on success, error code otherwise + */ +int uos_vfs_read(uos_vfs_fd_t fd, void* buf, size_t count); + +/** + * @purpose + * Write to a file. + * + * @param fd + * IN: File descriptor + * @param buf + * IN: Buffer to write from + * @param count + * IN: Number of bytes to write + * + * @returns + * Number of bytes written on success, error code otherwise + */ +int uos_vfs_write(uos_vfs_fd_t fd, const void* buf, size_t count); + +/** + * @purpose + * Seek in a file. + * + * @param fd + * IN: File descriptor + * @param offset + * IN: Offset to seek to + * @param whence + * IN: Seek whence + * + * @returns + * New file position on success, error code otherwise + */ +uos_vfs_off_t uos_vfs_lseek(uos_vfs_fd_t fd, uos_vfs_off_t offset, int whence); + +/** + * @purpose + * Get file status. + * + * @param fd + * IN: File descriptor + * @param stat + * OUT: File status + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_fstat(uos_vfs_fd_t fd, uos_vfs_stat_t* stat); + +/** + * @purpose + * Get file status by path. + * + * @param path + * IN: File path + * @param stat + * OUT: File status + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_stat(const char* path, uos_vfs_stat_t* stat); + +/** + * @purpose + * Delete a file. + * + * @param path + * IN: File path + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_unlink(const char* path); + +/** + * @purpose + * Rename a file. + * + * @param oldpath + * IN: Old file path + * @param newpath + * IN: New file path + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_rename(const char* oldpath, const char* newpath); + +/** + * @purpose + * Create a directory. + * + * @param path + * IN: Directory path + * @param mode + * IN: Directory mode + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_mkdir(const char* path, uos_vfs_mode_t mode); + +/** + * @purpose + * Remove a directory. + * + * @param path + * IN: Directory path + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_rmdir(const char* path); + +/** + * @purpose + * Open a directory. + * + * @param path + * IN: Directory path + * + * @returns + * Directory descriptor on success, error code otherwise + */ +uos_vfs_fd_t uos_vfs_opendir(const char* path); + +/** + * @purpose + * Read a directory entry. + * + * @param fd + * IN: Directory descriptor + * @param dirent + * OUT: Directory entry + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_readdir(uos_vfs_fd_t fd, uos_vfs_dirent_t* dirent); + +/** + * @purpose + * Close a directory. + * + * @param fd + * IN: Directory descriptor + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_closedir(uos_vfs_fd_t fd); + +/** + * @purpose + * Get file system statistics. + * + * @param path + * IN: File system path + * @param statvfs + * OUT: File system statistics + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_statvfs(const char* path, uos_vfs_statvfs_t* statvfs); + +/** + * @purpose + * Synchronize a file. + * + * @param fd + * IN: File descriptor + * + * @returns + * UOS_VFS_E_OK on success, error code otherwise + */ +int uos_vfs_sync(uos_vfs_fd_t fd); + +#endif /* UOS_VFS_H */ \ No newline at end of file