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

(spec) File.equals() spec suggests canonicalization but implemention does not canonicalize

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 1.3.0, 1.4.1
    • Fix Version/s: tbd
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • CPU:
      generic, sparc
    • OS:
      generic, solaris_8

      Description

      Name: nt126004 Date: 12/02/2002


      FULL PRODUCT VERSION :
      java version "1.4.1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
      Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      SunOS mammoth 5.8 Generic_108528-15 sun4u sparc SUNW,Ultra-80


      A DESCRIPTION OF THE PROBLEM :
      The documentation for java.io.File.equals() states that the
      method "Returns true if and only if the argument is not null
      and is an abstract pathname that denotes the same file or
      directory as this abstract pathname." However, a look at the
      source reveals that it delegates to the FileSystem class (same
      package), whose compare() method states "Compare two abstract
      pathnames lexicographically." These two contracts contradict
      one another.

      Refer to the sample program below and its output.
      On UNIX, at least, /dir1/dir2/../dir3/myfile and
      /dir1/dir3/myfile "denote the same file or directory."
      However, the strings are not lexicographically equal and
      File.equals() returns false.

      Either File.equals() should be changed to use canonical files
      to meet the contract set out in its documentation or the
      documentation should be changed to state explicitly that
      the files are compared using their path strings without
      reference to whether or not they refer to the same physical
      file.

      This bug is similar to a general case of bug #4143695. That
      bug's author asked for a change to File to assist with a
      permissions issue. I am not interested in permissions or in
      the specific case he mentions, however; I am concerned with
      the misleading inconsistency between what is implied in the
      method's documentation and what its implementation in fact
      does.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the sample code below.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The sample program outputs:

      File #1: /dir1/dir2/../dir3/myfile
      File #2: /dir1/dir3/myfile
      Equals: false

      Based on the File.equals() docs, I expected:

      File #1: /dir1/dir2/../dir3/myfile
      File #2: /dir1/dir3/myfile
      Equals: true

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.File;

      public class FileTest {
          public static void main(String[] args) {
              File f1 = new File("/dir1/dir2/../dir3/myfile");
              File f2 = new File("/dir1/dir3/myfile");
              System.out.println("File #1: " + f1);
              System.out.println("File #2: " + f2);
              System.out.println("Equals: " + f1.equals(f2));
          }
      }

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

      CUSTOMER WORKAROUND :
      Always compare canonical files:

      public static boolean equals(File f1, File f2) {
          File canonical1;
          try {
              canonical1 = f1.getCanonicalFile();
          } catch (IOException iox) {
              canonical1 = f1.getAbsoluteFile();
          }
          File canonical2;
          try {
              canonical2 = f2.getCanonicalFile();
          } catch (IOException iox) {
              canonical2 = f2.getAbsoluteFile();
          }
          return canonical1.equals(canonical2);
      }

      There are a couple of issues with the above:
      1.) It involves a couple object instatiations, and is hence
          relatively slow, and
      2.) In the event that an IOException occurs in
          getCanonicalFile(), the output is not guaranteed to be
          correct. However, it is *more likely* to be correct than
          the current code.
      (Review ID: 165782)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              alanb Alan Bateman
              Reporter:
              nthompsosunw Nathanael Thompson (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Imported:
                Indexed: