/* This file is part of the Keep project Copyright (C) 2006 Jean-Rémy Falleri Keep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Keep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Keep; if not, write to the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "rdbmanager.h" #include #include #include #include RDBManager::RDBManager() { } RDBManager::~RDBManager() { } void RDBManager::slotCheckBackup() { TQValueList backups = outdatedBackupList(); TQValueList::iterator it; for ( it = backups.begin(); it != backups.end(); ++it ) { doBackup(*it); } } void RDBManager::slotForceBackup(TQValueList backupList) { TQValueList::iterator it; for ( it = backupList.begin(); it != backupList.end(); ++it ) { doBackup(*it); } } TQString RDBManager::compareAtTime(Backup backup, TQDateTime date) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--compare-at-time"; *proc << TQString::number(date.toTime_t()); // increment date // Adds source and dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.source()))); *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); // Adds the listener RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList output = listen->stdOut(); TQStringList::iterator it = output.begin(); kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; return (*it); } TQString RDBManager::listChangedSince(Backup backup, TQDateTime date) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--list-changed-since"; *proc << TQString::number(date.toTime_t()); // increment date // Adds the dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); // Adds a listener RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList output = listen->stdOut(); TQStringList::iterator it = output.begin(); kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; return (*it); } TQString RDBManager::listAtTime(Backup backup, TQDateTime date) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--list-at-time"; *proc << TQString::number(date.toTime_t()); // increment date // Adds the dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); // Adds a listener RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList output = listen->stdOut(); TQStringList::iterator it = output.begin(); kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; return (*it); } TQValueList RDBManager::incrementList(Backup backup) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--list-increments"; *proc << "-v2"; *proc << "--parsable-output"; // Adds the dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); // Adds a listener RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList output = listen->stdOut(); TQStringList::iterator it = output.begin(); TQStringList lines = TQStringList::split("\n",*it); TQValueList dateList; TQStringList::iterator it2 = output.begin(); for ( it2 = lines.begin(); it2 != lines.end(); ++it2 ) { TQStringList field = TQStringList::split(" ",*it2); TQStringList::iterator dateStr = field.begin(); long timestamp = (*dateStr).toUInt(); TQDateTime datetime; datetime.setTime_t(timestamp); dateList.append(datetime); } kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; return dateList; } TQDateTime RDBManager::lastIncrement(Backup backup) { TQValueList increments = incrementList(backup); TQDateTime last = increments.last(); return last; } TQValueList RDBManager::outdatedBackupList() { BackupConfig config; TQValueList backups = config.backupList(); TQValueList outdated; TQValueList::iterator it; kdDebug() << "Detecting outdated backup." << endl; for ( it = backups.begin(); it != backups.end(); ++it ) { TQDateTime last = lastIncrement(*it); TQDate today = TQDate::currentDate(); if ( last.date().daysTo(today) >= (*it).interval() ) { kdDebug() << "Detected outdated backup: " << (*it).source() << endl; outdated.append(*it); } } return outdated; } void RDBManager::slotRestoreBackup(Backup backup,TQDateTime time) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--force"; *proc << "--restore-as-of"; *proc << TQString::number(time.toTime_t()); // Date of the increment to restore // Adds source and dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); *proc << TQString(TQFile::encodeName(KProcess::quote(backup.source()))); // Adds a listener (for output recording) RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); connect(proc,TQT_SIGNAL(receivedStderr(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdErr(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; kdDebug() << "Executed process: " << proc->args() << endl; if ( !listen->isOk() ) { kdDebug() << "Error message: " << listen->errorMessage() << endl; emit backupError(backup,listen->errorMessage()); } delete listen; delete proc; } bool RDBManager::isRDB() { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); *proc << "-V"; // Adds a listener (for output recording) RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList outList = listen->stdOut(); TQStringList::iterator out = outList.begin(); kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; if ( *out == "" ) return false; return true; } TQString RDBManager::RDBVersion() { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); *proc << "-V"; // Adds a listener (for output recording) RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; TQStringList outList = listen->stdOut(); TQStringList::iterator out = outList.begin(); kdDebug() << "Executed process: " << proc->args() << endl; delete listen; delete proc; return (*out).mid(13,5); } void RDBManager::doBackup(Backup backup) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(KeepSettings::controlRDBPriority,KeepSettings::rDBPriority()); // Adds include and exclude if ( backup.useIncludeExclude() ) { TQStringList includeExcludeList = backup.includeExcludeList(); TQStringList::iterator it; for ( it = includeExcludeList.begin(); it != includeExcludeList.end(); ++it ) { TQString type = (*it).left(1); TQString file = (*it).right((*it).length() - 1); if ( type == "I" ) { *proc << "--include"; *proc << TQString(TQFile::encodeName(KProcess::quote(file))); } else if ( type == "E" ) { *proc << "--exclude"; *proc << TQString(TQFile::encodeName(KProcess::quote(file))); } } } // Adds the option // For simple mode if ( !backup.useAdvancedConfig() ) { if ( !backup.useCompression() ) *proc << "--no-compression"; if ( backup.excludeSpecialFiles() ) *proc << "--exclude-special-files"; } // For advanced mode else { TQStringList optionList = backup.optionList(); for ( TQStringList::Iterator it = optionList.begin(); it != optionList.end(); ++it ) { *proc << *it; } } // Adds source and dest *proc << TQString(TQFile::encodeName(KProcess::quote(backup.source()))); *proc << TQString(TQFile::encodeName(KProcess::quote(backup.dest()))); // Adds a listener (for output recording) RDBListener *listen = new RDBListener(); connect(proc,TQT_SIGNAL(receivedStdout(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdOut(KProcess *,char *,int))); connect(proc,TQT_SIGNAL(receivedStderr(KProcess *,char *,int)),listen,TQT_SLOT(receivedStdErr(KProcess *,char *,int))); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; kdDebug() << "Executed process: " << proc->args() << endl; kdDebug() << "Process status: " << listen->isOk() << endl; if ( !listen->isOk() ) { kdDebug() << "Error message: " << listen->errorMessage() << endl; emit backupError(backup,listen->errorMessage()); } else emit backupSuccess(backup); delete listen; delete proc; if ( !backup.neverDelete() ) { removeOldIncrements(backup); } } void RDBManager::removeOldIncrements(Backup backup) { // Gets the rdiff-backup process KProcess *proc = RDBProcess(); // Adds the options *proc << "--remove-older-than" << TQString("%1").arg(backup.deleteAfter()) + "D"; // Adds dest *proc << backup.dest(); // Starts the process if ( !proc->start(KProcess::Block, KProcess::AllOutput) ) kdDebug() << "Error starting rdiff-backup" << endl; kdDebug() << "Executed process: " << proc->args() << endl; delete proc; } KProcess *RDBManager::RDBProcess(bool isNice,int niceLevel) { KProcess *proc = new KProcess(); proc->setUseShell(true); if ( isNice ) { *proc << "nice" << "-n" << TQString("%1").arg(niceLevel); } *proc << "rdiff-backup"; return proc; } #include "rdbmanager.moc"