Files.createDirectories throws AccessDeniedException for an existing directory
Brian Burkhalter
brian.burkhalter at oracle.com
Thu Nov 28 00:42:23 UTC 2024
Hi Ole,
On Nov 27, 2024, at 3:01 AM, ole.sh at gmx.de wrote:
thanks for our reply!
You are welcome!
I didn't mean to say that the behavior isn't correct, it just seemed a bit "unexpected" (at least to me as a "user" of the API not knowing the details of the implementation of Files.createDirectories).
Understood.
>> I took a closer look at it and saw that Files.createDirectories never
>> explicitly checks for the existence of the directory but relies on the
>> createDirectory of the underlying FileSystemProvider to throw an
>> FileAlreadyExistsException. In case of Linux the underlying
>> UnixFileSystemProvider calls the mkdir system call and checks/translates its
>> return code.
> I assume that you intend the system call itself here, as the JNI interface to
> the system call does not translate the errno value.
I was referring to UnixException.translateToIOException(String, String) which is called by UnixFileSystemProvider.createDirectory. It looks like it "translates" the errno (which I guessed is the return code of the system call) to regular IOExceptions like AccessDeniedException or FileAlreadyExistsException.
I don’t think we can translate an EACCES to AccessDeniedException here as this method is used in many places.
>> The problem is that the mkdir system call seems to be allowed (according to
>> Posix?) to return any of the matching return codes in case multiple return
>> codes are "correct”. And that happens in our NFS case.
> Do you have a link to documentation of this behavior / specification?
It is described in section "2.3 Error Numbers" in the "System Interfaces" volume of Posix (https://urldefense.com/v3/__https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/V2_chap02.html*tag_16_03__;Iw!!ACWV5N9M2RV99hQ!MCUMndmKonwTVE9x3yuFTw-vnGgYwv6pz-A_vlT8-OVma6Q4kosEWgjYJiDxKz-L6F78hyJQrPlDbP-os2Y1$ ):
"
If more than one error occurs in processing a function call, any one of the possible errors may be returned, as the order of detection is undefined.
"
Thanks.
>> We verified that the mkdir call sometimes returns EACCESS and sometimes EEXIST
>> (most likely due to some "caching" in the kernel NFS driver).
> That sounds like flakiness in the system itself, not in Java, perhaps an NFS
> configuration issue? It seems that Java is responding as expected to the errno
> values encontered.
I agree that it is a flakiness in the system though it seems to be "correct"/OK wrt. Posix.
That seems to be a weak point in the POSIX specification.
>> Although it is just an "edge case" I wonder if it makes sense to make
>> Files.createDirectories more "predictable" in such cases? A simple solution
>> might be to adapt Files.createAndCheckIsDirectory to check if the "dir" is a
>> directory not just in case of an FileAlreadyExistsException but also in case
>> of an AccessDeniedException:
>>
>> private static void createAndCheckIsDirectory(Path dir,
>> FileAttribute<!--?-->>... attrs)
>> throws IOException
>> {
>> try {
>> createDirectory(dir, attrs);
>> } catch (FileAlreadyExistsException x) {
>> if (!isDirectory(dir))
>> throw x;
>> + } catch (AccessDeniedException x) {
>> + if (!isDirectory(dir))
>> + throw x;
> I am not sure that we want to hide the AccessDeniedException when the target is
> a directory. Subsequently executed code might encounter problems and it could be
> harder to identify the cause. Also, this code is used by all platforms, not only
Linux.
>> }
>> }
>> Some additional notes:
>> * A similar problem was reported and fixed in JDK-8032220 for MacOS and
>> Windows
> In that issue, filtering of EISDIR was added but this appears to be an error
specific to macOS.
What I was referring more to were the changes made in the WindowsFileSystemProvider.createDirectory for JDK-8032220 (https://hg.openjdk.org/jdk9/jdk9/jdk/rev/8ff79b0e3503): An ERROR_ACCESS_DENIED is catched and a FileAlreadyExistException is thrown instead if the directory already exists.
I see.
In the bug ticket (https://bugs.openjdk.org/browse/JDK-8032220) it is said that "It does not appear to be an issue on Linux". This is true for the special case of "/" handled in the bug ticket. But given the behavior of mkdir regarding the return code according to Posix similar problems could/do occur on Linux (as in my NFS case)
To address your problem then the safest approach would appear to be overriding createDirectory() in LinuxFileSystemProvider to have the desired behavior, such as was done on Windows.
Best regards,
Brian
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/nio-dev/attachments/20241128/2af0b4a5/attachment-0001.htm>
More information about the nio-dev
mailing list