Closed Talkless closed 3 years ago
Oh, VS 2017 do support <filesystem>
, and in that case it changes 777
to 555
(still allows reading).
I guess I just won't be able to achieve that in posix-first std::filesystem?
Indeed, neither my implementation nor those from MSVC are able to do that with the fs::permissions
API, the simple chmod
type of POSIX permissions is not very expressive and there is no simple Read-Flag in Windows that can be removed, just a FILE_ATTRIBUTE_READONLY
. (See also the Answer of one of the developers behind the MS std::filesystem implementation here.)
I implemented my helper function to set DENY_ACCESS
for EVERYONE
using SetEntriesInAclA
by some MSDN example like this:
void TestBackup::removePermissionsOrFatal(const QString &path)
{
#ifdef Q_OS_WINDOWS
auto nativePath{QDir::toNativeSeparators(path).toStdString()};
struct ScopedPACL {
~ScopedPACL() {
if (pointer)
LocalFree(static_cast<HLOCAL>(pointer));
};
PACL pointer{nullptr};
};
struct ScopedSecurityDescriptor {
~ScopedSecurityDescriptor() {
if (pointer)
LocalFree(static_cast<HLOCAL>(pointer));
};
PSECURITY_DESCRIPTOR pointer{nullptr};
};
DWORD dwRes{};
ScopedPACL oldPacl;
ScopedSecurityDescriptor sd;
dwRes = GetNamedSecurityInfoA(nativePath.c_str(),
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
nullptr,
nullptr,
&oldPacl.pointer,
nullptr,
&sd.pointer);
if (dwRes != ERROR_SUCCESS) {
qFatal( "GetNamedSecurityInfo Error %u\n", dwRes);
}
std::string trusteeName{"EVERYONE"}; // we need non-const char*, cannot use string literal...
EXPLICIT_ACCESS ea{};
ea.grfAccessPermissions = GENERIC_ALL;
ea.grfAccessMode = DENY_ACCESS;
ea.grfInheritance = 0;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.ptstrName = trusteeName.data();
ScopedPACL newDACL;
dwRes = SetEntriesInAclA(1, &ea, oldPacl.pointer, &newDACL.pointer);
if (dwRes != ERROR_SUCCESS) {
qFatal("SetEntriesInAcl Error %u", dwRes);
}
dwRes = SetNamedSecurityInfoA(nativePath.data(),
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
nullptr,
nullptr,
newDACL.pointer,
nullptr);
if (dwRes != ERROR_SUCCESS) {
qFatal("SetNamedSecurityInfo Error %u\n", dwRes);
}
#else
if (!QFile::setPermissions(path, {})) {
qFatal("Failed to change permissions for file '%s'", qPrintable(path));
}
#endif
}
Nice that you found a solution and thank you for sharing it! I currently have no plan to implement ACL based permission handling as the MSVC version does not, but I might decide to change that and it sure will be helpful.
I use QFile::setPermissions() in a unit test where I want to imitate handling of "permission denied" error for some file operations, but that works only on unix-like systems...
Instead of dealing with WinAPI directly, I though I would try using this neat header-only lib.
But it seems the change I am getting at best is changing
666
to444
(seen usingghc::filesystem::status()
), either with:or with:
I understand that it "most certainly not lead to the expected behavior", but it seems it tries to change something, maybe I am doing something wrong?
Same with 1.4.0 (from Conan) and 1.5.0. Building with Visual Studio 2017 in x86 mode.