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

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

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P3: Somewhat important
    • 5.10
    • 4.6.1, 5.0.0 Beta 2
    • Core: I/O
    • None
    • 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

              thiago Thiago Macieira
              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