Skip to content
Permalink
Browse files

change project/backup file only after preparing the data

This avoids corrupted project files when crashing during the preparation of the XML data to write to the project file, e.g. due to a faulty plugin.
  • Loading branch information
SebDieBln committed Dec 22, 2015
1 parent 7c3cf64 commit e1586422a90e7823e9bb42b6e788f7388e96da8d
Showing with 39 additions and 42 deletions.
  1. +39 −42 src/core/qgsproject.cpp
@@ -1002,53 +1002,12 @@ bool QgsProject::write()
{
clearError();

// Create backup file
if ( QFile::exists( fileName() ) )
{
QFile backupFile( fileName() + '~' );
bool ok = true;
ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
ok &= imp_->file.open( QIODevice::ReadOnly );

QByteArray ba;
while ( ok && !imp_->file.atEnd() )
{
ba = imp_->file.read( 10240 );
ok &= backupFile.write( ba ) == ba.size();
}

imp_->file.close();
backupFile.close();

if ( !ok )
{
setError( tr( "Unable to create backup file %1" ).arg( backupFile.fileName() ) );
return false;
}

QFileInfo fi( fileName() );
struct utimbuf tb = { fi.lastRead().toTime_t(), fi.lastModified().toTime_t() };
utime( backupFile.fileName().toUtf8().constData(), &tb );
}

// if we have problems creating or otherwise writing to the project file,
// let's find out up front before we go through all the hand-waving
// necessary to create all the Dom objects
if ( !imp_->file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
{
imp_->file.close(); // even though we got an error, let's make
// sure it's closed anyway

setError( tr( "Unable to save to file %1" ).arg( imp_->file.fileName() ) );
return false;
}

QFileInfo myFileInfo( imp_->file );
if ( !myFileInfo.isWritable() )
if ( myFileInfo.exists() && !myFileInfo.isWritable() )
{
// even though we got an error, let's make
// sure it's closed anyway
imp_->file.close();
setError( tr( "%1 is not writable. Please adjust permissions (if possible) and try again." )
.arg( imp_->file.fileName() ) );
return false;
@@ -1149,6 +1108,44 @@ bool QgsProject::write()
// now wrap it up and ship it to the project file
doc->normalize(); // XXX I'm not entirely sure what this does

// Create backup file
if ( QFile::exists( fileName() ) )
{
QFile backupFile( fileName() + '~' );
bool ok = true;
ok &= backupFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
ok &= imp_->file.open( QIODevice::ReadOnly );

QByteArray ba;
while ( ok && !imp_->file.atEnd() )
{
ba = imp_->file.read( 10240 );
ok &= backupFile.write( ba ) == ba.size();
}

imp_->file.close();
backupFile.close();

if ( !ok )
{
setError( tr( "Unable to create backup file %1" ).arg( backupFile.fileName() ) );
return false;
}

QFileInfo fi( fileName() );
struct utimbuf tb = { fi.lastRead().toTime_t(), fi.lastModified().toTime_t() };
utime( backupFile.fileName().toUtf8().constData(), &tb );
}

if ( !imp_->file.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
{
imp_->file.close(); // even though we got an error, let's make
// sure it's closed anyway

setError( tr( "Unable to save to file %1" ).arg( imp_->file.fileName() ) );
return false;
}

QTemporaryFile tempFile;
bool ok = tempFile.open();
if ( ok )

0 comments on commit e158642

Please sign in to comment.
You can’t perform that action at this time.