@componentor/fs 3.0.12 → 3.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/workers/repair.worker.js +11 -7
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +1 -1
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +1 -1
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/src/vfs/layout.ts","../../src/src/errors.ts","../../src/src/vfs/engine.ts","../../src/src/workers/repair.worker.ts"],"sourcesContent":["/**\n * VFS Binary Layout Constants\n *\n * Defines the on-disk structure of the virtual filesystem binary file.\n * All reads/writes go through a FileSystemSyncAccessHandle.\n */\n\n// Magic number: \"VFS!\" in ASCII\nexport const VFS_MAGIC = 0x56465321;\nexport const VFS_VERSION = 1;\n\n// Default sizes\nexport const DEFAULT_BLOCK_SIZE = 4096;\nexport const DEFAULT_INODE_COUNT = 10000;\nexport const INODE_SIZE = 64; // bytes per inode entry\n\n// Superblock layout (64 bytes)\nexport const SUPERBLOCK = {\n SIZE: 64,\n MAGIC: 0, // uint32 - 0x56465321\n VERSION: 4, // uint32\n INODE_COUNT: 8, // uint32 - total inodes allocated\n BLOCK_SIZE: 12, // uint32 - data block size (default 4096)\n TOTAL_BLOCKS: 16, // uint32 - total data blocks\n FREE_BLOCKS: 20, // uint32 - available data blocks\n INODE_OFFSET: 24, // float64 - byte offset to inode table\n PATH_OFFSET: 32, // float64 - byte offset to path table\n DATA_OFFSET: 40, // float64 - byte offset to data region\n BITMAP_OFFSET: 48, // float64 - byte offset to free block bitmap\n PATH_USED: 56, // uint32 - bytes used in path table\n RESERVED: 60, // uint32\n} as const;\n\n// Inode entry layout (64 bytes each)\nexport const INODE = {\n TYPE: 0, // uint8 - 0=free, 1=file, 2=directory, 3=symlink\n FLAGS: 1, // uint8[3] - reserved\n PATH_OFFSET: 4, // uint32 - byte offset into path table\n PATH_LENGTH: 8, // uint16 - length of path string\n RESERVED_10: 10, // uint16\n MODE: 12, // uint32 - permissions (e.g. 0o100644)\n SIZE: 16, // float64 - file content size in bytes (using f64 for >4GB)\n FIRST_BLOCK: 24, // uint32 - index of first data block\n BLOCK_COUNT: 28, // uint32 - number of contiguous data blocks\n MTIME: 32, // float64 - last modification time (ms since epoch)\n CTIME: 40, // float64 - creation/change time (ms since epoch)\n ATIME: 48, // float64 - last access time (ms since epoch)\n UID: 56, // uint32 - owner\n GID: 60, // uint32 - group\n} as const;\n\n// Inode type constants\nexport const INODE_TYPE = {\n FREE: 0,\n FILE: 1,\n DIRECTORY: 2,\n SYMLINK: 3,\n} as const;\n\n// Default file modes\nexport const DEFAULT_FILE_MODE = 0o100644;\nexport const DEFAULT_DIR_MODE = 0o040755;\nexport const DEFAULT_SYMLINK_MODE = 0o120777;\nexport const DEFAULT_UMASK = 0o022;\n\n// POSIX file type bits\nexport const S_IFMT = 0o170000;\nexport const S_IFREG = 0o100000;\nexport const S_IFDIR = 0o040000;\nexport const S_IFLNK = 0o120000;\n\n// Max symlink depth for cycle detection\nexport const MAX_SYMLINK_DEPTH = 40;\n\n// Path table compaction threshold (25% dead space)\nexport const PATH_COMPACTION_THRESHOLD = 0.25;\n\n// Initial path table size (256KB)\nexport const INITIAL_PATH_TABLE_SIZE = 256 * 1024;\n\n// Initial data blocks (1024 blocks = 4MB with 4KB blocks)\nexport const INITIAL_DATA_BLOCKS = 1024;\n\n/**\n * Calculate section offsets for a fresh VFS.\n */\nexport function calculateLayout(inodeCount: number = DEFAULT_INODE_COUNT, blockSize: number = DEFAULT_BLOCK_SIZE, totalBlocks: number = INITIAL_DATA_BLOCKS) {\n const inodeTableOffset = SUPERBLOCK.SIZE;\n const inodeTableSize = inodeCount * INODE_SIZE;\n const pathTableOffset = inodeTableOffset + inodeTableSize;\n const pathTableSize = INITIAL_PATH_TABLE_SIZE;\n const bitmapOffset = pathTableOffset + pathTableSize;\n const bitmapSize = Math.ceil(totalBlocks / 8);\n // Align data region to block boundary\n const dataOffset = Math.ceil((bitmapOffset + bitmapSize) / blockSize) * blockSize;\n const totalSize = dataOffset + totalBlocks * blockSize;\n\n return {\n inodeTableOffset,\n inodeTableSize,\n pathTableOffset,\n pathTableSize,\n bitmapOffset,\n bitmapSize,\n dataOffset,\n totalSize,\n totalBlocks,\n };\n}\n","/**\n * Node.js compatible filesystem error classes\n */\n\nexport class FSError extends Error {\n code: string;\n errno: number;\n syscall?: string;\n path?: string;\n\n constructor(code: string, errno: number, message: string, syscall?: string, path?: string) {\n super(message);\n this.name = 'FSError';\n this.code = code;\n this.errno = errno;\n this.syscall = syscall;\n this.path = path;\n }\n}\n\nexport const ErrorCodes = {\n ENOENT: -2,\n EEXIST: -17,\n EISDIR: -21,\n ENOTDIR: -20,\n ENOTEMPTY: -39,\n EACCES: -13,\n EBADF: -9,\n EINVAL: -22,\n EMFILE: -24,\n ENOSPC: -28,\n EPERM: -1,\n ENOSYS: -38,\n ELOOP: -40,\n} as const;\n\n/** Binary protocol status codes → error code mapping */\nexport const STATUS_TO_CODE: Record<number, string> = {\n 0: 'OK',\n 1: 'ENOENT',\n 2: 'EEXIST',\n 3: 'EISDIR',\n 4: 'ENOTDIR',\n 5: 'ENOTEMPTY',\n 6: 'EACCES',\n 7: 'EINVAL',\n 8: 'EBADF',\n 9: 'ELOOP',\n 10: 'ENOSPC',\n};\n\n/** Error code → binary protocol status mapping */\nexport const CODE_TO_STATUS: Record<string, number> = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n};\n\nexport function createError(code: string, syscall: string, path: string): FSError {\n const errno = ErrorCodes[code as keyof typeof ErrorCodes] ?? -1;\n const messages: Record<string, string> = {\n ENOENT: 'no such file or directory',\n EEXIST: 'file already exists',\n EISDIR: 'illegal operation on a directory',\n ENOTDIR: 'not a directory',\n ENOTEMPTY: 'directory not empty',\n EACCES: 'permission denied',\n EINVAL: 'invalid argument',\n EBADF: 'bad file descriptor',\n ELOOP: 'too many symbolic links encountered',\n ENOSPC: 'no space left on device',\n };\n const msg = messages[code] ?? 'unknown error';\n return new FSError(code, errno, `${code}: ${msg}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function statusToError(status: number, syscall: string, path: string): FSError {\n const code = STATUS_TO_CODE[status] ?? 'EINVAL';\n return createError(code, syscall, path);\n}\n","/**\n * VFS Engine — operates on a FileSystemSyncAccessHandle\n *\n * Manages the binary VFS layout: superblock, inode table, path table,\n * free block bitmap, and data region. All operations are synchronous\n * and run inside the server worker.\n */\n\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_BLOCK_SIZE, DEFAULT_INODE_COUNT, DEFAULT_FILE_MODE, DEFAULT_DIR_MODE,\n DEFAULT_SYMLINK_MODE, DEFAULT_UMASK, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK,\n MAX_SYMLINK_DEPTH, INITIAL_DATA_BLOCKS, INITIAL_PATH_TABLE_SIZE,\n calculateLayout,\n} from './layout.js';\nimport { CODE_TO_STATUS } from '../errors.js';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\ninterface Inode {\n type: number;\n pathOffset: number;\n pathLength: number;\n mode: number;\n size: number;\n firstBlock: number;\n blockCount: number;\n mtime: number;\n ctime: number;\n atime: number;\n uid: number;\n gid: number;\n}\n\ninterface FdEntry {\n tabId: string;\n inodeIdx: number;\n position: number;\n flags: number;\n}\n\nexport class VFSEngine {\n private handle!: FileSystemSyncAccessHandle;\n private pathIndex = new Map<string, number>(); // path → inode index\n private inodeCount = 0;\n private blockSize = DEFAULT_BLOCK_SIZE;\n private totalBlocks = 0;\n private freeBlocks = 0;\n private inodeTableOffset = 0;\n private pathTableOffset = 0;\n private pathTableUsed = 0;\n private pathTableSize = 0;\n private bitmapOffset = 0;\n private dataOffset = 0;\n private umask = DEFAULT_UMASK;\n private processUid = 0;\n private processGid = 0;\n private strictPermissions = false;\n private debug = false;\n\n // File descriptor table\n private fdTable = new Map<number, FdEntry>();\n private nextFd = 3; // 0=stdin, 1=stdout, 2=stderr reserved\n\n // Reusable buffers to avoid allocations\n private inodeBuf = new Uint8Array(INODE_SIZE);\n private inodeView = new DataView(this.inodeBuf.buffer);\n\n // In-memory inode cache — eliminates disk reads for hot inodes\n private inodeCache = new Map<number, Inode>();\n private superblockBuf = new Uint8Array(SUPERBLOCK.SIZE);\n private superblockView = new DataView(this.superblockBuf.buffer);\n\n // In-memory bitmap cache — eliminates bitmap reads from OPFS\n private bitmap: Uint8Array | null = null;\n private bitmapDirtyLo = Infinity; // lowest dirty byte index\n private bitmapDirtyHi = -1; // highest dirty byte index (inclusive)\n private superblockDirty = false;\n\n // Free inode hint — skip O(n) scan\n private freeInodeHint = 0;\n\n init(\n handle: FileSystemSyncAccessHandle,\n opts?: { uid?: number; gid?: number; umask?: number; strictPermissions?: boolean; debug?: boolean }\n ): void {\n this.handle = handle;\n this.processUid = opts?.uid ?? 0;\n this.processGid = opts?.gid ?? 0;\n this.umask = opts?.umask ?? DEFAULT_UMASK;\n this.strictPermissions = opts?.strictPermissions ?? false;\n this.debug = opts?.debug ?? false;\n\n const size = handle.getSize();\n\n if (size === 0) {\n this.format();\n } else {\n this.mount();\n }\n }\n\n /** Release the sync access handle (call on fatal error or shutdown) */\n closeHandle(): void {\n try {\n this.handle?.close();\n } catch (_) {\n // Ignore — handle may already be closed\n }\n }\n\n /** Format a fresh VFS */\n private format(): void {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n\n this.inodeCount = DEFAULT_INODE_COUNT;\n this.blockSize = DEFAULT_BLOCK_SIZE;\n this.totalBlocks = layout.totalBlocks;\n this.freeBlocks = layout.totalBlocks;\n this.inodeTableOffset = layout.inodeTableOffset;\n this.pathTableOffset = layout.pathTableOffset;\n this.pathTableSize = layout.pathTableSize;\n this.pathTableUsed = 0;\n this.bitmapOffset = layout.bitmapOffset;\n this.dataOffset = layout.dataOffset;\n\n // Grow file to total size\n this.handle.truncate(layout.totalSize);\n\n // Write superblock\n this.writeSuperblock();\n\n // Zero out inode table (type=0 means free)\n const zeroBuf = new Uint8Array(layout.inodeTableSize);\n this.handle.write(zeroBuf, { at: this.inodeTableOffset });\n\n // Zero out bitmap and cache in memory\n this.bitmap = new Uint8Array(layout.bitmapSize);\n this.handle.write(this.bitmap, { at: this.bitmapOffset });\n\n // Create root directory inode\n this.createInode('/', INODE_TYPE.DIRECTORY, DEFAULT_DIR_MODE, 0);\n\n // Re-write superblock with updated pathTableUsed (createInode appended \"/\" to path table)\n this.writeSuperblock();\n this.handle.flush();\n }\n\n /** Mount an existing VFS from disk — validates superblock integrity */\n private mount(): void {\n const fileSize = this.handle.getSize();\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: file too small (${fileSize} bytes, need at least ${SUPERBLOCK.SIZE})`);\n }\n\n this.handle.read(this.superblockBuf, { at: 0 });\n const v = this.superblockView;\n\n // Validate magic\n const magic = v.getUint32(SUPERBLOCK.MAGIC, true);\n if (magic !== VFS_MAGIC) {\n throw new Error(`Corrupt VFS: bad magic 0x${magic.toString(16)} (expected 0x${VFS_MAGIC.toString(16)})`);\n }\n\n // Validate version\n const version = v.getUint32(SUPERBLOCK.VERSION, true);\n if (version !== VFS_VERSION) {\n throw new Error(`Corrupt VFS: unsupported version ${version} (expected ${VFS_VERSION})`);\n }\n\n // Read superblock fields\n const inodeCount = v.getUint32(SUPERBLOCK.INODE_COUNT, true);\n const blockSize = v.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n const totalBlocks = v.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n const freeBlocks = v.getUint32(SUPERBLOCK.FREE_BLOCKS, true);\n const inodeTableOffset = v.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n const pathTableOffset = v.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n const dataOffset = v.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n const bitmapOffset = v.getFloat64(SUPERBLOCK.BITMAP_OFFSET, true);\n const pathUsed = v.getUint32(SUPERBLOCK.PATH_USED, true);\n\n // Validate field sanity\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0) {\n throw new Error(`Corrupt VFS: invalid block size ${blockSize} (must be power of 2)`);\n }\n if (inodeCount === 0) {\n throw new Error('Corrupt VFS: inode count is 0');\n }\n if (freeBlocks > totalBlocks) {\n throw new Error(`Corrupt VFS: free blocks (${freeBlocks}) exceeds total blocks (${totalBlocks})`);\n }\n\n // Validate section ordering: superblock < inodes < paths < bitmap < data\n if (inodeTableOffset !== SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: inode table offset ${inodeTableOffset} (expected ${SUPERBLOCK.SIZE})`);\n }\n const expectedPathOffset = inodeTableOffset + inodeCount * INODE_SIZE;\n if (pathTableOffset !== expectedPathOffset) {\n throw new Error(`Corrupt VFS: path table offset ${pathTableOffset} (expected ${expectedPathOffset})`);\n }\n if (bitmapOffset <= pathTableOffset) {\n throw new Error(`Corrupt VFS: bitmap offset ${bitmapOffset} must be after path table ${pathTableOffset}`);\n }\n if (dataOffset <= bitmapOffset) {\n throw new Error(`Corrupt VFS: data offset ${dataOffset} must be after bitmap ${bitmapOffset}`);\n }\n const pathTableSize = bitmapOffset - pathTableOffset;\n if (pathUsed > pathTableSize) {\n throw new Error(`Corrupt VFS: path used (${pathUsed}) exceeds path table size (${pathTableSize})`);\n }\n\n // Validate file is large enough for the declared layout\n const expectedMinSize = dataOffset + totalBlocks * blockSize;\n if (fileSize < expectedMinSize) {\n throw new Error(`Corrupt VFS: file size ${fileSize} too small for layout (need ${expectedMinSize})`);\n }\n\n // All checks passed — commit to engine state\n this.inodeCount = inodeCount;\n this.blockSize = blockSize;\n this.totalBlocks = totalBlocks;\n this.freeBlocks = freeBlocks;\n this.inodeTableOffset = inodeTableOffset;\n this.pathTableOffset = pathTableOffset;\n this.dataOffset = dataOffset;\n this.bitmapOffset = bitmapOffset;\n this.pathTableUsed = pathUsed;\n this.pathTableSize = pathTableSize;\n\n // Load bitmap into memory\n const bitmapSize = Math.ceil(this.totalBlocks / 8);\n this.bitmap = new Uint8Array(bitmapSize);\n this.handle.read(this.bitmap, { at: this.bitmapOffset });\n\n this.rebuildIndex();\n\n // Verify root directory exists\n if (!this.pathIndex.has('/')) {\n throw new Error('Corrupt VFS: root directory \"/\" not found in inode table');\n }\n }\n\n private writeSuperblock(): void {\n const v = this.superblockView;\n v.setUint32(SUPERBLOCK.MAGIC, VFS_MAGIC, true);\n v.setUint32(SUPERBLOCK.VERSION, VFS_VERSION, true);\n v.setUint32(SUPERBLOCK.INODE_COUNT, this.inodeCount, true);\n v.setUint32(SUPERBLOCK.BLOCK_SIZE, this.blockSize, true);\n v.setUint32(SUPERBLOCK.TOTAL_BLOCKS, this.totalBlocks, true);\n v.setUint32(SUPERBLOCK.FREE_BLOCKS, this.freeBlocks, true);\n v.setFloat64(SUPERBLOCK.INODE_OFFSET, this.inodeTableOffset, true);\n v.setFloat64(SUPERBLOCK.PATH_OFFSET, this.pathTableOffset, true);\n v.setFloat64(SUPERBLOCK.DATA_OFFSET, this.dataOffset, true);\n v.setFloat64(SUPERBLOCK.BITMAP_OFFSET, this.bitmapOffset, true);\n v.setUint32(SUPERBLOCK.PATH_USED, this.pathTableUsed, true);\n this.handle.write(this.superblockBuf, { at: 0 });\n }\n\n /** Flush pending bitmap and superblock writes to disk (one write each) */\n private markBitmapDirty(lo: number, hi: number): void {\n if (lo < this.bitmapDirtyLo) this.bitmapDirtyLo = lo;\n if (hi > this.bitmapDirtyHi) this.bitmapDirtyHi = hi;\n }\n\n private commitPending(): void {\n // Trim trailing free blocks before flushing bitmap/superblock\n if (this.blocksFreedsinceTrim) {\n this.trimTrailingBlocks();\n this.blocksFreedsinceTrim = false;\n }\n\n if (this.bitmapDirtyHi >= 0) {\n const lo = this.bitmapDirtyLo;\n const hi = this.bitmapDirtyHi;\n this.handle.write(this.bitmap!.subarray(lo, hi + 1), { at: this.bitmapOffset + lo });\n this.bitmapDirtyLo = Infinity;\n this.bitmapDirtyHi = -1;\n }\n if (this.superblockDirty) {\n this.writeSuperblock();\n this.superblockDirty = false;\n }\n }\n\n /** Shrink the OPFS file by removing trailing free blocks from the data region.\n * Scans bitmap from end to find the last used block, then truncates. */\n private trimTrailingBlocks(): void {\n const bitmap = this.bitmap!;\n\n // Find the last used block by scanning bitmap from the end\n let lastUsed = -1;\n for (let byteIdx = Math.ceil(this.totalBlocks / 8) - 1; byteIdx >= 0; byteIdx--) {\n if (bitmap[byteIdx] !== 0) {\n // Find highest set bit in this byte\n for (let bit = 7; bit >= 0; bit--) {\n const blockIdx = byteIdx * 8 + bit;\n if (blockIdx < this.totalBlocks && (bitmap[byteIdx] & (1 << bit))) {\n lastUsed = blockIdx;\n break;\n }\n }\n break;\n }\n }\n\n const newTotal = Math.max(lastUsed + 1, INITIAL_DATA_BLOCKS);\n if (newTotal >= this.totalBlocks) return; // nothing to trim\n\n // Truncate the OPFS file\n this.handle.truncate(this.dataOffset + newTotal * this.blockSize);\n\n // Shrink in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n this.bitmap = bitmap.slice(0, newBitmapSize);\n\n // Update counters\n const trimmed = this.totalBlocks - newTotal;\n this.freeBlocks -= trimmed; // these free blocks no longer exist\n this.totalBlocks = newTotal;\n this.superblockDirty = true;\n\n // Re-mark entire bitmap dirty so the smaller bitmap is flushed\n this.bitmapDirtyLo = 0;\n this.bitmapDirtyHi = newBitmapSize - 1;\n }\n\n /** Rebuild in-memory path→inode index from disk.\n * Bulk-reads the entire inode table + path table in 2 I/O calls,\n * then parses in memory (avoids 10k+ individual reads). */\n private rebuildIndex(): void {\n this.pathIndex.clear();\n this.inodeCache.clear();\n\n // Bulk read entire inode table (e.g. 640KB for 10k inodes)\n const inodeTableSize = this.inodeCount * INODE_SIZE;\n const inodeBuf = new Uint8Array(inodeTableSize);\n this.handle.read(inodeBuf, { at: this.inodeTableOffset });\n const inodeView = new DataView(inodeBuf.buffer);\n\n // Bulk read used portion of path table\n const pathBuf = this.pathTableUsed > 0 ? new Uint8Array(this.pathTableUsed) : null;\n if (pathBuf) {\n this.handle.read(pathBuf, { at: this.pathTableOffset });\n }\n\n for (let i = 0; i < this.inodeCount; i++) {\n const off = i * INODE_SIZE;\n const type = inodeView.getUint8(off + INODE.TYPE);\n if (type === INODE_TYPE.FREE) continue;\n\n // Validate inode type\n if (type < INODE_TYPE.FILE || type > INODE_TYPE.SYMLINK) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid type ${type}`);\n }\n\n const pathOffset = inodeView.getUint32(off + INODE.PATH_OFFSET, true);\n const pathLength = inodeView.getUint16(off + INODE.PATH_LENGTH, true);\n const size = inodeView.getFloat64(off + INODE.SIZE, true);\n const firstBlock = inodeView.getUint32(off + INODE.FIRST_BLOCK, true);\n const blockCount = inodeView.getUint32(off + INODE.BLOCK_COUNT, true);\n\n // Validate path bounds\n if (pathLength === 0 || pathOffset + pathLength > this.pathTableUsed) {\n throw new Error(`Corrupt VFS: inode ${i} path out of bounds (offset=${pathOffset}, len=${pathLength}, tableUsed=${this.pathTableUsed})`);\n }\n\n // Validate data bounds for files/symlinks\n if (type !== INODE_TYPE.DIRECTORY) {\n if (size < 0 || !isFinite(size)) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid size ${size}`);\n }\n if (blockCount > 0 && firstBlock + blockCount > this.totalBlocks) {\n throw new Error(`Corrupt VFS: inode ${i} data blocks out of range (first=${firstBlock}, count=${blockCount}, total=${this.totalBlocks})`);\n }\n }\n\n const inode: Inode = {\n type,\n pathOffset,\n pathLength,\n mode: inodeView.getUint32(off + INODE.MODE, true),\n size,\n firstBlock,\n blockCount,\n mtime: inodeView.getFloat64(off + INODE.MTIME, true),\n ctime: inodeView.getFloat64(off + INODE.CTIME, true),\n atime: inodeView.getFloat64(off + INODE.ATIME, true),\n uid: inodeView.getUint32(off + INODE.UID, true),\n gid: inodeView.getUint32(off + INODE.GID, true),\n };\n this.inodeCache.set(i, inode);\n\n // Decode path from in-memory path table buffer (no disk read)\n let path: string;\n if (pathBuf) {\n path = decoder.decode(pathBuf.subarray(inode.pathOffset, inode.pathOffset + inode.pathLength));\n } else {\n path = this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n // Validate path format\n if (!path.startsWith('/') || path.includes('\\0')) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid path \"${path.substring(0, 50)}\"`);\n }\n\n this.pathIndex.set(path, i);\n }\n }\n\n // ========== Low-level inode I/O ==========\n\n private readInode(idx: number): Inode {\n const cached = this.inodeCache.get(idx);\n if (cached) return cached;\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.read(this.inodeBuf, { at: offset });\n const v = this.inodeView;\n const inode: Inode = {\n type: v.getUint8(INODE.TYPE),\n pathOffset: v.getUint32(INODE.PATH_OFFSET, true),\n pathLength: v.getUint16(INODE.PATH_LENGTH, true),\n mode: v.getUint32(INODE.MODE, true),\n size: v.getFloat64(INODE.SIZE, true),\n firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),\n blockCount: v.getUint32(INODE.BLOCK_COUNT, true),\n mtime: v.getFloat64(INODE.MTIME, true),\n ctime: v.getFloat64(INODE.CTIME, true),\n atime: v.getFloat64(INODE.ATIME, true),\n uid: v.getUint32(INODE.UID, true),\n gid: v.getUint32(INODE.GID, true),\n };\n this.inodeCache.set(idx, inode);\n return inode;\n }\n\n private writeInode(idx: number, inode: Inode): void {\n // Maintain inode cache\n if (inode.type === INODE_TYPE.FREE) {\n this.inodeCache.delete(idx);\n } else {\n this.inodeCache.set(idx, inode);\n }\n\n const v = this.inodeView;\n v.setUint8(INODE.TYPE, inode.type);\n v.setUint8(INODE.FLAGS, 0);\n v.setUint8(INODE.FLAGS + 1, 0);\n v.setUint8(INODE.FLAGS + 2, 0);\n v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);\n v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);\n v.setUint16(INODE.RESERVED_10, 0, true);\n v.setUint32(INODE.MODE, inode.mode, true);\n v.setFloat64(INODE.SIZE, inode.size, true);\n v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);\n v.setUint32(INODE.BLOCK_COUNT, inode.blockCount, true);\n v.setFloat64(INODE.MTIME, inode.mtime, true);\n v.setFloat64(INODE.CTIME, inode.ctime, true);\n v.setFloat64(INODE.ATIME, inode.atime, true);\n v.setUint32(INODE.UID, inode.uid, true);\n v.setUint32(INODE.GID, inode.gid, true);\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.write(this.inodeBuf, { at: offset });\n }\n\n // ========== Path table I/O ==========\n\n private readPath(offset: number, length: number): string {\n const buf = new Uint8Array(length);\n this.handle.read(buf, { at: this.pathTableOffset + offset });\n return decoder.decode(buf);\n }\n\n private appendPath(path: string): { offset: number; length: number } {\n const bytes = encoder.encode(path);\n const offset = this.pathTableUsed;\n\n // Check if path table needs to grow\n if (offset + bytes.byteLength > this.pathTableSize) {\n this.growPathTable(offset + bytes.byteLength);\n }\n\n this.handle.write(bytes, { at: this.pathTableOffset + offset });\n this.pathTableUsed += bytes.byteLength;\n\n // Defer superblock write — committed in commitPending()\n this.superblockDirty = true;\n\n return { offset, length: bytes.byteLength };\n }\n\n private growPathTable(needed: number): void {\n // Double the path table or grow to fit needed, whichever is larger\n const newSize = Math.max(this.pathTableSize * 2, needed + INITIAL_PATH_TABLE_SIZE);\n const growth = newSize - this.pathTableSize;\n\n // Need to shift bitmap and data region forward\n // Use in-memory bitmap (no read needed)\n\n // Read existing data region\n const dataSize = this.totalBlocks * this.blockSize;\n const dataBuf = new Uint8Array(dataSize);\n this.handle.read(dataBuf, { at: this.dataOffset });\n\n // Grow file\n const newTotalSize = this.handle.getSize() + growth;\n this.handle.truncate(newTotalSize);\n\n // Write data back at new offset\n const newBitmapOffset = this.bitmapOffset + growth;\n const newDataOffset = this.dataOffset + growth;\n this.handle.write(dataBuf, { at: newDataOffset });\n this.handle.write(this.bitmap!, { at: newBitmapOffset });\n\n // Update offsets\n this.pathTableSize = newSize;\n this.bitmapOffset = newBitmapOffset;\n this.dataOffset = newDataOffset;\n\n // Mark superblock dirty (will be written in commitPending)\n this.superblockDirty = true;\n }\n\n // ========== Bitmap I/O ==========\n\n private allocateBlocks(count: number): number {\n if (count === 0) return 0;\n\n const bitmap = this.bitmap!;\n let run = 0;\n let start = 0;\n\n for (let i = 0; i < this.totalBlocks; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n const used = (bitmap[byteIdx] >>> bitIdx) & 1;\n\n if (used) {\n run = 0;\n start = i + 1;\n } else {\n run++;\n if (run === count) {\n // Mark blocks as used in memory\n for (let j = start; j <= i; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n bitmap[bj] |= (1 << bi);\n }\n this.markBitmapDirty(start >>> 3, i >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n return start;\n }\n }\n }\n\n // No contiguous space — grow data region\n return this.growAndAllocate(count);\n }\n\n private growAndAllocate(count: number): number {\n const oldTotal = this.totalBlocks;\n // Grow by at least doubling or enough for the request\n const newTotal = Math.max(oldTotal * 2, oldTotal + count);\n const addedBlocks = newTotal - oldTotal;\n\n // Grow the file\n const newFileSize = this.dataOffset + newTotal * this.blockSize;\n this.handle.truncate(newFileSize);\n\n // Grow in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n const newBitmap = new Uint8Array(newBitmapSize);\n newBitmap.set(this.bitmap!);\n this.bitmap = newBitmap;\n\n this.totalBlocks = newTotal;\n this.freeBlocks += addedBlocks;\n\n // Allocate from the newly freed area\n const start = oldTotal;\n for (let j = start; j < start + count; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n this.bitmap[bj] |= (1 << bi);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n\n return start;\n }\n\n private blocksFreedsinceTrim = false;\n\n private freeBlockRange(start: number, count: number): void {\n if (count === 0) return;\n const bitmap = this.bitmap!;\n\n for (let i = start; i < start + count; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n bitmap[byteIdx] &= ~(1 << bitIdx);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks += count;\n this.superblockDirty = true;\n this.blocksFreedsinceTrim = true;\n }\n\n // updateSuperblockFreeBlocks is no longer needed — superblock writes are coalesced via commitPending()\n\n // ========== Inode allocation ==========\n\n private findFreeInode(): number {\n // Start from hint to skip already-used entries\n for (let i = this.freeInodeHint; i < this.inodeCount; i++) {\n // Check cache first — cached entries are never FREE\n if (this.inodeCache.has(i)) continue;\n\n const offset = this.inodeTableOffset + i * INODE_SIZE;\n const typeBuf = new Uint8Array(1);\n this.handle.read(typeBuf, { at: offset });\n if (typeBuf[0] === INODE_TYPE.FREE) {\n this.freeInodeHint = i + 1;\n return i;\n }\n }\n // All inodes used — grow inode table\n const idx = this.growInodeTable();\n this.freeInodeHint = idx + 1;\n return idx;\n }\n\n private growInodeTable(): number {\n const oldCount = this.inodeCount;\n const newCount = oldCount * 2;\n const growth = (newCount - oldCount) * INODE_SIZE;\n\n // Read everything after inode table\n const afterInodeOffset = this.inodeTableOffset + oldCount * INODE_SIZE;\n const afterSize = this.handle.getSize() - afterInodeOffset;\n const afterBuf = new Uint8Array(afterSize);\n this.handle.read(afterBuf, { at: afterInodeOffset });\n\n // Grow file\n this.handle.truncate(this.handle.getSize() + growth);\n\n // Write back shifted content\n this.handle.write(afterBuf, { at: afterInodeOffset + growth });\n\n // Zero out new inode entries\n const zeroes = new Uint8Array(growth);\n this.handle.write(zeroes, { at: afterInodeOffset });\n\n // Update offsets\n this.pathTableOffset += growth;\n this.bitmapOffset += growth;\n this.dataOffset += growth;\n this.inodeCount = newCount;\n\n this.superblockDirty = true;\n\n return oldCount; // First new free inode\n }\n\n // ========== Data I/O ==========\n\n private readData(firstBlock: number, blockCount: number, size: number): Uint8Array {\n const buf = new Uint8Array(size);\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.read(buf, { at: offset });\n return buf;\n }\n\n private writeData(firstBlock: number, data: Uint8Array): void {\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.write(data, { at: offset });\n }\n\n // ========== Path resolution ==========\n\n private resolvePath(path: string, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const idx = this.pathIndex.get(path);\n if (idx === undefined) {\n // Path not found directly — try component resolution (handles intermediate symlinks)\n return this.resolvePathComponents(path, true, depth);\n }\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK) {\n // Follow symlink\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(path, target);\n return this.resolvePath(resolved, depth + 1);\n }\n\n return idx;\n }\n\n /** Resolve symlinks in intermediate path components */\n private resolvePathComponents(path: string, followLast: boolean = true, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const parts = path.split('/').filter(Boolean);\n let current = '/';\n\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1;\n current = current === '/' ? '/' + parts[i] : current + '/' + parts[i];\n\n const idx = this.pathIndex.get(current);\n if (idx === undefined) return undefined;\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK && (!isLast || followLast)) {\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(current, target);\n\n if (isLast) {\n // Use resolvePathComponents (not resolvePath) so intermediate symlinks\n // in the resolved target path are also followed\n return this.resolvePathComponents(resolved, true, depth + 1);\n }\n\n // Reconstruct remaining path with resolved symlink\n const remaining = parts.slice(i + 1).join('/');\n const newPath = resolved + (remaining ? '/' + remaining : '');\n return this.resolvePathComponents(newPath, followLast, depth + 1);\n }\n }\n\n return this.pathIndex.get(current);\n }\n\n private resolveRelative(from: string, target: string): string {\n const dir = from.substring(0, from.lastIndexOf('/')) || '/';\n const parts = (dir + '/' + target).split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const p of parts) {\n if (p === '.') continue;\n if (p === '..') { resolved.pop(); continue; }\n resolved.push(p);\n }\n return '/' + resolved.join('/');\n }\n\n // ========== Core inode creation helper ==========\n\n private createInode(path: string, type: number, mode: number, size: number, data?: Uint8Array): number {\n const idx = this.findFreeInode();\n const { offset: pathOff, length: pathLen } = this.appendPath(path);\n const now = Date.now();\n\n let firstBlock = 0;\n let blockCount = 0;\n\n if (data && data.byteLength > 0) {\n blockCount = Math.ceil(data.byteLength / this.blockSize);\n firstBlock = this.allocateBlocks(blockCount);\n this.writeData(firstBlock, data);\n }\n\n const inode: Inode = {\n type,\n pathOffset: pathOff,\n pathLength: pathLen,\n mode,\n size,\n firstBlock,\n blockCount,\n mtime: now,\n ctime: now,\n atime: now,\n uid: this.processUid,\n gid: this.processGid,\n };\n\n this.writeInode(idx, inode);\n this.pathIndex.set(path, idx);\n\n return idx;\n }\n\n // ========== Public API — called by server worker dispatch ==========\n\n /** Normalize a path: ensure leading /, resolve . and .. */\n normalizePath(p: string): string {\n if (p.charCodeAt(0) !== 47) p = '/' + p; // 47 = '/'\n // Fast path: already normalized (no '.', '..', '//', trailing '/')\n if (p.length === 1) return p; // \"/\"\n if (p.indexOf('/.') === -1 && p.indexOf('//') === -1 && p.charCodeAt(p.length - 1) !== 47) {\n return p;\n }\n // Slow path: full normalize\n const parts = p.split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const part of parts) {\n if (part === '.') continue;\n if (part === '..') { resolved.pop(); continue; }\n resolved.push(part);\n }\n return '/' + resolved.join('/');\n }\n\n // ---- READ ----\n read(path: string): { status: number; data: Uint8Array | null } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n\n // Fast path: direct index lookup (skips component-by-component walk)\n let idx = this.pathIndex.get(path);\n if (idx !== undefined) {\n const inode = this.inodeCache.get(idx);\n if (inode) {\n // Symlink? Fall through to full resolve\n if (inode.type === INODE_TYPE.SYMLINK) {\n idx = this.resolvePathComponents(path, true);\n } else if (inode.type === INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.EISDIR, data: null };\n } else {\n // Hot path: cached inode, no symlinks\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (fast)`);\n }\n return { status: 0, data };\n }\n }\n }\n\n // Slow path: full component resolution (handles symlinks, uncached inodes)\n if (idx === undefined) idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR, data: null };\n\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (slow path)`);\n }\n\n return { status: 0, data };\n }\n\n // ---- WRITE ----\n write(path: string, data: Uint8Array, flags: number = 0): { status: number } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n const t1 = this.debug ? performance.now() : 0;\n\n // Ensure parent directory exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus };\n const t2 = this.debug ? performance.now() : 0;\n\n const existingIdx = this.resolvePathComponents(path, true);\n const t3 = this.debug ? performance.now() : 0;\n\n let tAlloc = t3, tData = t3, tInode = t3;\n\n if (existingIdx !== undefined) {\n // Update existing file\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n const neededBlocks = Math.ceil(data.byteLength / this.blockSize);\n\n if (neededBlocks <= inode.blockCount) {\n // Fits in current blocks\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(inode.firstBlock, data);\n tData = this.debug ? performance.now() : 0;\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n } else {\n // Need more blocks — free old, allocate new\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(newFirst, data);\n tData = this.debug ? performance.now() : 0;\n inode.firstBlock = newFirst;\n }\n\n inode.size = data.byteLength;\n inode.blockCount = neededBlocks;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n tInode = this.debug ? performance.now() : 0;\n } else {\n // Create new file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.FILE, mode, data.byteLength, data);\n tAlloc = this.debug ? performance.now() : 0;\n tData = tAlloc;\n tInode = tAlloc;\n }\n\n if (flags & 1) {\n this.commitPending();\n this.handle.flush();\n }\n const tFlush = this.debug ? performance.now() : 0;\n\n if (this.debug) {\n const existing = existingIdx !== undefined;\n console.log(`[VFS write] path=${path} size=${data.byteLength} ${existing ? 'UPDATE' : 'CREATE'} normalize=${(t1-t0).toFixed(3)}ms parent=${(t2-t1).toFixed(3)}ms resolve=${(t3-t2).toFixed(3)}ms alloc=${(tAlloc-t3).toFixed(3)}ms data=${(tData-tAlloc).toFixed(3)}ms inode=${(tInode-tData).toFixed(3)}ms flush=${(tFlush-tInode).toFixed(3)}ms TOTAL=${(tFlush-t0).toFixed(3)}ms`);\n }\n\n return { status: 0 };\n }\n\n // ---- APPEND ----\n append(path: string, data: Uint8Array): { status: number } {\n path = this.normalizePath(path);\n const existingIdx = this.resolvePathComponents(path, true);\n\n if (existingIdx === undefined) {\n // Create new file with the data\n return this.write(path, data);\n }\n\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Read existing data\n const existing = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n // Concat\n const combined = new Uint8Array(existing.byteLength + data.byteLength);\n combined.set(existing);\n combined.set(data, existing.byteLength);\n\n // Rewrite\n const neededBlocks = Math.ceil(combined.byteLength / this.blockSize);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n this.writeData(newFirst, combined);\n\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n inode.size = combined.byteLength;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- UNLINK ----\n unlink(path: string): { status: number } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Free data blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n\n // Mark inode as free\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n\n // Remove from index\n this.pathIndex.delete(path);\n // Reset free inode hint\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- STAT ----\n stat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n // ---- LSTAT (no symlink follow) ----\n lstat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n private encodeStatResponse(idx: number): { status: number; data: Uint8Array } {\n const inode = this.readInode(idx);\n // Encode stat into binary: type(1) + mode(4) + size(8) + mtime(8) + ctime(8) + atime(8) + uid(4) + gid(4) + ino(4) = 49 bytes\n const buf = new Uint8Array(49);\n const view = new DataView(buf.buffer);\n view.setUint8(0, inode.type);\n view.setUint32(1, inode.mode, true);\n view.setFloat64(5, inode.size, true);\n view.setFloat64(13, inode.mtime, true);\n view.setFloat64(21, inode.ctime, true);\n view.setFloat64(29, inode.atime, true);\n view.setUint32(37, inode.uid, true);\n view.setUint32(41, inode.gid, true);\n view.setUint32(45, idx, true); // ino = inode index\n\n return { status: 0, data: buf };\n }\n\n // ---- MKDIR ----\n mkdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n\n if (recursive) {\n return this.mkdirRecursive(path);\n }\n\n // Check if already exists\n if (this.pathIndex.has(path)) return { status: CODE_TO_STATUS.EEXIST, data: null };\n\n // Ensure parent exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus, data: null };\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n // Return created path as data\n const pathBytes = encoder.encode(path);\n return { status: 0, data: pathBytes };\n }\n\n private mkdirRecursive(path: string): { status: number; data: Uint8Array | null } {\n const parts = path.split('/').filter(Boolean);\n let current = '';\n let firstCreated: string | null = null;\n\n for (const part of parts) {\n current += '/' + part;\n\n if (this.pathIndex.has(current)) {\n const idx = this.pathIndex.get(current)!;\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n }\n continue;\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(current, INODE_TYPE.DIRECTORY, mode, 0);\n if (!firstCreated) firstCreated = current;\n }\n\n this.commitPending();\n const result = firstCreated ? encoder.encode(firstCreated) : undefined;\n return { status: 0, data: result ?? null };\n }\n\n // ---- RMDIR ----\n rmdir(path: string, flags: number = 0): { status: number } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };\n\n // Check for children\n const children = this.getDirectChildren(path);\n\n if (children.length > 0) {\n if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };\n\n // Recursive delete\n for (const child of this.getAllDescendants(path)) {\n const childIdx = this.pathIndex.get(child)!;\n const childInode = this.readInode(childIdx);\n this.freeBlockRange(childInode.firstBlock, childInode.blockCount);\n childInode.type = INODE_TYPE.FREE;\n this.writeInode(childIdx, childInode);\n this.pathIndex.delete(child);\n }\n }\n\n // Remove the directory itself\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n this.pathIndex.delete(path);\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READDIR ----\n readdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n const withFileTypes = (flags & 1) !== 0;\n const children = this.getDirectChildren(path);\n\n if (withFileTypes) {\n // Encode as: count(u32) + entries[name_len(u16) + name(bytes) + type(u8)]\n let totalSize = 4;\n const entries: { name: Uint8Array; type: number }[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n const childIdx = this.pathIndex.get(childPath)!;\n const childInode = this.readInode(childIdx);\n entries.push({ name: nameBytes, type: childInode.type });\n totalSize += 2 + nameBytes.byteLength + 1; // nameLen + name + type\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, entries.length, true);\n let offset = 4;\n\n for (const entry of entries) {\n view.setUint16(offset, entry.name.byteLength, true);\n offset += 2;\n buf.set(entry.name, offset);\n offset += entry.name.byteLength;\n buf[offset++] = entry.type;\n }\n\n return { status: 0, data: buf };\n }\n\n // Simple name list: count(u32) + entries[name_len(u16) + name(bytes)]\n let totalSize = 4;\n const nameEntries: Uint8Array[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n nameEntries.push(nameBytes);\n totalSize += 2 + nameBytes.byteLength;\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, nameEntries.length, true);\n let offset = 4;\n\n for (const nameBytes of nameEntries) {\n view.setUint16(offset, nameBytes.byteLength, true);\n offset += 2;\n buf.set(nameBytes, offset);\n offset += nameBytes.byteLength;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- RENAME ----\n rename(oldPath: string, newPath: string): { status: number } {\n oldPath = this.normalizePath(oldPath);\n newPath = this.normalizePath(newPath);\n\n const idx = this.pathIndex.get(oldPath);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n // Ensure parent of new path exists\n const parentStatus = this.ensureParent(newPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n // If target exists, remove it\n const existingIdx = this.pathIndex.get(newPath);\n if (existingIdx !== undefined) {\n const existingInode = this.readInode(existingIdx);\n this.freeBlockRange(existingInode.firstBlock, existingInode.blockCount);\n existingInode.type = INODE_TYPE.FREE;\n this.writeInode(existingIdx, existingInode);\n this.pathIndex.delete(newPath);\n }\n\n // Update inode with new path\n const inode = this.readInode(idx);\n const { offset: pathOff, length: pathLen } = this.appendPath(newPath);\n inode.pathOffset = pathOff;\n inode.pathLength = pathLen;\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n // Update index\n this.pathIndex.delete(oldPath);\n this.pathIndex.set(newPath, idx);\n\n // If it's a directory, rename all descendants\n if (inode.type === INODE_TYPE.DIRECTORY) {\n const prefix = oldPath === '/' ? '/' : oldPath + '/';\n const toRename: [string, number][] = [];\n\n for (const [p, i] of this.pathIndex) {\n if (p.startsWith(prefix)) {\n toRename.push([p, i]);\n }\n }\n\n for (const [p, i] of toRename) {\n const suffix = p.substring(oldPath.length);\n const childNewPath = newPath + suffix;\n const childInode = this.readInode(i);\n const { offset: cpo, length: cpl } = this.appendPath(childNewPath);\n childInode.pathOffset = cpo;\n childInode.pathLength = cpl;\n this.writeInode(i, childInode);\n this.pathIndex.delete(p);\n this.pathIndex.set(childNewPath, i);\n }\n }\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- EXISTS ----\n exists(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n const buf = new Uint8Array(1);\n buf[0] = idx !== undefined ? 1 : 0;\n return { status: 0, data: buf };\n }\n\n // ---- TRUNCATE ----\n truncate(path: string, len: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n if (len === 0) {\n // Free all blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n inode.firstBlock = 0;\n inode.blockCount = 0;\n inode.size = 0;\n } else if (len < inode.size) {\n // Shrink\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n } else if (len > inode.size) {\n // Grow (zero-fill)\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Need more blocks\n const oldData = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newData = new Uint8Array(len);\n newData.set(oldData);\n // Rest is already zero-filled\n this.writeData(newFirst, newData);\n inode.firstBlock = newFirst;\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n }\n\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- COPY ----\n copy(srcPath: string, destPath: string, flags: number = 0): { status: number } {\n srcPath = this.normalizePath(srcPath);\n destPath = this.normalizePath(destPath);\n\n const srcIdx = this.resolvePathComponents(srcPath, true);\n if (srcIdx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const srcInode = this.readInode(srcIdx);\n if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // COPYFILE_EXCL check\n if ((flags & 1) && this.pathIndex.has(destPath)) {\n return { status: CODE_TO_STATUS.EEXIST };\n }\n\n // Read source data\n const data = srcInode.size > 0\n ? this.readData(srcInode.firstBlock, srcInode.blockCount, srcInode.size)\n : new Uint8Array(0);\n\n return this.write(destPath, data);\n }\n\n // ---- ACCESS ----\n access(path: string, mode: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n if (mode === 0) return { status: 0 }; // F_OK — just check existence\n\n if (!this.strictPermissions) return { status: 0 }; // Relaxed mode\n\n const inode = this.readInode(idx);\n // Check permission bits against process identity\n const filePerm = this.getEffectivePermission(inode);\n\n if ((mode & 4) && !(filePerm & 4)) return { status: CODE_TO_STATUS.EACCES }; // R_OK\n if ((mode & 2) && !(filePerm & 2)) return { status: CODE_TO_STATUS.EACCES }; // W_OK\n if ((mode & 1) && !(filePerm & 1)) return { status: CODE_TO_STATUS.EACCES }; // X_OK\n\n return { status: 0 };\n }\n\n private getEffectivePermission(inode: Inode): number {\n const modeBits = inode.mode & 0o777;\n if (this.processUid === inode.uid) return (modeBits >>> 6) & 7;\n if (this.processGid === inode.gid) return (modeBits >>> 3) & 7;\n return modeBits & 7;\n }\n\n // ---- REALPATH ----\n realpath(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n // Find the resolved path for this inode\n const inode = this.readInode(idx);\n const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);\n return { status: 0, data: encoder.encode(resolvedPath) };\n }\n\n // ---- CHMOD ----\n chmod(path: string, mode: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n // Preserve file type bits, update permission bits\n inode.mode = (inode.mode & S_IFMT) | (mode & 0o7777);\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- CHOWN ----\n chown(path: string, uid: number, gid: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.uid = uid;\n inode.gid = gid;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- UTIMES ----\n utimes(path: string, atime: number, mtime: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.atime = atime;\n inode.mtime = mtime;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- SYMLINK ----\n symlink(target: string, linkPath: string): { status: number } {\n linkPath = this.normalizePath(linkPath);\n if (this.pathIndex.has(linkPath)) return { status: CODE_TO_STATUS.EEXIST };\n\n const parentStatus = this.ensureParent(linkPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n const targetBytes = encoder.encode(target);\n this.createInode(linkPath, INODE_TYPE.SYMLINK, DEFAULT_SYMLINK_MODE, targetBytes.byteLength, targetBytes);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READLINK ----\n readlink(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.SYMLINK) return { status: CODE_TO_STATUS.EINVAL, data: null };\n\n const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n return { status: 0, data: target };\n }\n\n // ---- LINK (hard link — copies the file) ----\n link(existingPath: string, newPath: string): { status: number } {\n return this.copy(existingPath, newPath);\n }\n\n // ---- OPEN (file descriptor) ----\n open(path: string, flags: number, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n\n const hasCreate = (flags & 64) !== 0; // O_CREAT\n const hasTrunc = (flags & 512) !== 0; // O_TRUNC\n const hasExcl = (flags & 128) !== 0; // O_EXCL\n\n let idx = this.resolvePathComponents(path, true);\n\n if (idx === undefined) {\n if (!hasCreate) return { status: CODE_TO_STATUS.ENOENT, data: null };\n // Create file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n idx = this.createInode(path, INODE_TYPE.FILE, mode, 0);\n } else if (hasExcl && hasCreate) {\n return { status: CODE_TO_STATUS.EEXIST, data: null };\n }\n\n if (hasTrunc) {\n this.truncate(path, 0);\n }\n\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- CLOSE ----\n close(fd: number): { status: number } {\n if (!this.fdTable.has(fd)) return { status: CODE_TO_STATUS.EBADF };\n this.fdTable.delete(fd);\n return { status: 0 };\n }\n\n // ---- FREAD ----\n fread(fd: number, length: number, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const pos = position ?? entry.position;\n const readLen = Math.min(length, inode.size - pos);\n\n if (readLen <= 0) return { status: 0, data: new Uint8Array(0) };\n\n // Read from specific offset within the file's data blocks\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n const buf = new Uint8Array(readLen);\n this.handle.read(buf, { at: dataOffset });\n\n // Update position\n if (position === null) {\n entry.position += readLen;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- FWRITE ----\n fwrite(fd: number, data: Uint8Array, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const isAppend = (entry.flags & 1024) !== 0; // O_APPEND\n const pos = isAppend ? inode.size : (position ?? entry.position);\n const endPos = pos + data.byteLength;\n\n // Check if we need to grow\n if (endPos > inode.size) {\n const neededBlocks = Math.ceil(endPos / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Grow — read old data, reallocate, write back\n const oldData = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newBuf = new Uint8Array(endPos);\n newBuf.set(oldData);\n newBuf.set(data, pos);\n this.writeData(newFirst, newBuf);\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n } else {\n // Fits, write at position\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n inode.size = endPos;\n } else {\n // Write within existing bounds\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n\n inode.mtime = Date.now();\n this.writeInode(entry.inodeIdx, inode);\n\n // Update position\n if (position === null) {\n entry.position = endPos;\n }\n\n this.commitPending();\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, data.byteLength, true);\n return { status: 0, data: buf };\n }\n\n // ---- FSTAT ----\n fstat(fd: number): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n return this.encodeStatResponse(entry.inodeIdx);\n }\n\n // ---- FTRUNCATE ----\n ftruncate(fd: number, len: number = 0): { status: number } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF };\n\n const inode = this.readInode(entry.inodeIdx);\n const path = this.readPath(inode.pathOffset, inode.pathLength);\n return this.truncate(path, len);\n }\n\n // ---- FSYNC ----\n fsync(): { status: number } {\n this.commitPending();\n this.handle.flush();\n return { status: 0 };\n }\n\n // ---- OPENDIR ----\n opendir(path: string, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n // Use fd table for dir handles too\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags: 0 });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- MKDTEMP ----\n mkdtemp(prefix: string): { status: number; data: Uint8Array | null } {\n const suffix = Math.random().toString(36).substring(2, 8);\n const path = this.normalizePath(prefix + suffix);\n\n // Ensure parent directories exist\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) {\n // Auto-create parent directories for mkdtemp\n const parentPath = path.substring(0, path.lastIndexOf('/'));\n if (parentPath) {\n this.mkdirRecursive(parentPath);\n }\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n return { status: 0, data: encoder.encode(path) };\n }\n\n // ========== Helpers ==========\n\n private getDirectChildren(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const children: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path === dirPath) continue;\n if (!path.startsWith(prefix)) continue;\n // Direct child: no more slashes after prefix\n const rest = path.substring(prefix.length);\n if (!rest.includes('/')) {\n children.push(path);\n }\n }\n\n return children.sort();\n }\n\n private getAllDescendants(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const descendants: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path.startsWith(prefix)) descendants.push(path);\n }\n\n // Sort by depth (deepest first) for safe deletion\n return descendants.sort((a, b) => {\n const da = a.split('/').length;\n const db = b.split('/').length;\n return db - da;\n });\n }\n\n private ensureParent(path: string): number {\n const lastSlash = path.lastIndexOf('/');\n if (lastSlash <= 0) return 0; // Parent is root, always exists\n\n const parentPath = path.substring(0, lastSlash);\n const parentIdx = this.pathIndex.get(parentPath);\n if (parentIdx === undefined) return CODE_TO_STATUS.ENOENT;\n\n const parentInode = this.readInode(parentIdx);\n if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;\n\n return 0;\n }\n\n /** Clean up all fds owned by a tab */\n cleanupTab(tabId: string): void {\n for (const [fd, entry] of this.fdTable) {\n if (entry.tabId === tabId) {\n this.fdTable.delete(fd);\n }\n }\n }\n\n /** Get all file paths and their data for OPFS sync */\n getAllFiles(): { path: string; idx: number }[] {\n const files: { path: string; idx: number }[] = [];\n for (const [path, idx] of this.pathIndex) {\n files.push({ path, idx });\n }\n return files;\n }\n\n /** Get file path for a file descriptor (used by OPFS sync for FD-based ops) */\n getPathForFd(fd: number): string | null {\n const entry = this.fdTable.get(fd);\n if (!entry) return null;\n const inode = this.readInode(entry.inodeIdx);\n return this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n /** Get file data by inode index */\n getInodeData(idx: number): { type: number; data: Uint8Array; mtime: number } {\n const inode = this.readInode(idx);\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n return { type: inode.type, data, mtime: inode.mtime };\n }\n\n /** Export all files/dirs/symlinks from the VFS */\n exportAll(): Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> {\n const result: Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> = [];\n for (const [path, idx] of this.pathIndex) {\n const inode = this.readInode(idx);\n let data: Uint8Array | null = null;\n if (inode.type === INODE_TYPE.FILE || inode.type === INODE_TYPE.SYMLINK) {\n data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n }\n result.push({ path, type: inode.type, data, mode: inode.mode, mtime: inode.mtime });\n }\n // Sort directories first so parents are created before children\n result.sort((a, b) => {\n if (a.type === INODE_TYPE.DIRECTORY && b.type !== INODE_TYPE.DIRECTORY) return -1;\n if (a.type !== INODE_TYPE.DIRECTORY && b.type === INODE_TYPE.DIRECTORY) return 1;\n return a.path.localeCompare(b.path);\n });\n return result;\n }\n\n flush(): void {\n this.handle.flush();\n }\n}\n","/**\n * Repair Worker — handles VFS repair and load operations.\n *\n * Spawned by helpers.ts when the caller doesn't have sync handle access\n * (e.g. main thread). All VFS writes go through createSyncAccessHandle\n * for direct disk I/O — no MemoryHandle, no RAM bloat.\n *\n * Operations:\n * - 'repair': Scan corrupt .vfs.bin, rebuild valid entries into fresh VFS\n * - 'load': Read OPFS files, create fresh VFS from them\n *\n * Safety guarantees:\n * - Original .vfs.bin is never deleted until the replacement is verified\n * - Temp file (.vfs.bin.tmp) is verified via re-mount before swap\n * - Orphaned .vfs.bin.tmp is cleaned up on entry\n * - Repair fails fast if critical operations exceed error threshold\n */\n\nimport { VFSEngine } from '../vfs/engine.js';\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS,\n INITIAL_PATH_TABLE_SIZE, calculateLayout,\n} from '../vfs/layout.js';\n\nself.onmessage = async (event: MessageEvent) => {\n try {\n const msg = event.data;\n if (msg.type === 'repair') {\n (self as any).postMessage(await handleRepair(msg.root));\n } else if (msg.type === 'load') {\n (self as any).postMessage(await handleLoad(msg.root));\n } else {\n throw new Error(`Unknown message type: ${msg.type}`);\n }\n } catch (err: any) {\n (self as any).postMessage({ error: err.message || String(err) });\n }\n};\n\n// ========== OPFS navigation (duplicated for bundle isolation) ==========\n\nasync function navigateToRoot(root: string): Promise<FileSystemDirectoryHandle> {\n let dir = await navigator.storage.getDirectory();\n if (root && root !== '/') {\n for (const seg of root.split('/').filter(Boolean)) {\n dir = await dir.getDirectoryHandle(seg, { create: true });\n }\n }\n return dir;\n}\n\ninterface OPFSEntry {\n path: string;\n type: 'file' | 'directory';\n data?: ArrayBuffer;\n}\n\nasync function readOPFSRecursive(\n dir: FileSystemDirectoryHandle,\n prefix: string,\n skip: Set<string>,\n): Promise<OPFSEntry[]> {\n const result: OPFSEntry[] = [];\n for await (const [name, handle] of (dir as any).entries()) {\n if (prefix === '' && skip.has(name)) continue;\n const fullPath = prefix ? `${prefix}/${name}` : `/${name}`;\n if (handle.kind === 'directory') {\n result.push({ path: fullPath, type: 'directory' });\n const children = await readOPFSRecursive(handle as FileSystemDirectoryHandle, fullPath, skip);\n result.push(...children);\n } else {\n const file = await (handle as FileSystemFileHandle).getFile();\n const data = await file.arrayBuffer();\n result.push({ path: fullPath, type: 'file', data });\n }\n }\n return result;\n}\n\n// ========== Cleanup orphaned temp files ==========\n\nasync function cleanupTmpFile(rootDir: FileSystemDirectoryHandle): Promise<void> {\n try { await rootDir.removeEntry('.vfs.bin.tmp'); } catch {}\n}\n\n// ========== Verify VFS via re-mount ==========\n\n/**\n * Open the file, mount it as a VFS, verify superblock + inode table,\n * then close. Throws if the VFS is corrupt.\n */\nasync function verifyVFS(fileHandle: FileSystemFileHandle): Promise<void> {\n const handle = await (fileHandle as any).createSyncAccessHandle();\n try {\n const engine = new VFSEngine();\n engine.init(handle); // calls mount() which validates superblock + rebuilds index\n } finally {\n handle.close();\n }\n}\n\n// ========== Safe file swap: copy-then-delete ==========\n\n/**\n * Safely replace .vfs.bin with .vfs.bin.tmp:\n * 1. Verify the temp file is a valid VFS (re-mount test)\n * 2. Copy temp → .vfs.bin (overwrite via truncate + chunked write)\n * 3. Only then delete .vfs.bin.tmp\n *\n * If the copy is interrupted mid-write, the original .vfs.bin.tmp\n * still exists intact for retry.\n */\nasync function swapTmpToVFS(\n rootDir: FileSystemDirectoryHandle,\n tmpFileHandle: FileSystemFileHandle,\n): Promise<void> {\n // Step 1: Verify temp file is valid before touching original\n await verifyVFS(tmpFileHandle);\n\n // Step 2: Copy tmp → .vfs.bin (overwrite)\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin', { create: true });\n\n const srcHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n const dstHandle = await (vfsFileHandle as any).createSyncAccessHandle();\n try {\n const size: number = srcHandle.getSize();\n dstHandle.truncate(size);\n const CHUNK = 1024 * 1024; // 1MB\n const buf = new Uint8Array(CHUNK);\n for (let off = 0; off < size; off += CHUNK) {\n const n: number = srcHandle.read(buf, { at: off });\n dstHandle.write(n < CHUNK ? buf.subarray(0, n) : buf, { at: off });\n }\n dstHandle.flush();\n } finally {\n dstHandle.close();\n srcHandle.close();\n }\n\n // Step 3: Only delete tmp after successful copy\n try { await rootDir.removeEntry('.vfs.bin.tmp'); } catch {}\n}\n\n// ========== Repair handler ==========\n\nasync function handleRepair(root: string) {\n const rootDir = await navigateToRoot(root);\n\n // Clean up any orphaned temp file from a previous failed repair\n await cleanupTmpFile(rootDir);\n\n // Read old .vfs.bin\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin');\n const file = await vfsFileHandle.getFile();\n const raw = new Uint8Array(await file.arrayBuffer());\n const fileSize = raw.byteLength;\n\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`VFS file too small to repair (${fileSize} bytes)`);\n }\n\n // Parse superblock\n const view = new DataView(raw.buffer);\n let inodeCount: number;\n let blockSize: number;\n let totalBlocks: number;\n let inodeTableOffset: number;\n let pathTableOffset: number;\n let dataOffset: number;\n let pathTableUsed: number;\n\n const magic = view.getUint32(SUPERBLOCK.MAGIC, true);\n const version = view.getUint32(SUPERBLOCK.VERSION, true);\n const superblockValid = magic === VFS_MAGIC && version === VFS_VERSION;\n\n if (superblockValid) {\n inodeCount = view.getUint32(SUPERBLOCK.INODE_COUNT, true);\n blockSize = view.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n totalBlocks = view.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n inodeTableOffset = view.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n pathTableOffset = view.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n dataOffset = view.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n pathTableUsed = view.getUint32(SUPERBLOCK.PATH_USED, true);\n\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0 || inodeCount === 0 ||\n inodeTableOffset >= fileSize || pathTableOffset >= fileSize || dataOffset >= fileSize) {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n inodeCount = DEFAULT_INODE_COUNT;\n blockSize = DEFAULT_BLOCK_SIZE;\n totalBlocks = INITIAL_DATA_BLOCKS;\n inodeTableOffset = layout.inodeTableOffset;\n pathTableOffset = layout.pathTableOffset;\n dataOffset = layout.dataOffset;\n pathTableUsed = INITIAL_PATH_TABLE_SIZE;\n }\n } else {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n inodeCount = DEFAULT_INODE_COUNT;\n blockSize = DEFAULT_BLOCK_SIZE;\n totalBlocks = INITIAL_DATA_BLOCKS;\n inodeTableOffset = layout.inodeTableOffset;\n pathTableOffset = layout.pathTableOffset;\n dataOffset = layout.dataOffset;\n pathTableUsed = INITIAL_PATH_TABLE_SIZE;\n }\n\n // Scan inodes for recoverable entries\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const recovered: Array<{\n path: string;\n type: number;\n dataOffset: number;\n dataSize: number;\n /** true when inode was found but data blocks were out of bounds */\n contentLost: boolean;\n }> = [];\n let lost = 0;\n\n const maxInodes = Math.min(inodeCount, Math.floor((fileSize - inodeTableOffset) / INODE_SIZE));\n\n for (let i = 0; i < maxInodes; i++) {\n const off = inodeTableOffset + i * INODE_SIZE;\n if (off + INODE_SIZE > fileSize) break;\n\n const type = raw[off + INODE.TYPE];\n if (type < INODE_TYPE.FILE || type > INODE_TYPE.SYMLINK) continue;\n\n const inodeView = new DataView(raw.buffer, off, INODE_SIZE);\n const pathOff = inodeView.getUint32(INODE.PATH_OFFSET, true);\n const pathLength = inodeView.getUint16(INODE.PATH_LENGTH, true);\n const size = inodeView.getFloat64(INODE.SIZE, true);\n const firstBlock = inodeView.getUint32(INODE.FIRST_BLOCK, true);\n\n // Validate path bounds against both the path table and file size\n const absPathOffset = pathTableOffset + pathOff;\n if (pathLength === 0 || pathLength > 4096 ||\n absPathOffset + pathLength > fileSize ||\n pathOff + pathLength > pathTableUsed) {\n lost++;\n continue;\n }\n\n // Decode path with strict UTF-8 (fatal: true rejects invalid sequences)\n let entryPath: string;\n try {\n entryPath = decoder.decode(raw.subarray(absPathOffset, absPathOffset + pathLength));\n } catch {\n lost++;\n continue;\n }\n\n if (!entryPath.startsWith('/') || entryPath.includes('\\0')) {\n lost++;\n continue;\n }\n\n if (type === INODE_TYPE.DIRECTORY) {\n recovered.push({ path: entryPath, type, dataOffset: 0, dataSize: 0, contentLost: false });\n continue;\n }\n\n if (size < 0 || size > fileSize || !isFinite(size)) {\n lost++;\n continue;\n }\n\n const blockCount = inodeView.getUint32(INODE.BLOCK_COUNT, true);\n const dataStart = dataOffset + firstBlock * blockSize;\n if (dataStart + size > fileSize || firstBlock >= totalBlocks ||\n (blockCount > 0 && firstBlock + blockCount > totalBlocks)) {\n // Inode metadata is valid but data blocks are out of bounds — content is lost\n recovered.push({ path: entryPath, type, dataOffset: 0, dataSize: 0, contentLost: true });\n lost++;\n continue;\n }\n\n recovered.push({ path: entryPath, type, dataOffset: dataStart, dataSize: size, contentLost: false });\n }\n\n // Build repaired VFS in temp file — original .vfs.bin untouched until verified\n const tmpFileHandle = await rootDir.getFileHandle('.vfs.bin.tmp', { create: true });\n const tmpHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n\n let repairOk = false;\n let criticalErrors = 0;\n const MAX_CRITICAL_ERRORS = 5;\n\n try {\n const engine = new VFSEngine();\n engine.init(tmpHandle);\n\n const dirs = recovered\n .filter(e => e.type === INODE_TYPE.DIRECTORY && e.path !== '/')\n .sort((a, b) => a.path.localeCompare(b.path));\n const files = recovered.filter(e => e.type === INODE_TYPE.FILE);\n const symlinks = recovered.filter(e => e.type === INODE_TYPE.SYMLINK);\n\n // Create directories — failure here is critical (blocks child files)\n for (const dir of dirs) {\n if (engine.mkdir(dir.path, 0o040755).status !== 0) {\n criticalErrors++;\n lost++;\n if (criticalErrors >= MAX_CRITICAL_ERRORS) {\n throw new Error(`Repair aborted: too many critical errors (${criticalErrors} mkdir failures)`);\n }\n }\n }\n\n // Write files\n for (const f of files) {\n const data = f.dataSize > 0\n ? raw.subarray(f.dataOffset, f.dataOffset + f.dataSize)\n : new Uint8Array(0);\n if (engine.write(f.path, data).status !== 0) {\n lost++;\n // File write failures are less critical than mkdir — parent may be missing\n }\n }\n\n // Write symlinks — validate target before creating\n for (const sym of symlinks) {\n if (sym.dataSize === 0 && sym.contentLost) {\n // Symlink target was lost — skip, don't create a broken symlink\n lost++;\n continue;\n }\n const data = sym.dataSize > 0\n ? raw.subarray(sym.dataOffset, sym.dataOffset + sym.dataSize)\n : new Uint8Array(0);\n let target: string;\n try {\n target = decoder.decode(data);\n } catch {\n // Invalid UTF-8 in symlink target — skip\n lost++;\n continue;\n }\n if (target.length === 0 || target.includes('\\0')) {\n lost++;\n continue;\n }\n if (engine.symlink(target, sym.path).status !== 0) lost++;\n }\n\n engine.flush();\n repairOk = true;\n } finally {\n tmpHandle.close();\n if (!repairOk) {\n await cleanupTmpFile(rootDir);\n }\n }\n\n // Verify repaired VFS via re-mount, then swap into place\n // swapTmpToVFS calls verifyVFS internally — if verification fails,\n // .vfs.bin.tmp still exists and .vfs.bin is untouched\n try {\n await swapTmpToVFS(rootDir, tmpFileHandle);\n } catch (err: any) {\n // Swap failed — clean up temp file, throw descriptive error\n await cleanupTmpFile(rootDir);\n throw new Error(`Repair built a VFS but verification failed: ${err.message}`);\n }\n\n const entries = recovered\n .filter(e => e.path !== '/')\n .map(e => ({\n path: e.path,\n type: (e.type === INODE_TYPE.FILE ? 'file' : e.type === INODE_TYPE.DIRECTORY ? 'directory' : 'symlink') as 'file' | 'directory' | 'symlink',\n size: e.dataSize,\n contentLost: e.contentLost,\n }));\n\n return { recovered: entries.length, lost, entries };\n}\n\n// ========== Load handler ==========\n\nasync function handleLoad(root: string) {\n const rootDir = await navigateToRoot(root);\n\n // Clean up any orphaned temp file\n await cleanupTmpFile(rootDir);\n\n // Read all OPFS files FIRST (before touching .vfs.bin)\n const opfsEntries = await readOPFSRecursive(rootDir, '', new Set(['.vfs.bin', '.vfs.bin.tmp']));\n\n // Build fresh VFS in temp file — original .vfs.bin untouched until verified\n const tmpFileHandle = await rootDir.getFileHandle('.vfs.bin.tmp', { create: true });\n const tmpHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n\n let buildOk = false;\n let files = 0;\n let directories = 0;\n\n try {\n const engine = new VFSEngine();\n engine.init(tmpHandle);\n\n const dirs = opfsEntries\n .filter(e => e.type === 'directory')\n .sort((a, b) => a.path.localeCompare(b.path));\n\n for (const dir of dirs) {\n if (engine.mkdir(dir.path, 0o040755).status === 0) {\n directories++;\n }\n }\n\n const fileEntries = opfsEntries.filter(e => e.type === 'file');\n for (const file of fileEntries) {\n if (engine.write(file.path, new Uint8Array(file.data ?? new ArrayBuffer(0))).status === 0) {\n files++;\n }\n }\n\n engine.flush();\n buildOk = true;\n } finally {\n tmpHandle.close();\n if (!buildOk) {\n await cleanupTmpFile(rootDir);\n }\n }\n\n // Verify then swap (verifyVFS + copy-then-delete)\n try {\n await swapTmpToVFS(rootDir, tmpFileHandle);\n } catch (err: any) {\n await cleanupTmpFile(rootDir);\n throw new Error(`Load built a VFS but verification failed: ${err.message}`);\n }\n\n return { files, directories };\n}\n"],"mappings":"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","names":["inode","data","totalSize","buf","view","offset","decoder"]}
|
|
1
|
+
{"version":3,"sources":["../../src/src/vfs/layout.ts","../../src/src/errors.ts","../../src/src/vfs/engine.ts","../../src/src/workers/repair.worker.ts"],"sourcesContent":["/**\n * VFS Binary Layout Constants\n *\n * Defines the on-disk structure of the virtual filesystem binary file.\n * All reads/writes go through a FileSystemSyncAccessHandle.\n */\n\n// Magic number: \"VFS!\" in ASCII\nexport const VFS_MAGIC = 0x56465321;\nexport const VFS_VERSION = 1;\n\n// Default sizes\nexport const DEFAULT_BLOCK_SIZE = 4096;\nexport const DEFAULT_INODE_COUNT = 10000;\nexport const INODE_SIZE = 64; // bytes per inode entry\n\n// Superblock layout (64 bytes)\nexport const SUPERBLOCK = {\n SIZE: 64,\n MAGIC: 0, // uint32 - 0x56465321\n VERSION: 4, // uint32\n INODE_COUNT: 8, // uint32 - total inodes allocated\n BLOCK_SIZE: 12, // uint32 - data block size (default 4096)\n TOTAL_BLOCKS: 16, // uint32 - total data blocks\n FREE_BLOCKS: 20, // uint32 - available data blocks\n INODE_OFFSET: 24, // float64 - byte offset to inode table\n PATH_OFFSET: 32, // float64 - byte offset to path table\n DATA_OFFSET: 40, // float64 - byte offset to data region\n BITMAP_OFFSET: 48, // float64 - byte offset to free block bitmap\n PATH_USED: 56, // uint32 - bytes used in path table\n RESERVED: 60, // uint32\n} as const;\n\n// Inode entry layout (64 bytes each)\nexport const INODE = {\n TYPE: 0, // uint8 - 0=free, 1=file, 2=directory, 3=symlink\n FLAGS: 1, // uint8[3] - reserved\n PATH_OFFSET: 4, // uint32 - byte offset into path table\n PATH_LENGTH: 8, // uint16 - length of path string\n RESERVED_10: 10, // uint16\n MODE: 12, // uint32 - permissions (e.g. 0o100644)\n SIZE: 16, // float64 - file content size in bytes (using f64 for >4GB)\n FIRST_BLOCK: 24, // uint32 - index of first data block\n BLOCK_COUNT: 28, // uint32 - number of contiguous data blocks\n MTIME: 32, // float64 - last modification time (ms since epoch)\n CTIME: 40, // float64 - creation/change time (ms since epoch)\n ATIME: 48, // float64 - last access time (ms since epoch)\n UID: 56, // uint32 - owner\n GID: 60, // uint32 - group\n} as const;\n\n// Inode type constants\nexport const INODE_TYPE = {\n FREE: 0,\n FILE: 1,\n DIRECTORY: 2,\n SYMLINK: 3,\n} as const;\n\n// Default file modes\nexport const DEFAULT_FILE_MODE = 0o100644;\nexport const DEFAULT_DIR_MODE = 0o040755;\nexport const DEFAULT_SYMLINK_MODE = 0o120777;\nexport const DEFAULT_UMASK = 0o022;\n\n// POSIX file type bits\nexport const S_IFMT = 0o170000;\nexport const S_IFREG = 0o100000;\nexport const S_IFDIR = 0o040000;\nexport const S_IFLNK = 0o120000;\n\n// Max symlink depth for cycle detection\nexport const MAX_SYMLINK_DEPTH = 40;\n\n// Path table compaction threshold (25% dead space)\nexport const PATH_COMPACTION_THRESHOLD = 0.25;\n\n// Initial path table size (256KB)\nexport const INITIAL_PATH_TABLE_SIZE = 256 * 1024;\n\n// Initial data blocks (1024 blocks = 4MB with 4KB blocks)\nexport const INITIAL_DATA_BLOCKS = 1024;\n\n/**\n * Calculate section offsets for a fresh VFS.\n */\nexport function calculateLayout(inodeCount: number = DEFAULT_INODE_COUNT, blockSize: number = DEFAULT_BLOCK_SIZE, totalBlocks: number = INITIAL_DATA_BLOCKS) {\n const inodeTableOffset = SUPERBLOCK.SIZE;\n const inodeTableSize = inodeCount * INODE_SIZE;\n const pathTableOffset = inodeTableOffset + inodeTableSize;\n const pathTableSize = INITIAL_PATH_TABLE_SIZE;\n const bitmapOffset = pathTableOffset + pathTableSize;\n const bitmapSize = Math.ceil(totalBlocks / 8);\n // Align data region to block boundary\n const dataOffset = Math.ceil((bitmapOffset + bitmapSize) / blockSize) * blockSize;\n const totalSize = dataOffset + totalBlocks * blockSize;\n\n return {\n inodeTableOffset,\n inodeTableSize,\n pathTableOffset,\n pathTableSize,\n bitmapOffset,\n bitmapSize,\n dataOffset,\n totalSize,\n totalBlocks,\n };\n}\n","/**\n * Node.js compatible filesystem error classes\n */\n\nexport class FSError extends Error {\n code: string;\n errno: number;\n syscall?: string;\n path?: string;\n\n constructor(code: string, errno: number, message: string, syscall?: string, path?: string) {\n super(message);\n this.name = 'FSError';\n this.code = code;\n this.errno = errno;\n this.syscall = syscall;\n this.path = path;\n }\n}\n\nexport const ErrorCodes = {\n ENOENT: -2,\n EEXIST: -17,\n EISDIR: -21,\n ENOTDIR: -20,\n ENOTEMPTY: -39,\n EACCES: -13,\n EBADF: -9,\n EINVAL: -22,\n EMFILE: -24,\n ENOSPC: -28,\n EPERM: -1,\n ENOSYS: -38,\n ELOOP: -40,\n} as const;\n\n/** Binary protocol status codes → error code mapping */\nexport const STATUS_TO_CODE: Record<number, string> = {\n 0: 'OK',\n 1: 'ENOENT',\n 2: 'EEXIST',\n 3: 'EISDIR',\n 4: 'ENOTDIR',\n 5: 'ENOTEMPTY',\n 6: 'EACCES',\n 7: 'EINVAL',\n 8: 'EBADF',\n 9: 'ELOOP',\n 10: 'ENOSPC',\n};\n\n/** Error code → binary protocol status mapping */\nexport const CODE_TO_STATUS: Record<string, number> = {\n OK: 0,\n ENOENT: 1,\n EEXIST: 2,\n EISDIR: 3,\n ENOTDIR: 4,\n ENOTEMPTY: 5,\n EACCES: 6,\n EINVAL: 7,\n EBADF: 8,\n ELOOP: 9,\n ENOSPC: 10,\n};\n\nexport function createError(code: string, syscall: string, path: string): FSError {\n const errno = ErrorCodes[code as keyof typeof ErrorCodes] ?? -1;\n const messages: Record<string, string> = {\n ENOENT: 'no such file or directory',\n EEXIST: 'file already exists',\n EISDIR: 'illegal operation on a directory',\n ENOTDIR: 'not a directory',\n ENOTEMPTY: 'directory not empty',\n EACCES: 'permission denied',\n EINVAL: 'invalid argument',\n EBADF: 'bad file descriptor',\n ELOOP: 'too many symbolic links encountered',\n ENOSPC: 'no space left on device',\n };\n const msg = messages[code] ?? 'unknown error';\n return new FSError(code, errno, `${code}: ${msg}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function statusToError(status: number, syscall: string, path: string): FSError {\n const code = STATUS_TO_CODE[status] ?? 'EINVAL';\n return createError(code, syscall, path);\n}\n","/**\n * VFS Engine — operates on a FileSystemSyncAccessHandle\n *\n * Manages the binary VFS layout: superblock, inode table, path table,\n * free block bitmap, and data region. All operations are synchronous\n * and run inside the server worker.\n */\n\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_BLOCK_SIZE, DEFAULT_INODE_COUNT, DEFAULT_FILE_MODE, DEFAULT_DIR_MODE,\n DEFAULT_SYMLINK_MODE, DEFAULT_UMASK, S_IFMT, S_IFREG, S_IFDIR, S_IFLNK,\n MAX_SYMLINK_DEPTH, INITIAL_DATA_BLOCKS, INITIAL_PATH_TABLE_SIZE,\n calculateLayout,\n} from './layout.js';\nimport { CODE_TO_STATUS } from '../errors.js';\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\ninterface Inode {\n type: number;\n pathOffset: number;\n pathLength: number;\n mode: number;\n size: number;\n firstBlock: number;\n blockCount: number;\n mtime: number;\n ctime: number;\n atime: number;\n uid: number;\n gid: number;\n}\n\ninterface FdEntry {\n tabId: string;\n inodeIdx: number;\n position: number;\n flags: number;\n}\n\nexport class VFSEngine {\n private handle!: FileSystemSyncAccessHandle;\n private pathIndex = new Map<string, number>(); // path → inode index\n private inodeCount = 0;\n private blockSize = DEFAULT_BLOCK_SIZE;\n private totalBlocks = 0;\n private freeBlocks = 0;\n private inodeTableOffset = 0;\n private pathTableOffset = 0;\n private pathTableUsed = 0;\n private pathTableSize = 0;\n private bitmapOffset = 0;\n private dataOffset = 0;\n private umask = DEFAULT_UMASK;\n private processUid = 0;\n private processGid = 0;\n private strictPermissions = false;\n private debug = false;\n\n // File descriptor table\n private fdTable = new Map<number, FdEntry>();\n private nextFd = 3; // 0=stdin, 1=stdout, 2=stderr reserved\n\n // Reusable buffers to avoid allocations\n private inodeBuf = new Uint8Array(INODE_SIZE);\n private inodeView = new DataView(this.inodeBuf.buffer);\n\n // In-memory inode cache — eliminates disk reads for hot inodes\n private inodeCache = new Map<number, Inode>();\n private superblockBuf = new Uint8Array(SUPERBLOCK.SIZE);\n private superblockView = new DataView(this.superblockBuf.buffer);\n\n // In-memory bitmap cache — eliminates bitmap reads from OPFS\n private bitmap: Uint8Array | null = null;\n private bitmapDirtyLo = Infinity; // lowest dirty byte index\n private bitmapDirtyHi = -1; // highest dirty byte index (inclusive)\n private superblockDirty = false;\n\n // Free inode hint — skip O(n) scan\n private freeInodeHint = 0;\n\n init(\n handle: FileSystemSyncAccessHandle,\n opts?: { uid?: number; gid?: number; umask?: number; strictPermissions?: boolean; debug?: boolean }\n ): void {\n this.handle = handle;\n this.processUid = opts?.uid ?? 0;\n this.processGid = opts?.gid ?? 0;\n this.umask = opts?.umask ?? DEFAULT_UMASK;\n this.strictPermissions = opts?.strictPermissions ?? false;\n this.debug = opts?.debug ?? false;\n\n const size = handle.getSize();\n\n if (size === 0) {\n this.format();\n } else {\n this.mount();\n }\n }\n\n /** Release the sync access handle (call on fatal error or shutdown) */\n closeHandle(): void {\n try {\n this.handle?.close();\n } catch (_) {\n // Ignore — handle may already be closed\n }\n }\n\n /** Format a fresh VFS */\n private format(): void {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n\n this.inodeCount = DEFAULT_INODE_COUNT;\n this.blockSize = DEFAULT_BLOCK_SIZE;\n this.totalBlocks = layout.totalBlocks;\n this.freeBlocks = layout.totalBlocks;\n this.inodeTableOffset = layout.inodeTableOffset;\n this.pathTableOffset = layout.pathTableOffset;\n this.pathTableSize = layout.pathTableSize;\n this.pathTableUsed = 0;\n this.bitmapOffset = layout.bitmapOffset;\n this.dataOffset = layout.dataOffset;\n\n // Grow file to total size\n this.handle.truncate(layout.totalSize);\n\n // Write superblock\n this.writeSuperblock();\n\n // Zero out inode table (type=0 means free)\n const zeroBuf = new Uint8Array(layout.inodeTableSize);\n this.handle.write(zeroBuf, { at: this.inodeTableOffset });\n\n // Zero out bitmap and cache in memory\n this.bitmap = new Uint8Array(layout.bitmapSize);\n this.handle.write(this.bitmap, { at: this.bitmapOffset });\n\n // Create root directory inode\n this.createInode('/', INODE_TYPE.DIRECTORY, DEFAULT_DIR_MODE, 0);\n\n // Re-write superblock with updated pathTableUsed (createInode appended \"/\" to path table)\n this.writeSuperblock();\n this.handle.flush();\n }\n\n /** Mount an existing VFS from disk — validates superblock integrity */\n private mount(): void {\n const fileSize = this.handle.getSize();\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: file too small (${fileSize} bytes, need at least ${SUPERBLOCK.SIZE})`);\n }\n\n this.handle.read(this.superblockBuf, { at: 0 });\n const v = this.superblockView;\n\n // Validate magic\n const magic = v.getUint32(SUPERBLOCK.MAGIC, true);\n if (magic !== VFS_MAGIC) {\n throw new Error(`Corrupt VFS: bad magic 0x${magic.toString(16)} (expected 0x${VFS_MAGIC.toString(16)})`);\n }\n\n // Validate version\n const version = v.getUint32(SUPERBLOCK.VERSION, true);\n if (version !== VFS_VERSION) {\n throw new Error(`Corrupt VFS: unsupported version ${version} (expected ${VFS_VERSION})`);\n }\n\n // Read superblock fields\n const inodeCount = v.getUint32(SUPERBLOCK.INODE_COUNT, true);\n const blockSize = v.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n const totalBlocks = v.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n const freeBlocks = v.getUint32(SUPERBLOCK.FREE_BLOCKS, true);\n const inodeTableOffset = v.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n const pathTableOffset = v.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n const dataOffset = v.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n const bitmapOffset = v.getFloat64(SUPERBLOCK.BITMAP_OFFSET, true);\n const pathUsed = v.getUint32(SUPERBLOCK.PATH_USED, true);\n\n // Validate field sanity\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0) {\n throw new Error(`Corrupt VFS: invalid block size ${blockSize} (must be power of 2)`);\n }\n if (inodeCount === 0) {\n throw new Error('Corrupt VFS: inode count is 0');\n }\n if (freeBlocks > totalBlocks) {\n throw new Error(`Corrupt VFS: free blocks (${freeBlocks}) exceeds total blocks (${totalBlocks})`);\n }\n\n // Validate section ordering: superblock < inodes < paths < bitmap < data\n if (inodeTableOffset !== SUPERBLOCK.SIZE) {\n throw new Error(`Corrupt VFS: inode table offset ${inodeTableOffset} (expected ${SUPERBLOCK.SIZE})`);\n }\n const expectedPathOffset = inodeTableOffset + inodeCount * INODE_SIZE;\n if (pathTableOffset !== expectedPathOffset) {\n throw new Error(`Corrupt VFS: path table offset ${pathTableOffset} (expected ${expectedPathOffset})`);\n }\n if (bitmapOffset <= pathTableOffset) {\n throw new Error(`Corrupt VFS: bitmap offset ${bitmapOffset} must be after path table ${pathTableOffset}`);\n }\n if (dataOffset <= bitmapOffset) {\n throw new Error(`Corrupt VFS: data offset ${dataOffset} must be after bitmap ${bitmapOffset}`);\n }\n const pathTableSize = bitmapOffset - pathTableOffset;\n if (pathUsed > pathTableSize) {\n throw new Error(`Corrupt VFS: path used (${pathUsed}) exceeds path table size (${pathTableSize})`);\n }\n\n // Validate file is large enough for the declared layout\n const expectedMinSize = dataOffset + totalBlocks * blockSize;\n if (fileSize < expectedMinSize) {\n throw new Error(`Corrupt VFS: file size ${fileSize} too small for layout (need ${expectedMinSize})`);\n }\n\n // All checks passed — commit to engine state\n this.inodeCount = inodeCount;\n this.blockSize = blockSize;\n this.totalBlocks = totalBlocks;\n this.freeBlocks = freeBlocks;\n this.inodeTableOffset = inodeTableOffset;\n this.pathTableOffset = pathTableOffset;\n this.dataOffset = dataOffset;\n this.bitmapOffset = bitmapOffset;\n this.pathTableUsed = pathUsed;\n this.pathTableSize = pathTableSize;\n\n // Load bitmap into memory\n const bitmapSize = Math.ceil(this.totalBlocks / 8);\n this.bitmap = new Uint8Array(bitmapSize);\n this.handle.read(this.bitmap, { at: this.bitmapOffset });\n\n this.rebuildIndex();\n\n // Verify root directory exists\n if (!this.pathIndex.has('/')) {\n throw new Error('Corrupt VFS: root directory \"/\" not found in inode table');\n }\n }\n\n private writeSuperblock(): void {\n const v = this.superblockView;\n v.setUint32(SUPERBLOCK.MAGIC, VFS_MAGIC, true);\n v.setUint32(SUPERBLOCK.VERSION, VFS_VERSION, true);\n v.setUint32(SUPERBLOCK.INODE_COUNT, this.inodeCount, true);\n v.setUint32(SUPERBLOCK.BLOCK_SIZE, this.blockSize, true);\n v.setUint32(SUPERBLOCK.TOTAL_BLOCKS, this.totalBlocks, true);\n v.setUint32(SUPERBLOCK.FREE_BLOCKS, this.freeBlocks, true);\n v.setFloat64(SUPERBLOCK.INODE_OFFSET, this.inodeTableOffset, true);\n v.setFloat64(SUPERBLOCK.PATH_OFFSET, this.pathTableOffset, true);\n v.setFloat64(SUPERBLOCK.DATA_OFFSET, this.dataOffset, true);\n v.setFloat64(SUPERBLOCK.BITMAP_OFFSET, this.bitmapOffset, true);\n v.setUint32(SUPERBLOCK.PATH_USED, this.pathTableUsed, true);\n this.handle.write(this.superblockBuf, { at: 0 });\n }\n\n /** Flush pending bitmap and superblock writes to disk (one write each) */\n private markBitmapDirty(lo: number, hi: number): void {\n if (lo < this.bitmapDirtyLo) this.bitmapDirtyLo = lo;\n if (hi > this.bitmapDirtyHi) this.bitmapDirtyHi = hi;\n }\n\n private commitPending(): void {\n // Trim trailing free blocks before flushing bitmap/superblock\n if (this.blocksFreedsinceTrim) {\n this.trimTrailingBlocks();\n this.blocksFreedsinceTrim = false;\n }\n\n if (this.bitmapDirtyHi >= 0) {\n const lo = this.bitmapDirtyLo;\n const hi = this.bitmapDirtyHi;\n this.handle.write(this.bitmap!.subarray(lo, hi + 1), { at: this.bitmapOffset + lo });\n this.bitmapDirtyLo = Infinity;\n this.bitmapDirtyHi = -1;\n }\n if (this.superblockDirty) {\n this.writeSuperblock();\n this.superblockDirty = false;\n }\n }\n\n /** Shrink the OPFS file by removing trailing free blocks from the data region.\n * Scans bitmap from end to find the last used block, then truncates. */\n private trimTrailingBlocks(): void {\n const bitmap = this.bitmap!;\n\n // Find the last used block by scanning bitmap from the end\n let lastUsed = -1;\n for (let byteIdx = Math.ceil(this.totalBlocks / 8) - 1; byteIdx >= 0; byteIdx--) {\n if (bitmap[byteIdx] !== 0) {\n // Find highest set bit in this byte\n for (let bit = 7; bit >= 0; bit--) {\n const blockIdx = byteIdx * 8 + bit;\n if (blockIdx < this.totalBlocks && (bitmap[byteIdx] & (1 << bit))) {\n lastUsed = blockIdx;\n break;\n }\n }\n break;\n }\n }\n\n const newTotal = Math.max(lastUsed + 1, INITIAL_DATA_BLOCKS);\n if (newTotal >= this.totalBlocks) return; // nothing to trim\n\n // Truncate the OPFS file\n this.handle.truncate(this.dataOffset + newTotal * this.blockSize);\n\n // Shrink in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n this.bitmap = bitmap.slice(0, newBitmapSize);\n\n // Update counters\n const trimmed = this.totalBlocks - newTotal;\n this.freeBlocks -= trimmed; // these free blocks no longer exist\n this.totalBlocks = newTotal;\n this.superblockDirty = true;\n\n // Re-mark entire bitmap dirty so the smaller bitmap is flushed\n this.bitmapDirtyLo = 0;\n this.bitmapDirtyHi = newBitmapSize - 1;\n }\n\n /** Rebuild in-memory path→inode index from disk.\n * Bulk-reads the entire inode table + path table in 2 I/O calls,\n * then parses in memory (avoids 10k+ individual reads). */\n private rebuildIndex(): void {\n this.pathIndex.clear();\n this.inodeCache.clear();\n\n // Bulk read entire inode table (e.g. 640KB for 10k inodes)\n const inodeTableSize = this.inodeCount * INODE_SIZE;\n const inodeBuf = new Uint8Array(inodeTableSize);\n this.handle.read(inodeBuf, { at: this.inodeTableOffset });\n const inodeView = new DataView(inodeBuf.buffer);\n\n // Bulk read used portion of path table\n const pathBuf = this.pathTableUsed > 0 ? new Uint8Array(this.pathTableUsed) : null;\n if (pathBuf) {\n this.handle.read(pathBuf, { at: this.pathTableOffset });\n }\n\n for (let i = 0; i < this.inodeCount; i++) {\n const off = i * INODE_SIZE;\n const type = inodeView.getUint8(off + INODE.TYPE);\n if (type === INODE_TYPE.FREE) continue;\n\n // Validate inode type\n if (type < INODE_TYPE.FILE || type > INODE_TYPE.SYMLINK) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid type ${type}`);\n }\n\n const pathOffset = inodeView.getUint32(off + INODE.PATH_OFFSET, true);\n const pathLength = inodeView.getUint16(off + INODE.PATH_LENGTH, true);\n const size = inodeView.getFloat64(off + INODE.SIZE, true);\n const firstBlock = inodeView.getUint32(off + INODE.FIRST_BLOCK, true);\n const blockCount = inodeView.getUint32(off + INODE.BLOCK_COUNT, true);\n\n // Validate path bounds\n if (pathLength === 0 || pathOffset + pathLength > this.pathTableUsed) {\n throw new Error(`Corrupt VFS: inode ${i} path out of bounds (offset=${pathOffset}, len=${pathLength}, tableUsed=${this.pathTableUsed})`);\n }\n\n // Validate data bounds for files/symlinks\n if (type !== INODE_TYPE.DIRECTORY) {\n if (size < 0 || !isFinite(size)) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid size ${size}`);\n }\n if (blockCount > 0 && firstBlock + blockCount > this.totalBlocks) {\n throw new Error(`Corrupt VFS: inode ${i} data blocks out of range (first=${firstBlock}, count=${blockCount}, total=${this.totalBlocks})`);\n }\n }\n\n const inode: Inode = {\n type,\n pathOffset,\n pathLength,\n mode: inodeView.getUint32(off + INODE.MODE, true),\n size,\n firstBlock,\n blockCount,\n mtime: inodeView.getFloat64(off + INODE.MTIME, true),\n ctime: inodeView.getFloat64(off + INODE.CTIME, true),\n atime: inodeView.getFloat64(off + INODE.ATIME, true),\n uid: inodeView.getUint32(off + INODE.UID, true),\n gid: inodeView.getUint32(off + INODE.GID, true),\n };\n this.inodeCache.set(i, inode);\n\n // Decode path from in-memory path table buffer (no disk read)\n let path: string;\n if (pathBuf) {\n path = decoder.decode(pathBuf.subarray(inode.pathOffset, inode.pathOffset + inode.pathLength));\n } else {\n path = this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n // Validate path format\n if (!path.startsWith('/') || path.includes('\\0')) {\n throw new Error(`Corrupt VFS: inode ${i} has invalid path \"${path.substring(0, 50)}\"`);\n }\n\n this.pathIndex.set(path, i);\n }\n }\n\n // ========== Low-level inode I/O ==========\n\n private readInode(idx: number): Inode {\n const cached = this.inodeCache.get(idx);\n if (cached) return cached;\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.read(this.inodeBuf, { at: offset });\n const v = this.inodeView;\n const inode: Inode = {\n type: v.getUint8(INODE.TYPE),\n pathOffset: v.getUint32(INODE.PATH_OFFSET, true),\n pathLength: v.getUint16(INODE.PATH_LENGTH, true),\n mode: v.getUint32(INODE.MODE, true),\n size: v.getFloat64(INODE.SIZE, true),\n firstBlock: v.getUint32(INODE.FIRST_BLOCK, true),\n blockCount: v.getUint32(INODE.BLOCK_COUNT, true),\n mtime: v.getFloat64(INODE.MTIME, true),\n ctime: v.getFloat64(INODE.CTIME, true),\n atime: v.getFloat64(INODE.ATIME, true),\n uid: v.getUint32(INODE.UID, true),\n gid: v.getUint32(INODE.GID, true),\n };\n this.inodeCache.set(idx, inode);\n return inode;\n }\n\n private writeInode(idx: number, inode: Inode): void {\n // Maintain inode cache\n if (inode.type === INODE_TYPE.FREE) {\n this.inodeCache.delete(idx);\n } else {\n this.inodeCache.set(idx, inode);\n }\n\n const v = this.inodeView;\n v.setUint8(INODE.TYPE, inode.type);\n v.setUint8(INODE.FLAGS, 0);\n v.setUint8(INODE.FLAGS + 1, 0);\n v.setUint8(INODE.FLAGS + 2, 0);\n v.setUint32(INODE.PATH_OFFSET, inode.pathOffset, true);\n v.setUint16(INODE.PATH_LENGTH, inode.pathLength, true);\n v.setUint16(INODE.RESERVED_10, 0, true);\n v.setUint32(INODE.MODE, inode.mode, true);\n v.setFloat64(INODE.SIZE, inode.size, true);\n v.setUint32(INODE.FIRST_BLOCK, inode.firstBlock, true);\n v.setUint32(INODE.BLOCK_COUNT, inode.blockCount, true);\n v.setFloat64(INODE.MTIME, inode.mtime, true);\n v.setFloat64(INODE.CTIME, inode.ctime, true);\n v.setFloat64(INODE.ATIME, inode.atime, true);\n v.setUint32(INODE.UID, inode.uid, true);\n v.setUint32(INODE.GID, inode.gid, true);\n\n const offset = this.inodeTableOffset + idx * INODE_SIZE;\n this.handle.write(this.inodeBuf, { at: offset });\n }\n\n // ========== Path table I/O ==========\n\n private readPath(offset: number, length: number): string {\n const buf = new Uint8Array(length);\n this.handle.read(buf, { at: this.pathTableOffset + offset });\n return decoder.decode(buf);\n }\n\n private appendPath(path: string): { offset: number; length: number } {\n const bytes = encoder.encode(path);\n const offset = this.pathTableUsed;\n\n // Check if path table needs to grow\n if (offset + bytes.byteLength > this.pathTableSize) {\n this.growPathTable(offset + bytes.byteLength);\n }\n\n this.handle.write(bytes, { at: this.pathTableOffset + offset });\n this.pathTableUsed += bytes.byteLength;\n\n // Defer superblock write — committed in commitPending()\n this.superblockDirty = true;\n\n return { offset, length: bytes.byteLength };\n }\n\n private growPathTable(needed: number): void {\n // Double the path table or grow to fit needed, whichever is larger\n const newSize = Math.max(this.pathTableSize * 2, needed + INITIAL_PATH_TABLE_SIZE);\n const growth = newSize - this.pathTableSize;\n\n // Need to shift bitmap and data region forward\n // Use in-memory bitmap (no read needed)\n\n // Read existing data region\n const dataSize = this.totalBlocks * this.blockSize;\n const dataBuf = new Uint8Array(dataSize);\n this.handle.read(dataBuf, { at: this.dataOffset });\n\n // Grow file\n const newTotalSize = this.handle.getSize() + growth;\n this.handle.truncate(newTotalSize);\n\n // Write data back at new offset\n const newBitmapOffset = this.bitmapOffset + growth;\n const newDataOffset = this.dataOffset + growth;\n this.handle.write(dataBuf, { at: newDataOffset });\n this.handle.write(this.bitmap!, { at: newBitmapOffset });\n\n // Update offsets\n this.pathTableSize = newSize;\n this.bitmapOffset = newBitmapOffset;\n this.dataOffset = newDataOffset;\n\n // Mark superblock dirty (will be written in commitPending)\n this.superblockDirty = true;\n }\n\n // ========== Bitmap I/O ==========\n\n private allocateBlocks(count: number): number {\n if (count === 0) return 0;\n\n const bitmap = this.bitmap!;\n let run = 0;\n let start = 0;\n\n for (let i = 0; i < this.totalBlocks; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n const used = (bitmap[byteIdx] >>> bitIdx) & 1;\n\n if (used) {\n run = 0;\n start = i + 1;\n } else {\n run++;\n if (run === count) {\n // Mark blocks as used in memory\n for (let j = start; j <= i; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n bitmap[bj] |= (1 << bi);\n }\n this.markBitmapDirty(start >>> 3, i >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n return start;\n }\n }\n }\n\n // No contiguous space — grow data region\n return this.growAndAllocate(count);\n }\n\n private growAndAllocate(count: number): number {\n const oldTotal = this.totalBlocks;\n // Grow by at least doubling or enough for the request\n const newTotal = Math.max(oldTotal * 2, oldTotal + count);\n const addedBlocks = newTotal - oldTotal;\n\n // Grow the file\n const newFileSize = this.dataOffset + newTotal * this.blockSize;\n this.handle.truncate(newFileSize);\n\n // Grow in-memory bitmap\n const newBitmapSize = Math.ceil(newTotal / 8);\n const newBitmap = new Uint8Array(newBitmapSize);\n newBitmap.set(this.bitmap!);\n this.bitmap = newBitmap;\n\n this.totalBlocks = newTotal;\n this.freeBlocks += addedBlocks;\n\n // Allocate from the newly freed area\n const start = oldTotal;\n for (let j = start; j < start + count; j++) {\n const bj = j >>> 3;\n const bi = j & 7;\n this.bitmap[bj] |= (1 << bi);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks -= count;\n this.superblockDirty = true;\n\n return start;\n }\n\n private blocksFreedsinceTrim = false;\n\n private freeBlockRange(start: number, count: number): void {\n if (count === 0) return;\n const bitmap = this.bitmap!;\n\n for (let i = start; i < start + count; i++) {\n const byteIdx = i >>> 3;\n const bitIdx = i & 7;\n bitmap[byteIdx] &= ~(1 << bitIdx);\n }\n\n this.markBitmapDirty(start >>> 3, (start + count - 1) >>> 3);\n this.freeBlocks += count;\n this.superblockDirty = true;\n this.blocksFreedsinceTrim = true;\n }\n\n // updateSuperblockFreeBlocks is no longer needed — superblock writes are coalesced via commitPending()\n\n // ========== Inode allocation ==========\n\n private findFreeInode(): number {\n // Start from hint to skip already-used entries\n for (let i = this.freeInodeHint; i < this.inodeCount; i++) {\n // Check cache first — cached entries are never FREE\n if (this.inodeCache.has(i)) continue;\n\n const offset = this.inodeTableOffset + i * INODE_SIZE;\n const typeBuf = new Uint8Array(1);\n this.handle.read(typeBuf, { at: offset });\n if (typeBuf[0] === INODE_TYPE.FREE) {\n this.freeInodeHint = i + 1;\n return i;\n }\n }\n // All inodes used — grow inode table\n const idx = this.growInodeTable();\n this.freeInodeHint = idx + 1;\n return idx;\n }\n\n private growInodeTable(): number {\n const oldCount = this.inodeCount;\n const newCount = oldCount * 2;\n const growth = (newCount - oldCount) * INODE_SIZE;\n\n // Read everything after inode table\n const afterInodeOffset = this.inodeTableOffset + oldCount * INODE_SIZE;\n const afterSize = this.handle.getSize() - afterInodeOffset;\n const afterBuf = new Uint8Array(afterSize);\n this.handle.read(afterBuf, { at: afterInodeOffset });\n\n // Grow file\n this.handle.truncate(this.handle.getSize() + growth);\n\n // Write back shifted content\n this.handle.write(afterBuf, { at: afterInodeOffset + growth });\n\n // Zero out new inode entries\n const zeroes = new Uint8Array(growth);\n this.handle.write(zeroes, { at: afterInodeOffset });\n\n // Update offsets\n this.pathTableOffset += growth;\n this.bitmapOffset += growth;\n this.dataOffset += growth;\n this.inodeCount = newCount;\n\n this.superblockDirty = true;\n\n return oldCount; // First new free inode\n }\n\n // ========== Data I/O ==========\n\n private readData(firstBlock: number, blockCount: number, size: number): Uint8Array {\n const buf = new Uint8Array(size);\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.read(buf, { at: offset });\n return buf;\n }\n\n private writeData(firstBlock: number, data: Uint8Array): void {\n const offset = this.dataOffset + firstBlock * this.blockSize;\n this.handle.write(data, { at: offset });\n }\n\n // ========== Path resolution ==========\n\n private resolvePath(path: string, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const idx = this.pathIndex.get(path);\n if (idx === undefined) {\n // Path not found directly — try component resolution (handles intermediate symlinks)\n return this.resolvePathComponents(path, true, depth);\n }\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK) {\n // Follow symlink\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(path, target);\n return this.resolvePath(resolved, depth + 1);\n }\n\n return idx;\n }\n\n /** Resolve symlinks in intermediate path components */\n private resolvePathComponents(path: string, followLast: boolean = true, depth: number = 0): number | undefined {\n if (depth > MAX_SYMLINK_DEPTH) return undefined; // ELOOP\n\n const parts = path.split('/').filter(Boolean);\n let current = '/';\n\n for (let i = 0; i < parts.length; i++) {\n const isLast = i === parts.length - 1;\n current = current === '/' ? '/' + parts[i] : current + '/' + parts[i];\n\n const idx = this.pathIndex.get(current);\n if (idx === undefined) return undefined;\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.SYMLINK && (!isLast || followLast)) {\n const target = decoder.decode(this.readData(inode.firstBlock, inode.blockCount, inode.size));\n const resolved = target.startsWith('/') ? target : this.resolveRelative(current, target);\n\n if (isLast) {\n // Use resolvePathComponents (not resolvePath) so intermediate symlinks\n // in the resolved target path are also followed\n return this.resolvePathComponents(resolved, true, depth + 1);\n }\n\n // Reconstruct remaining path with resolved symlink\n const remaining = parts.slice(i + 1).join('/');\n const newPath = resolved + (remaining ? '/' + remaining : '');\n return this.resolvePathComponents(newPath, followLast, depth + 1);\n }\n }\n\n return this.pathIndex.get(current);\n }\n\n private resolveRelative(from: string, target: string): string {\n const dir = from.substring(0, from.lastIndexOf('/')) || '/';\n const parts = (dir + '/' + target).split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const p of parts) {\n if (p === '.') continue;\n if (p === '..') { resolved.pop(); continue; }\n resolved.push(p);\n }\n return '/' + resolved.join('/');\n }\n\n // ========== Core inode creation helper ==========\n\n private createInode(path: string, type: number, mode: number, size: number, data?: Uint8Array): number {\n const idx = this.findFreeInode();\n const { offset: pathOff, length: pathLen } = this.appendPath(path);\n const now = Date.now();\n\n let firstBlock = 0;\n let blockCount = 0;\n\n if (data && data.byteLength > 0) {\n blockCount = Math.ceil(data.byteLength / this.blockSize);\n firstBlock = this.allocateBlocks(blockCount);\n this.writeData(firstBlock, data);\n }\n\n const inode: Inode = {\n type,\n pathOffset: pathOff,\n pathLength: pathLen,\n mode,\n size,\n firstBlock,\n blockCount,\n mtime: now,\n ctime: now,\n atime: now,\n uid: this.processUid,\n gid: this.processGid,\n };\n\n this.writeInode(idx, inode);\n this.pathIndex.set(path, idx);\n\n return idx;\n }\n\n // ========== Public API — called by server worker dispatch ==========\n\n /** Normalize a path: ensure leading /, resolve . and .. */\n normalizePath(p: string): string {\n if (p.charCodeAt(0) !== 47) p = '/' + p; // 47 = '/'\n // Fast path: already normalized (no '.', '..', '//', trailing '/')\n if (p.length === 1) return p; // \"/\"\n if (p.indexOf('/.') === -1 && p.indexOf('//') === -1 && p.charCodeAt(p.length - 1) !== 47) {\n return p;\n }\n // Slow path: full normalize\n const parts = p.split('/').filter(Boolean);\n const resolved: string[] = [];\n for (const part of parts) {\n if (part === '.') continue;\n if (part === '..') { resolved.pop(); continue; }\n resolved.push(part);\n }\n return '/' + resolved.join('/');\n }\n\n // ---- READ ----\n read(path: string): { status: number; data: Uint8Array | null } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n\n // Fast path: direct index lookup (skips component-by-component walk)\n let idx = this.pathIndex.get(path);\n if (idx !== undefined) {\n const inode = this.inodeCache.get(idx);\n if (inode) {\n // Symlink? Fall through to full resolve\n if (inode.type === INODE_TYPE.SYMLINK) {\n idx = this.resolvePathComponents(path, true);\n } else if (inode.type === INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.EISDIR, data: null };\n } else {\n // Hot path: cached inode, no symlinks\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (fast)`);\n }\n return { status: 0, data };\n }\n }\n }\n\n // Slow path: full component resolution (handles symlinks, uncached inodes)\n if (idx === undefined) idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR, data: null };\n\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n if (this.debug) {\n const t1 = performance.now();\n console.log(`[VFS read] path=${path} size=${inode.size} TOTAL=${(t1-t0).toFixed(3)}ms (slow path)`);\n }\n\n return { status: 0, data };\n }\n\n // ---- WRITE ----\n write(path: string, data: Uint8Array, flags: number = 0): { status: number } {\n const t0 = this.debug ? performance.now() : 0;\n path = this.normalizePath(path);\n const t1 = this.debug ? performance.now() : 0;\n\n // Ensure parent directory exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus };\n const t2 = this.debug ? performance.now() : 0;\n\n const existingIdx = this.resolvePathComponents(path, true);\n const t3 = this.debug ? performance.now() : 0;\n\n let tAlloc = t3, tData = t3, tInode = t3;\n\n if (existingIdx !== undefined) {\n // Update existing file\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n const neededBlocks = Math.ceil(data.byteLength / this.blockSize);\n\n if (neededBlocks <= inode.blockCount) {\n // Fits in current blocks\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(inode.firstBlock, data);\n tData = this.debug ? performance.now() : 0;\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n } else {\n // Need more blocks — free old, allocate new\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n tAlloc = this.debug ? performance.now() : 0;\n this.writeData(newFirst, data);\n tData = this.debug ? performance.now() : 0;\n inode.firstBlock = newFirst;\n }\n\n inode.size = data.byteLength;\n inode.blockCount = neededBlocks;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n tInode = this.debug ? performance.now() : 0;\n } else {\n // Create new file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.FILE, mode, data.byteLength, data);\n tAlloc = this.debug ? performance.now() : 0;\n tData = tAlloc;\n tInode = tAlloc;\n }\n\n // Always commit pending superblock/bitmap changes (matches unlink, mkdir, etc.)\n // Without this, PATH_USED won't be persisted for newly created files,\n // causing \"path out of bounds\" corruption on reload.\n this.commitPending();\n if (flags & 1) {\n this.handle.flush();\n }\n const tFlush = this.debug ? performance.now() : 0;\n\n if (this.debug) {\n const existing = existingIdx !== undefined;\n console.log(`[VFS write] path=${path} size=${data.byteLength} ${existing ? 'UPDATE' : 'CREATE'} normalize=${(t1-t0).toFixed(3)}ms parent=${(t2-t1).toFixed(3)}ms resolve=${(t3-t2).toFixed(3)}ms alloc=${(tAlloc-t3).toFixed(3)}ms data=${(tData-tAlloc).toFixed(3)}ms inode=${(tInode-tData).toFixed(3)}ms flush=${(tFlush-tInode).toFixed(3)}ms TOTAL=${(tFlush-t0).toFixed(3)}ms`);\n }\n\n return { status: 0 };\n }\n\n // ---- APPEND ----\n append(path: string, data: Uint8Array): { status: number } {\n path = this.normalizePath(path);\n const existingIdx = this.resolvePathComponents(path, true);\n\n if (existingIdx === undefined) {\n // Create new file with the data\n return this.write(path, data);\n }\n\n const inode = this.readInode(existingIdx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Read existing data\n const existing = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n\n // Concat\n const combined = new Uint8Array(existing.byteLength + data.byteLength);\n combined.set(existing);\n combined.set(data, existing.byteLength);\n\n // Rewrite\n const neededBlocks = Math.ceil(combined.byteLength / this.blockSize);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n this.writeData(newFirst, combined);\n\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n inode.size = combined.byteLength;\n inode.mtime = Date.now();\n this.writeInode(existingIdx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- UNLINK ----\n unlink(path: string): { status: number } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // Free data blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n\n // Mark inode as free\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n\n // Remove from index\n this.pathIndex.delete(path);\n // Reset free inode hint\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- STAT ----\n stat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n // ---- LSTAT (no symlink follow) ----\n lstat(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n return this.encodeStatResponse(idx);\n }\n\n private encodeStatResponse(idx: number): { status: number; data: Uint8Array } {\n const inode = this.readInode(idx);\n // Encode stat into binary: type(1) + mode(4) + size(8) + mtime(8) + ctime(8) + atime(8) + uid(4) + gid(4) + ino(4) = 49 bytes\n const buf = new Uint8Array(49);\n const view = new DataView(buf.buffer);\n view.setUint8(0, inode.type);\n view.setUint32(1, inode.mode, true);\n view.setFloat64(5, inode.size, true);\n view.setFloat64(13, inode.mtime, true);\n view.setFloat64(21, inode.ctime, true);\n view.setFloat64(29, inode.atime, true);\n view.setUint32(37, inode.uid, true);\n view.setUint32(41, inode.gid, true);\n view.setUint32(45, idx, true); // ino = inode index\n\n return { status: 0, data: buf };\n }\n\n // ---- MKDIR ----\n mkdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n\n if (recursive) {\n return this.mkdirRecursive(path);\n }\n\n // Check if already exists\n if (this.pathIndex.has(path)) return { status: CODE_TO_STATUS.EEXIST, data: null };\n\n // Ensure parent exists\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) return { status: parentStatus, data: null };\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n // Return created path as data\n const pathBytes = encoder.encode(path);\n return { status: 0, data: pathBytes };\n }\n\n private mkdirRecursive(path: string): { status: number; data: Uint8Array | null } {\n const parts = path.split('/').filter(Boolean);\n let current = '';\n let firstCreated: string | null = null;\n\n for (const part of parts) {\n current += '/' + part;\n\n if (this.pathIndex.has(current)) {\n const idx = this.pathIndex.get(current)!;\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) {\n return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n }\n continue;\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(current, INODE_TYPE.DIRECTORY, mode, 0);\n if (!firstCreated) firstCreated = current;\n }\n\n this.commitPending();\n const result = firstCreated ? encoder.encode(firstCreated) : undefined;\n return { status: 0, data: result ?? null };\n }\n\n // ---- RMDIR ----\n rmdir(path: string, flags: number = 0): { status: number } {\n path = this.normalizePath(path);\n const recursive = (flags & 1) !== 0;\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR };\n\n // Check for children\n const children = this.getDirectChildren(path);\n\n if (children.length > 0) {\n if (!recursive) return { status: CODE_TO_STATUS.ENOTEMPTY };\n\n // Recursive delete\n for (const child of this.getAllDescendants(path)) {\n const childIdx = this.pathIndex.get(child)!;\n const childInode = this.readInode(childIdx);\n this.freeBlockRange(childInode.firstBlock, childInode.blockCount);\n childInode.type = INODE_TYPE.FREE;\n this.writeInode(childIdx, childInode);\n this.pathIndex.delete(child);\n }\n }\n\n // Remove the directory itself\n inode.type = INODE_TYPE.FREE;\n this.writeInode(idx, inode);\n this.pathIndex.delete(path);\n if (idx < this.freeInodeHint) this.freeInodeHint = idx;\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READDIR ----\n readdir(path: string, flags: number = 0): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n const withFileTypes = (flags & 1) !== 0;\n const children = this.getDirectChildren(path);\n\n if (withFileTypes) {\n // Encode as: count(u32) + entries[name_len(u16) + name(bytes) + type(u8)]\n let totalSize = 4;\n const entries: { name: Uint8Array; type: number }[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n const childIdx = this.pathIndex.get(childPath)!;\n const childInode = this.readInode(childIdx);\n entries.push({ name: nameBytes, type: childInode.type });\n totalSize += 2 + nameBytes.byteLength + 1; // nameLen + name + type\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, entries.length, true);\n let offset = 4;\n\n for (const entry of entries) {\n view.setUint16(offset, entry.name.byteLength, true);\n offset += 2;\n buf.set(entry.name, offset);\n offset += entry.name.byteLength;\n buf[offset++] = entry.type;\n }\n\n return { status: 0, data: buf };\n }\n\n // Simple name list: count(u32) + entries[name_len(u16) + name(bytes)]\n let totalSize = 4;\n const nameEntries: Uint8Array[] = [];\n\n for (const childPath of children) {\n const name = childPath.substring(childPath.lastIndexOf('/') + 1);\n const nameBytes = encoder.encode(name);\n nameEntries.push(nameBytes);\n totalSize += 2 + nameBytes.byteLength;\n }\n\n const buf = new Uint8Array(totalSize);\n const view = new DataView(buf.buffer);\n view.setUint32(0, nameEntries.length, true);\n let offset = 4;\n\n for (const nameBytes of nameEntries) {\n view.setUint16(offset, nameBytes.byteLength, true);\n offset += 2;\n buf.set(nameBytes, offset);\n offset += nameBytes.byteLength;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- RENAME ----\n rename(oldPath: string, newPath: string): { status: number } {\n oldPath = this.normalizePath(oldPath);\n newPath = this.normalizePath(newPath);\n\n const idx = this.pathIndex.get(oldPath);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n // Ensure parent of new path exists\n const parentStatus = this.ensureParent(newPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n // If target exists, remove it\n const existingIdx = this.pathIndex.get(newPath);\n if (existingIdx !== undefined) {\n const existingInode = this.readInode(existingIdx);\n this.freeBlockRange(existingInode.firstBlock, existingInode.blockCount);\n existingInode.type = INODE_TYPE.FREE;\n this.writeInode(existingIdx, existingInode);\n this.pathIndex.delete(newPath);\n }\n\n // Update inode with new path\n const inode = this.readInode(idx);\n const { offset: pathOff, length: pathLen } = this.appendPath(newPath);\n inode.pathOffset = pathOff;\n inode.pathLength = pathLen;\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n // Update index\n this.pathIndex.delete(oldPath);\n this.pathIndex.set(newPath, idx);\n\n // If it's a directory, rename all descendants\n if (inode.type === INODE_TYPE.DIRECTORY) {\n const prefix = oldPath === '/' ? '/' : oldPath + '/';\n const toRename: [string, number][] = [];\n\n for (const [p, i] of this.pathIndex) {\n if (p.startsWith(prefix)) {\n toRename.push([p, i]);\n }\n }\n\n for (const [p, i] of toRename) {\n const suffix = p.substring(oldPath.length);\n const childNewPath = newPath + suffix;\n const childInode = this.readInode(i);\n const { offset: cpo, length: cpl } = this.appendPath(childNewPath);\n childInode.pathOffset = cpo;\n childInode.pathLength = cpl;\n this.writeInode(i, childInode);\n this.pathIndex.delete(p);\n this.pathIndex.set(childNewPath, i);\n }\n }\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- EXISTS ----\n exists(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n const buf = new Uint8Array(1);\n buf[0] = idx !== undefined ? 1 : 0;\n return { status: 0, data: buf };\n }\n\n // ---- TRUNCATE ----\n truncate(path: string, len: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n if (inode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n if (len === 0) {\n // Free all blocks\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n inode.firstBlock = 0;\n inode.blockCount = 0;\n inode.size = 0;\n } else if (len < inode.size) {\n // Shrink\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks < inode.blockCount) {\n this.freeBlockRange(inode.firstBlock + neededBlocks, inode.blockCount - neededBlocks);\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n } else if (len > inode.size) {\n // Grow (zero-fill)\n const neededBlocks = Math.ceil(len / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Need more blocks\n const oldData = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newData = new Uint8Array(len);\n newData.set(oldData);\n // Rest is already zero-filled\n this.writeData(newFirst, newData);\n inode.firstBlock = newFirst;\n }\n inode.blockCount = neededBlocks;\n inode.size = len;\n }\n\n inode.mtime = Date.now();\n this.writeInode(idx, inode);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- COPY ----\n copy(srcPath: string, destPath: string, flags: number = 0): { status: number } {\n srcPath = this.normalizePath(srcPath);\n destPath = this.normalizePath(destPath);\n\n const srcIdx = this.resolvePathComponents(srcPath, true);\n if (srcIdx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const srcInode = this.readInode(srcIdx);\n if (srcInode.type === INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.EISDIR };\n\n // COPYFILE_EXCL check\n if ((flags & 1) && this.pathIndex.has(destPath)) {\n return { status: CODE_TO_STATUS.EEXIST };\n }\n\n // Read source data\n const data = srcInode.size > 0\n ? this.readData(srcInode.firstBlock, srcInode.blockCount, srcInode.size)\n : new Uint8Array(0);\n\n return this.write(destPath, data);\n }\n\n // ---- ACCESS ----\n access(path: string, mode: number = 0): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n if (mode === 0) return { status: 0 }; // F_OK — just check existence\n\n if (!this.strictPermissions) return { status: 0 }; // Relaxed mode\n\n const inode = this.readInode(idx);\n // Check permission bits against process identity\n const filePerm = this.getEffectivePermission(inode);\n\n if ((mode & 4) && !(filePerm & 4)) return { status: CODE_TO_STATUS.EACCES }; // R_OK\n if ((mode & 2) && !(filePerm & 2)) return { status: CODE_TO_STATUS.EACCES }; // W_OK\n if ((mode & 1) && !(filePerm & 1)) return { status: CODE_TO_STATUS.EACCES }; // X_OK\n\n return { status: 0 };\n }\n\n private getEffectivePermission(inode: Inode): number {\n const modeBits = inode.mode & 0o777;\n if (this.processUid === inode.uid) return (modeBits >>> 6) & 7;\n if (this.processGid === inode.gid) return (modeBits >>> 3) & 7;\n return modeBits & 7;\n }\n\n // ---- REALPATH ----\n realpath(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n // Find the resolved path for this inode\n const inode = this.readInode(idx);\n const resolvedPath = this.readPath(inode.pathOffset, inode.pathLength);\n return { status: 0, data: encoder.encode(resolvedPath) };\n }\n\n // ---- CHMOD ----\n chmod(path: string, mode: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n // Preserve file type bits, update permission bits\n inode.mode = (inode.mode & S_IFMT) | (mode & 0o7777);\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- CHOWN ----\n chown(path: string, uid: number, gid: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.uid = uid;\n inode.gid = gid;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- UTIMES ----\n utimes(path: string, atime: number, mtime: number): { status: number } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT };\n\n const inode = this.readInode(idx);\n inode.atime = atime;\n inode.mtime = mtime;\n inode.ctime = Date.now();\n this.writeInode(idx, inode);\n\n return { status: 0 };\n }\n\n // ---- SYMLINK ----\n symlink(target: string, linkPath: string): { status: number } {\n linkPath = this.normalizePath(linkPath);\n if (this.pathIndex.has(linkPath)) return { status: CODE_TO_STATUS.EEXIST };\n\n const parentStatus = this.ensureParent(linkPath);\n if (parentStatus !== 0) return { status: parentStatus };\n\n const targetBytes = encoder.encode(target);\n this.createInode(linkPath, INODE_TYPE.SYMLINK, DEFAULT_SYMLINK_MODE, targetBytes.byteLength, targetBytes);\n\n this.commitPending();\n return { status: 0 };\n }\n\n // ---- READLINK ----\n readlink(path: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.pathIndex.get(path);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.SYMLINK) return { status: CODE_TO_STATUS.EINVAL, data: null };\n\n const target = this.readData(inode.firstBlock, inode.blockCount, inode.size);\n return { status: 0, data: target };\n }\n\n // ---- LINK (hard link — copies the file) ----\n link(existingPath: string, newPath: string): { status: number } {\n return this.copy(existingPath, newPath);\n }\n\n // ---- OPEN (file descriptor) ----\n open(path: string, flags: number, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n\n const hasCreate = (flags & 64) !== 0; // O_CREAT\n const hasTrunc = (flags & 512) !== 0; // O_TRUNC\n const hasExcl = (flags & 128) !== 0; // O_EXCL\n\n let idx = this.resolvePathComponents(path, true);\n\n if (idx === undefined) {\n if (!hasCreate) return { status: CODE_TO_STATUS.ENOENT, data: null };\n // Create file\n const mode = DEFAULT_FILE_MODE & ~(this.umask & 0o777);\n idx = this.createInode(path, INODE_TYPE.FILE, mode, 0);\n } else if (hasExcl && hasCreate) {\n return { status: CODE_TO_STATUS.EEXIST, data: null };\n }\n\n if (hasTrunc) {\n this.truncate(path, 0);\n }\n\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- CLOSE ----\n close(fd: number): { status: number } {\n if (!this.fdTable.has(fd)) return { status: CODE_TO_STATUS.EBADF };\n this.fdTable.delete(fd);\n return { status: 0 };\n }\n\n // ---- FREAD ----\n fread(fd: number, length: number, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const pos = position ?? entry.position;\n const readLen = Math.min(length, inode.size - pos);\n\n if (readLen <= 0) return { status: 0, data: new Uint8Array(0) };\n\n // Read from specific offset within the file's data blocks\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n const buf = new Uint8Array(readLen);\n this.handle.read(buf, { at: dataOffset });\n\n // Update position\n if (position === null) {\n entry.position += readLen;\n }\n\n return { status: 0, data: buf };\n }\n\n // ---- FWRITE ----\n fwrite(fd: number, data: Uint8Array, position: number | null): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n\n const inode = this.readInode(entry.inodeIdx);\n const isAppend = (entry.flags & 1024) !== 0; // O_APPEND\n const pos = isAppend ? inode.size : (position ?? entry.position);\n const endPos = pos + data.byteLength;\n\n // Check if we need to grow\n if (endPos > inode.size) {\n const neededBlocks = Math.ceil(endPos / this.blockSize);\n if (neededBlocks > inode.blockCount) {\n // Grow — read old data, reallocate, write back\n const oldData = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n this.freeBlockRange(inode.firstBlock, inode.blockCount);\n const newFirst = this.allocateBlocks(neededBlocks);\n const newBuf = new Uint8Array(endPos);\n newBuf.set(oldData);\n newBuf.set(data, pos);\n this.writeData(newFirst, newBuf);\n inode.firstBlock = newFirst;\n inode.blockCount = neededBlocks;\n } else {\n // Fits, write at position\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n inode.size = endPos;\n } else {\n // Write within existing bounds\n const dataOffset = this.dataOffset + inode.firstBlock * this.blockSize + pos;\n this.handle.write(data, { at: dataOffset });\n }\n\n inode.mtime = Date.now();\n this.writeInode(entry.inodeIdx, inode);\n\n // Update position\n if (position === null) {\n entry.position = endPos;\n }\n\n this.commitPending();\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, data.byteLength, true);\n return { status: 0, data: buf };\n }\n\n // ---- FSTAT ----\n fstat(fd: number): { status: number; data: Uint8Array | null } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF, data: null };\n return this.encodeStatResponse(entry.inodeIdx);\n }\n\n // ---- FTRUNCATE ----\n ftruncate(fd: number, len: number = 0): { status: number } {\n const entry = this.fdTable.get(fd);\n if (!entry) return { status: CODE_TO_STATUS.EBADF };\n\n const inode = this.readInode(entry.inodeIdx);\n const path = this.readPath(inode.pathOffset, inode.pathLength);\n return this.truncate(path, len);\n }\n\n // ---- FSYNC ----\n fsync(): { status: number } {\n this.commitPending();\n this.handle.flush();\n return { status: 0 };\n }\n\n // ---- OPENDIR ----\n opendir(path: string, tabId: string): { status: number; data: Uint8Array | null } {\n path = this.normalizePath(path);\n const idx = this.resolvePathComponents(path, true);\n if (idx === undefined) return { status: CODE_TO_STATUS.ENOENT, data: null };\n\n const inode = this.readInode(idx);\n if (inode.type !== INODE_TYPE.DIRECTORY) return { status: CODE_TO_STATUS.ENOTDIR, data: null };\n\n // Use fd table for dir handles too\n const fd = this.nextFd++;\n this.fdTable.set(fd, { tabId, inodeIdx: idx, position: 0, flags: 0 });\n\n const buf = new Uint8Array(4);\n new DataView(buf.buffer).setUint32(0, fd, true);\n return { status: 0, data: buf };\n }\n\n // ---- MKDTEMP ----\n mkdtemp(prefix: string): { status: number; data: Uint8Array | null } {\n const suffix = Math.random().toString(36).substring(2, 8);\n const path = this.normalizePath(prefix + suffix);\n\n // Ensure parent directories exist\n const parentStatus = this.ensureParent(path);\n if (parentStatus !== 0) {\n // Auto-create parent directories for mkdtemp\n const parentPath = path.substring(0, path.lastIndexOf('/'));\n if (parentPath) {\n this.mkdirRecursive(parentPath);\n }\n }\n\n const mode = DEFAULT_DIR_MODE & ~(this.umask & 0o777);\n this.createInode(path, INODE_TYPE.DIRECTORY, mode, 0);\n\n this.commitPending();\n return { status: 0, data: encoder.encode(path) };\n }\n\n // ========== Helpers ==========\n\n private getDirectChildren(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const children: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path === dirPath) continue;\n if (!path.startsWith(prefix)) continue;\n // Direct child: no more slashes after prefix\n const rest = path.substring(prefix.length);\n if (!rest.includes('/')) {\n children.push(path);\n }\n }\n\n return children.sort();\n }\n\n private getAllDescendants(dirPath: string): string[] {\n const prefix = dirPath === '/' ? '/' : dirPath + '/';\n const descendants: string[] = [];\n\n for (const path of this.pathIndex.keys()) {\n if (path.startsWith(prefix)) descendants.push(path);\n }\n\n // Sort by depth (deepest first) for safe deletion\n return descendants.sort((a, b) => {\n const da = a.split('/').length;\n const db = b.split('/').length;\n return db - da;\n });\n }\n\n private ensureParent(path: string): number {\n const lastSlash = path.lastIndexOf('/');\n if (lastSlash <= 0) return 0; // Parent is root, always exists\n\n const parentPath = path.substring(0, lastSlash);\n const parentIdx = this.pathIndex.get(parentPath);\n if (parentIdx === undefined) return CODE_TO_STATUS.ENOENT;\n\n const parentInode = this.readInode(parentIdx);\n if (parentInode.type !== INODE_TYPE.DIRECTORY) return CODE_TO_STATUS.ENOTDIR;\n\n return 0;\n }\n\n /** Clean up all fds owned by a tab */\n cleanupTab(tabId: string): void {\n for (const [fd, entry] of this.fdTable) {\n if (entry.tabId === tabId) {\n this.fdTable.delete(fd);\n }\n }\n }\n\n /** Get all file paths and their data for OPFS sync */\n getAllFiles(): { path: string; idx: number }[] {\n const files: { path: string; idx: number }[] = [];\n for (const [path, idx] of this.pathIndex) {\n files.push({ path, idx });\n }\n return files;\n }\n\n /** Get file path for a file descriptor (used by OPFS sync for FD-based ops) */\n getPathForFd(fd: number): string | null {\n const entry = this.fdTable.get(fd);\n if (!entry) return null;\n const inode = this.readInode(entry.inodeIdx);\n return this.readPath(inode.pathOffset, inode.pathLength);\n }\n\n /** Get file data by inode index */\n getInodeData(idx: number): { type: number; data: Uint8Array; mtime: number } {\n const inode = this.readInode(idx);\n const data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n return { type: inode.type, data, mtime: inode.mtime };\n }\n\n /** Export all files/dirs/symlinks from the VFS */\n exportAll(): Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> {\n const result: Array<{ path: string; type: number; data: Uint8Array | null; mode: number; mtime: number }> = [];\n for (const [path, idx] of this.pathIndex) {\n const inode = this.readInode(idx);\n let data: Uint8Array | null = null;\n if (inode.type === INODE_TYPE.FILE || inode.type === INODE_TYPE.SYMLINK) {\n data = inode.size > 0\n ? this.readData(inode.firstBlock, inode.blockCount, inode.size)\n : new Uint8Array(0);\n }\n result.push({ path, type: inode.type, data, mode: inode.mode, mtime: inode.mtime });\n }\n // Sort directories first so parents are created before children\n result.sort((a, b) => {\n if (a.type === INODE_TYPE.DIRECTORY && b.type !== INODE_TYPE.DIRECTORY) return -1;\n if (a.type !== INODE_TYPE.DIRECTORY && b.type === INODE_TYPE.DIRECTORY) return 1;\n return a.path.localeCompare(b.path);\n });\n return result;\n }\n\n flush(): void {\n this.handle.flush();\n }\n}\n","/**\n * Repair Worker — handles VFS repair and load operations.\n *\n * Spawned by helpers.ts when the caller doesn't have sync handle access\n * (e.g. main thread). All VFS writes go through createSyncAccessHandle\n * for direct disk I/O — no MemoryHandle, no RAM bloat.\n *\n * Operations:\n * - 'repair': Scan corrupt .vfs.bin, rebuild valid entries into fresh VFS\n * - 'load': Read OPFS files, create fresh VFS from them\n *\n * Safety guarantees:\n * - Original .vfs.bin is never deleted until the replacement is verified\n * - Temp file (.vfs.bin.tmp) is verified via re-mount before swap\n * - Orphaned .vfs.bin.tmp is cleaned up on entry\n * - Repair fails fast if critical operations exceed error threshold\n */\n\nimport { VFSEngine } from '../vfs/engine.js';\nimport {\n VFS_MAGIC, VFS_VERSION, SUPERBLOCK, INODE, INODE_SIZE, INODE_TYPE,\n DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS,\n INITIAL_PATH_TABLE_SIZE, calculateLayout,\n} from '../vfs/layout.js';\n\nself.onmessage = async (event: MessageEvent) => {\n try {\n const msg = event.data;\n if (msg.type === 'repair') {\n (self as any).postMessage(await handleRepair(msg.root));\n } else if (msg.type === 'load') {\n (self as any).postMessage(await handleLoad(msg.root));\n } else {\n throw new Error(`Unknown message type: ${msg.type}`);\n }\n } catch (err: any) {\n (self as any).postMessage({ error: err.message || String(err) });\n }\n};\n\n// ========== OPFS navigation (duplicated for bundle isolation) ==========\n\nasync function navigateToRoot(root: string): Promise<FileSystemDirectoryHandle> {\n let dir = await navigator.storage.getDirectory();\n if (root && root !== '/') {\n for (const seg of root.split('/').filter(Boolean)) {\n dir = await dir.getDirectoryHandle(seg, { create: true });\n }\n }\n return dir;\n}\n\ninterface OPFSEntry {\n path: string;\n type: 'file' | 'directory';\n data?: ArrayBuffer;\n}\n\nasync function readOPFSRecursive(\n dir: FileSystemDirectoryHandle,\n prefix: string,\n skip: Set<string>,\n): Promise<OPFSEntry[]> {\n const result: OPFSEntry[] = [];\n for await (const [name, handle] of (dir as any).entries()) {\n if (prefix === '' && skip.has(name)) continue;\n const fullPath = prefix ? `${prefix}/${name}` : `/${name}`;\n if (handle.kind === 'directory') {\n result.push({ path: fullPath, type: 'directory' });\n const children = await readOPFSRecursive(handle as FileSystemDirectoryHandle, fullPath, skip);\n result.push(...children);\n } else {\n const file = await (handle as FileSystemFileHandle).getFile();\n const data = await file.arrayBuffer();\n result.push({ path: fullPath, type: 'file', data });\n }\n }\n return result;\n}\n\n// ========== Cleanup orphaned temp files ==========\n\nasync function cleanupTmpFile(rootDir: FileSystemDirectoryHandle): Promise<void> {\n try { await rootDir.removeEntry('.vfs.bin.tmp'); } catch {}\n}\n\n// ========== Verify VFS via re-mount ==========\n\n/**\n * Open the file, mount it as a VFS, verify superblock + inode table,\n * then close. Throws if the VFS is corrupt.\n */\nasync function verifyVFS(fileHandle: FileSystemFileHandle): Promise<void> {\n const handle = await (fileHandle as any).createSyncAccessHandle();\n try {\n const engine = new VFSEngine();\n engine.init(handle); // calls mount() which validates superblock + rebuilds index\n } finally {\n handle.close();\n }\n}\n\n// ========== Safe file swap: copy-then-delete ==========\n\n/**\n * Safely replace .vfs.bin with .vfs.bin.tmp:\n * 1. Verify the temp file is a valid VFS (re-mount test)\n * 2. Copy temp → .vfs.bin (overwrite via truncate + chunked write)\n * 3. Only then delete .vfs.bin.tmp\n *\n * If the copy is interrupted mid-write, the original .vfs.bin.tmp\n * still exists intact for retry.\n */\nasync function swapTmpToVFS(\n rootDir: FileSystemDirectoryHandle,\n tmpFileHandle: FileSystemFileHandle,\n): Promise<void> {\n // Step 1: Verify temp file is valid before touching original\n await verifyVFS(tmpFileHandle);\n\n // Step 2: Copy tmp → .vfs.bin (overwrite)\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin', { create: true });\n\n const srcHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n const dstHandle = await (vfsFileHandle as any).createSyncAccessHandle();\n try {\n const size: number = srcHandle.getSize();\n dstHandle.truncate(size);\n const CHUNK = 1024 * 1024; // 1MB\n const buf = new Uint8Array(CHUNK);\n for (let off = 0; off < size; off += CHUNK) {\n const n: number = srcHandle.read(buf, { at: off });\n dstHandle.write(n < CHUNK ? buf.subarray(0, n) : buf, { at: off });\n }\n dstHandle.flush();\n } finally {\n dstHandle.close();\n srcHandle.close();\n }\n\n // Step 3: Only delete tmp after successful copy\n try { await rootDir.removeEntry('.vfs.bin.tmp'); } catch {}\n}\n\n// ========== Repair handler ==========\n\nasync function handleRepair(root: string) {\n const rootDir = await navigateToRoot(root);\n\n // Clean up any orphaned temp file from a previous failed repair\n await cleanupTmpFile(rootDir);\n\n // Read old .vfs.bin\n const vfsFileHandle = await rootDir.getFileHandle('.vfs.bin');\n const file = await vfsFileHandle.getFile();\n const raw = new Uint8Array(await file.arrayBuffer());\n const fileSize = raw.byteLength;\n\n if (fileSize < SUPERBLOCK.SIZE) {\n throw new Error(`VFS file too small to repair (${fileSize} bytes)`);\n }\n\n // Parse superblock\n const view = new DataView(raw.buffer);\n let inodeCount: number;\n let blockSize: number;\n let totalBlocks: number;\n let inodeTableOffset: number;\n let pathTableOffset: number;\n let dataOffset: number;\n let bitmapOffset: number;\n let pathTableSize: number;\n\n const magic = view.getUint32(SUPERBLOCK.MAGIC, true);\n const version = view.getUint32(SUPERBLOCK.VERSION, true);\n const superblockValid = magic === VFS_MAGIC && version === VFS_VERSION;\n\n if (superblockValid) {\n inodeCount = view.getUint32(SUPERBLOCK.INODE_COUNT, true);\n blockSize = view.getUint32(SUPERBLOCK.BLOCK_SIZE, true);\n totalBlocks = view.getUint32(SUPERBLOCK.TOTAL_BLOCKS, true);\n inodeTableOffset = view.getFloat64(SUPERBLOCK.INODE_OFFSET, true);\n pathTableOffset = view.getFloat64(SUPERBLOCK.PATH_OFFSET, true);\n dataOffset = view.getFloat64(SUPERBLOCK.DATA_OFFSET, true);\n bitmapOffset = view.getFloat64(SUPERBLOCK.BITMAP_OFFSET, true);\n // Use the full allocated path table size (not PATH_USED) for repair validation.\n // PATH_USED may be stale if the superblock wasn't flushed after a write —\n // paths were written to OPFS but the superblock counter wasn't updated.\n pathTableSize = bitmapOffset - pathTableOffset;\n\n if (blockSize === 0 || (blockSize & (blockSize - 1)) !== 0 || inodeCount === 0 ||\n inodeTableOffset >= fileSize || pathTableOffset >= fileSize || dataOffset >= fileSize ||\n pathTableSize <= 0) {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n inodeCount = DEFAULT_INODE_COUNT;\n blockSize = DEFAULT_BLOCK_SIZE;\n totalBlocks = INITIAL_DATA_BLOCKS;\n inodeTableOffset = layout.inodeTableOffset;\n pathTableOffset = layout.pathTableOffset;\n dataOffset = layout.dataOffset;\n bitmapOffset = layout.bitmapOffset;\n pathTableSize = bitmapOffset - pathTableOffset;\n }\n } else {\n const layout = calculateLayout(DEFAULT_INODE_COUNT, DEFAULT_BLOCK_SIZE, INITIAL_DATA_BLOCKS);\n inodeCount = DEFAULT_INODE_COUNT;\n blockSize = DEFAULT_BLOCK_SIZE;\n totalBlocks = INITIAL_DATA_BLOCKS;\n inodeTableOffset = layout.inodeTableOffset;\n pathTableOffset = layout.pathTableOffset;\n dataOffset = layout.dataOffset;\n bitmapOffset = layout.bitmapOffset;\n pathTableSize = bitmapOffset - pathTableOffset;\n }\n\n // Scan inodes for recoverable entries\n const decoder = new TextDecoder('utf-8', { fatal: true });\n const recovered: Array<{\n path: string;\n type: number;\n dataOffset: number;\n dataSize: number;\n /** true when inode was found but data blocks were out of bounds */\n contentLost: boolean;\n }> = [];\n let lost = 0;\n\n const maxInodes = Math.min(inodeCount, Math.floor((fileSize - inodeTableOffset) / INODE_SIZE));\n\n for (let i = 0; i < maxInodes; i++) {\n const off = inodeTableOffset + i * INODE_SIZE;\n if (off + INODE_SIZE > fileSize) break;\n\n const type = raw[off + INODE.TYPE];\n if (type < INODE_TYPE.FILE || type > INODE_TYPE.SYMLINK) continue;\n\n const inodeView = new DataView(raw.buffer, off, INODE_SIZE);\n const pathOff = inodeView.getUint32(INODE.PATH_OFFSET, true);\n const pathLength = inodeView.getUint16(INODE.PATH_LENGTH, true);\n const size = inodeView.getFloat64(INODE.SIZE, true);\n const firstBlock = inodeView.getUint32(INODE.FIRST_BLOCK, true);\n\n // Validate path bounds against the allocated path table region and file size.\n // Use pathTableSize (not PATH_USED from superblock) because PATH_USED may be\n // stale if the superblock wasn't flushed — the path bytes are still on disk.\n const absPathOffset = pathTableOffset + pathOff;\n if (pathLength === 0 || pathLength > 4096 ||\n absPathOffset + pathLength > fileSize ||\n pathOff + pathLength > pathTableSize) {\n lost++;\n continue;\n }\n\n // Decode path with strict UTF-8 (fatal: true rejects invalid sequences)\n let entryPath: string;\n try {\n entryPath = decoder.decode(raw.subarray(absPathOffset, absPathOffset + pathLength));\n } catch {\n lost++;\n continue;\n }\n\n if (!entryPath.startsWith('/') || entryPath.includes('\\0')) {\n lost++;\n continue;\n }\n\n if (type === INODE_TYPE.DIRECTORY) {\n recovered.push({ path: entryPath, type, dataOffset: 0, dataSize: 0, contentLost: false });\n continue;\n }\n\n if (size < 0 || size > fileSize || !isFinite(size)) {\n lost++;\n continue;\n }\n\n const blockCount = inodeView.getUint32(INODE.BLOCK_COUNT, true);\n const dataStart = dataOffset + firstBlock * blockSize;\n if (dataStart + size > fileSize || firstBlock >= totalBlocks ||\n (blockCount > 0 && firstBlock + blockCount > totalBlocks)) {\n // Inode metadata is valid but data blocks are out of bounds — content is lost\n recovered.push({ path: entryPath, type, dataOffset: 0, dataSize: 0, contentLost: true });\n lost++;\n continue;\n }\n\n recovered.push({ path: entryPath, type, dataOffset: dataStart, dataSize: size, contentLost: false });\n }\n\n // Build repaired VFS in temp file — original .vfs.bin untouched until verified\n const tmpFileHandle = await rootDir.getFileHandle('.vfs.bin.tmp', { create: true });\n const tmpHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n\n let repairOk = false;\n let criticalErrors = 0;\n const MAX_CRITICAL_ERRORS = 5;\n\n try {\n const engine = new VFSEngine();\n engine.init(tmpHandle);\n\n const dirs = recovered\n .filter(e => e.type === INODE_TYPE.DIRECTORY && e.path !== '/')\n .sort((a, b) => a.path.localeCompare(b.path));\n const files = recovered.filter(e => e.type === INODE_TYPE.FILE);\n const symlinks = recovered.filter(e => e.type === INODE_TYPE.SYMLINK);\n\n // Create directories — failure here is critical (blocks child files)\n for (const dir of dirs) {\n if (engine.mkdir(dir.path, 0o040755).status !== 0) {\n criticalErrors++;\n lost++;\n if (criticalErrors >= MAX_CRITICAL_ERRORS) {\n throw new Error(`Repair aborted: too many critical errors (${criticalErrors} mkdir failures)`);\n }\n }\n }\n\n // Write files\n for (const f of files) {\n const data = f.dataSize > 0\n ? raw.subarray(f.dataOffset, f.dataOffset + f.dataSize)\n : new Uint8Array(0);\n if (engine.write(f.path, data).status !== 0) {\n lost++;\n // File write failures are less critical than mkdir — parent may be missing\n }\n }\n\n // Write symlinks — validate target before creating\n for (const sym of symlinks) {\n if (sym.dataSize === 0 && sym.contentLost) {\n // Symlink target was lost — skip, don't create a broken symlink\n lost++;\n continue;\n }\n const data = sym.dataSize > 0\n ? raw.subarray(sym.dataOffset, sym.dataOffset + sym.dataSize)\n : new Uint8Array(0);\n let target: string;\n try {\n target = decoder.decode(data);\n } catch {\n // Invalid UTF-8 in symlink target — skip\n lost++;\n continue;\n }\n if (target.length === 0 || target.includes('\\0')) {\n lost++;\n continue;\n }\n if (engine.symlink(target, sym.path).status !== 0) lost++;\n }\n\n engine.flush();\n repairOk = true;\n } finally {\n tmpHandle.close();\n if (!repairOk) {\n await cleanupTmpFile(rootDir);\n }\n }\n\n // Verify repaired VFS via re-mount, then swap into place\n // swapTmpToVFS calls verifyVFS internally — if verification fails,\n // .vfs.bin.tmp still exists and .vfs.bin is untouched\n try {\n await swapTmpToVFS(rootDir, tmpFileHandle);\n } catch (err: any) {\n // Swap failed — clean up temp file, throw descriptive error\n await cleanupTmpFile(rootDir);\n throw new Error(`Repair built a VFS but verification failed: ${err.message}`);\n }\n\n const entries = recovered\n .filter(e => e.path !== '/')\n .map(e => ({\n path: e.path,\n type: (e.type === INODE_TYPE.FILE ? 'file' : e.type === INODE_TYPE.DIRECTORY ? 'directory' : 'symlink') as 'file' | 'directory' | 'symlink',\n size: e.dataSize,\n contentLost: e.contentLost,\n }));\n\n return { recovered: entries.length, lost, entries };\n}\n\n// ========== Load handler ==========\n\nasync function handleLoad(root: string) {\n const rootDir = await navigateToRoot(root);\n\n // Clean up any orphaned temp file\n await cleanupTmpFile(rootDir);\n\n // Read all OPFS files FIRST (before touching .vfs.bin)\n const opfsEntries = await readOPFSRecursive(rootDir, '', new Set(['.vfs.bin', '.vfs.bin.tmp']));\n\n // Build fresh VFS in temp file — original .vfs.bin untouched until verified\n const tmpFileHandle = await rootDir.getFileHandle('.vfs.bin.tmp', { create: true });\n const tmpHandle = await (tmpFileHandle as any).createSyncAccessHandle();\n\n let buildOk = false;\n let files = 0;\n let directories = 0;\n\n try {\n const engine = new VFSEngine();\n engine.init(tmpHandle);\n\n const dirs = opfsEntries\n .filter(e => e.type === 'directory')\n .sort((a, b) => a.path.localeCompare(b.path));\n\n for (const dir of dirs) {\n if (engine.mkdir(dir.path, 0o040755).status === 0) {\n directories++;\n }\n }\n\n const fileEntries = opfsEntries.filter(e => e.type === 'file');\n for (const file of fileEntries) {\n if (engine.write(file.path, new Uint8Array(file.data ?? new ArrayBuffer(0))).status === 0) {\n files++;\n }\n }\n\n engine.flush();\n buildOk = true;\n } finally {\n tmpHandle.close();\n if (!buildOk) {\n await cleanupTmpFile(rootDir);\n }\n }\n\n // Verify then swap (verifyVFS + copy-then-delete)\n try {\n await swapTmpToVFS(rootDir, tmpFileHandle);\n } catch (err: any) {\n await cleanupTmpFile(rootDir);\n throw new Error(`Load built a VFS but verification failed: ${err.message}`);\n }\n\n return { files, directories };\n}\n"],"mappings":"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","names":["inode","data","totalSize","buf","view","offset","decoder"]}
|