Partially fixed logic in the file system class with changes to support fs table structure instead of a tree

This commit is contained in:
2025-12-02 04:02:19 +01:00
parent 85d98a41c1
commit 8e0ae3dd83
3 changed files with 145 additions and 132 deletions

View File

@@ -15,6 +15,12 @@ export type BashInitArgs = {
fs: any;
};
export type TimeStamps = {
mTime: Date;
cTime: Date;
aTime: Date;
}
// TODO: Finish this
// TODO: Change into a type instead of an enum for performance (low priority)
export enum ExitCode {
@@ -29,8 +35,8 @@ export type User = {
readonly gid: number; // Primary group | 'Users' 1000 - Others - 1000+ root - 0 //TODO: Make a formated type
home: string; //TODO: Make a formated type
history: string[];
cwd?: string[]; //TODO: Make a formated type
pwd?: string[]; //TODO: Make a formated type
cwd?: number; //TODO: Make a formated type
pwd?: number; //TODO: Make a formated type
};
export type Group = {
@@ -69,11 +75,11 @@ export class Bash {
}
}
getCwd(): string[] {
getCwd(): number {
return this.vfs.cwd;
}
getPwd(): string[] {
getPwd(): number {
return this.vfs.pwd;
}
@@ -89,13 +95,6 @@ export class Bash {
return this._group[1].members.includes(uid);
}
changeUser(user: User) {
this.user = user;
this.vfs.home = this.vfs._splitPathString(user.home);
this.vfs.cwd = user.cwd ? user.cwd : this.vfs._splitPathString(user.home);
this.vfs.pwd = user.pwd ? user.pwd : this.vfs._splitPathString(user.home);
}
executeCommand(commandName: string, args: CommandArgs): void {
let result: Result = { exitCode: ExitCode.ERROR };
const command = this._commands[commandName];
@@ -121,23 +120,12 @@ export class Bash {
}
}
userLogin(username: string, passwd: string): ExitCode {
const user: User | undefined = this._passwd.find((u) => u.username === username);
if (user === undefined) return ExitCode.ERROR;
if (user.passwd === passwd) {
this._instances.push(user);
this.changeUser(user);
return ExitCode.ERROR; //TODO: Make it return the exitcode of changeUser() if needed
} else return ExitCode.ERROR;
}
userLogout() {
this._instances.pop();
if (this._instances.size() === 0) {
//TODO: Implement system logout
} else {
this.changeUser(this._instances.peek()!);
//this.changeUser(this._instances.peek()!);
}
}

View File

@@ -1,9 +1,12 @@
import type { readonly } from 'svelte/store';
import type { Permission, User } from './bash';
import type { Permission, TimeStamps, User } from './bash';
import { Stack } from '../stack';
import { Pause } from '@lucide/svelte';
export enum Type {
Directory = 16384,
File = 32768
File = 32768,
SymblicLink = 40960
}
export type NodePerms = {
@@ -18,118 +21,132 @@ export type FsInitArgs = {
};
export type TreeNode = {
inode: number;
parent?: number;
name: string;
type: Type;
readonly: boolean;
children: number[];
content: string; // GUID of the cache file that contains the file contents.
link: number; // Links
permission: NodePerms;
owner: number;
group: number;
timestamps: TimeStamps;
interactible: boolean;
func: any;
children: TreeNode[];
content: string; // Path to the content of the file
link: string[]; // Symlink
permission: NodePerms;
owner: string;
group: string;
modtime: Date;
parent?: TreeNode;
};
export class VirtualFS {
private root: TreeNode; // TODO make this the correct type
private FsTable: Map<number, TreeNode>;
private rootINode: number;
home: string[];
cwd: string[];
pwd: string[];
home: number;
cwd: number;
pwd: number;
constructor(args: FsInitArgs) {
this.root = args.fs;
this.home = this._splitPathString(args.user.home);
this.FsTable = args.fs;
this.rootINode = 1;
this.home = this._pathStringToINode(args.user.home);
this.cwd = args.user.cwd ? args.user.cwd : this.home;
this.pwd = args.user.pwd ? args.user.pwd : this.cwd;
console.log(this.home);
console.log(this.cwd);
console.log(this.pwd);
console.log('VFS INIT ', this._getNodeByPathArray(['/', 'home', 'kamil']));
}
private _iNodeToPathString(inode: number): string {
let components: Stack<string> = new Stack<string>();
let currentNode = this.FsTable.get(inode);
let path: string = '';
if(!currentNode) throw new Error('iNode does not exist,');
_splitPathString(path: string): string[] {
if (path === '/') return ['/'];
components.push(currentNode.name);
const raw: string[] = path.split('/');
const parts: string[] = [];
if(!currentNode.parent) {
for(let i = 0; i < components.size(); i++) {
path += components.pop() + '/';
}
for (let i = 0; i < raw.length; i++) {
if (raw[i].length > 0) parts.push(raw[i]);
} else {
this._iNodeToPathString(currentNode.parent);
}
return parts;
return path;
}
_isAbsolutePath = (path: string): boolean => {
private _pathStringToINode(path: string): number {
const normalizedPath = path.replace(/^\/+|\/+$/g, '');
const pathComponents = normalizedPath.split('/').filter(component => component.length > 0);
if(pathComponents.length === 0) return this.rootINode;
let currentNode = this.FsTable.get(this.rootINode);
if(!currentNode) throw new Error('iNode does not exist,');
for(const component of pathComponents) {
const childINode = this._findChildNodeByName(currentNode, component);
if(childINode === null) throw new Error('this child iNode does not exist,');
const nextNode = this.FsTable.get(childINode);
if(!nextNode) throw new Error('iNode child does not exist,');
currentNode = nextNode;
}
return currentNode.inode;
}
private _findChildNodeByName(node: TreeNode, name: string): number {
for(const childINode of node.children) {
const child = this.FsTable.get(childINode);
if(child && child.name === name) {
return childINode;
}
}
throw new Error('could not find the specified child node');
}
private _isAbsolutePath = (path: string): boolean => {
return typeof path === 'string' && path.startsWith('/');
};
pathArrayToString(path: string[]): string {
if (path.length === 1 && path[0] === '/') return '/';
return '/' + path.join('/');
}
formatPath(path: string): string {
const prefix = this.pathArrayToString(this.home);
const prefix = this._iNodeToPathString(this.home);
if (path.startsWith(prefix)) {
return path.replace(prefix, '~');
} else return path;
}
resolvePath(path: string): string[] {
if (path === '' || path === undefined || path === null) return this.cwd.slice();
if (path.startsWith('/') && path.length === 1) return [];
resolvePath(path: string): TreeNode{
if(path === '/') return this._getNodeByINode(this.rootINode);
if (path.startsWith('~')) {
const trail: string = path === '~' ? '' : path.slice(1);
const home: string = this.pathArrayToString(this.home);
path = home + (trail ? (trail.startsWith('/') ? '' : '/') + trail : '');
if (!this._isAbsolutePath(path)) {
const trail: string = this._iNodeToPathString(this.cwd);
path = trail + path;
}
else if (path.startsWith('~')) {
const trail: string = this._iNodeToPathString(this.home);
path = trail + path
}
const start = this._isAbsolutePath(path) ? [] : this.cwd.slice();
const parts = this._splitPathString(path);
console.log(path);
for (let i = 0; i < parts.length; i++) {
const seg = parts[i];
const INode: number = this._pathStringToINode(path);
const Node: TreeNode = this._getNodeByINode(INode);
if (seg === '.' || seg === '') continue;
if (seg === '..') {
if (start.length > 1) start.pop();
continue;
}
start.push(seg);
}
if (start.length === 0) return [];
console.log('OUTPUT', start);
return start;
return Node;
}
_getNodeByPathArray(path: string[]): TreeNode | null {
if (path.length === 1 && path[0] === '/') return this.root;
let node: TreeNode = this.root;
const parts: string[] = path.slice(path[0] === '/' ? 1 : 0);
for (let i = 0; i < parts.length; i++) {
const seg: string = parts[i];
if (node.type === Type.File) return node;
const newNode = node.children.find((child) => child.name === seg);
console.log(newNode);
if (newNode !== undefined) node = newNode;
else return null;
}
private _getNodeByINode(inode: number): TreeNode {
const node: TreeNode | undefined = this.FsTable.get(inode);
if(!node) throw new Error('Could not get the node, no such i node exists');
return node;
}
_getPathToNode(node: TreeNode): string[] {
private _getPathToNode(node: TreeNode): string[] {
const path: string[] = [];
let current = node;
path.push(node.name);

View File

@@ -8,44 +8,52 @@ export function isInitializing(): boolean {
return initializing;
}
function jsonToTreeNode(data: any, parent?: TreeNode): TreeNode {
const node: TreeNode = {
name: data.Name,
type: data.Type,
readonly: data.ReadOnly,
interactible: data.Interactible,
func: data.Func,
children: [],
content: data.Content,
link: data.Link || [],
permission: {
user: {
r: data.Permission[0]?.Read,
w: data.Permission[0]?.Write,
x: data.Permission[0]?.Exec
},
group: {
r: data.Permission[1]?.Read,
w: data.Permission[1]?.Write,
x: data.Permission[1]?.Exec
},
other: {
r: data.Permission[2]?.Read,
w: data.Permission[2]?.Write,
x: data.Permission[2]?.Exec
}
},
owner: data.Owner,
group: data.Group,
modtime: new Date(data.Mtime),
parent: parent
};
function jsonToNodeTable(data: any, parent?: number): Map<number, TreeNode> {
const FsTable: Map<number, TreeNode> = new Map<number, TreeNode>;
const keyList = Object.keys(data);
node.children = data.Children
? data.Children.map((child: any) => jsonToTreeNode(child, node))
: [];
for(const key in keyList) {
const object = data[key];
const node: TreeNode = {
inode: object.Inode,
name: object.Name,
type: object.Type,
interactible: object.Interactible,
func: object.Func,
children: [],
content: object.Content,
link: object.Link || [],
permission: {
user: {
r: object.Permission[0]?.Read,
w: object.Permission[0]?.Write,
x: object.Permission[0]?.Exec
},
group: {
r: object.Permission[1]?.Read,
w: object.Permission[1]?.Write,
x: object.Permission[1]?.Exec
},
other: {
r: object.Permission[2]?.Read,
w: object.Permission[2]?.Write,
x: object.Permission[2]?.Exec
}
},
owner: object.Owner,
group: object.Group,
timestamps: {
mTime: new Date(object.TimeStamps.MTime),
cTime: new Date(object.TimeStamps.CTime),
aTime: new Date(object.TimeStamps.ATime)
},
parent: object.parent
};
return node;
FsTable.set(object.Inode, node);
}
console.log(FsTable);
return FsTable;
}
async function fetchFsJson(sig: string): Promise<any> {
@@ -95,7 +103,7 @@ export async function initTerminal(user: User, callbackInit: any): Promise<Termi
try {
const sig = await fetchFsSignature('/src/lib/assets/fs/signature');
const fsJson = await fetchFsJson(sig);
const fs: TreeNode = jsonToTreeNode(fsJson);
const fs: Map<number, TreeNode> = jsonToNodeTable(fsJson);
const args: TermInitArgs = {
bash: {