Khalid Saleem · Feb 5, 2018

Determine write-access to a directory

I am trying to determine the write-access to a windows-directory, using the method %File.Writeable(). But, this method always returns the boolean "true", even when I have revoked the write-access of Healthshare-user in this directory.

1) When the same ensemble-service tries to write a file in this directory (which it says is "writeable"), it fails.
2) The method %File.Writeable(...) works perfectly in the case of files.

Any help is appreciated.
Thanks in advance... :-)

0 766
Discussion (17)1
Log in or sign up to continue

You have to be aware that  you access the file by the rather high privileged account that Caché service is running in.
Have you blocked this account too ?

Yes, I have blocked the user-account which Cache-service is running in.

See Robert's answers. The %File.Writeable(...) method's underlying implementation ($zutil(140,12,filename,2)=0) is apparently not able to determine whether or not a directory is writeable, despite the method doc stating "Return true if the file/directory is writable and false if it is not"

See this older doc for $zutil(140) information.

You could try raising the issue with InterSystems WRC, but my guess is they'll say it's a bug in the comment on the method.

But $ZU(140,1,Directory) ALWAYS returns -5  "no access"

tested on Cache for Windows (x86-64) 2016.2

I am testing it using Ensemble-service and terminal both. The results are the same.

This didn't work for me. Here's what result contained:

The /D switch is only valid with the /S switch.

Anyway, AFAIK the Read-only attribute of a Windows folder is of limited use. Even if you set it using the attrib command this won't prevent you from being able to modify files within the folder (provided those files don't have their Read-only attribute set).

I think the OP was referring to permissions on the folder, not attributes. And in my testing, even if I explicitly deny Write permission on a folder to my user, the ##class(%File).Writeable(...) method still tells me I can write to a file that's in the folder. Of course, when I actually try to open it for write, the timed OPEN command fails correctly.


Set file="full file reference"
OPEN file:("WN"):0  Else  Write "write lock on file",!

My reading of the post is that the OP is saying that %File.Writeable(...) on the Windows platform returns the correct answer for a file but not for a directory. I haven't investigated yet.

You are right. Open Parameter should be "WN"
It is just an indirect test as OPEN on a directory fails with < NOTOPEN>
And it also fails if the file already exists and can be accessed.

I tried issuing "Open" command on a directory. But it always returns the failure "NOTOPEN", irrespective of the fact whether the directory has write-access or not. So, this does not resolve the issue I am facing.

Just try to create/open random new file in a directory.

I can check the write-access to a folder by trying to write a file in it. But, I am looking for a more elegant solution.

Quite interesting on my WIN10_prof   I had no need of /S as I wante exactly THIS directory

And you are right. If the file exists already and is accessible nothing prevents you from modifying it.
You probably can't delete it as this requires access to directory.
And you are also right that ATTRIB doesn't propagate it.   

So I think the whole approach to check the directory is misleading.
Now we are back to the initial proposal.
Do an OPEN with timeout in this directory ("WN")  and on success you can write to the directory.
The test file can be removed by CLOSE file:"D"  if you didn't open with "WND" .

And it tells you can I write there YES/NO
And this is independent of any status and flags and don't know what in whatever filesystem I work on.


How do you test?

Terminal runs under your own OS user.

Your observation is correct.
I checked the underlying system call.
In Windows  {for me Win10} all you get back  is the flag ="isDirectory"
So you need to do the indirect check as described in the comments

There is a solution using WIN command  attrib to check read only access flag.
It doesn't write files.
You are welcome to discuss about "elegance" .

    set dir=yourDirectory
    set dev="|CPIPE|"
    set cmd="attrib /d "
    set result=""
    open dev:(cmd_dir:"R"):0
    if $test use dev read result close dev
    if $piece($zstrip(result,"<>"," "),dir)["R" write "directory read only",!
    else  write "directory accessible"