|
| 1 | +/** |
| 2 | + * File System Manager Module |
| 3 | + * Handles file system operations and virtual file system |
| 4 | + */ |
| 5 | +class FileSystemManager { |
| 6 | + constructor() { |
| 7 | + this.fileSystem = {}; |
| 8 | + this.currentPath = '/'; |
| 9 | + } |
| 10 | + |
| 11 | + /** |
| 12 | + * Initialize the virtual file system |
| 13 | + */ |
| 14 | + initializeFileSystem() { |
| 15 | + this.fileSystem = { |
| 16 | + '/': { |
| 17 | + type: 'directory', |
| 18 | + children: { |
| 19 | + 'bin': { type: 'directory', children: { |
| 20 | + 'bash': { type: 'executable', size: 1234567, content: '#!/bin/bash\n# Bash shell executable\n# System shell program' }, |
| 21 | + 'node': { type: 'executable', size: 45678901, content: '#!/usr/bin/env node\n// Node.js runtime executable' }, |
| 22 | + 'python3': { type: 'executable', size: 23456789, content: '#!/usr/bin/python3\n# Python 3 interpreter' } |
| 23 | + }}, |
| 24 | + 'etc': { type: 'directory', children: { |
| 25 | + 'nginx': { type: 'directory', children: { |
| 26 | + 'nginx.conf': { type: 'config', size: 2048, content: 'server {\n listen 80;\n server_name localhost;\n location / {\n root /var/www/html;\n }\n}' } |
| 27 | + }}, |
| 28 | + 'systemd': { type: 'directory', children: { |
| 29 | + 'system': { type: 'directory', children: { |
| 30 | + 'nginx.service': { type: 'service', size: 512, content: '[Unit]\nDescription=The nginx HTTP and reverse proxy server\n[Service]\nType=forking\nExecStart=/usr/sbin/nginx\n[Install]\nWantedBy=multi-user.target' } |
| 31 | + }} |
| 32 | + }} |
| 33 | + }}, |
| 34 | + 'var': { type: 'directory', children: { |
| 35 | + 'www': { type: 'directory', children: { |
| 36 | + 'html': { type: 'directory', children: { |
| 37 | + 'index.html': { type: 'html', size: 1024, content: '<!DOCTYPE html>\n<html>\n<head>\n <title>Welcome to nginx!</title>\n <style>\n body { font-family: Arial; background: #f0f0f0; }\n .container { max-width: 800px; margin: 50px auto; padding: 20px; }\n h1 { color: #333; text-align: center; }\n </style>\n</head>\n<body>\n <div class="container">\n <h1>Welcome to nginx!</h1>\n <p>If you can see this page, the nginx web server is successfully installed and working.</p>\n </div>\n</body>\n</html>' }, |
| 38 | + 'app.js': { type: 'script', size: 856, content: 'const express = require(\'express\');\nconst app = express();\nconst port = 3000;\n\napp.get(\'/\', (req, res) => {\n res.send(\'Hello World from Node.js!\');\n});\n\napp.listen(port, () => {\n console.log(`Server running at http://localhost:${port}`);\n});' } |
| 39 | + }} |
| 40 | + }} |
| 41 | + }}, |
| 42 | + 'home': { type: 'directory', children: { |
| 43 | + 'user': { type: 'directory', children: { |
| 44 | + 'documents': { type: 'directory', children: { |
| 45 | + 'notes.txt': { type: 'text', size: 256, content: 'Important system notes:\n1. Remember to update the server weekly\n2. Check logs for any suspicious activity\n3. Backup the database nightly' } |
| 46 | + }}, |
| 47 | + 'projects': { type: 'directory', children: { |
| 48 | + 'webapp': { type: 'directory', children: { |
| 49 | + 'index.js': { type: 'script', size: 1024, content: 'const http = require(\'http\');\n\nconst server = http.createServer((req, res) => {\n res.statusCode = 200;\n res.setHeader(\'Content-Type\', \'text/plain\');\n res.end(\'Hello World\\n\');\n});\n\nserver.listen(8080, \'localhost\', () => {\n console.log(\'Server running at http://localhost:8080/\');\n});' }, |
| 50 | + 'package.json': { type: 'json', size: 512, content: '{\n "name": "webapp",\n "version": "1.0.0",\n "description": "A simple web application",\n "main": "index.js",\n "scripts": {\n "start": "node index.js"\n },\n "dependencies": {\n "express": "^4.17.1"\n }\n}' } |
| 51 | + }} |
| 52 | + }} |
| 53 | + }} |
| 54 | + }} |
| 55 | + } |
| 56 | + } |
| 57 | + }; |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * Get file or directory at path |
| 62 | + * @param {string} path - Path to file or directory |
| 63 | + * @returns {Object} File or directory object |
| 64 | + */ |
| 65 | + getItemAtPath(path) { |
| 66 | + if (path === '/') { |
| 67 | + return this.fileSystem['/']; |
| 68 | + } |
| 69 | + |
| 70 | + const parts = path.split('/').filter(Boolean); |
| 71 | + let current = this.fileSystem['/']; |
| 72 | + |
| 73 | + for (const part of parts) { |
| 74 | + if (!current.children || !current.children[part]) { |
| 75 | + return null; |
| 76 | + } |
| 77 | + current = current.children[part]; |
| 78 | + } |
| 79 | + |
| 80 | + return current; |
| 81 | + } |
| 82 | + |
| 83 | + /** |
| 84 | + * Get file content |
| 85 | + * @param {string} path - Path to file |
| 86 | + * @returns {string} File content or null if not found |
| 87 | + */ |
| 88 | + getFileContent(path) { |
| 89 | + const file = this.getItemAtPath(path); |
| 90 | + if (!file || file.type === 'directory') { |
| 91 | + return null; |
| 92 | + } |
| 93 | + return file.content; |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * List directory contents |
| 98 | + * @param {string} path - Path to directory |
| 99 | + * @returns {Array} Array of items in directory |
| 100 | + */ |
| 101 | + listDirectory(path) { |
| 102 | + const dir = this.getItemAtPath(path); |
| 103 | + if (!dir || dir.type !== 'directory') { |
| 104 | + return []; |
| 105 | + } |
| 106 | + |
| 107 | + return Object.entries(dir.children).map(([name, item]) => ({ |
| 108 | + name, |
| 109 | + type: item.type, |
| 110 | + size: item.size || 0, |
| 111 | + isDirectory: item.type === 'directory' |
| 112 | + })); |
| 113 | + } |
| 114 | + |
| 115 | + /** |
| 116 | + * Change current directory |
| 117 | + * @param {string} path - Path to change to |
| 118 | + * @returns {boolean} Success |
| 119 | + */ |
| 120 | + changeDirectory(path) { |
| 121 | + // Handle absolute paths |
| 122 | + if (path.startsWith('/')) { |
| 123 | + const dir = this.getItemAtPath(path); |
| 124 | + if (dir && dir.type === 'directory') { |
| 125 | + this.currentPath = path; |
| 126 | + return true; |
| 127 | + } |
| 128 | + return false; |
| 129 | + } |
| 130 | + |
| 131 | + // Handle relative paths |
| 132 | + if (path === '..') { |
| 133 | + if (this.currentPath === '/') { |
| 134 | + return true; |
| 135 | + } |
| 136 | + const parts = this.currentPath.split('/').filter(Boolean); |
| 137 | + parts.pop(); |
| 138 | + this.currentPath = '/' + parts.join('/'); |
| 139 | + return true; |
| 140 | + } |
| 141 | + |
| 142 | + // Handle current directory |
| 143 | + if (path === '.') { |
| 144 | + return true; |
| 145 | + } |
| 146 | + |
| 147 | + // Handle subdirectory |
| 148 | + const newPath = this.currentPath === '/' |
| 149 | + ? `/${path}` |
| 150 | + : `${this.currentPath}/${path}`; |
| 151 | + |
| 152 | + const dir = this.getItemAtPath(newPath); |
| 153 | + if (dir && dir.type === 'directory') { |
| 154 | + this.currentPath = newPath; |
| 155 | + return true; |
| 156 | + } |
| 157 | + |
| 158 | + return false; |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * Get file size in human-readable format |
| 163 | + * @param {number} size - File size in bytes |
| 164 | + * @returns {string} Human-readable size |
| 165 | + */ |
| 166 | + getHumanReadableSize(size) { |
| 167 | + const units = ['B', 'KB', 'MB', 'GB', 'TB']; |
| 168 | + let unitIndex = 0; |
| 169 | + let fileSize = size; |
| 170 | + |
| 171 | + while (fileSize >= 1024 && unitIndex < units.length - 1) { |
| 172 | + fileSize /= 1024; |
| 173 | + unitIndex++; |
| 174 | + } |
| 175 | + |
| 176 | + return `${fileSize.toFixed(1)} ${units[unitIndex]}`; |
| 177 | + } |
| 178 | +} |
0 commit comments