diff --git a/data/OpenOS/bin/tree.lua b/data/OpenOS/bin/tree.lua index 0f6dcb6..6198b81 100644 --- a/data/OpenOS/bin/tree.lua +++ b/data/OpenOS/bin/tree.lua @@ -269,9 +269,6 @@ local function writeEntry(entry, levelStack) if opts.Q then io.write('"') end if opts.color == "always" then - if not entry.extension then - print("entry:", entry) - end io.write("\27[" .. colorize(entry) .. "m") end diff --git a/data/OpenOS/boot/89_rc.lua b/data/OpenOS/boot/89_rc.lua index 941a0e6..fb44408 100644 --- a/data/OpenOS/boot/89_rc.lua +++ b/data/OpenOS/boot/89_rc.lua @@ -7,4 +7,3 @@ require("event").listen("init", function() dofile(require("shell").resolve("rc", "lua")) return false end) - diff --git a/data/OpenOS/etc/edit.cfg b/data/OpenOS/etc/edit.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/data/OpenOS/etc/profile.lua b/data/OpenOS/etc/profile.lua index 0fb2ac0..6c54cb4 100644 --- a/data/OpenOS/etc/profile.lua +++ b/data/OpenOS/etc/profile.lua @@ -40,6 +40,5 @@ shell.setWorkingDirectory(os.getenv("HOME")) local home_shrc = shell.resolve(".shrc") if fs.exists(home_shrc) then - local resolved = shell.resolve("source", "lua") - assert(loadfile(resolved))(home_shrc) + loadfile(shell.resolve("source", "lua"))(home_shrc) end diff --git a/data/OpenOS/lib/core/boot.lua b/data/OpenOS/lib/core/boot.lua index 5e03e8b..34c966c 100644 --- a/data/OpenOS/lib/core/boot.lua +++ b/data/OpenOS/lib/core/boot.lua @@ -73,7 +73,7 @@ local function dofile(file) status("> " .. file) local program, reason = raw_loadfile(file) if program then - local result = table.pack(xpcall(program, debug.traceback)) + local result = table.pack(pcall(program)) if result[1] then return table.unpack(result, 2, result.n) else diff --git a/data/OpenOS/usr/misc/greetings.txt b/data/OpenOS/usr/misc/greetings.txt index 134a583..e645e68 100644 --- a/data/OpenOS/usr/misc/greetings.txt +++ b/data/OpenOS/usr/misc/greetings.txt @@ -16,7 +16,7 @@ Most blocks act as 'cables' - use relays and power distributors to create separa Welcome to the dark side - here, have some cookies. Screens can display Unicode - paste the special chars or use unicode.char. Run `help` or `man programname` for ingame help on programs shipped with OpenOS - start with `man man`. -For more help, there's a wiki at https://ocdoc.cil.li/ - or find the IRC loot disk and join #oc. +For more help, there's a wiki at http://ocdoc.cil.li/ - or find the IRC loot disk and join #oc. Computers have a very basic, built-in speaker - control it using computer.beep(). Many component methods have a short documentation - use `=component.componentName.methodName` in the Lua interpreter to see it. You can get a list of all attached components using the `components` program. diff --git a/src/main.c b/src/main.c index c60ea7b..b2838dd 100644 --- a/src/main.c +++ b/src/main.c @@ -10,6 +10,7 @@ #include #include #include +#include nn_Architecture getLuaArch(); @@ -379,7 +380,7 @@ int main(int argc, char **argv) { printf("%zu bytes logically used by OpenOS\n", ncl_spaceUsedIn(ncl_defaultFS, "data/OpenOS")); printf("%zu bytes physically used by OpenOS\n", ncl_spaceUsedBy(ncl_defaultFS, "data/OpenOS")); - + nn_Component *eepromCard = nn_createVEEPROM(u, "eeprom", &veeprom, &nn_defaultEEPROMs[3]); nn_Component *managedfs = ncl_createFilesystem(u, "mainFS", "data/OpenOS", &nn_defaultFilesystems[3], true); diff --git a/src/ncomplib.c b/src/ncomplib.c index 2216de5..a2e8a4f 100644 --- a/src/ncomplib.c +++ b/src/ncomplib.c @@ -95,25 +95,12 @@ bool ncl_defaultHandler(ncl_VFSRequest *request) { ncl_Stat *stat = request->stat.stat; stat->isDirectory = S_ISDIR(s.st_mode); stat->diskSize = s.st_blocks * 512; - stat->size = 0; - if(!stat->isDirectory) { - FILE *f = fopen(request->stat.path, "r"); - if(f == NULL) { - // horribly off but don't care atp - stat->size = s.st_size; - } else { - fseek(f, SEEK_END, 0); - stat->size = ftell(f); - fclose(f); - } - } + stat->size = stat->isDirectory ? 0 : s.st_size; stat->lastModified = s.st_mtime; return true; } if(request->action == NCL_VFS_MKDIR) { - // we're not meant to have executables. - int mode = 6*64 + 6*8 + 6; - return mkdir(request->mkdir, mode) == 0; + return mkdir(request->mkdir, 0777) == 0; } #endif return false; // not supported @@ -232,11 +219,9 @@ size_t ncl_spaceUsedIn(ncl_VFS vfs, const char *path) { if(dir == NULL) return spaceUsed; char name[NN_MAX_PATH]; while(ncl_readdir(vfs, dir, name)) { - if(strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { - char subpath[NN_MAX_PATH]; - snprintf(subpath, sizeof(subpath), "%s%c%s", path, vfs.pathsep, name); - spaceUsed += ncl_spaceUsedIn(vfs, subpath); - } + char subpath[NN_MAX_PATH]; + snprintf(subpath, sizeof(subpath), "%s%c%s", path, vfs.pathsep, name); + spaceUsed += ncl_spaceUsedIn(vfs, subpath); } ncl_closedir(vfs, dir); return spaceUsed; @@ -251,11 +236,9 @@ size_t ncl_spaceUsedBy(ncl_VFS vfs, const char *path) { if(dir == NULL) return spaceUsed; char name[NN_MAX_PATH]; while(ncl_readdir(vfs, dir, name)) { - if(strcmp(name, ".") != 0 && strcmp(name, "..") != 0) { - char subpath[NN_MAX_PATH]; - snprintf(subpath, sizeof(subpath), "%s%c%s", path, vfs.pathsep, name); - spaceUsed += ncl_spaceUsedBy(vfs, subpath); - } + char subpath[NN_MAX_PATH]; + snprintf(subpath, sizeof(subpath), "%s%c%s", path, vfs.pathsep, name); + spaceUsed += ncl_spaceUsedBy(vfs, subpath); } ncl_closedir(vfs, dir); return spaceUsed; @@ -298,7 +281,94 @@ bool ncl_mkdir(ncl_VFS vfs, const char *path) { return vfs.handler(&req); } -bool ncl_mkdirRecursive(ncl_VFS vfs, const char *path); +bool ncl_mkdirRecursive(ncl_VFS vfs, const char *path) { + ncl_Stat s; + if(ncl_stat(vfs, path, &s)) { + return s.isDirectory; + } + char buf[NN_MAX_PATH]; + // use snprintf instead of strncpy cuz NULL terminator + snprintf(buf, NN_MAX_PATH, "%s", path); + char *sep = strrchr(buf, '/'); + if(sep == NULL) { + return ncl_mkdir(vfs, path); + } + *sep = '\0'; + if(!ncl_mkdirRecursive(vfs, buf)) return false; + return ncl_mkdir(vfs, path); +} + +static bool ncl_copydir(ncl_VFS vfs, const char *from, const char *to) { + bool created = ncl_mkdir(vfs, to); + if(!created) return false; + void *dir = ncl_opendir(vfs, from); + if(dir == NULL) goto fail; + + char name[NN_MAX_PATH]; + while(ncl_readdir(vfs, dir, name)) { + char subpath[NN_MAX_PATH]; + snprintf(subpath, NN_MAX_PATH, "%s%c%s", from, vfs.pathsep, name); + char subdest[NN_MAX_PATH]; + snprintf(subdest, NN_MAX_PATH, "%s%c%s", to, vfs.pathsep, name); + printf("%s -> %s\n", subpath, subdest); + if(!ncl_copyto(vfs, subpath, subdest)) goto fail; + } + + ncl_closedir(vfs, dir); + return true; +fail: + if(dir != NULL) ncl_closedir(vfs, dir); + // erase all evidence + //ncl_removeRecursive(vfs, to); + return false; +} + +static bool ncl_copyfile(ncl_VFS vfs, const char *from, const char *to) { + // copy some files! + void *src = NULL; + void *dest = NULL; + src = ncl_openfile(vfs, from, "r"); + if(src == NULL) goto fail; + dest = ncl_openfile(vfs, to, "w"); + if(dest == NULL) goto fail; + + char buf[NN_MAX_READ]; + size_t len = NN_MAX_READ; + while(ncl_readfile(vfs, src, buf, &len)) { + if(!ncl_writefile(vfs, dest, buf, len)) goto fail; + len = NN_MAX_READ; + } + ncl_closefile(vfs, src); + ncl_closefile(vfs, dest); + + return true; +fail: + if(src != NULL) ncl_closefile(vfs, src); + if(dest != NULL) ncl_closefile(vfs, dest); + //ncl_remove(vfs, to); + return false; +} + +static bool ncl_isIllegalCopy(const char *from, const char *to) { + // check if to starts with from, or from starts with to + if(strncmp(from, to, strlen(from)) == 0) return true; + if(strncmp(to, from, strlen(to)) == 0) return true; + return false; +} + +bool ncl_copyto(ncl_VFS vfs, const char *from, const char *to) { + if(strcmp(from, to) == 0) return true; + if(ncl_isIllegalCopy(from, to)) return false; + // already exists + if(ncl_exists(vfs, to)) return false; + + ncl_Stat s; + // missing + if(!ncl_stat(vfs, from, &s)) return false; + + if(s.isDirectory) return ncl_copydir(vfs, from, to); + return ncl_copyfile(vfs, from, to); +} typedef struct ncl_ScreenPixel { nn_codepoint codepoint; @@ -533,6 +603,8 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) { return NN_EBADCALL; } state->fds[fd] = NULL; + state->spaceUsed = 0; + state->realSpaceUsed = 0; volatile ncl_VFS vfs = state->vfs; nn_unlock(ctx, state->lock); // out of lock for the most minimal of performance @@ -571,6 +643,8 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) { return NN_EBADCALL; } bool ok = ncl_writefile(state->vfs, file, req->write.buf, req->write.len); + state->spaceUsed = 0; + state->realSpaceUsed = 0; nn_unlock(ctx, state->lock); if(ok) return NN_OK; nn_setError(C, "write failed"); @@ -655,13 +729,14 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) { } if(req->action == NN_FS_STAT) { nn_lock(ctx, state->lock); + state->usage++; char path[NN_MAX_PATH]; ncl_fixPath(state, req->stat.path, path); ncl_Stat s; if(!ncl_stat(state->vfs, path, &s)) { nn_unlock(ctx, state->lock); - nn_setError(C, "no such file or directory"); - return NN_EBADCALL; + req->stat.path = NULL; + return NN_OK; } req->stat.isDirectory = s.isDirectory; req->stat.size = s.size; @@ -669,7 +744,80 @@ static nn_Exit ncl_fsHandler(nn_FSRequest *req) { nn_unlock(ctx, state->lock); return NN_OK; } - // TODO: mkdir, rename + if(req->action == NN_FS_MKDIR) { + nn_lock(ctx, state->lock); + state->usage++; + char path[NN_MAX_PATH]; + ncl_fixPath(state, req->mkdir, path); + ncl_Stat s; + if(ncl_stat(state->vfs, path, &s)) { + nn_unlock(ctx, state->lock); + if(s.isDirectory) { + return NN_OK; + } + nn_setError(C, "not a directory"); + return NN_EBADCALL; + } + if(!ncl_mkdirRecursive(state->vfs, path)) { + nn_unlock(ctx, state->lock); + nn_setError(C, "operation failed"); + return NN_EBADCALL; + } + size_t newSpaceUsed = ncl_spaceUsedIn(state->vfs, state->path); + if(newSpaceUsed > state->conf.spaceTotal) { + ncl_removeRecursive(state->vfs, path); + nn_unlock(ctx, state->lock); + nn_setError(C, "out of space"); + return NN_EBADCALL; + } + state->spaceUsed = newSpaceUsed; + state->realSpaceUsed = 0; + nn_unlock(ctx, state->lock); + return NN_OK; + } + if(req->action == NN_FS_RENAME) { + if(req->rename.from[0] == '\0') { + nn_setError(C, "root is forbidden"); + return NN_EBADCALL; + } + if(req->rename.to != NULL && req->rename.to[0] == '\0') { + nn_setError(C, "root is forbidden"); + return NN_EBADCALL; + } + nn_lock(ctx, state->lock); + state->usage++; + char from[NN_MAX_PATH]; + ncl_fixPath(state, req->rename.from, from); + if(req->rename.to == NULL) { + bool ok = ncl_removeRecursive(state->vfs, from); + nn_unlock(ctx, state->lock); + if(!ok) { + nn_setError(C, "operation failed"); + return NN_EBADCALL; + } + return NN_OK; + } + char to[NN_MAX_PATH]; + ncl_fixPath(state, req->rename.to, to); + // copy a to a is illegal btw + if(ncl_isIllegalCopy(from, to)) { + nn_unlock(ctx, state->lock); + nn_setError(C, "illegal copy operation"); + return NN_EBADCALL; + } + bool ok = ncl_copyto(state->vfs, from, to); + if(ok) { + ncl_removeRecursive(state->vfs, from); + } + state->spaceUsed = 0; + state->realSpaceUsed = 0; + nn_unlock(ctx, state->lock); + if(!ok) { + nn_setError(C, "operation failed"); + return NN_EBADCALL; + } + return NN_OK; + } if(C) nn_setError(C, "not implemented yet"); return NN_EBADCALL; diff --git a/src/ncomplib.h b/src/ncomplib.h index 9b2181e..6868ac4 100644 --- a/src/ncomplib.h +++ b/src/ncomplib.h @@ -150,6 +150,8 @@ bool ncl_removeRecursive(ncl_VFS vfs, const char *path); bool ncl_mkdir(ncl_VFS vfs, const char *path); bool ncl_mkdirRecursive(ncl_VFS vfs, const char *path); +bool ncl_copyto(ncl_VFS vfs, const char *from, const char *to); + typedef struct ncl_EncodedState { char *buf; size_t len; diff --git a/src/neonucleus.c b/src/neonucleus.c index c6af2ff..14568a1 100644 --- a/src/neonucleus.c +++ b/src/neonucleus.c @@ -3272,10 +3272,10 @@ nn_Component *nn_createEEPROM(nn_Universe *universe, const char *address, const [NN_EENUM_GETDATA] = {"getData", "function(): string - Get the data stored on the eeprom", NN_DIRECT}, [NN_EENUM_GETLABEL] = {"getLabel", "function(): string? - Get the label stored on the eeprom, if any", NN_DIRECT}, [NN_EENUM_GETARCH] = {"getArchitecture", "function(): string? - Get the desired architecture stored on the eeprom, if any", NN_DIRECT}, - [NN_EENUM_SET] = {"set", "function(code: string) - Set the code on the EEPROM", NN_DIRECT}, - [NN_EENUM_SETDATA] = {"setData", "function(data: string) - Set the data on the EEPROM", NN_DIRECT}, - [NN_EENUM_SETLABEL] = {"setLabel", "function(label?: string) - Set the label", NN_DIRECT}, - [NN_EENUM_SETARCH] = {"setArchitecture", "function(arch?: string) - Set the desired architecture", NN_DIRECT}, + [NN_EENUM_SET] = {"set", "function(code: string) - Set the code on the EEPROM", NN_INDIRECT}, + [NN_EENUM_SETDATA] = {"setData", "function(data: string) - Set the data on the EEPROM", NN_INDIRECT}, + [NN_EENUM_SETLABEL] = {"setLabel", "function(label?: string) - Set the label", NN_INDIRECT}, + [NN_EENUM_SETARCH] = {"setArchitecture", "function(arch?: string) - Set the desired architecture", NN_INDIRECT}, }; nn_Exit e = nn_setComponentMethodsArray(c, methods, NN_EENUM_COUNT); if(e) { @@ -3740,7 +3740,7 @@ nn_Component *nn_createFilesystem(nn_Universe *universe, const char *address, co [NN_FSNUM_SPACETOTAL] = {"spaceTotal", "function(): integer - Capacity of the drive", NN_DIRECT}, [NN_FSNUM_SPACEUSED] = {"spaceUsed", "function(): integer - Amount of space used", NN_DIRECT}, [NN_FSNUM_GETLABEL] = {"getLabel", "function(): string? - Gets the label of the drive, if any", NN_DIRECT}, - [NN_FSNUM_SETLABEL] = {"setLabel", "function(label?: string): string - Sets the label of the drive. Returns the new label, which may be truncated", NN_DIRECT}, + [NN_FSNUM_SETLABEL] = {"setLabel", "function(label?: string): string - Sets the label of the drive. Returns the new label, which may be truncated", NN_INDIRECT}, [NN_FSNUM_ISRO] = {"isReadOnly", "function(): boolean - Returns whether the drive is read-only", NN_DIRECT}, [NN_FSNUM_OPEN] = {"open", "function(path: string, mode?: 'r'|'w'|'a'): integer - Open a file", NN_DIRECT}, [NN_FSNUM_READ] = {"read", "function(fd: integer, len?: integer): string? - Read from a file, returns nothing on EoF", NN_DIRECT}, @@ -3753,8 +3753,8 @@ nn_Component *nn_createFilesystem(nn_Universe *universe, const char *address, co [NN_FSNUM_SIZE] = {"size", "function(path: string): integer - Returns the size of an entry", NN_DIRECT}, [NN_FSNUM_LASTMODIFIED] = {"lastModified", "function(path: string): integer - Returns the UNIX timestamp of the last modified time", NN_DIRECT}, [NN_FSNUM_MKDIR] = {"makeDirectory", "function(path: string): boolean - Create a directory, recursively. Does not fail if directory already exists", NN_DIRECT}, - [NN_FSNUM_REMOVE] = {"remove", "function(path: string): boolean - Recursively deletes an entry", NN_DIRECT}, - [NN_FSNUM_RENAME] = {"rename", "function(from: string, to: string): boolean - Renames/moves an entry", NN_DIRECT}, + [NN_FSNUM_REMOVE] = {"remove", "function(path: string): boolean - Recursively deletes an entry", NN_INDIRECT}, + [NN_FSNUM_RENAME] = {"rename", "function(from: string, to: string): boolean - Renames/moves an entry", NN_INDIRECT}, }; nn_Exit e = nn_setComponentMethodsArray(c, methods, NN_FSNUM_COUNT); if(e) {