Can you add a comment explaining why reparse points need special handling?
Both branches appear to do the same thing using different APIs. I assume this has to do with whether you're tweaking the reparse point itself or the file it points to, but that's not super obvious.
(And if that is the reason, then I'd expect these branches to be the other way around.)
Is it worth skipping the Set operation if the file (or reparse point) has no effect?
I imagine a common thing to do is to set permissions on zillions of files at once, so avoiding an extra system call when its not necessary seems like it would be worth the cost of an extra conditional branch.
Same question about skipping the Sets when they're not necessary.
Sure, can add a comment.
The branch is the right way around (a couple tests fail if it's flipped) - the get/set functions that take a filename operate on the reparse point itself. The CreateFile function (wrapped by WinHandle) resolves to the reparse target unless FILE_FLAG_OPEN_REPARSE_POINT is passed.
I guess one could simplify the code by always using the handle codepath but optionally setting the FILE_FLAG_OPEN_REPARSE_POINT flag - but that codepath uses a couple more syscalls, so maybe it's worth keeping both - with some more comments.
Sure, I can change that.
Rebased, retriggering CI.
This is also a bit restructured from the version @amccarth reviewed, as I moved the code out from the __permissions() function into posix-like fchmod() and fchmodat(). That refactoring itself is pretty straightforward, and allowed getting rid of a lot of extra ifdefs.
I don't understand the purpose of that function. Isn't that equivalent to just static_cast<::mode_t>(prms)?
If so, this function is called only once below. Why don't we simply use:
#if defined(_LIBCPP_WIN32API) using ModeT = int; #else using ModeT = ::mode_t; #endif const auto real_perms = static_cast<ModeT>(prms);
Well, you get the idea.