30 #include <QTemporaryFile>
43 class KSaveFile::Private
49 QFile::FileError
error;
82 if ( d->realFileName.isNull() ) {
83 d->error=QFile::OpenError;
84 d->errorString=
i18n(
"No target filename has been given.");
88 if ( !d->tempFileName.isNull() ) {
89 #if 0 // do not set an error here, this open() fails, but the file itself is without errors
90 d->error=QFile::OpenError;
91 d->errorString=
i18n(
"Already opened.");
100 d->error=QFile::PermissionsError;
101 d->errorString=
i18n(
"Insufficient permissions in target directory.");
107 tempFile.setAutoRemove(
false);
108 tempFile.setFileTemplate(d->realFileName + QLatin1String(
"XXXXXX.new"));
109 if (!tempFile.open()) {
110 d->error=QFile::OpenError;
111 d->errorString=
i18n(
"Unable to open temporary file.");
119 QFileInfo fi ( d->realFileName );
122 if (fchown(tempFile.handle(), fi.ownerId(), fi.groupId())) {
124 fchown(tempFile.handle(), -1, fi.groupId());
127 tempFile.setPermissions(fi.permissions());
131 fchmod(tempFile.handle(), 0666&(~umsk));
135 QFile::setFileName(tempFile.fileName());
137 tempFile.setAutoRemove(
true);
141 d->tempFileName = tempFile.fileName();
143 d->errorString.clear();
149 d->realFileName = filename;
152 if ( QDir::isRelativePath( filename ) ) {
153 d->realFileName = QDir::current().absoluteFilePath( filename );
167 return QFile::error();
173 if ( !d->errorString.isEmpty() ) {
174 return d->errorString;
176 return QFile::errorString();
182 return d->realFileName;
188 QFile::remove(d->tempFileName);
189 d->wasFinalized =
true;
192 #ifdef HAVE_FDATASYNC
193 # define FDATASYNC fdatasync
195 # define FDATASYNC fsync
200 bool success =
false;
202 if ( !d->wasFinalized ) {
205 static int extraSync = -1;
207 extraSync = getenv(
"KDE_EXTRA_FSYNC") != 0 ? 1 : 0;
213 if (errno != EINTR) {
214 d->error = QFile::WriteError;
215 d->errorString =
i18n(
"Synchronization to disk failed");
226 QFile::remove(d->tempFileName);
233 else if (0 ==
KDE::rename(d->tempFileName,d->realFileName)) {
235 d->errorString.clear();
238 d->error=QFile::OpenError;
239 d->errorString=
i18n(
"Error during rename.");
240 QFile::remove(d->tempFileName);
243 d->wasFinalized =
true;
261 int maxnum = g.
readEntry(
"MaxBackups", 10 );
262 if ( type.toLower() == QLatin1String(
"numbered") ) {
264 }
else if ( type.toLower() == QLatin1String(
"rcs") ) {
273 const QString& backupExtension )
275 QString backupFileName = qFilename + backupExtension;
277 if ( !backupDir.isEmpty() ) {
278 QFileInfo fileInfo ( qFilename );
279 backupFileName = backupDir + QLatin1Char(
'/') + fileInfo.fileName() + backupExtension;
283 QFile::remove(backupFileName);
284 return QFile::copy(qFilename, backupFileName);
291 QFileInfo fileInfo ( qFilename );
294 if ( backupDir.isEmpty() ) {
295 qBackupFilename = qFilename;
297 qBackupFilename = backupDir + fileInfo.fileName();
299 qBackupFilename += QString::fromLatin1(
",v" );
304 if ( !backupDir.isEmpty() )
306 if ( !QFile::copy(qFilename, backupDir + fileInfo.fileName()) ) {
309 fileInfo.setFile(backupDir + QLatin1Char(
'/') + fileInfo.fileName());
315 if ( cipath.isEmpty() || copath.isEmpty() || rcspath.isEmpty() )
320 if ( !backupDir.isEmpty() )
321 ci.setWorkingDirectory( backupDir );
322 ci.start( cipath,
QStringList() << QString::fromLatin1(
"-u") << fileInfo.filePath() );
323 if ( !ci.waitForStarted() )
325 ci.write( backupMessage.toLatin1() );
327 ci.closeWriteChannel();
328 if( !ci.waitForFinished() )
333 if ( !backupDir.isEmpty() )
334 rcs.setWorkingDirectory( backupDir );
335 rcs.start( rcspath,
QStringList() << QString::fromLatin1(
"-U") << qBackupFilename );
336 if ( !rcs.waitForFinished() )
341 if ( !backupDir.isEmpty() )
342 co.setWorkingDirectory( backupDir );
343 co.start( copath,
QStringList() << qBackupFilename );
344 if ( !co.waitForFinished() )
347 if ( !backupDir.isEmpty() ) {
348 return QFile::remove( fileInfo.filePath() );
356 const QString& backupExtension,
357 const uint maxBackups )
359 QFileInfo fileInfo ( qFilename );
363 if ( backupDir.isEmpty() ) {
364 sTemplate = qFilename + QLatin1String(
".%1") + backupExtension;
366 sTemplate = backupDir + QLatin1Char(
'/') + fileInfo.fileName() + QLatin1String(
".%1") + backupExtension;
371 QDir d = backupDir.isEmpty() ? fileInfo.dir() : backupDir;
372 d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );
373 const QStringList nameFilters =
QStringList( fileInfo.fileName() + QLatin1String(
".*") + backupExtension );
374 d.setNameFilters( nameFilters );
375 d.setSorting( QDir::Name );
377 uint maxBackupFound = 0;
378 foreach (
const QFileInfo &fi, d.entryInfoList() ) {
379 if ( fi.fileName().endsWith( backupExtension ) ) {
382 sTemp.truncate( fi.fileName().length()-backupExtension.length() );
384 int idex = sTemp.lastIndexOf( QLatin1Char(
'.') );
387 uint num = sTemp.mid( idex+1 ).toUInt( &ok );
389 if ( num >= maxBackups ) {
390 QFile::remove( fi.filePath() );
392 maxBackupFound = qMax( maxBackupFound, num );
400 QString to=sTemplate.arg( maxBackupFound+1 );
401 for (
int i=maxBackupFound; i>0; i-- ) {
402 QString from = sTemplate.arg( i );
410 return QFile::copy(qFilename, sTemplate.arg(1));