From 4581c59f4d27bac5e88533d26d77acdce86ccb13 Mon Sep 17 00:00:00 2001 From: IonutParau Date: Wed, 16 Jul 2025 16:41:10 +0200 Subject: [PATCH] more work on fs NOTE: tree / broke again --- src/components/filesystem.c | 136 ++++++++++++++++++++++++---- src/components/volatileFilesystem.c | 22 +++++ src/emulator.c | 34 ++++--- src/neonucleus.h | 32 +++---- 4 files changed, 174 insertions(+), 50 deletions(-) diff --git a/src/components/filesystem.c b/src/components/filesystem.c index ff93acc..6f73d6d 100644 --- a/src/components/filesystem.c +++ b/src/components/filesystem.c @@ -46,11 +46,13 @@ void nn_retainFilesystem(nn_filesystem *fs) { nn_bool_t nn_destroyFilesystem(nn_filesystem *fs) { if(!nn_decRef(&fs->refc)) return false; + + nn_errorbuf_t err = ""; // ignored // close all files for(nn_size_t i = 0; i < NN_MAX_OPEN_FILES; i++) { void *f = fs->files[i]; - if(f != NULL) fs->table.close(fs->table.userdata, f); + if(f != NULL) fs->table.close(fs->table.userdata, f, err); } if(fs->table.deinit != NULL) { @@ -141,9 +143,14 @@ void nn_fs_createCost(nn_filesystem *fs, nn_size_t count, nn_component *componen void nn_fs_getLabel(nn_filesystem *fs, void *_, nn_component *component, nn_computer *computer) { char buf[NN_LABEL_SIZE]; nn_size_t l = NN_LABEL_SIZE; + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - fs->table.getLabel(fs->table.userdata, buf, &l); + fs->table.getLabel(fs->table.userdata, buf, &l, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } if(l == 0) { nn_return(computer, nn_values_nil()); } else { @@ -161,9 +168,14 @@ void nn_fs_setLabel(nn_filesystem *fs, void *_, nn_component *component, nn_comp nn_setCError(computer, "bad label (string expected)"); return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - l = fs->table.setLabel(fs->table.userdata, buf, l); + l = fs->table.setLabel(fs->table.userdata, buf, l, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return_string(computer, buf, l); nn_fs_writeCost(fs, l, component); @@ -179,9 +191,14 @@ void nn_fs_spaceTotal(nn_filesystem *fs, nn_componentMethod *_, nn_component *co } void nn_fs_isReadOnly(nn_filesystem *fs, nn_componentMethod *_, nn_component *component, nn_computer *computer) { + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_return_boolean(computer, fs->table.isReadOnly(fs->table.userdata)); + nn_return_boolean(computer, fs->table.isReadOnly(fs->table.userdata, err)); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } } void nn_fs_size(nn_filesystem *fs, nn_componentMethod *_, nn_component *component, nn_computer *computer) { @@ -197,9 +214,14 @@ void nn_fs_size(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_size_t byteSize = fs->table.size(fs->table.userdata, canonical); + nn_size_t byteSize = fs->table.size(fs->table.userdata, canonical, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return(computer, nn_values_integer(byteSize)); } @@ -217,9 +239,14 @@ void nn_fs_remove(nn_filesystem *fs, nn_componentMethod *_, nn_component *compon return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_size_t removed = fs->table.remove(fs->table.userdata, canonical); + nn_size_t removed = fs->table.remove(fs->table.userdata, canonical, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return_boolean(computer, removed > 0); nn_fs_removeCost(fs, removed, component); @@ -238,9 +265,14 @@ void nn_fs_lastModified(nn_filesystem *fs, nn_componentMethod *_, nn_component * return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_size_t t = fs->table.lastModified(fs->table.userdata, canonical); + nn_size_t t = fs->table.lastModified(fs->table.userdata, canonical, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } // OpenOS does BULLSHIT with this thing, dividing it by 1000 and expecting it to be // fucking usable as a date, meaning it needs to be an int. @@ -275,9 +307,14 @@ void nn_fs_rename(nn_filesystem *fs, nn_componentMethod *_, nn_component *compon return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_size_t movedCount = fs->table.rename(fs->table.userdata, canonicalFrom, canonicalTo); + nn_size_t movedCount = fs->table.rename(fs->table.userdata, canonicalFrom, canonicalTo, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return(computer, nn_values_boolean(movedCount > 0)); nn_fs_removeCost(fs, movedCount, component); @@ -297,9 +334,14 @@ void nn_fs_exists(nn_filesystem *fs, nn_componentMethod *_, nn_component *compon return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_return_boolean(computer, fs->table.exists(fs->table.userdata, canonical)); + nn_return_boolean(computer, fs->table.exists(fs->table.userdata, canonical, err)); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } } void nn_fs_isDirectory(nn_filesystem *fs, nn_componentMethod *_, nn_component *component, nn_computer *computer) { @@ -315,9 +357,13 @@ void nn_fs_isDirectory(nn_filesystem *fs, nn_componentMethod *_, nn_component *c return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_return_boolean(computer, fs->table.isDirectory(fs->table.userdata, canonical)); + nn_return_boolean(computer, fs->table.isDirectory(fs->table.userdata, canonical, err)); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + } } void nn_fs_makeDirectory(nn_filesystem *fs, nn_componentMethod *_, nn_component *component, nn_computer *computer) { @@ -333,9 +379,13 @@ void nn_fs_makeDirectory(nn_filesystem *fs, nn_componentMethod *_, nn_component return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_return_boolean(computer, fs->table.makeDirectory(fs->table.userdata, canonical)); + nn_return_boolean(computer, fs->table.makeDirectory(fs->table.userdata, canonical, err)); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + } nn_fs_createCost(fs, 1, component); } @@ -355,10 +405,20 @@ void nn_fs_list(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen nn_Alloc *alloc = nn_getAllocator(nn_getUniverse(computer)); + nn_errorbuf_t err = ""; nn_size_t fileCount = 0; nn_lock(&fs->ctx, fs->lock); - char **files = fs->table.list(alloc, fs->table.userdata, canonical, &fileCount); + char **files = fs->table.list(alloc, fs->table.userdata, canonical, &fileCount, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + if(files != NULL) { + for(nn_size_t i = 0; i < fileCount; i++) { + nn_deallocStr(alloc, files[i]); + } + nn_dealloc(alloc, files, sizeof(char *) * fileCount); + } + nn_setError(computer, err); + } if(files != NULL) { // operation succeeded @@ -391,11 +451,17 @@ void nn_fs_open(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen mode = "r"; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); // technically wrongfully - if(!fs->table.exists(fs->table.userdata, path)) { + if(!fs->table.exists(fs->table.userdata, path, err)) { nn_fs_createCost(fs, 1, component); } + if(!nn_error_isEmpty(err)) { + nn_unlock(&fs->ctx, fs->lock); + nn_setError(computer, err); + return; + } nn_size_t fd = 0; while(fs->files[fd] != NULL) { @@ -406,13 +472,25 @@ void nn_fs_open(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen return; } } - void *file = fs->table.open(fs->table.userdata, canonical, mode); + void *file = fs->table.open(fs->table.userdata, canonical, mode, err); + if(!nn_error_isEmpty(err)) { + if(file != NULL) { + fs->table.close(fs->table.userdata, file, err); + } + nn_unlock(&fs->ctx, fs->lock); + nn_setError(computer, err); + return; + } if(file == NULL) { nn_unlock(&fs->ctx, fs->lock); nn_setCError(computer, "no such file or directory"); return; } nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } fs->files[fd] = file; nn_return(computer, nn_values_integer(fd)); } @@ -426,12 +504,17 @@ void nn_fs_close(nn_filesystem *fs, nn_componentMethod *_, nn_component *compone return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); - nn_bool_t closed = fs->table.close(fs->table.userdata, file); + nn_bool_t closed = fs->table.close(fs->table.userdata, file, err); if(closed) { fs->files[fd] = NULL; } nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return(computer, nn_values_boolean(closed)); } @@ -446,7 +529,8 @@ void nn_fs_write(nn_filesystem *fs, nn_componentMethod *_, nn_component *compone nn_setCError(computer, "bad buffer (string expected)"); return; } - + + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); nn_size_t spaceRemaining = nn_fs_getSpaceRemaining(fs); @@ -463,10 +547,14 @@ void nn_fs_write(nn_filesystem *fs, nn_componentMethod *_, nn_component *compone return; } - nn_bool_t written = fs->table.write(fs->table.userdata, file, buf, len); + nn_bool_t written = fs->table.write(fs->table.userdata, file, buf, len, err); nn_return(computer, nn_values_boolean(written)); if(written) nn_fs_invalidateSpaceUsed(fs); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_fs_writeCost(fs, len, component); } @@ -482,6 +570,7 @@ void nn_fs_read(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen if(len > capacity) len = capacity; nn_size_t byteLen = len; + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); void *file = nn_fs_unwrapFD(fs, fd); if(file == NULL) { @@ -498,8 +587,12 @@ void nn_fs_read(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen return; } - nn_size_t readLen = fs->table.read(fs->table.userdata, file, buf, byteLen); + nn_size_t readLen = fs->table.read(fs->table.userdata, file, buf, byteLen, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } if(readLen > 0) { // Nothing read means EoF. nn_return_string(computer, buf, readLen); @@ -533,6 +626,7 @@ void nn_fs_seek(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen return; } + nn_errorbuf_t err = ""; nn_lock(&fs->ctx, fs->lock); void *file = nn_fs_unwrapFD(fs, fd); if(file == NULL) { @@ -541,8 +635,12 @@ void nn_fs_seek(nn_filesystem *fs, nn_componentMethod *_, nn_component *componen return; } - nn_size_t pos = fs->table.seek(fs->table.userdata, file, whence, off); + nn_size_t pos = fs->table.seek(fs->table.userdata, file, whence, off, err); nn_unlock(&fs->ctx, fs->lock); + if(!nn_error_isEmpty(err)) { + nn_setError(computer, err); + return; + } nn_return_integer(computer, pos); } diff --git a/src/components/volatileFilesystem.c b/src/components/volatileFilesystem.c index 52cc741..7c5bc6f 100644 --- a/src/components/volatileFilesystem.c +++ b/src/components/volatileFilesystem.c @@ -159,6 +159,28 @@ nn_size_t nn_vf_getIdealCapacity(nn_vfnode *file, nn_size_t spaceNeeded) { return cap; } +void nn_vf_clampHandlePosition(nn_vfhandle *handle) { + nn_size_t len = handle->node->len; + if(handle->position < 0) handle->position = 0; + if(handle->position > len) handle->position = len; +} + +nn_vfnode *nn_vf_resolvePathFromNode(nn_vfnode *node, const char *path) { + if(path[0] == 0) return node; + char firstDirectory[NN_MAX_PATH]; + char subpath[NN_MAX_PATH]; + if(nn_path_firstName(path, firstDirectory, subpath)) { + return nn_vf_find(node, firstDirectory); + } + + nn_vfnode *dir = nn_vf_find(node, firstDirectory); + return nn_vf_resolvePathFromNode(dir, subpath); +} + +nn_vfnode *nn_vf_resolvePath(nn_vfilesystem *fs, const char *path) { + return nn_vf_resolvePathFromNode(fs->root, path); +} + // methods void nn_vfs_deinit(nn_vfilesystem *fs) { diff --git a/src/emulator.c b/src/emulator.c index 6a054f9..21bc45c 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -197,7 +197,7 @@ nn_size_t ne_fs_setLabel(void *_, const char *buf, size_t buflen) { return 0; } -nn_bool_t ne_fs_isReadOnly(void *_) { +nn_bool_t ne_fs_isReadOnly(void *_, nn_errorbuf_t err) { return false; } @@ -217,7 +217,7 @@ const char *ne_fs_diskPath(nn_address addr, const char *path) { return buf; } -void *ne_fs_open(nn_address address, const char *path, const char *mode) { +void *ne_fs_open(nn_address address, const char *path, const char *mode, nn_errorbuf_t err) { const char *trueMode = "rb"; if(strcmp(mode, "w") == 0) { trueMode = "wb"; @@ -228,28 +228,32 @@ void *ne_fs_open(nn_address address, const char *path, const char *mode) { const char *p = ne_fs_diskPath(address, path); if(p[0] == '/') p++; + if(DirectoryExists(p)) { + nn_error_write(err, "Is a directory"); + return NULL; + } FILE *f = fopen(p, trueMode); if(f == NULL) { - printf("open(%s) failure: %s\n", path, strerror(errno)); + nn_error_write(err, strerror(errno)); } return f; } -bool ne_fs_close(nn_address addr, FILE *f) { +bool ne_fs_close(nn_address addr, FILE *f, nn_errorbuf_t err) { fclose(f); return true; } -bool ne_fs_write(nn_address addr, FILE *f, const char *buf, size_t len) { +bool ne_fs_write(nn_address addr, FILE *f, const char *buf, size_t len, nn_errorbuf_t err) { return fwrite(buf, sizeof(char), len, f) > 0; } -size_t ne_fs_read(nn_address addr, FILE *f, char *buf, size_t required) { +size_t ne_fs_read(nn_address addr, FILE *f, char *buf, size_t required, nn_errorbuf_t err) { if(feof(f)) return 0; return fread(buf, sizeof(char), required, f); } -size_t ne_fs_seek(nn_address addr, FILE *f, const char *whence, int off) { +size_t ne_fs_seek(nn_address addr, FILE *f, const char *whence, int off, nn_errorbuf_t err) { int w = SEEK_SET; if(strcmp(whence, "cur") == 0) { w = SEEK_CUR; @@ -261,7 +265,7 @@ size_t ne_fs_seek(nn_address addr, FILE *f, const char *whence, int off) { return ftell(f); } -char **ne_fs_list(nn_Alloc *alloc, nn_address addr, const char *path, size_t *len) { +char **ne_fs_list(nn_Alloc *alloc, nn_address addr, const char *path, size_t *len, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; @@ -278,7 +282,7 @@ char **ne_fs_list(nn_Alloc *alloc, nn_address addr, const char *path, size_t *le return buf; } -size_t ne_fs_size(nn_address addr, const char *path) { +size_t ne_fs_size(nn_address addr, const char *path, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; @@ -287,28 +291,28 @@ size_t ne_fs_size(nn_address addr, const char *path) { return GetFileLength(p); } -size_t ne_fs_lastModified(nn_address addr, const char *path) { +size_t ne_fs_lastModified(nn_address addr, const char *path, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; return GetFileModTime(p); } -bool ne_fs_isDirectory(nn_address addr, const char *path) { +bool ne_fs_isDirectory(nn_address addr, const char *path, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; return DirectoryExists(p); } -bool ne_fs_makeDirectory(nn_address addr, const char *path) { +bool ne_fs_makeDirectory(nn_address addr, const char *path, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; return MakeDirectory(p) == 0; } -bool ne_fs_exists(nn_address addr, const char *path) { +bool ne_fs_exists(nn_address addr, const char *path, nn_errorbuf_t err) { const char *p = ne_fs_diskPath(addr, path); if(p[0] == '/') p++; @@ -647,8 +651,8 @@ int main() { nn_filesystemTable genericFSTable = { .userdata = fsFolder, .deinit = NULL, - .getLabel = ne_fs_getLabel, - .setLabel = ne_fs_setLabel, + .getLabel = ne_eeprom_getLabel, + .setLabel = ne_eeprom_setLabel, .spaceUsed = ne_fs_spaceUsed, .spaceTotal = 1*1024*1024, .isReadOnly = ne_fs_isReadOnly, diff --git a/src/neonucleus.h b/src/neonucleus.h index 6d19977..2798830 100644 --- a/src/neonucleus.h +++ b/src/neonucleus.h @@ -682,37 +682,37 @@ typedef struct nn_filesystemTable { void *userdata; void (*deinit)(void *userdata); - void (*getLabel)(void *userdata, char *buf, nn_size_t *buflen); - nn_size_t (*setLabel)(void *userdata, const char *buf, nn_size_t buflen); + void (*getLabel)(void *userdata, char *buf, nn_size_t *buflen, nn_errorbuf_t err); + nn_size_t (*setLabel)(void *userdata, const char *buf, nn_size_t buflen, nn_errorbuf_t err); nn_size_t (*spaceUsed)(void *userdata); nn_size_t spaceTotal; - nn_bool_t (*isReadOnly)(void *userdata); + nn_bool_t (*isReadOnly)(void *userdata, nn_errorbuf_t err); // general operations - nn_size_t (*size)(void *userdata, const char *path); - nn_size_t (*remove)(void *userdata, const char *path); - nn_size_t (*lastModified)(void *userdata, const char *path); - nn_size_t (*rename)(void *userdata, const char *from, const char *to); - nn_bool_t (*exists)(void *userdata, const char *path); + nn_size_t (*size)(void *userdata, const char *path, nn_errorbuf_t err); + nn_size_t (*remove)(void *userdata, const char *path, nn_errorbuf_t err); + nn_size_t (*lastModified)(void *userdata, const char *path, nn_errorbuf_t err); + nn_size_t (*rename)(void *userdata, const char *from, const char *to, nn_errorbuf_t err); + nn_bool_t (*exists)(void *userdata, const char *path, nn_errorbuf_t err); // directory operations - nn_bool_t (*isDirectory)(void *userdata, const char *path); - nn_bool_t (*makeDirectory)(void *userdata, const char *path); + nn_bool_t (*isDirectory)(void *userdata, const char *path, nn_errorbuf_t err); + nn_bool_t (*makeDirectory)(void *userdata, const char *path, nn_errorbuf_t err); // The returned array should be allocated with the supplied allocator. // The strings should be null terminated. Use nn_strdup for the allocation to guarantee nn_deallocStr deallocates it correctly. // For the array, the *exact* size of the allocation should be sizeof(char *) * (*len), // If it is not, the behavior is undefined. // We recommend first computing len then allocating, though if that is not doable or practical, // consider nn_resize()ing it to the correct size to guarantee a correct deallocation. - char **(*list)(nn_Alloc *alloc, void *userdata, const char *path, nn_size_t *len); + char **(*list)(nn_Alloc *alloc, void *userdata, const char *path, nn_size_t *len, nn_errorbuf_t err); // file operations - void *(*open)(void *userdata, const char *path, const char *mode); - nn_bool_t (*close)(void *userdata, void *fd); - nn_bool_t (*write)(void *userdata, void *fd, const char *buf, nn_size_t len); - nn_size_t (*read)(void *userdata, void *fd, char *buf, nn_size_t required); - nn_size_t (*seek)(void *userdata, void *fd, const char *whence, int off); + void *(*open)(void *userdata, const char *path, const char *mode, nn_errorbuf_t err); + nn_bool_t (*close)(void *userdata, void *fd, nn_errorbuf_t err); + nn_bool_t (*write)(void *userdata, void *fd, const char *buf, nn_size_t len, nn_errorbuf_t err); + nn_size_t (*read)(void *userdata, void *fd, char *buf, nn_size_t required, nn_errorbuf_t err); + nn_size_t (*seek)(void *userdata, void *fd, const char *whence, int off, nn_errorbuf_t err); } nn_filesystemTable; typedef struct nn_filesystem nn_filesystem;