Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

packageslave.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include "packageslave.h"
00022 
00023 /* OPIE */
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 /* QT */
00032 #ifdef Q_WS_QWS
00033 #include <qcopchannel_qws.h>
00034 #endif
00035 #include <qtextstream.h>
00036 
00037 /* STD */
00038 #include <stdlib.h>
00039 #include <sys/stat.h> // mkdir()
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     // setup qcop channel
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     // Don't emit that for now, I still couldn't test it (Wener)
00105     //sendReply( "installFailed(QString)", package );
00106     //return;
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 ); // No tr
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 ); // No tr
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     //make a copy so we can remove the symlinks later
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     //#### revise
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() ) {        // until end of file...
00169         s = ts.readLine();       // line of text excluding '\n'
00170         // for s, do link/mkdir.
00171         if ( s.right(1) == "/" ) {
00172         odebug << "do mkdir for " << s.ascii() << "" << oendl;
00173 #ifndef Q_OS_WIN32
00174         mkdir( s.ascii(), 0777 );
00175         //possible optimization: symlink directories
00176         //that don't exist already. -- Risky.
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     // get list of *.list in location/usr/lib/ipkg/info/*.list
00199     QDir dir(location + "/usr/lib/ipkg/info", "*.list",  // No tr
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() ) {        // until end of file...
00221         s = ts.readLine();       // line of text excluding '\n'
00222         // for s, do link/mkdir.
00223         if ( s.right(1) == "/" ) {
00224         //should rmdir if empty, after all files have been removed
00225         } else {
00226 #ifndef Q_OS_WIN32
00227         odebug << "remove symlink for " << s.ascii() << "" << oendl;
00228         //check if it is a symlink first (don't remove /etc/passwd...)
00229         char buf[10]; //we don't care about the contents
00230         if ( ::readlink( s.ascii(),buf, 10 >= 0 ) )
00231              ::unlink( s.ascii() );
00232 #else
00233         // ### revise
00234         owarn << "Unable to remove symlink " << __FILE__ << ":" << __LINE__ << "" << oendl;
00235 #endif
00236         }
00237     }
00238     f.close();
00239 
00240         //remove the list file
00241     ::unlink( listfile.ascii() );
00242 
00243     }
00244 }
00245 
00246 void PackageHandler::cleanupPackages( const QString &location )
00247 {
00248     // get list of *.list in location/usr/lib/ipkg/info/*.list
00249     QDir dir( "/usr/lib/ipkg/info/"+location, "*.list",  // No tr
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     //remove the backup directory
00261     //###
00262 }
00263 
00264 void PackageHandler::prepareInstall( const QString& size, const QString& path )
00265 {
00266     // Check whether there will be enough space to install the next package.
00267     bool ok;
00268     unsigned int s = size.toUInt( &ok );
00269 
00270     if ( !ok )
00271     return;
00272 
00273     // Shamelessly stolen from the sysinfo application (Werner)
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         //odebug << "############### Not enough space left ###############" << oendl;
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" ) ) // No tr
00327         sendReply( "installStep(QString)", "one" ); // No tr
00328     else if ( line.contains( "Configuring" ) ) // No tr
00329         sendReply( "installStep(QString)", "two" ); // No tr
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     //get list of filesystems
00344 
00345     //call cleanupPackages for the ones that have disappeared
00346 
00347     //call addPackageFiles for the new ones
00348 }

Generated on Sat Nov 5 16:15:31 2005 for OPIE by  doxygen 1.4.2