1/* This file is part of the KDE project
2 Copyright (C) 2008 Omat Holding B.V. <info@omat.nl>
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17*/
18
19#include "backup.h"
20#include "global.h"
21
22#include <KDebug>
23#include <KIO/NetAccess>
24#include <KProcess>
25#include <KStandardDirs>
26#include <KTempDir>
27#include <KUrl>
28
29#include <QDir>
30
31#include <akonadi/private/xdgbasedirs_p.h>
32#include <akonadi/agentmanager.h>
33
34
35using namespace Akonadi;
36
37/**
38 * Use this class to create a backup. possible() will tell you if all
39 * apps needed for the backup are available. Don't proceed without them.
40 * After that call create() to get it running. Please make sure the parameter
41 * has the tar.bz2 extension.
42 */
43Backup::Backup( QWidget *parent ) : QWidget( parent )
44{
45}
46
47bool Backup::possible()
48{
49 Tray::Global global;
50 QString dbDumpAppName;
51 if( global.dbdriver() == QLatin1String("QPSQL") )
52 dbDumpAppName = QLatin1String("pg_dump");
53 else if( global.dbdriver() == QLatin1String("QMYSQL") )
54 dbDumpAppName = QLatin1String("mysqldump");
55 else {
56 kError() << "Could not find an application to dump the database.";
57 }
58
59 m_dbDumpApp = KStandardDirs::findExe( dbDumpAppName );
60 const QString bzip2 = KStandardDirs::findExe( QLatin1String("bzip2") );
61 const QString tar = KStandardDirs::findExe( QLatin1String("tar") );
62 kDebug() << "m_dbDumpApp:" << m_dbDumpApp << "bzip2:" << bzip2 << "tar:" << tar;
63 return !m_dbDumpApp.isEmpty() && !bzip2.isEmpty() && !tar.isEmpty();
64}
65
66void Backup::create( const KUrl& filename )
67{
68 if ( filename.isEmpty() ) {
69 emit completed( false );
70 return;
71 }
72
73 const QString sep( QDir::separator() );
74 /* first create the temp folder. */
75 KTempDir *tempDir = new KTempDir( KStandardDirs::locateLocal( "tmp", QLatin1String("akonadi") ) );
76 tempDir->setAutoRemove( false );
77 KIO::NetAccess::mkdir( QString(tempDir->name() + QLatin1String("kdeconfig")), this );
78 KIO::NetAccess::mkdir( QString(tempDir->name() + QLatin1String("akonadiconfig")), this );
79 KIO::NetAccess::mkdir( QString(tempDir->name() + QLatin1String("db")), this );
80
81 QStringList filesToBackup;
82
83 /* Copy over the KDE config files. */
84 AgentManager *manager = AgentManager::self();
85 const AgentInstance::List list = manager->instances();
86 foreach( const AgentInstance &agent, list ) {
87 const QString agentFileName = agent.identifier() + QLatin1String("rc");
88 const QString configFileName = KStandardDirs::locateLocal( "config", agentFileName );
89 bool exists = KIO::NetAccess::exists( configFileName, KIO::NetAccess::DestinationSide, this );
90 if ( exists ) {
91 KIO::NetAccess::file_copy( configFileName,
92 QString(tempDir->name() + QLatin1String("kdeconfig") + sep + agentFileName), this );
93 filesToBackup << QLatin1String("kdeconfig") + sep + agentFileName;
94 }
95 }
96
97 /* Copy over the Akonadi config files */
98 const QString config = XdgBaseDirs::findResourceDir( "config", QLatin1String("akonadi") );
99 QDir dir( config );
100 const QStringList configlist = dir.entryList( QDir::Files );
101 foreach( const QString& item, configlist ) {
102 KIO::NetAccess::file_copy( QString(config + sep + item),
103 QString(tempDir->name() + QLatin1String("akonadiconfig") + sep + item), this );
104 filesToBackup << QLatin1String("akonadiconfig/") + item;
105 }
106
107 /* Dump the database */
108 Tray::Global global;
109 KProcess *proc = new KProcess( this );
110 QStringList params;
111
112 if( global.dbdriver() == QLatin1String("QMYSQL") ) {
113 params << QLatin1String("--single-transaction")
114 << QLatin1String("--flush-logs")
115 << QLatin1String("--triggers")
116 << QLatin1String("--result-file=") + tempDir->name() + QLatin1String("db") + sep + QLatin1String("database.sql")
117 << global.dboptions()
118 << global.dbname();
119 }
120 else if ( global.dbdriver() == QLatin1String("QPSQL") ) {
121 params << QLatin1String("--format=custom")
122 << QLatin1String("--blobs")
123 << QLatin1String("--file=") + tempDir->name() + QLatin1String("db") + sep + QLatin1String("database.sql")
124 << global.dboptions()
125 << global.dbname();
126 }
127
128 kDebug() << "Executing: " << m_dbDumpApp << params;
129 proc->setProgram( m_dbDumpApp, params );
130 int result = proc->execute();
131 delete proc;
132 if ( result != 0 ) {
133 kWarning() << "Executed: " << m_dbDumpApp << params << "Result: " << result;
134 tempDir->unlink();
135 delete tempDir;
136 emit completed( false );
137 return;
138 }
139 filesToBackup << QLatin1String("db") + sep + QLatin1String("database.sql");
140
141 /* Make a nice tar file. */
142 proc = new KProcess( this );
143 params.clear();
144 params << QLatin1String("-C") << tempDir->name();
145 params << QLatin1String("-cjf");
146 params << filename.toLocalFile() << filesToBackup;
147 proc->setWorkingDirectory( tempDir->name() );
148 proc->setProgram( KStandardDirs::findExe( QLatin1String("tar") ), params );
149 result = proc->execute();
150 delete proc;
151 if ( result != 0 ) {
152 kWarning() << "Executed: " << KStandardDirs::findExe( QLatin1String("tar") ) << params << QLatin1String("Result: ") << result;
153 tempDir->unlink();
154 delete tempDir;
155 emit completed( false );
156 return;
157 }
158
159 tempDir->unlink();
160 delete tempDir;
161 emit completed( true );
162}
163
164