diff options
| author | Agando <roduccomm@gmail.com> | 2026-10-27 12:32:37 +0100 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-10-27 12:32:37 +0100 |
| commit | 669b66591b3efbb8fc8642d25a67c55d93cfe4e9 (patch) | |
| tree | 032b044c840b0e3e5113f7ea0d06684cd5d1fa83 /modules/core/module-fs.js | |
| parent | d2de622744212ea0ba720b3f4212b82940ffe84b (diff) | |
fix(newos4): never overwrite a directory node; ls honours a path after its flags
MAINT-010 and MAINT-016, the two high items the review left open. Both were re-probed
before the change and the new test is red on HEAD (5 passed, 7 FAILED).
- virtual-fs.js rename()/copy(): they assigned dst.dir.content[dst.name] with no destination
type check, so `mv file /docs` replaced the /docs node and every child vanished while the
command printed "Moved: …". Refuse when the destination is a real directory node (the
virtual /sys entry is exempt). rename() also erased the file on `mv a a`, because assigning
and then deleting the same key removes it; that path is now an explicit no-op.
- module-fs.js mv/cp: a refusal used to surface as "No such file or directory", which sent
the operator looking for a missing source. The destination is now inspected first and the
message says "is a directory — refusing to overwrite it".
- module-fs.js ls: the path was only read from argv[0], so `ls -l /work` listed the cwd.
The first non-flag argument is now the target; the path-first form is unchanged.
Tests: modules/test/test-fs-mv-cp-guard.js (12 asserts) — RED on HEAD (A1-A3, B1, B2, C2, E1),
GREEN now; maintain --fix reports "node tests 7/7 pass". Browser on v4.6.104:
"mv: /vtest: is a directory — refusing to overwrite it", child and source intact,
"ls -l /vtest" lists /vtest (keep.txt), not the cwd.
Diffstat (limited to 'modules/core/module-fs.js')
| -rw-r--r-- | modules/core/module-fs.js | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/modules/core/module-fs.js b/modules/core/module-fs.js index f2b215a..583cfda 100644 --- a/modules/core/module-fs.js +++ b/modules/core/module-fs.js @@ -44,8 +44,11 @@ class FileSystemModule { registerCommands() { const self = this; this.commands['ls'] = (args) => { - const target = args && args.length > 0 && !args[0].startsWith('-') ? args[0] : undefined; - const flags = (args || []).filter(a => a.startsWith('-')); + const argv = args || []; + // v4.6.104: the path may follow the flags — `ls -l /work` used to list the cwd + // because only argv[0] was considered (MAINT-016). + const flags = argv.filter(a => a.startsWith('-')); + const target = argv.find(a => !a.startsWith('-')); const showLong = flags.some(f => f.includes('l')); const showHidden = flags.some(f => f.includes('a')); const files = this.terminal.fs.ls(target); @@ -180,14 +183,24 @@ class FileSystemModule { }; this.commands['mv'] = (args) => { if(!args[0] || !args[1]) return this.terminal.print('Usage: mv <source> <dest>', 'warning'); - if (this.terminal.fs.mv(args[0], args[1])) + const fs = this.terminal.fs; + const d = fs._resolvePath(args[1]); + const dn = d && d.name ? d.dir.content[d.name] : null; + if (dn && dn.type === 'dir' && !dn._virtual) + return this.terminal.print('mv: ' + args[1] + ': is a directory — refusing to overwrite it', 'error'); + if (fs.mv(args[0], args[1])) this.terminal.print('Moved: ' + args[0] + ' to ' + args[1], 'success'); else this.terminal.print('mv: ' + args[0] + ': No such file or directory', 'error'); }; this.commands['cp'] = (args) => { if(!args[0] || !args[1]) return this.terminal.print('Usage: cp <source> <dest>', 'warning'); - if (this.terminal.fs.cp(args[0], args[1])) + const fs = this.terminal.fs; + const d = fs._resolvePath(args[1]); + const dn = d && d.name ? d.dir.content[d.name] : null; + if (dn && dn.type === 'dir' && !dn._virtual) + return this.terminal.print('cp: ' + args[1] + ': is a directory — refusing to overwrite it', 'error'); + if (fs.cp(args[0], args[1])) this.terminal.print('Copied: ' + args[0] + ' to ' + args[1], 'success'); else this.terminal.print('cp: ' + args[0] + ': No such file or directory', 'error'); |