Currently, the access() and chmod() wrappers in in src/win/fs.c do not take windows ACLs into account. These are the most common methods by which a file can have e.g. executable permissions granted/restricted. As an example, Cygwin's chmod implementation uses windows ACLs to encode the user/group/other triplet of permissions bits. The Cygwin implementation is quite complex, (you can read some of it here: https://github.com/Alexpux/Cygwin/blob/b61dc22adaf82114eee3edce91cc3433bcd27fe5/winsup/cygwin/sec_acl.cc#L130-L134) but we have been working on an implementation that is relatively self-contained, and gives us satisfying chmod() and access() semantics. We're not quite ready to open a PR to upstream this yet, as we have yet to test this in a production Julia release and be certain that it works in all edge cases (ACLs are unfortunately rather complex beasts, and we've already had to work around one win32 bug) but you can see the current state of our patch here: JuliaLang/libuv@35b1504...JuliaLang:sf/access_chmod
We are interested in any feedback from the libuv devs regarding the overall approach and any edge cases you might think of that we haven't considered. Our motivating use case for this is calculating git tree hashes, as we use that algorithm to content-address filesystem trees. This requires an accurate check on the executable permissions of the file, hence the need for fs__access() and fs__chmod() to do something useful on Windows. The rest of the machinery within fs__chmod() that sets writable and readable bits for user, group and other was me being stubborn and not wanting to half-build something that just set executable bits.
I did spend a day looking into making fs__stat_handle() work in a similar way and fill out st_mode properly. At first, I hoped that the AccessCheck() win32 call, which works so well for fs__access(), could be used with separate tokens (one for file owner, file group, and the Everyone group) and permission masks (read, write, execute) to probe the 9 bits within the rwx triplets, however there is one issue; while we can easily derive a token for the current user and the everyone group, I have not found a way to generate a token for an arbitrary user or group; I can only generate a token (via CreateRestrictedToken) for groups that the current user belongs to, by blacklisting all other group and user SIDs. This means that, for files owned by a different user or a group that that user does not belong to, the results will always be all-deny.
I haven't found any other nice win32 APIs to perform the ACL result calculation for arbitrary SIDs yet; if anyone knows of a good alternative, I'd love to have a stat() implementation that works properly. From what I can tell, Cygwin simulates the ACL permission rules internally, and that's far too much complexity for what is, for our usecases, simply a "nice to have".
Currently, the
access()andchmod()wrappers in insrc/win/fs.cdo not take windows ACLs into account. These are the most common methods by which a file can have e.g. executable permissions granted/restricted. As an example, Cygwin'schmodimplementation uses windows ACLs to encode the user/group/other triplet of permissions bits. The Cygwin implementation is quite complex, (you can read some of it here: https://github.com/Alexpux/Cygwin/blob/b61dc22adaf82114eee3edce91cc3433bcd27fe5/winsup/cygwin/sec_acl.cc#L130-L134) but we have been working on an implementation that is relatively self-contained, and gives us satisfyingchmod()andaccess()semantics. We're not quite ready to open a PR to upstream this yet, as we have yet to test this in a production Julia release and be certain that it works in all edge cases (ACLs are unfortunately rather complex beasts, and we've already had to work around one win32 bug) but you can see the current state of our patch here: JuliaLang/libuv@35b1504...JuliaLang:sf/access_chmodWe are interested in any feedback from the libuv devs regarding the overall approach and any edge cases you might think of that we haven't considered. Our motivating use case for this is calculating git tree hashes, as we use that algorithm to content-address filesystem trees. This requires an accurate check on the executable permissions of the file, hence the need for
fs__access()andfs__chmod()to do something useful on Windows. The rest of the machinery withinfs__chmod()that sets writable and readable bits for user, group and other was me being stubborn and not wanting to half-build something that just set executable bits.I did spend a day looking into making
fs__stat_handle()work in a similar way and fill outst_modeproperly. At first, I hoped that theAccessCheck()win32 call, which works so well forfs__access(), could be used with separate tokens (one for file owner, file group, and theEveryonegroup) and permission masks (read, write, execute) to probe the 9 bits within therwxtriplets, however there is one issue; while we can easily derive a token for the current user and the everyone group, I have not found a way to generate a token for an arbitrary user or group; I can only generate a token (viaCreateRestrictedToken) for groups that the current user belongs to, by blacklisting all other group and user SIDs. This means that, for files owned by a different user or a group that that user does not belong to, the results will always be all-deny.I haven't found any other nice win32 APIs to perform the ACL result calculation for arbitrary SIDs yet; if anyone knows of a good alternative, I'd love to have a
stat()implementation that works properly. From what I can tell, Cygwin simulates the ACL permission rules internally, and that's far too much complexity for what is, for our usecases, simply a "nice to have".