| 1 | /* |
| 2 | This file is part of the KDE libraries |
| 3 | |
| 4 | SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org> |
| 5 | SPDX-FileCopyrightText: 2006 Allen Winter <winter@kde.org> |
| 6 | SPDX-FileCopyrightText: 2006 Gregory S. Hayes <syncomm@kde.org> |
| 7 | SPDX-FileCopyrightText: 2006 Jaison Lee <lee.jaison@gmail.com> |
| 8 | SPDX-FileCopyrightText: 2011 Romain Perier <bambi@ubuntu.com> |
| 9 | |
| 10 | SPDX-License-Identifier: LGPL-2.0-only |
| 11 | */ |
| 12 | |
| 13 | #include "kbackup.h" |
| 14 | |
| 15 | #include <QDir> |
| 16 | #include <QFileInfo> |
| 17 | |
| 18 | namespace KBackup |
| 19 | { |
| 20 | bool simpleBackupFile(const QString &qFilename, const QString &backupDir, const QString &backupExtension) |
| 21 | { |
| 22 | QString backupFileName = qFilename + backupExtension; |
| 23 | |
| 24 | if (!backupDir.isEmpty()) { |
| 25 | QFileInfo fileInfo(qFilename); |
| 26 | backupFileName = backupDir + QLatin1Char('/') + fileInfo.fileName() + backupExtension; |
| 27 | } |
| 28 | |
| 29 | // qCDebug(KCOREADDONS_DEBUG) << "KBackup copying " << qFilename << " to " << backupFileName; |
| 30 | QFile::remove(fileName: backupFileName); |
| 31 | return QFile::copy(fileName: qFilename, newName: backupFileName); |
| 32 | } |
| 33 | |
| 34 | bool numberedBackupFile(const QString &qFilename, const QString &backupDir, const QString &backupExtension, const uint maxBackups) |
| 35 | { |
| 36 | QFileInfo fileInfo(qFilename); |
| 37 | |
| 38 | // The backup file name template. |
| 39 | QString sTemplate; |
| 40 | if (backupDir.isEmpty()) { |
| 41 | sTemplate = qFilename + QLatin1String(".%1" ) + backupExtension; |
| 42 | } else { |
| 43 | sTemplate = backupDir + QLatin1Char('/') + fileInfo.fileName() + QLatin1String(".%1" ) + backupExtension; |
| 44 | } |
| 45 | |
| 46 | // First, search backupDir for numbered backup files to remove. |
| 47 | // Remove all with number 'maxBackups' and greater. |
| 48 | QDir d = backupDir.isEmpty() ? fileInfo.dir() : backupDir; |
| 49 | d.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); |
| 50 | const QStringList nameFilters = QStringList(fileInfo.fileName() + QLatin1String(".*" ) + backupExtension); |
| 51 | d.setNameFilters(nameFilters); |
| 52 | d.setSorting(QDir::Name); |
| 53 | |
| 54 | uint maxBackupFound = 0; |
| 55 | const QFileInfoList infoList = d.entryInfoList(); |
| 56 | for (const QFileInfo &fi : infoList) { |
| 57 | if (fi.fileName().endsWith(s: backupExtension)) { |
| 58 | // sTemp holds the file name, without the ending backupExtension |
| 59 | QString sTemp = fi.fileName(); |
| 60 | sTemp.truncate(pos: fi.fileName().length() - backupExtension.length()); |
| 61 | // compute the backup number |
| 62 | int idex = sTemp.lastIndexOf(c: QLatin1Char('.')); |
| 63 | if (idex > 0) { |
| 64 | bool ok; |
| 65 | const uint num = QStringView(sTemp).mid(pos: idex + 1).toUInt(ok: &ok); |
| 66 | if (ok) { |
| 67 | if (num >= maxBackups) { |
| 68 | QFile::remove(fileName: fi.filePath()); |
| 69 | } else { |
| 70 | maxBackupFound = qMax(a: maxBackupFound, b: num); |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // Next, rename max-1 to max, max-2 to max-1, etc. |
| 78 | QString to = sTemplate.arg(a: maxBackupFound + 1); |
| 79 | for (int i = maxBackupFound; i > 0; i--) { |
| 80 | QString from = sTemplate.arg(a: i); |
| 81 | // qCDebug(KCOREADDONS_DEBUG) << "KBackup renaming " << from << " to " << to; |
| 82 | QFile::rename(oldName: from, newName: to); |
| 83 | to = from; |
| 84 | } |
| 85 | |
| 86 | // Finally create most recent backup by copying the file to backup number 1. |
| 87 | // qCDebug(KCOREADDONS_DEBUG) << "KBackup copying " << qFilename << " to " << sTemplate.arg(1); |
| 88 | return QFile::copy(fileName: qFilename, newName: sTemplate.arg(a: 1)); |
| 89 | } |
| 90 | |
| 91 | } |
| 92 | |