00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "packageslave.h"
00022
00023
00024 #include <opie2/odebug.h>
00025 #include <qtopia/qprocess.h>
00026 #ifdef Q_WS_QWS
00027 #include <qtopia/qcopenvelope_qws.h>
00028 #endif
00029 using namespace Opie::Core;
00030
00031
00032 #ifdef Q_WS_QWS
00033 #include <qcopchannel_qws.h>
00034 #endif
00035 #include <qtextstream.h>
00036
00037
00038 #include <stdlib.h>
00039 #include <sys/stat.h>
00040 #if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
00041 #include <unistd.h>
00042 #include <sys/vfs.h>
00043 #include <mntent.h>
00044 #elif defined(Q_OS_MACX)
00045 #include <unistd.h>
00046 #endif
00047
00048
00049 PackageHandler::PackageHandler( QObject *parent, char* name )
00050 : QObject( parent, name ), packageChannel( 0 ), currentProcess( 0 ), mNoSpaceLeft( FALSE )
00051 {
00052
00053 #ifndef QT_NO_COP
00054 packageChannel = new QCopChannel( "QPE/Package", this );
00055 connect( packageChannel, SIGNAL( received(const QCString&,const QByteArray&) ),
00056 this, SLOT( qcopMessage(const QCString&,const QByteArray&) ) );
00057 #endif
00058 }
00059
00060 void PackageHandler::qcopMessage( const QCString &msg, const QByteArray &data )
00061 {
00062 QDataStream stream( data, IO_ReadOnly );
00063
00064 if ( msg == "installPackage(QString)" ) {
00065 QString file;
00066 stream >> file;
00067 installPackage( file );
00068 } else if ( msg == "installPackage(QString,QString)" ) {
00069 QString file, dest;
00070 stream >> file >> dest;
00071 installPackage( file, dest );
00072 } else if ( msg == "removePackage(QString)" ) {
00073 QString file;
00074 stream >> file;
00075 removePackage( file );
00076 } else if ( msg == "addPackageFiles(QString,QString)" ) {
00077 QString location, listfile;
00078 stream >> location >> listfile;
00079 addPackageFiles( location, listfile);
00080 } else if ( msg == "addPackages(QString)" ) {
00081 QString location;
00082 stream >> location;
00083 addPackages( location );
00084 } else if ( msg == "cleanupPackageFiles(QString)" ) {
00085 QString listfile;
00086 stream >> listfile;
00087 cleanupPackageFiles( listfile );
00088 } else if ( msg == "cleanupPackages(QString)" ) {
00089 QString location;
00090 stream >> location;
00091 cleanupPackages( location );
00092 } else if ( msg == "prepareInstall(QString,QString)" ) {
00093 QString size, path;
00094 stream >> size;
00095 stream >> path;
00096 prepareInstall( size, path );
00097 }
00098 }
00099
00100 void PackageHandler::installPackage( const QString &package, const QString &dest )
00101 {
00102 if ( mNoSpaceLeft ) {
00103 mNoSpaceLeft = FALSE;
00104
00105
00106
00107 }
00108
00109 QStringList cmd;
00110 cmd << "ipkg";
00111 if ( !dest.isEmpty() ) {
00112 cmd << "-d" << dest;
00113 }
00114 cmd << "install" << package;
00115 currentProcess = new QProcess( cmd );
00116 connect( currentProcess, SIGNAL( processExited() ), SLOT( iProcessExited() ) );
00117 connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) );
00118 connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) );
00119 currentPackage = package;
00120
00121 currentProcessError="";
00122 sendReply( "installStarted(QString)", package );
00123 currentProcess->start();
00124 }
00125
00126 void PackageHandler::removePackage( const QString &package )
00127 {
00128 currentProcess = new QProcess( QStringList() << "ipkg" << "remove" << package );
00129 connect( currentProcess, SIGNAL( processExited() ), SLOT( rmProcessExited() ) );
00130 connect( currentProcess, SIGNAL( readyReadStdout() ), SLOT( readyReadStdout() ) );
00131 connect( currentProcess, SIGNAL( readyReadStderr() ), SLOT( readyReadStderr() ) );
00132 currentPackage = package;
00133
00134 currentProcessError="";
00135 sendReply( "removeStarted(QString)", package );
00136 currentProcess->start();
00137 }
00138
00139 void PackageHandler::sendReply( const QCString& msg, const QString& arg )
00140 {
00141 #ifndef QT_NO_COP
00142 QCopEnvelope e( "QPE/Desktop", msg );
00143 e << arg;
00144 #endif
00145 }
00146
00147 void PackageHandler::addPackageFiles( const QString &location,
00148 const QString &listfile )
00149 {
00150 QFile f(listfile);
00151 #ifndef Q_OS_WIN32
00152
00153 mkdir( ("/usr/lib/ipkg/info/"+location).ascii(), 0777 );
00154 system(("cp " + f.name() + " /usr/lib/ipkg/info/"+location).ascii());
00155 #else
00156 QDir d;
00157
00158 odebug << "Copy file at " << __FILE__ << ": " << __LINE__ << "" << oendl;
00159 d.mkdir(("/usr/lib/ipkg/info/" + location).ascii());
00160 system(("copy " + f.name() + " /usr/lib/ipkg/info/"+location).ascii());
00161 #endif
00162
00163
00164 if ( f.open(IO_ReadOnly) ) {
00165 QTextStream ts(&f);
00166
00167 QString s;
00168 while ( !ts.eof() ) {
00169 s = ts.readLine();
00170
00171 if ( s.right(1) == "/" ) {
00172 odebug << "do mkdir for " << s.ascii() << "" << oendl;
00173 #ifndef Q_OS_WIN32
00174 mkdir( s.ascii(), 0777 );
00175
00176
00177 #else
00178 d.mkdir( s.ascii());
00179 #endif
00180
00181 } else {
00182 #ifndef Q_OS_WIN32
00183 odebug << "do symlink for " << s.ascii() << "" << oendl;
00184 symlink( (location + s).ascii(), s.ascii() );
00185 #else
00186 odebug << "Copy file instead of a symlink for WIN32" << oendl;
00187 if (!CopyFile((TCHAR*)qt_winTchar((location + s), TRUE), (TCHAR*)qt_winTchar(s, TRUE), FALSE))
00188 owarn << "Unable to create symlinkfor " << (location + s).ascii() << oendl;
00189 #endif
00190 }
00191 }
00192 f.close();
00193 }
00194 }
00195
00196 void PackageHandler::addPackages( const QString &location )
00197 {
00198
00199 QDir dir(location + "/usr/lib/ipkg/info", "*.list",
00200 QDir::Name, QDir::Files);
00201 if ( !dir.exists() )
00202 return;
00203
00204 QStringList packages = dir.entryList();
00205 for ( QStringList::Iterator it = packages.begin();
00206 it != packages.end(); ++it ) {
00207 addPackageFiles( location, *it );
00208 }
00209 }
00210
00211
00212 void PackageHandler::cleanupPackageFiles( const QString &listfile )
00213 {
00214 QFile f(listfile);
00215
00216 if ( f.open(IO_ReadOnly) ) {
00217 QTextStream ts(&f);
00218
00219 QString s;
00220 while ( !ts.eof() ) {
00221 s = ts.readLine();
00222
00223 if ( s.right(1) == "/" ) {
00224
00225 } else {
00226 #ifndef Q_OS_WIN32
00227 odebug << "remove symlink for " << s.ascii() << "" << oendl;
00228
00229 char buf[10];
00230 if ( ::readlink( s.ascii(),buf, 10 >= 0 ) )
00231 ::unlink( s.ascii() );
00232 #else
00233
00234 owarn << "Unable to remove symlink " << __FILE__ << ":" << __LINE__ << "" << oendl;
00235 #endif
00236 }
00237 }
00238 f.close();
00239
00240
00241 ::unlink( listfile.ascii() );
00242
00243 }
00244 }
00245
00246 void PackageHandler::cleanupPackages( const QString &location )
00247 {
00248
00249 QDir dir( "/usr/lib/ipkg/info/"+location, "*.list",
00250 QDir::Name, QDir::Files);
00251 if ( !dir.exists() )
00252 return;
00253
00254 QStringList packages = dir.entryList();
00255 for ( QStringList::Iterator it = packages.begin();
00256 it != packages.end(); ++it ) {
00257 cleanupPackageFiles( *it );
00258 }
00259
00260
00261
00262 }
00263
00264 void PackageHandler::prepareInstall( const QString& size, const QString& path )
00265 {
00266
00267 bool ok;
00268 unsigned int s = size.toUInt( &ok );
00269
00270 if ( !ok )
00271 return;
00272
00273
00274 #if defined(_OS_LINUX_) || defined(Q_OS_LINUX)
00275 struct statfs fs;
00276 if ( statfs( path.latin1(), &fs ) == 0 )
00277 if ( s > fs.f_bsize * fs.f_bavail ) {
00278
00279 mNoSpaceLeft = TRUE;
00280 }
00281 #endif
00282 }
00283
00284 void PackageHandler::iProcessExited()
00285 {
00286 if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 )
00287 sendReply( "installDone(QString)", currentPackage );
00288 else {
00289 #ifndef QT_NO_COP
00290 QCopEnvelope e( "QPE/Desktop", "installFailed(QString,int,QString)" );
00291 e << currentPackage << currentProcess->exitStatus()
00292 << currentProcessError;
00293 #endif
00294 }
00295
00296 delete currentProcess;
00297 currentProcess = 0;
00298
00299 #ifndef QT_NO_COP
00300 QCopEnvelope e("QPE/System", "linkChanged(QString)");
00301 QString lf = QString::null;
00302 e << lf;
00303 #endif
00304 unlink( currentPackage );
00305 }
00306
00307 void PackageHandler::rmProcessExited()
00308 {
00309 if ( currentProcess->normalExit() && currentProcess->exitStatus() == 0 )
00310 sendReply( "removeDone(QString)", currentPackage );
00311 else
00312 sendReply( "removeFailed(QString)", currentPackage );
00313
00314 #ifndef QT_NO_COP
00315 QCopEnvelope e("QPE/System", "linkChanged(QString)");
00316 QString lf = QString::null;
00317 e << lf;
00318 #endif
00319 }
00320
00321 void PackageHandler::readyReadStdout()
00322 {
00323 while ( currentProcess->canReadLineStdout() ) {
00324 QString line = currentProcess->readLineStdout();
00325 currentProcessError.append("OUT:"+line);
00326 if ( line.contains( "Unpacking" ) )
00327 sendReply( "installStep(QString)", "one" );
00328 else if ( line.contains( "Configuring" ) )
00329 sendReply( "installStep(QString)", "two" );
00330 }
00331 }
00332
00333 void PackageHandler::readyReadStderr()
00334 {
00335 while ( currentProcess->canReadLineStderr() ) {
00336 QString line = currentProcess->readLineStderr();
00337 currentProcessError.append("ERR:"+line);
00338 }
00339 }
00340
00341 void PackageHandler::redoPackages()
00342 {
00343
00344
00345
00346
00347
00348 }