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

        1. qdir_test.cpp
          0.7 kB
          Patrick Hartling

        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