#25474 Added read-only warnings when saving documents (#25532)

* #25474 Added read-only warnings when saving documents

Block saving a file and notify user if windows is unable to save to the file for any reason, or the read-only attribute is checked. Also check std::filesystem::perms for write permission and other checks in FileInfo::isWritable(), although it doesn't seem to matter on windows.

Co-authored-by: Chris Hennes <chennes@pioneerlibrarysystem.org>
This commit is contained in:
Andrew Burks
2025-11-23 00:09:32 -05:00
committed by GitHub
parent 3ab8dbe194
commit bad2989b7b
2 changed files with 44 additions and 0 deletions

View File

@@ -336,6 +336,44 @@ bool FileInfo::isWritable() const
if (fs::is_directory(path)) {
return directoryIsWritable(path);
}
#ifdef FC_OS_WIN32
// convert filename from UTF-8 to windows WSTRING
std::wstring fileNameWstring = toStdWString();
// requires import of <windows.h>
DWORD attributes = GetFileAttributes(fileNameWstring.c_str());
if (attributes == INVALID_FILE_ATTRIBUTES) {
// Log the error?
std::clog << "GetFileAttributes failed for file: " << FileName << '\n';
// usually indicates some kind of network file issue, so the file is probably not writable
return false;
}
if ((attributes & FILE_ATTRIBUTE_READONLY) != 0) {
return false;
}
// TEST if file is truly writable, because windows ACL does not map well to POSIX perms,
// and there are other potential blockers (app or shared file locks, etc)
HANDLE hFile = CreateFileW(
fileNameWstring.c_str(),
GENERIC_WRITE,
0, // ----> no sharing: fail if anyone else has it open
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) {
return false;
}
return false;
}
if (!CloseHandle(hFile)) {
std::clog << "CloseHandle failed for file: " << FileName
<< " while checking for write access." << '\n';
}
#endif
fs::file_status stat = fs::status(path);
fs::perms perms = stat.permissions();
return (perms & fs::perms::owner_write) == fs::perms::owner_write;