Recent

Author Topic: Test if I could write to a certain file  (Read 12064 times)

dietmar

  • Full Member
  • ***
  • Posts: 170
Test if I could write to a certain file
« on: August 01, 2021, 09:38:36 pm »
Hi,

does anyone have a test routine ready to determine whether I am allowed to write to a specific file?
The caveat is, that this file may be already existent, but should not be changed (yet).
Using Unix, I would just use fpaccess - is there an equivalent for windows?

Thx,
--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Test if I could write to a certain file
« Reply #1 on: August 02, 2021, 10:55:59 am »
On Windows: try to open it in write mode (fmOpenWrite or fmShareDenyWrite).
As long as you don't do any writing, the file won't change.

Bart

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Test if I could write to a certain file
« Reply #2 on: August 02, 2021, 11:08:00 am »
Alternatively you could use SysUtils.FileIsReadOnly(), e.g.
Code: Pascal  [Select][+][-]
  1. { uses sysutils }
  2. function FileIsWriteable(const AFilename; String): Boolean;
  3. begin
  4.   Result := FileExists(AFilename) and not FileIsReadOnly(AFilename);
  5. end;


Never mind; all it does elsewhere than on *nix is to check the file attributes, which doesn't guarantee that it can indeed can written to :-[
« Last Edit: August 02, 2021, 11:15:41 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #3 on: August 02, 2021, 03:17:05 pm »
I now tried:

function FileIsWriteable(fn: String) : Boolean;
begin
  //exit(FileOpen(fn,fmOpenWrite or fmShareDenyWrite)<>-1);
  exit(FileOpen(fn,fmOpenWrite or fmShareDenyWrite)<>THandle(-1));
end;

Both variants don't work and always return TRUE. The first variant additionally gives a strange compiler warning.

--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Test if I could write to a certain file
« Reply #4 on: August 03, 2021, 09:03:35 am »
I now tried:

function FileIsWriteable(fn: String) : Boolean;
begin
  //exit(FileOpen(fn,fmOpenWrite or fmShareDenyWrite)<>-1);
  exit(FileOpen(fn,fmOpenWrite or fmShareDenyWrite)<>THandle(-1));
end;

Both variants don't work and always return TRUE. The first variant additionally gives a strange compiler warning.

Independent of if it works for your purpose or not: if a valid handle is returned you should close it with FileClose before leaving FileIsWriteable otherwise you'll leak handles.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #5 on: August 03, 2021, 02:43:53 pm »
Thanks for the tip. I now changed it:

Code: Pascal  [Select][+][-]
  1. function FileIsWriteable(fn: String) : Boolean;
  2. var h: THandle;
  3. begin
  4.   h := FileOpen(fn,fmOpenWrite or fmShareDenyWrite);
  5.   if (h=-1) then
  6.     exit(False)
  7.   else begin
  8.     FileClose(h);
  9.     exit(True);
  10.   end;
  11. end;
  12.  

