-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
[RFC] On windows don't check for exec bit in is_executable() #3224
Conversation
@equalsraf is it certain that libuv doesn't fix this already? |
Last time I checked libuv does not return the exec bit as set (nor should it). We can also change the macro to always return true. Some context: |
Even in the NT kernel? I was thinking this was left over from Vim windows 95 assumptions. |
Don't know, but PATHEXT is still defined in my system and contains .COM,.BAT,.EXE and also scripts extensions like .rb for ruby. |
Well I'll be a kitten's mitten. I just created a text file in Windows 7, invoked it it in cmd.exe, and it tried to execute every line of the text file. If I disable the "Read & Execute" setting in the file's "Security" properties, then "Read" is also disabled. From MSDN:
|
#if WIN32 | ||
// Windows does not have exec bit, just check if | ||
// the file exists | ||
return (S_ISREG(mode)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could do this instead:
return os_access(name, F_OK);
Then os_getperm
is not needed for the WIN32 branch. This will require defining F_OK in win_defs.h:
# define F_OK 0
See justinmk@b1e18dc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops we don't have os_access
, we use uv_fs_access
directly. So never mind I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm the Vim docs say this:
On MS-DOS and MS-Windows it only checks if the file exists and
is not a directory, not if it's really executable.
So the original diff should suffice no?
Eg: even if I remove Read & Execute (and therefore Read) permissions
and then do this in Vim:
:echom executable("test.bat")
Vim will still return 1 even though I can't run said Batch script from a Windows shell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vim will still return 1 even though I can't run said Batch script from a Windows shell.
If we can make executable()
do something actually useful on Windows, then it doesn't matter what Vim's behavior is. So os_file_is_readable()
seems like a good idea to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Works for me. Will update the docs too.
… and uses the read permission to determine whether the file can be executed.
On MS-DOS and MS-Windows it only checks if the file exists and | ||
is not a directory, not if it's really executable. | ||
On MS-DOS and MS-Windows it checks if the file exists, is not | ||
a directory and is readable, not if it's really executable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove MS-DOS
@sethjackson The commits in #810 might be in WIP state, so please note the commit guidelines at https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-guidelines |
// Windows does not have an executable bit. | ||
// Instead check if the file exists and is readable. | ||
return os_file_is_readable((char *) name); | ||
#else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I should have read the docs more carefully. We do need to use S_ISREG
because that checks that the file is not a directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea. I just realized that after I pushed. :/
Also there appears to be this weird problem with uv_fs_access
on Windows where if you request anything but W_OK
it short circuits and returns 0 without actually checking the file attributes which means os_is_file_readable
always returns true even if the user doesn't have permission to access the given file. :(
Personally I feel that's a bug in the libuv implementation so perhaps a libuv PR is in order?
See: https://github.com/libuv/libuv/blob/df62b54aa2b3d916ca442ee84f0678129a848c4f/src/win/fs.c#L1346
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sethjackson It would be worth opening an issue at libuv at least to get confirmation. They are very responsive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check this issue first though: libuv/libuv#316
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the logic is ok, can you give a scenario where it would be wrong? The call to GetFileAttributes()
above that will fail if the file doesn't exist.
@justinmk ok. Will probably open an issue but I might check what CPython does first. ;) And yea I'm hoping that all the stuff for win_defs.h can be squashed into one commit. There is a bunch of stuff in there... |
Most of it is here: equalsraf@d02f0d6 But I am not sure all of it is needed, it would be better to include each part with the relevant function changes. For example, |
In Windows there is not equivalent to the filesystem executable bit,
the documentation states that for Windows :executable() returns
1 for all files. But this behaviour was broken because is_executable()
checked for the UNIX bit.
When WIN32 is set we now skip the S_IXUSR check.
Cherry picked from #810.