Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I detect the pre-existance of a QFile after opening it in read/write/append mode?

Tags:

c++

boost

qt

qfile

I want to write some text to a file with a randomly chosen filename, but want to require that the file doesn't exist yet. There's a race-condition between a simple QFile::exists check followed by an open with the checked name.

What's the best way to ensure that the file wasn't pre-existing when I open it with QFile? The same thing with a directory works nicely when using boost::filesystem::create_directory, because it returns a boolean that indicates whether a directory was pre-existing or not. But I don't see how it works for files.

like image 345
Johannes Schaub - litb Avatar asked Jan 16 '19 16:01

Johannes Schaub - litb


1 Answers

I must admit that I never tried this personally.

However, I remembered that the usual approach for preventing race conditions in file I/O is to try and handle the possible error case respectively.

Hence, I had a look into QFile::open() what it does offer and found:

QIODevice::NewOnly:

Fail if the file to be opened already exists. Create and open the file only if it does not exist. There is a guarantee from the operating system that you are the only one creating and opening the file. Note that this mode implies WriteOnly, and combining it with ReadWrite is allowed. This flag currently only affects QFile. Other classes might use this flag in the future, but until then using this flag with any classes other than QFile may result in undefined behavior. (since Qt 5.11)


I just realized that (beside of our productive Qt 5.9 installation) I have a newer one which I installed for private fiddling.

Thus, I made a little sample to check this out:

#include <QtWidgets>

int main()
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  for (int i = 1; i <= 2; ++i) {
    qDebug() << "Iteration" << i;
    QFile qFile("test.txt");
    if (!qFile.open(QIODevice::WriteOnly | QIODevice::NewOnly)) {
      qDebug() << "qFile.open failed! Error code" << qFile.error();
    }
    qFile.write("test");
    qFile.close();
  }
  return 0;
}

Output:

Qt Version: 5.11.2
Iteration 1
Iteration 2
qFile.open failed! Error code 5
QIODevice::write (QFile, "test.txt"): device not open

I'm still not quite sure how to find out that it failed exactly due to the already existing file (and not for any other reason). In my case for sure but in general?

(The error code 5 is simply QFileDevice::OpenError.)

like image 71
Scheff's Cat Avatar answered Sep 30 '22 02:09

Scheff's Cat