#define FS_TYPE_UNSUPPORTED -1 #define FS_TYPE_SYSTEM 0 #define FS_TYPE_REDSEA 1 #define FS_TYPE_9P 2 #define DE_TYPE_FILE 0 #define DE_TYPE_DIR 1 class @dir_entry { U8 mode; U8 type; U32 atime; U32 mtime; U64 size; U8 name[255]; U8 uid[255]; U8 gid[255]; @dir_entry* next; }; extern Bool @plan9fs_file_find(U8* path); extern @dir_entry* @plan9fs_get_files(U8* path); extern U8* @plan9fs_read_file(U8* path, I64* size); extern I64 @plan9fs_write_file(U8* path, U64 buffer, I64 size); class @filesystem { I64 root_fs_type; @dir_entry (*GetFiles)(U8* path); U8* (*GetFileExtension)(U8* path); U0 (*Init)(); Bool (*PathExists)(U8* path); U8* (*ReadFile)(U8* path, I64* size); I64* (*WriteFile)(U8* path, U64 buffer, I64 size); }; @filesystem FileSystem; U8* @filesystem_resolve_path(U8* path) { U8* abs_path = CAlloc(StrLen(path)); I64 argc; I64 i; I64 pos = 0; U8** argv; U8** outv; U8* path_cpy = StrNew(path); argv = String.Split(path_cpy, '/', &argc); outv = CAlloc(sizeof(U64) * argc); for (i = 0; i < argc; i++) { if (!(!StrCmp(argv[i], ".") || !StrCmp(argv[i], "") || !StrCmp(argv[i], ".."))) { outv[pos] = argv[i]; pos++; } if (!StrCmp(argv[i], "..")) { pos = Max(0, pos - 1); } } for (i = 0; i < pos; i++) String.Append(abs_path, "/%s", outv[i]); Free(path_cpy); Free(outv); if (abs_path[StrLen(abs_path) - 1] == '/') abs_path[StrLen(abs_path) - 1] = NULL; if (!StrLen(abs_path)) StrCpy(abs_path, "/"); return abs_path; } I64 @filesystem_get_type(U8* path) { if (!MemCmp(path, "/mnt/redsea/", 12) && StrLen(path) > 12) return FS_TYPE_REDSEA; if (!MemCmp(path, "/sys/", 5)) return FS_TYPE_SYSTEM; return FileSystem.root_fs_type; } @dir_entry* @filesystem_get_files_9p(U8* path) { return @plan9fs_get_files(path); } @dir_entry* @filesystem_get_files_redsea(U8* path) { CDirEntry* de = FilesFind(path); CDirEntry* tmpde = NULL; @dir_entry* entries = NULL; @dir_entry* entry = NULL; @dir_entry* new = NULL; if (de) { entries = CAlloc(sizeof(@dir_entry)); entry = entries; tmpde = de; while (tmpde) { new = CAlloc(sizeof(@dir_entry)); entry->next = new; StrCpy(&new->name, &tmpde->name); StrCpy(&new->uid, "templeos"); // No file ownership in TempleOS StrCpy(&new->gid, "templeos"); // No file ownership in TempleOS new->size = tmpde->size; new->type = T(IsDir(tmpde->full_name), 1, 0); entry = new; tmpde = tmpde->next; } DirTreeDel(de); return entries; } return NULL; } @dir_entry* @filesystem_get_files(U8* path) { if (!path) return NULL; U8 buf[512]; I64 type = @filesystem_get_type(path); switch (type) { case FS_TYPE_SYSTEM: SysHlt; break; case FS_TYPE_REDSEA: StrPrint(&buf, "%c:%s", ToUpper(path[12]), path + 13); if (buf[StrLen(&buf) - 1] == ':') buf[StrLen(&buf)] = '/'; if (buf[StrLen(&buf) - 1] == '/') buf[StrLen(&buf)] = '.'; return @filesystem_get_files_redsea(&buf); break; case FS_TYPE_9P: return @filesystem_get_files_9p(path); break; default: break; } return NULL; } U8* @filesystem_get_file_extension(U8* path) { return (StrLastOcc(path, ".") + 1); } Bool @filesystem_path_exists(U8* opath) { if (!opath) return FALSE; U8 buf[512]; U8* path = @filesystem_resolve_path(opath); I64 type = @filesystem_get_type(path); switch (type) { case FS_TYPE_SYSTEM: return NULL; SysHlt; break; case FS_TYPE_REDSEA: StrPrint(&buf, "%c:%s", ToUpper(path[12]), path + 13); if (buf[StrLen(&buf) - 1] == ':') buf[StrLen(&buf)] = '/'; if (buf[StrLen(&buf) - 1] == '/') buf[StrLen(&buf)] = '.'; Free(path); return FileFind(&buf); break; case FS_TYPE_9P: return NULL; Free(path); return @plan9fs_file_find(path); break; default: break; } return NULL; } U8* @filesystem_read_file(U8* path, I64* size) { if (!path) return FALSE; U8 buf[512]; I64 type = @filesystem_get_type(path); switch (type) { case FS_TYPE_SYSTEM: SysHlt; break; case FS_TYPE_REDSEA: StrPrint(&buf, "%c:%s", ToUpper(path[12]), path + 13); return FileRead(&buf, size); break; case FS_TYPE_9P: return @plan9fs_read_file(path, size); break; default: break; } return NULL; } I64 @filesystem_write_file(U8* path, U8* buffer, I64 size) { if (!path || !buffer || !size) return FALSE; U8 buf[512]; I64 type = @filesystem_get_type(path); switch (type) { case FS_TYPE_SYSTEM: SysHlt; break; case FS_TYPE_REDSEA: StrPrint(&buf, "%c:%s", ToUpper(path[12]), path + 13); return FileWrite(&buf, buffer, size); break; case FS_TYPE_9P: return @plan9fs_write_file(path, buffer, size); break; default: break; } return NULL; } FileSystem.GetFiles = &@filesystem_get_files; FileSystem.GetFileExtension = &@filesystem_get_file_extension; FileSystem.PathExists = &@filesystem_path_exists; FileSystem.ReadFile = &@filesystem_read_file; FileSystem.WriteFile = &@filesystem_write_file; "filesystem ";