TiddlyWiki5
TiddlyWiki5 copied to clipboard
[BUG] Rendering to CON on Windows causes a crash
Describe the bug
The filename "CON" on Windows causes data written to the file to appear in the console. CON is a reserved filename and it cannot be used with a path. If I run:
tiddlywiki "WikiName" --render "." "CON" "text/plain" '$:/core/templates/exporters/JsonFile' "exportFilter" "[!is[system]!tag[image]]"
to get the TW rendered to the console, I get an error:
node:internal/fs/utils:347
throw err;
^
Error: EINVAL: invalid argument, open '.........\output\CON'
at Object.openSync (node:fs:599:3)
at Object.writeFileSync (node:fs:2221:35)
at $:/core/modules/commands/render.js:58:7
at $tw.utils.each ($:/boot/boot.js:146:12)
at Command.execute ($:/core/modules/commands/render.js:47:13)
at Commander.executeNextCommand ($:/core/modules/commander.js:107:14)
at Commander.execute ($:/core/modules/commander.js:64:7)
at exports.startup ($:/core/modules/startup/commands.js:34:12)
at $tw.boot.executeNextStartupTask ($:/boot/boot.js:2542:10)
at $tw.boot.executeNextStartupTask ($:/boot/boot.js:2540:21) {
errno: -4071,
syscall: 'open',
code: 'EINVAL',
path: '.........................\\output\\CON'
}
Node.js v18.6.0
It looks like TW is adding the path to the CON filename, which is illegal under Windows. If I add --output ""
to set the path to nothing, I get this error:
> tiddlywiki --output "" "WikiName" --render "." "CON" "text/plain" '$:/core/templates/exporters/JsonFile' "exportFilter" "[!is[system]!tag[image]]"
node:internal/fs/utils:347
throw err;
^
Error: EINVAL: invalid argument, open '.......\WikiName\CON'
at Object.openSync (node:fs:599:3)
at Object.writeFileSync (node:fs:2221:35)
at $:/core/modules/commands/render.js:58:7
at $tw.utils.each ($:/boot/boot.js:146:12)
at Command.execute ($:/core/modules/commands/render.js:47:13)
at Commander.executeNextCommand ($:/core/modules/commander.js:107:14)
at Commander.executeNextCommand ($:/core/modules/commander.js:111:12)
at Commander.execute ($:/core/modules/commander.js:64:7)
at exports.startup ($:/core/modules/startup/commands.js:34:12)
at $tw.boot.executeNextStartupTask ($:/boot/boot.js:2542:10) {
errno: -4071,
syscall: 'open',
code: 'EINVAL',
path: '......\\WikiName\\CON'
}
Node.js v18.6.0
Admittedly the CON filename is a rare case. Is there another way of rendering to stdout rather than a file?
Expected behavior
The JSON data should be rendered to the console.
To Reproduce
- On a NodeJS TW, run
tiddlywiki "WikiName" --render "." "CON" "text/plain" '$:/core/templates/exporters/JsonFile' "exportFilter" "[!is[system]!tag[image]]"
Screenshots
No response
TiddlyWiki Configuration
- Version v5.2.2
- Saving mechanism Node.js
- Plugins installed: extended-button-widgets, Relink, Todolist
Desktop (please complete the following information):
- OS: Windows 10
- Browser Edge
- Version 103
Additional context
No response
Thank you @kravlost, that's an interesting problem!
My first thought was that I could test it on my Mac using /dev/tty
:
tiddlywiki editions/tw5.com --verbose --render '.' '/dev/tty' 'text/plain' '$:/core/templates/exporters/JsonFile' 'exportFilter' 'HelloThere'
But it turns out that that works as expected; it seems that on macOS/Linux the Node.js function path.resolve()
has special knowledge of /dev/tty
, and discards the other path elements.
I used Google Code search to find quite a few projects that have ended up with a hardcoded list of special filenames in Windows:
https://github.com/tilt-dev/go-get/blob/90f57eece58af5259762820bbe3f091ec8c23bc9/path.go#L169-L191
This comment clarifies that these are actually prefixes:
The following special “files”, which access devices, exist in all directories, case-insensitively, and with all possible endings after a period or colon, except in pathnames that start with \?: "NUL", "CON", "PRN", "AUX", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
https://cs.github.com/MicahElliott/vrod/blob/d0f598051530005c0dd868dea1900f803c82086b/racket/doc/paths.txt#L762
I found a reasonable looking regexp to match these names:
https://cs.github.com/seiya-npm/sei-helper/blob/fe688d20798546398e3bfcc2d28f2c8f2428eb5c/src/main.js#L140
However, it doesn't seem to account for CLOCK$
which appears in some lists:
https://cs.github.com/seiya-npm/sei-helper/blob/fe688d20798546398e3bfcc2d28f2c8f2428eb5c/src/main.js#L140
Another point to note about the quote above is that "CON" exists in every directory; therefore I'd have expected it not to matter that we've resolved it into the current working directory.
All very frustrating; this feels like something that Node.js should be handling automatically.
Anyhow, I guess one possible fix would be to make our own custom version of path.resolve
that when on Windows
One small point is that your example here is incorrect:
tiddlywiki --output "" "WikiName" --render "." "CON" "text/plain" '$:/core/templates/exporters/JsonFile' "exportFilter" "[!is[system]!tag[image]]"
The --output
command should go after the path to the wiki:
tiddlywiki "WikiName" --output "" --render "." "CON" "text/plain" '$:/core/templates/exporters/JsonFile' "exportFilter" "[!is[system]!tag[image]]"
Thanks for the analysis, @Jermolene . I've noticed that if I use a forbidden character in a tiddler title, then it is sanitised with replacement underscores before being used as a filename, so something is handling it!
One small point is that your example here is incorrect:
It is indeed, sorry about that.