Skip to content

Commit 6dcdd6f

Browse files
committed
Ajouter l’intégration et les commandes du système de fichiers I-Node
Intègre un nouveau système de fichiers basé sur I-Node avec adaptateur, commandes (ln, stat, links, du, fsck) et couches de compatibilité. Met à jour les opérations sur les fichiers principaux (ls, mkdir, rm, touch, édition de fichier) pour utiliser le système I-Node lorsqu’il est disponible, tout en maintenant le repli vers le système hérité. Améliore la commande ls avec une prise en charge complète des options et améliore la liste, le tri et le formatage des fichiers. Ajoute la migration, la persistance et la population du répertoire bin pour le nouveau système de fichiers. Améliore également la logique de téléchargement des codes QR et la gestion de l’enregistrement des fichiers.
1 parent 4905bda commit 6dcdd6f

7 files changed

Lines changed: 2514 additions & 149 deletions

File tree

contents/js/app.js

Lines changed: 610 additions & 53 deletions
Large diffs are not rendered by default.
Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,381 @@
1+
// Importer INodeFileSystem
2+
import INodeFileSystem from './inode-filesystem.js';
3+
4+
/**
5+
* Adaptateur pour intégrer le système I-Node dans l'application Console Linux
6+
* Fait le pont entre l'ancien système de fichiers et le nouveau système I-Node
7+
*/
8+
9+
class INodeAdapter {
10+
constructor(app) {
11+
this.app = app;
12+
this.inodeFS = new INodeFileSystem();
13+
14+
// Migrer l'ancien système de fichiers si nécessaire
15+
this.migrateFromLegacyFileSystem();
16+
}
17+
18+
/**
19+
* Migre l'ancien système de fichiers vers le système I-Node
20+
*/
21+
migrateFromLegacyFileSystem() {
22+
if (!this.app.fileSystem) return;
23+
24+
try {
25+
this.migrateFSNode('/', this.app.fileSystem['/']);
26+
console.log('✅ Migration du système de fichiers terminée');
27+
} catch (error) {
28+
console.error('❌ Erreur lors de la migration:', error);
29+
}
30+
}
31+
32+
/**
33+
* Migre récursivement un noeud du système de fichiers
34+
*/
35+
migrateFSNode(path, node) {
36+
if (!node || typeof node !== 'object') return;
37+
38+
if (node.type === 'directory' && node.children) {
39+
// Créer le dossier s'il n'existe pas déjà
40+
if (path !== '/') {
41+
const pathParts = path.split('/').filter(p => p !== '');
42+
const dirName = pathParts.pop();
43+
const parentPath = pathParts.length > 0 ? '/' + pathParts.join('/') : '/';
44+
45+
const existingInode = this.inodeFS.getInodeByPath(path);
46+
if (!existingInode) {
47+
const dirInode = this.inodeFS.createDirectory();
48+
this.inodeFS.addToDirectory(parentPath, dirName, dirInode.id);
49+
}
50+
}
51+
52+
// Migrer récursivement les enfants
53+
for (const [name, child] of Object.entries(node.children)) {
54+
if (name !== '.' && name !== '..') {
55+
const childPath = path === '/' ? `/${name}` : `${path}/${name}`;
56+
this.migrateFSNode(childPath, child);
57+
}
58+
}
59+
} else if (node.type === 'file') {
60+
// Créer le fichier
61+
const pathParts = path.split('/').filter(p => p !== '');
62+
const fileName = pathParts.pop();
63+
const parentPath = pathParts.length > 0 ? '/' + pathParts.join('/') : '/';
64+
65+
const existingInode = this.inodeFS.getInodeByPath(path);
66+
if (!existingInode) {
67+
const fileInode = this.inodeFS.createFile(node.content || '');
68+
this.inodeFS.addToDirectory(parentPath, fileName, fileInode.id);
69+
}
70+
}
71+
}
72+
73+
/**
74+
* Crée un nouveau fichier dans le système I-Node
75+
*/
76+
createFile(dirPath, fileName, content = '') {
77+
try {
78+
const fileInode = this.inodeFS.createFile(content);
79+
this.inodeFS.addToDirectory(dirPath, fileName, fileInode.id);
80+
return true;
81+
} catch (error) {
82+
console.error('Erreur création fichier:', error);
83+
return false;
84+
}
85+
}
86+
87+
/**
88+
* Crée un nouveau dossier dans le système I-Node
89+
*/
90+
createDirectory(parentPath, dirName) {
91+
try {
92+
const dirInode = this.inodeFS.createDirectory();
93+
this.inodeFS.addToDirectory(parentPath, dirName, dirInode.id);
94+
return true;
95+
} catch (error) {
96+
console.error('Erreur création dossier:', error);
97+
return false;
98+
}
99+
}
100+
101+
/**
102+
* Supprime un fichier ou dossier
103+
*/
104+
remove(parentPath, name) {
105+
try {
106+
this.inodeFS.removeFromDirectory(parentPath, name);
107+
return true;
108+
} catch (error) {
109+
console.error('Erreur suppression:', error);
110+
return false;
111+
}
112+
}
113+
114+
/**
115+
* Lit le contenu d'un fichier
116+
*/
117+
readFile(path) {
118+
try {
119+
return this.inodeFS.readFile(path);
120+
} catch (error) {
121+
console.error('Erreur lecture fichier:', error);
122+
return null;
123+
}
124+
}
125+
126+
/**
127+
* Écrit dans un fichier
128+
*/
129+
writeFile(path, content) {
130+
try {
131+
this.inodeFS.writeFile(path, content);
132+
return true;
133+
} catch (error) {
134+
console.error('Erreur écriture fichier:', error);
135+
return false;
136+
}
137+
}
138+
139+
/**
140+
* Liste le contenu d'un dossier
141+
*/
142+
listDirectory(path) {
143+
try {
144+
return this.inodeFS.listDirectory(path);
145+
} catch (error) {
146+
console.error('Erreur listage dossier:', error);
147+
return [];
148+
}
149+
}
150+
151+
/**
152+
* Récupère les informations d'un I-Node
153+
*/
154+
stat(path) {
155+
try {
156+
return this.inodeFS.statInode(path);
157+
} catch (error) {
158+
console.error('Erreur stat:', error);
159+
return null;
160+
}
161+
}
162+
163+
/**
164+
* Crée un lien dur
165+
*/
166+
createHardLink(sourcePath, targetDirPath, linkName) {
167+
try {
168+
this.inodeFS.createHardLink(sourcePath, targetDirPath, linkName);
169+
return true;
170+
} catch (error) {
171+
console.error('Erreur création lien dur:', error);
172+
return false;
173+
}
174+
}
175+
176+
/**
177+
* Trouve tous les chemins vers un I-Node
178+
*/
179+
findAllPathsToInode(inodeId) {
180+
return this.inodeFS.findAllPathsToInode(inodeId);
181+
}
182+
183+
/**
184+
* Vérifie l'intégrité du système de fichiers
185+
*/
186+
checkFileSystemIntegrity() {
187+
const issues = [];
188+
const warnings = [];
189+
let checked = 0;
190+
191+
try {
192+
// Vérifier tous les I-Nodes
193+
for (const [inodeId, inode] of this.inodeFS.inodes.entries()) {
194+
checked++;
195+
196+
// Vérifier la cohérence des liens
197+
const allPaths = this.findAllPathsToInode(inodeId);
198+
if (allPaths.length !== inode.linkCount) {
199+
warnings.push(`I-Node ${inodeId}: compteur de liens incohérent (${inode.linkCount} vs ${allPaths.length})`);
200+
}
201+
202+
// Vérifier les références orphelines
203+
if (inode.linkCount === 0 && this.inodeFS.inodes.has(inodeId)) {
204+
issues.push(`I-Node ${inodeId}: orphelin détecté`);
205+
}
206+
}
207+
208+
// Vérifier les structures de dossiers
209+
for (const [dirInodeId, entries] of this.inodeFS.directories.entries()) {
210+
if (!this.inodeFS.inodes.has(dirInodeId)) {
211+
issues.push(`Structure de dossier ${dirInodeId}: I-Node manquant`);
212+
}
213+
214+
for (const [name, targetInodeId] of entries.entries()) {
215+
if (name !== '.' && name !== '..' && !this.inodeFS.inodes.has(targetInodeId)) {
216+
issues.push(`Dossier ${dirInodeId}: référence vers I-Node inexistant ${targetInodeId}`);
217+
}
218+
}
219+
}
220+
221+
} catch (error) {
222+
issues.push(`Erreur lors de la vérification: ${error.message}`);
223+
}
224+
225+
return { issues, warnings, checked };
226+
}
227+
228+
/**
229+
* Émule l'ancien système getPath pour compatibilité
230+
*/
231+
getPath(path) {
232+
try {
233+
const inode = this.inodeFS.getInodeByPath(path);
234+
if (!inode) return null;
235+
236+
if (inode.type === 'file') {
237+
return {
238+
type: 'file',
239+
content: inode.data
240+
};
241+
} else if (inode.type === 'directory') {
242+
const children = {};
243+
const dirEntries = this.inodeFS.directories.get(inode.id);
244+
245+
if (dirEntries) {
246+
for (const [name, childInodeId] of dirEntries.entries()) {
247+
if (name !== '.' && name !== '..') {
248+
const childInode = this.inodeFS.inodes.get(childInodeId);
249+
if (childInode) {
250+
if (childInode.type === 'file') {
251+
children[name] = {
252+
type: 'file',
253+
content: childInode.data
254+
};
255+
} else {
256+
children[name] = {
257+
type: 'directory',
258+
children: {} // Simplifié pour compatibilité
259+
};
260+
}
261+
}
262+
}
263+
}
264+
}
265+
266+
return {
267+
type: 'directory',
268+
children: children
269+
};
270+
}
271+
} catch (error) {
272+
console.error('Erreur getPath:', error);
273+
return null;
274+
}
275+
}
276+
277+
/**
278+
* Peuple le répertoire /bin avec les commandes disponibles
279+
*/
280+
populateBinDirectory() {
281+
try {
282+
const binPath = '/bin';
283+
const binInode = this.inodeFS.getInodeByPath(binPath);
284+
285+
if (!binInode) {
286+
console.warn('Dossier /bin non trouvé');
287+
return;
288+
}
289+
290+
// Ajouter des fichiers factices pour les commandes
291+
const commands = Object.keys(this.app.commands || {});
292+
293+
for (const cmd of commands) {
294+
try {
295+
const cmdFileInode = this.inodeFS.createFile(`#!/bin/sh\n# Commande: ${cmd}\n# Description: ${this.app.COMMAND_METADATA?.[cmd]?.description || 'Commande système'}\necho "Exécution de ${cmd}"`);
296+
this.inodeFS.addToDirectory(binPath, cmd, cmdFileInode.id);
297+
} catch (error) {
298+
// Ignorer si la commande existe déjà
299+
}
300+
}
301+
302+
console.log(`✅ ${commands.length} commandes ajoutées au répertoire /bin`);
303+
} catch (error) {
304+
console.error('Erreur peuplement /bin:', error);
305+
}
306+
}
307+
308+
/**
309+
* Exporte le système I-Node
310+
*/
311+
export() {
312+
return this.inodeFS.export();
313+
}
314+
315+
/**
316+
* Importe un système I-Node
317+
*/
318+
import(data) {
319+
this.inodeFS.import(data);
320+
}
321+
322+
/**
323+
* Sauvegarde vers le format legacy pour compatibilité
324+
*/
325+
saveToLegacyFormat() {
326+
try {
327+
const legacyFS = this.convertToLegacyFormat('/', {});
328+
return legacyFS;
329+
} catch (error) {
330+
console.error('Erreur conversion legacy:', error);
331+
return null;
332+
}
333+
}
334+
335+
/**
336+
* Convertit récursivement vers le format legacy
337+
*/
338+
convertToLegacyFormat(path, result) {
339+
const inode = this.inodeFS.getInodeByPath(path);
340+
if (!inode) return result;
341+
342+
if (inode.type === 'directory') {
343+
const dirData = {
344+
type: 'directory',
345+
children: {}
346+
};
347+
348+
const dirEntries = this.inodeFS.directories.get(inode.id);
349+
if (dirEntries) {
350+
for (const [name, childInodeId] of dirEntries.entries()) {
351+
if (name !== '.' && name !== '..') {
352+
const childPath = path === '/' ? `/${name}` : `${path}/${name}`;
353+
const childInode = this.inodeFS.inodes.get(childInodeId);
354+
355+
if (childInode) {
356+
if (childInode.type === 'file') {
357+
dirData.children[name] = {
358+
type: 'file',
359+
content: childInode.data
360+
};
361+
} else {
362+
dirData.children[name] = this.convertToLegacyFormat(childPath, {
363+
type: 'directory',
364+
children: {}
365+
});
366+
}
367+
}
368+
}
369+
}
370+
}
371+
372+
result[path] = dirData;
373+
return dirData;
374+
}
375+
376+
return result;
377+
}
378+
}
379+
380+
// Export en tant que module ES6
381+
export default INodeAdapter;

0 commit comments

Comments
 (0)