Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8307887

(fs) Files.createSymbolicLink throws less specific exception when in developer mode and file already exists

XMLWordPrintable

    • b26
    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10 > 1703

      A DESCRIPTION OF THE PROBLEM :
      The solution for issue JDK-8221852 prevents the actual error from symlink creation from being relayed to the user in the mentioned environment.

      The exception from the second attempt at symlink creation, the one with the flag allowing symlinks without elevation, is discarded unconditionally. However, Windows *appears* to check the flag/privileges situation first, and only then looks into whether the target already exists.

      Thus, the exception from the second attempt should only be discarded if it is either ERROR_PRIVILEGE_NOT_HELD (developer mode not enabled) or ERROR_INVALID_PARAMETER (flag not supported). In any other case, the new error should be relayed to the calling code instead of the original one.

      See problematic change at: https://github.com/openjdk/jdk/commit/5952e2bc6496e349874d9f8748b1bfda9a7e4cc4#diff-70b8da266a5d031447f4f390981470464c400a0b012591788f17f19ca19d336fR948

      I also checked in the most recent jdk-21-ea build, and the problem persists. The symlink creation code on Windows seems unchanged since the mentioned commit.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Create two files A and B by any means
      2. Call Files.createSymbolicLink with the paths of A and B

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Exception FileAlreadyExistsException is thrown, stating that A (the would-be link) already exists.
      ACTUAL -
      On Windows, the exception is FileSystemException (stating that the client is missing a required privilege), even when developer mode is enabled. The actual exception is lost.

      ---------- BEGIN SOURCE ----------
      import java.nio.file.Files;
      import java.nio.file.Path;

      public class Test {
          public static void main(String[] args) throws Exception {
              final var pA = Files.createTempFile("link", null);
              final var pB = Files.createTempFile("target", null);
              
              try {
                  Files.createSymbolicLink(pA, pB);
              } catch (java.nio.file.FileAlreadyExistsException e) {
                  System.out.println("OK");
              }
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      The only workaround I have found is to manually check whether the target exists beforehand, but this is naturally racy.

      FREQUENCY : always


            bpb Brian Burkhalter
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: