Files.createDirectories throws AccessDeniedException for an existing directory
Ole SH
ole.sh at gmx.de
Fri Nov 29 22:13:29 UTC 2024
Hi Brian,
> 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.
>
As a "user" of the API I would appreciate such a change.
Best regards,
Ole
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/nio-dev/attachments/20241129/10ea8f65/attachment-0001.htm>
More information about the nio-dev
mailing list