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

QFile::rename() fails if names differ only in case

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3: Somewhat important
    • Resolution: Done
    • Affects Version/s: 4.6.1, 5.0.0 Beta 2
    • Fix Version/s: 5.10
    • Component/s: Core: I/O
    • Labels:
      None
    • Commits:
      d3dc0f21225845f404262ea563870044cbbbe53f 363dc9146e53e24172bb9c0ae68100a8543bd9ae

      Description

      On Windows, QFile::rename() fails if names differ only in case. The Windows filesystem is not case sensitive for manipulating files, but the case is stored on the filesystem.

      Therefore, renaming the file qtsoftware.txt to QtSoftware.txt is usually possible on Windows but it fails with Qt.

      Here is a test case to reproduce the issue:

      #include <QtTest/QtTest>
       #include <QtCore/qfile.h>
       #include <stdio.h>
       #include <unistd.h>
      
      class Test : public QObject\{
       Q_OBJECT
       private:
       void createFile()
      
      \{ QFile file("qtsoftware.txt"); file.open(QIODevice::WriteOnly); file.close(); }
      
      void cleanFiles()
      
      \{ unlink("QtSoftware.txt"); unlink("qtsoftware.txt"); }
      
      private slots:
       void testRenameChangeFilename()
      
      \{ cleanFiles(); createFile(); QFile file("qtsoftware.txt"); // rename QCOMPARE(file.rename("QtSoftware.txt"), true); cleanFiles(); }
      
      };
      
      QTEST_MAIN(Test)
       #include "test.moc"
      

      Here is a patch for the issue, if the name differs only by the case, it uses the fileEngine to rename the file. A better patch should check if the filesystem is case sensitive instead of checking if it is windows (the filesystem of mac can be case sensitive or not depending on the configuration for example):

      diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
       index dde159f..353fa11 100644
       — a/src/corelib/io/qfile.cpp
       +++ b/src/corelib/io/qfile.cpp
       @@ -671,6 +671,15 @@ QFile::rename(const QString &newName)
       qWarning("QFile::rename: Empty or null file name");
       return false;
       }
       +#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
       + QString currentName = fileName();
       + if (newName.compare(currentName, Qt::CaseInsensitive) == 0 && currentName != newName) \{
       + if (fileEngine()->rename(newName))
      
      \{ + unsetError(); + return true; + }
      
      + }
       +#endif
       if (QFile(newName).exists()) \{
       // ### Race condition. If a file is moved in after this, it /will/ be
       // overwritten. On Unix, the proper solution is to use hardlinks:
      

        Attachments

          Issue Links

          For Gerrit Dashboard: QTBUG-3570
          # Subject Branch Project Status CR V

            Activity

              People

              Assignee:
              thiago Thiago Macieira
              Reporter:
              poulain Benjamin Poulain (closed Nokia identity) (Inactive)
              Votes:
              8 Vote for this issue
              Watchers:
              16 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes