On Tue, 15 Apr 2025 07:46:52 GMT, Alan Bateman <al...@openjdk.org> wrote:

>> Hi, this is a proposal to fix 8352728.
>> 
>> The main idea is to replace 
>> [`java.nio.file.Path::toRealPath`](https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/nio/file/Path.html#toRealPath(java.nio.file.LinkOption...))
>>  by 
>> [`java.io.File::getCanonicalPath`](https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/File.html#getCanonicalPath())
>>  for path canonicalization purposes. The rationale behind this decision is 
>> the following:
>> 
>> 1. In _Windows_, `File::getCanonicalPath` handles restricted permissions in 
>> parent directories. Contrarily, `Path::toRealPath` fails with 
>> `AccessDeniedException`.
>> 2. In _Linux_, `File::getCanonicalPath` handles non-regular files (e.g. 
>> `/dev/stdin`). Contrarily, `Path::toRealPath` fails with 
>> `NoSuchFileException`.
>> 
>> #### Windows Case
>> 
>> @martinuy and I tracked down the `File::getCanonicalPath` vs 
>> `Path::toRealPath` behaviour differences in _Windows_. Both methods end up 
>> calling the 
>> [`FindFirstFileW`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findfirstfilew)
>>  API inside a loop for each parent directory in the path, until they include 
>> the leaf:
>> 
>> * 
>> [`File::getCanonicalPath`](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/share/classes/java/io/File.java#L618
>>  "src/java.base/share/classes/java/io/File.java:618") goes through the 
>> following stack into `FindFirstFileW`:
>>     * 
>> [`WinNTFileSystem::canonicalize`](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/windows/classes/java/io/WinNTFileSystem.java#L473
>>  "src/java.base/windows/classes/java/io/WinNTFileSystem.java:473")
>>     * 
>> [`WinNTFileSystem::canonicalize0`](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/windows/native/libjava/WinNTFileSystem_md.c#L288
>>  "src/java.base/windows/native/libjava/WinNTFileSystem_md.c:288")
>>     * 
>> [`wcanonicalize`](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/windows/native/libjava/canonicalize_md.c#L233
>>  "src/java.base/windows/native/libjava/canonicalize_md.c:233") (here is the 
>> loop)
>>     * If `FindFirstFileW` fails with `ERROR_ACCESS_DENIED`, 
>> `lastErrorReportable` is consulted, the error is [considered 
>> non-reportable](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/windows/native/libjava/canonicalize_md.c#L139
>>  "src/java.base/windows/native/libjava/canonicalize_md.c:139") and the 
>> iteration is stopped 
>> [here](https://github.com/openjdk/jdk/blob/jdk-24-ga/src/java.base/windows/native/libjava/canonicalize_md.c#L246-L250
>>  "src/ja...
>
>> File::getCanonicalPath seems to take the best-effort approach (both in Linux 
>> and Windows), whereas Path::toRealPath is stricter.
> 
> Path::toRealPath is doing the right thing, and consistent with realpath(2). 
> The issue with File::getCanonicalXXX is that it is specified to return a 
> canonical file even if it doesn't exist, so this is why you see a lot more 
> code to compute a result.
> 
> Maybe the recursive include check them maybe it should use the file key 
> instead.

@AlanBateman are you ok with letting the original 
c6f1d5f374bfa9bde75765391d5dae0e8e28b4ab reviewers know of this fix and take a 
look? Or do you think further discussion is needed somewhere else?

-------------

PR Comment: https://git.openjdk.org/jdk/pull/24465#issuecomment-2842800806

Reply via email to