[Qt-interest] QFile::copy() fails on Windows Vista if the source is in resources (Was Re: QFile::remove() fails on Windows Vista)

Constantin Makshin dinosaur-rus at users.sourceforge.net
Tue Jun 23 19:56:48 CEST 2009


Qt calls close(), but please read QTemporaryFile documentation:

Reopening a QTemporaryFile after calling close() is safe. For as long as  
the QTemporaryFile object itself is not destroyed, the unique temporary  
file will exist and be kept open internally by QTemporaryFile.

On Tue, 23 Jun 2009 21:52:38 +0400, Yevgen Muntyan <muntyan at fastmail.fm>  
wrote:
> QTemporaryFile::close() doesn't close it? I believe Qt calls close()  
> before
> renaming.
>
>
> Constantin Makshin wrote:
>> I guess I've found the source of this problem -- QFile::copy() uses   
>> temporary file when native API can't do the work (and that happens  
>> because  native APIs don't know about Qt reources), and since  
>> QTemporaryFile object  doesn't close its file until it (object) is  
>> destroyed, any attempt to  delete it (file) fails.
>>
>> As a workaround, you can use something like this:
>>
>> QFile file(":/deltest.pro"),
>>        destFile("copycopy.txt");
>> if (srcFile.open(QIODevice::ReadOnly) &&
>>      destFile.open(QIODevice::WriteOnly))
>> {
>>      QByteArray data = file.readAll();
>>      destFile.write(data);
>> }
>> file.close();
>> destFile.close();
>>
>> On Tue, 23 Jun 2009 08:05:14 +0400, Yevgen Muntyan  
>> <muntyan at fastmail.fm>  wrote:
>>
>>> Hey,
>>>
>>> I tried simple QFile::rename(), it works fine for regular files. My   
>>> program copies a file from
>>> resources and apparently that hits an unlucky code path.
>>>
>>> DeleteFile fails because the file is held by someone else. I can't   
>>> delete the file while the application
>>> is sitting in debugger right before DeleteFile call. DeleteFile  
>>> returns  0, and GetLastError is 32.
>>> Trying to delete file in cmd.exe I get "The process cannot access the   
>>> file because it is being used
>>> by another process." After I let the program run further (and after   
>>> QFile::rename() fails), I can
>>> delete the file without problems, with or without "\\?\" prefix. What  
>>> I  said earlier about the prefix
>>> was wrong, I simply tried to delete the file while the program was   
>>> stopped.
>>>
>>> The following is a complete test case which reproduces my problem  
>>> (you  need to add a resource
>>> file which includes some file, deltest.pro in this code):
>>>
>>> #include <QtGui>
>>>
>>> int main(int argc, char *argv[])
>>> {
>>>     QApplication app(argc, argv);
>>>     QFile file(":/deltest.pro");
>>>     if (file.copy("copycopy.txt"))
>>>         QMessageBox::information(0, "yay!", "yay!");
>>>     else
>>>         QMessageBox::critical(0, "oops!", file.errorString());
>>>     return 0;
>>> }
>>>
>>> It gives me "Cannot create copycopy.txt for output" (it's lying, the   
>>> error message is overwritten inside
>>> QFile::copy).
>>>
>>> Best regards,
>>> Yevgen
>>>
>>> Constantin Makshin wrote:
>>>
>>>> "\\?\" prefix is used to extend the maximum path length from 259 to   
>>>> ~32000  characters. Could you call DeleteFileW(L"\\?\<path>"), where   
>>>> <path> is the  absolute path to your temporary file with backslashes  
>>>> as  path delimiters,  directly and see what it returns?
>>>>
>>>> On Mon, 22 Jun 2009 21:00:48 +0400, Yevgen Muntyan   
>>>> <muntyan at fastmail.fm>  wrote:
>>>>
>>>>
>>>>> Yevgen Muntyan wrote:
>>>>>
>>>>>
>>>>>> Hey,
>>>>>>
>>>>>> I have a problem with QFile::rename: it fails when it tries to   
>>>>>> remove  the
>>>>>> temporary file it uses, because DeleteFileW() fails inside
>>>>>> QFSFileEngine::remove(). My code is roughly the following:
>>>>>>
>>>>>> QFile source(":/gap/ggap.g");
>>>>>> source.copy("C:/Users/muntyan/AppData/Local/Temp/ggap-000025cb/ggap.g")
>>>>>>
>>>>>> The copy() call here fails.
>>>>>> "C:/Users/muntyan/AppData/Local/Temp/ggap-000025cb" directory is   
>>>>>> created
>>>>>> with QDir::mkdir(), and I do have permissions to delete files from   
>>>>>> it,  and I
>>>>>> can delete files from it in explorer. The temporary files    
>>>>>> qt_temp.XXXXXX are
>>>>>> not read-only, so DeleteFile() isn't supposed to fail. But it does!
>>>>>>
>>>>>>
>>>>>>
>>>>> I found out that Qt calls DeleteFile() on some funny long version  
>>>>> of  the
>>>>> filename, namely it passes
>>>>> the following string to DeleteFile:
>>>>>
>>>>> \\?\c:\Users\muntyan\AppData\Local\Temp\ggap-00002d22\qt_temp.Za5308
>>>>>
>>>>> it prepends \\?\ in QFSFileEnginePrivate::longFileName().  
>>>>> DeleteFile()
>>>>> doesn't fail if I call it on
>>>>> the filename without that prefix. Ideas?
>>>>>
>>>>> Thanks,
>>>>> Yevgen

-- 
Constantin "Dinosaur" Makshin



More information about the Qt-interest-old mailing list