Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-23476

QFileSystemEngine::slowCanonicalized() returns empty string for mounted volume with no drive letter

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P2: Important
    • 6.0
    • 4.8.0
    • Core: I/O
    • None
    • Windows 7 SP1 x64
      Visual C++ 2008
      Qt 4.8.0

    Description

      When using QDir::canonicalPath() on Windows with a directory that includes a mount point for a volume with no drive letter, an empty string is returned. This is because QFileSystemEngine::slowCanonicalized() returns an empty string. The following illustrates my scenario:

      Format a partition and mount it as C:\Qt\4.8 without assigning a drive letter to the volume. I did this using the standard Disk Management tool in Windows 7.
      The volume for the formatted partition is assigned a UUID that I will refer to as a-b-c-d-e.
      Running 'dir C:\Qt' includes the following output:

      01/05/2012 08:45 AM <JUNCTION> 4.8 [??\Volume

      {a-b-c-d-e}

      ]

      The following behavior occurs for QDir objects created using the identified input path:

      "C:/Qt" – canonicalPath() returns "C:/Qt"
      "C:/Qt/4.8" – canonicalPath() returns ""
      "C:/Qt/4.8/src" – canonicalPath() returns ""

      If Volume a-b-c-d-e were assigned to the Q drive and still mounted at C:\Qt\4.8, then the canonical path results would be the following:

      "C:/Qt" – canonicalPath() returns "C:/Qt"
      "C:/Qt/4.8" – canonicalPath() returns "Q:/"
      "C:/Qt/4.8/src" – canonicalPath() returns "Q:/src"

      From stepping through the code, it appears that lines 109-110 of qfilesystemengine.cpp are meant to detect the case of a symlink that points to itself. However, that handing is incorrect when the file system entity is a junction to a volume that has no drive letter. For that case, the value returned by resolving the symlink target is "C:/Qt/4.8" which seems correct. (The target resolution is done by the Windows-specific QFileEngine::getLinkTarget() implementation.) However, that path is already in the set of known paths since it was the original input.

      It is not clear to me if the difference between a Windows 7 symlink and a Windows junction is a critical detail. Assuming that the behavior of QFileSystemEngine::slowCanonicalize() is to return an empty string for a symlink/junction that points to itself, then the code behaves correctly. To illustrate, I can do the following:

      mklink /D link_test link_test
      dir
      [...]
      01/05/2012 08:45 AM <SYMLINKD> link_test [link_test]

      If I create a QDir for link_test, invoking QDir::canonicalPath() returns an empty string. Calling QDir::canonicalPath() on a junction that points to itself also returns an empty string.

      Ultimately, it seems that some sort of special case handling is needed, but I do not know what. I have attached a trivial test program that can be used to show the behavior, but I have not been able to come up with a proper fix. For my purposes, I can assign a drive letter to my mounted volume. It is worth noting that this was unnecessary with Qt 4.7.

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              Unassigned Unassigned
              patrickh Patrick Hartling
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes