Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected behavior for fd_prestat with an empty prefix? #227

Closed
zeux opened this issue Jan 17, 2021 · 9 comments
Closed

Expected behavior for fd_prestat with an empty prefix? #227

zeux opened this issue Jan 17, 2021 · 9 comments

Comments

@zeux
Copy link

zeux commented Jan 17, 2021

I'm using wasi-libc with a custom implemention of WASI on top of it to bridge file system calls from the guest to the host OS; the intention is to provide a pass-through scheme where file paths are handed off as is.

My current implementation of prestat returns a single directory with an empty path.

This works well for relative paths, and for absolute paths on Windows, but doesn't work for absolute paths on Linux/macOS, since a call to open a file "/foo/bar" is translated to a call to path_open with "foo/bar" (no leading slash) - and the same is true for a call to open a file "foo/bar". So from the point of WASI implementation it's impossible to distinguish "foo/bar" from "/foo/bar" when using an empty prestat.

Is that behavior intended? I suspect I can work around this by registering two prestat paths, "/" and "", but it would be great to avoid that for simplicity...

@sbc100
Copy link
Member

sbc100 commented Jan 17, 2021

I think if you want to give full access to host FS you would basically map "/" on the host to "/" on the libc/preopen side.

The notion of current working directory is not part of WASI today, but there was some support recently added to wasi-libc to fake it: #214. With that change PWD mostly works for wasi-libc-based programs although as you will see from the discussion we don't yet have an agreed upon way to set the PWD when a program first start. One way to do that today is to link in a helper functions or some library code that will call chdir based on the incoming $PWD environment variable (of course you would also need to pass that environment variable to the module too).

@zeux
Copy link
Author

zeux commented Jan 17, 2021

Thanks! I'll look at that PR and try to adapt to the behavior there.

@zeux zeux closed this as completed Jan 17, 2021
@zeux
Copy link
Author

zeux commented Jan 17, 2021

Ok - I was able to get this to work. In context of my application I can't setup chdir for the wasm code to the native path, I really need to forward paths from the embedded code to the host as is.

So what I ended up doing is registering two mounts, / and /fake-folder-name, and in the host code that implements WASI remapping fake-folder-name accesses back to current-folder-relative.

This is not great and probably isn't future proof, as right now fopen("../foo") isn't converted to fopen("/foo") after chdir("/fake-folder-name") which makes this work, but it might change in the future. But it's the only approach I found that actually works.

@sbc100
Copy link
Member

sbc100 commented Jan 17, 2021

Why doesn't it work do have the application do chdir(getenv("PWD")) on startup?

If the PWD is set to, for sample, /home/bob when the application is started and '/' is mapped to '/' then the application should have no problem doing its fake/userspace chdir into /home/bob on startup. Are you missing the change form #214, perhaps?

@zeux
Copy link
Author

zeux commented Jan 17, 2021

To be clear, chdir(getenv("PWD")) would work mechanically (as in, the code would run), but that doesn't fit the use pattern - I'm using wasm in a reactor-style application that's embedded into a JS library (so there's no real file system); the said JS library is then wrapped into a command-line JS application that does have a real file system as implemented by node.

So for the above to work with the real pwd I'd need to expose an interface to set the current directory from the JS library which I was/am reluctant to do, hence the workaround.

@zeux
Copy link
Author

zeux commented Jan 17, 2021

(I should say I'm also not sure how the "absolute" path handling in libc would work on Windows with drive paths. My current workaround does work but that also may be an accident...)

@sbc100
Copy link
Member

sbc100 commented Jan 17, 2021

OK sounds like you have a solution for now. As an alternative perhaps you could export chdir from your module and then wrap all your other reactor entry points so they call chdir before calling the real entry point?

@zeux
Copy link
Author

zeux commented Jan 17, 2021

Yeah that’s more or less what I am doing atm

@zeux
Copy link
Author

zeux commented Jan 17, 2021

Just to close the loop on this, I decided to try the suggested workaround of passing the real current directory through to WASI and as I feared it's not compatible with Windows drive paths so it doesn't really work on Windows.

E.g. if I'm currently in C:\work directory, node's process.cwd will return C:\work; if I chdir to that, and then fopen("C:\path\to\file"), internally the paths will get concatenated to fopen("C:\work\C:\path\to\file");this path is not valid and can't be opened by node's fs.readFileSync.

This seems to be a problem for any code that wants to use WASI for something like Emscripten's noderawfs; I initially expected the empty prestat folder to work with that but unfortunately it doesn't, so I have to resort to my hacky workaround with a fake folder :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants