your code was a bit erroneous. I have corrected that (see below).
Nevertheless: Thanks very much, because now it WORKS ;-))
Except, it doesn't actually work, at least not the way you originally asked for it:
does anyone have a test routine ready to determine whether I am allowed to write to a specific file?
If the caller actually passed in a full file path, the code is not creating/opening the
requested file anymore, it merely determines the parent folder of the file and then creates its own random file in that folder, completely ignoring the
requested file. Essentially, you have now created a
FolderIsWriteable() type of function (and in that scenario, using
MakeRandomString() is overkill, when you can just use
GetTempFileName() instead, or a GUID).
For Windows, I would opt for something more like the following instead. If you need something that is cross-platform,
{$IFDEF} the code accordingly:
uses
.., Windows;
function FileIsWriteable(fn: String; KeepFileIfCreatedNew: Boolean = False) : Boolean;
var
h: THandle;
Err: DWord;
begin
h := CreateFile(PChar(fn), GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
Result := h <> INVALID_HANDLE_VALUE;
if Result then begin
Err := GetLastError;
CloseHandle(h);
if (Err <> ERROR_ALREADY_EXISTS) and (not KeepFileIfCreatedNew) then
DeleteFile(PChar(fn));
end;
end;
If
CreateFile() succeeds, you are guaranteed to have write access to the file via the returned
THandle only. Once you close that
THandle, all bets are off, you lose any guarantee that you will still have write access to the same file at a later time (ie, someone else could open the file and decide not to share write access to it, etc).
The mere presence of a
FileIsWriteable()-like function introduces a
TOCTOU race condition that you really should not be introducing to begin with. If you want write access to a file, then just open the file for writing AT THE TIME you want to write to it, then actually write to it (and keep it open for later writes, if needed), and then close it when you are done using it. Handle any failure that may occur during that time as needed.
You know the old saying "It is better to ask for forgiveness than permission"? Well, that applies here, too. If you want to do something (write to a file, etc), then just go ahead and attempt to do it, and handle the consequences as needed. Don't try asking for permission first.