But the main problem remains. Even for Filenames like "C:\Programs\bla.txt", the function results a file handle... :(
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

marcio2003

  • Jr. Member
  • **
  • Posts: 69
Lazarus 2.0.10 Windows 10 64bits

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Test if I could write to a certain file
« Reply #7 on: August 03, 2021, 04:06:08 pm »
Try it.
http://blog.vitorrubio.com.br/2010/10/obtendo-atributos-de-arquivos-com-o.html

That's basically what FileIsReadOnly() does, i.e. read the file attributes. Unfortunately that's not enough because the file might not have the read-only attr. set but be nevertheless unwriteable due to file/folder permissions, etc. :(
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #8 on: August 04, 2021, 02:33:49 pm »
I tried another solution:

Code: Pascal  [Select][+][-]
  1. function FileIsWriteable(fn: String) : Boolean;
  2. var
  3.   s: String;
  4.   h: THandle;
  5. begin
  6.   // try to write random file in same directory
  7.   repeat
  8.     s := ExtractFilePath(fn) + MakeRandomString(16) + '.$$$';
  9.   until not FileExists(s);
  10.   h := FileCreate(s,fmShareExclusive);
  11.   if (h=-1) then
  12.     exit(False)
  13.   else begin
  14.     FileClose(h);
  15.     exit(True);
  16.   end;
  17. end;
  18.  

Didn't help either :(
What am I doing wrong? I am very desperate now...

--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Test if I could write to a certain file
« Reply #9 on: August 04, 2021, 02:39:55 pm »
Have you checked whether the file is indeed created or (for previous attempts) if you can in fact write to that file?
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #10 on: August 04, 2021, 02:51:03 pm »
I tried it with C:\Program Files\Test.dat.
A random file name C:\Program Files\32Afk4jf...$$$ was generated, but I could not write to this file. When choosing another folder like C:\ProgramData, it works...

--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Test if I could write to a certain file
« Reply #11 on: August 04, 2021, 03:05:21 pm »
A random file name C:\Program Files\32Afk4jf...$$$ was generated, but I could not write to this file.

So FileCreate() didn't fail, after all ... but if you try a FileWrite() it fails, is that it? Now, that's certainly strange but it also means that to check if you can write to a file you'll have to ... try to write to it.

Apparently nothing else works ... unless, now I think about it, maybe trying to change its timestamp or its attributes would also work. Just remeber to store the previous vales, to restore them in case it does work after all.

In the meantime I'll see if I can mount and fire on a Windows machine to make some tests of my own.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #12 on: August 04, 2021, 03:08:37 pm »
In my function, I added

Code: Pascal  [Select][+][-]
  1.     For I:=0 to 100 do
  2.       FileWrite(h,I,SizeOf(i));
  3.  

just before the FileClose. It worked (in ProgramData) and didn't work in C:\Program Files - as it should. But nevertheless, both tests result in TRUE...

--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Test if I could write to a certain file
« Reply #13 on: August 04, 2021, 03:22:18 pm »
You forgot to check the result of FileWrite. This should work:
Code: Pascal  [Select][+][-]
  1. function FileIsWriteable(fn: String) : Boolean;
  2. var
  3.   s: String;
  4.   h: THandle;
  5. begin
  6.   // try to write random file in same directory
  7.   repeat
  8.     s := ExtractFilePath(fn) + MakeRandomString(16) + '.$$$';
  9.   until not FileExists(s);
  10.   { Note that this only tests if you can create a file and write
  11.     to it in that directory, not the writeability of the file "fn"}
  12.   h := FileCreate(s,fmShareExclusive)
  13.   Result := h <> -1;
  14.   if Result then begin
  15.     Result := FileWrite(h, s[1], Lentgh(s));
  16.     FileClose(h);
  17.   end;
  18. end;
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

dietmar

  • Full Member
  • ***
  • Posts: 170
Re: Test if I could write to a certain file
« Reply #14 on: August 04, 2021, 08:38:07 pm »
Hi,

your code was a bit erroneous. I have corrected that (see below).
Nevertheless: Thanks very much, because now it WORKS ;-))

Just for the records or for anyone who can need this:

Code: Pascal  [Select][+][-]
  1. function MakeRandomString(l: Byte): String;
  2. var i: Integer;
  3.     s: String;
  4. begin
  5.   s := '';
  6.   for i:=1 to l do
  7.     case random(3) of
  8.       0: s := s + Chr(65+Random(26));
  9.       1: s := s + Chr(97+Random(26));
  10.       2: s := s + Chr(48+Random(10));
  11.     end;
  12.   exit(s);
  13. end;
  14.  
  15. function FileIsWriteable(fn: String) : Boolean;
  16. var
  17.   s: String;
  18.   h: THandle;
  19. begin
  20.   repeat
  21.     s := ExtractFilePath(fn) + MakeRandomString(16) + '.$$$';
  22.   until not FileExists(s);
  23.   h := FileCreate(s,fmShareExclusive);
  24.   Result := h<>-1;
  25.   if Result then begin
  26.     Result := FileWrite(h,s[1],Length(s))<>-1;
  27.     FileClose(h);
  28.     DeleteFile(PChar(s));
  29.   end;
  30. end;
  31.  

Greetz
--Dietmar
Lazarus 2.2.0RC1 with FPC 3.2.2 (32 Bit) on Windows10 (64Bit)

 

TinyPortal © 2005-2018