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

[nodefs] Fix execute permission bit on Windows when retrieving mode attribute #21902

Merged

Conversation

fluiddot
Copy link
Contributor

@fluiddot fluiddot commented May 7, 2024

On Windows, files and directories created within a mounted NODEFS instance consistently have the execution permission bit x disabled, even though they are actually accessible. The permissions returned consistently indicate 0666. If this value is used to create other files or directories to match the same permissions, they will possess a different value, potentially leading to inconsistencies.

This PR applies a solution similar to #5847, albeit within the getattr function of NODEFS.

test/test_other.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm % some nits and tests updates

@@ -127,6 +127,11 @@ addToLibrary({
if (NODEFS.isWindows && !stat.blocks) {
stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0;
}
if (NODEFS.isWindows) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you combine this with the block above so we only check isWindows once?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I applied this suggestion in ef0ec92.

def test_windows_nodefs_execution_permission(self):
if self.get_setting('WASMFS'):
self.set_setting('FORCE_FILESYSTEM')
delete_dir('new-dir')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to do this here since tests are guaranteed to start with an empty dir

}
'''.replace('{{WORKING_DIR}}', Path(self.working_dir).as_posix())
self.emcc_args += ['-lnodefs.js']
self.do_run(src)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can combine these two lines into self.do_run(src, emcc_args=['-lnodefs.js'])

int main(int argc, char * argv[]) {
EM_ASM(
FS.mkdir('/working');
FS.mount(NODEFS, { root: '{{WORKING_DIR}}' }, '/working');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just do { root: '.' } here? Unless I'm missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, true. I think I introduced this early on when I was running the test without using the test runner. Now using the test runner, I confirmed that using { root: '.' } works as expected. I'll update it.

FS.mount(NODEFS, { root: '{{WORKING_DIR}}' }, '/working');
FS.mkdir('/working/new-dir');
FS.writeFile('/working/new-dir/test.txt', 'test');
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put this EM_ASM block into a separate setup() function?

@only_windows('Check that directory permissions are properly retrieved on Windows')
@requires_node
def test_windows_nodefs_execution_permission(self):
if self.get_setting('WASMFS'):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will always be false unless you add @also_with_wasmfs. I'm not sure if you want to do that here though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this part based on what I saw in other tests (example). Not exactly sure if it's needed but we could remove it if it's not 👍.

@requires_node
def test_windows_nodefs_execution_permission(self):
if self.get_setting('WASMFS'):
self.set_setting('FORCE_FILESYSTEM')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? Maybe just remove these two lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As shared here, probably not. I'll remove it.

err = stat("/working/new-dir/test.txt", &s);
assert((s.st_mode & S_IXUSR) == S_IXUSR);
assert((s.st_mode & S_IXGRP) == S_IXGRP);
assert((s.st_mode & S_IXOTH) == S_IXOTH);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just do assert(s.st_mode & S_IXOTH) since each of those defines is just a single bit

if (NODEFS.isWindows) {
// Node.js on Windows never represents permission bit 'x', so
// propagate read bits to execute bits.
stat.mode = stat.mode | (stat.mode & 292) >> 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put brackets around the (stat.mode & 292) >> 2 so its clear that the shift only applies the part of this expression?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed you updated the code where this is based in #21904. I'll apply the same here. Thanks 🙇 !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 75abe47.

sbc100 added a commit to sbc100/emscripten that referenced this pull request May 7, 2024
sbc100 added a commit that referenced this pull request May 7, 2024
@fluiddot
Copy link
Contributor Author

fluiddot commented May 8, 2024

@sbc100 thank you so much for reviewing the PR so quickly 🙇 ! I've checked the feedback and pushed changes accordingly. Let me know if you could take another look, thanks!

@fluiddot fluiddot requested a review from sbc100 May 8, 2024 09:51
@sbc100 sbc100 changed the title Fix execute permission bit on Windows when retrieving mode attribute [nodefs] Fix execute permission bit on Windows when retrieving mode attribute May 8, 2024
Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!

@sbc100 sbc100 merged commit 7224d52 into emscripten-core:main May 14, 2024
27 of 29 checks passed
@fluiddot fluiddot deleted the fix-nodefs-mode-attribute-windows branch May 14, 2024 15:01
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

Successfully merging this pull request may close these issues.

None yet

2 participants