@CheckForNull
    public static File resolveSymlinkToFile(@NonNull File link) throws InterruptedException, IOException {
        String target = resolveSymlink(link);
        if (target == null)   return null;

        File f = new File(target);
        if (f.isAbsolute()) return f;   // absolute symlink
        return new File(link.getParentFile(), target);   // relative symlink
    }
@Test
    @Issue("SECURITY-904")
    public void resolveSymlinkToFile() throws Exception {
        assumeFalse(Functions.isWindows());
        //  root
        //      /a
        //          /aa
        //              aa.txt
        //          /_b => symlink to /root/b
        //      /b
        //          /_a => symlink to /root/a
        File root = tmp.getRoot();
        File a = new File(root, "a");
        File aa = new File(a, "aa");
        aa.mkdirs();
        File aaTxt = new File(aa, "aa.txt");
        Files.writeString(aaTxt.toPath(), "aa", StandardCharsets.US_ASCII);

        File b = new File(root, "b");
        b.mkdir();

        File _a = new File(b, "_a");
        Util.createSymlink(_a.getParentFile(), a.getAbsolutePath(), _a.getName(), TaskListener.NULL);

        File _b = new File(a, "_b");
        Util.createSymlink(_b.getParentFile(), b.getAbsolutePath(), _b.getName(), TaskListener.NULL);

        assertTrue(Files.isSymbolicLink(_a.toPath()));
        assertTrue(Files.isSymbolicLink(_b.toPath()));

        // direct symlinks are resolved
        assertEquals(Util.resolveSymlinkToFile(_a), a);
        assertEquals(Util.resolveSymlinkToFile(_b), b);

        // intermediate symlinks are NOT resolved
        assertNull(Util.resolveSymlinkToFile(new File(_a, "aa")));
        assertNull(Util.resolveSymlinkToFile(new File(_a, "aa/aa.txt")));
    }